示例#1
0
    def setup(self):
        self.mesh = UnitCubeMesh(5, 5, 5)

        # Create time
        self.time = Constant(0.0)

        # Create stimulus
        self.stimulus = Expression("2.0*t", t=self.time, degree=1)

        # Create ac
        self.applied_current = Expression("sin(2*pi*x[0])*t",
                                          t=self.time,
                                          degree=3)

        # Create conductivity "tensors"
        self.M_i = 1.0
        self.M_e = 2.0

        self.cell_model = FitzHughNagumoManual()
        self.cardiac_model = CardiacModel(self.mesh, self.time, self.M_i,
                                          self.M_e, self.cell_model,
                                          self.stimulus, self.applied_current)

        dt = 0.1
        self.t0 = 0.0
        self.dt = [(0.0, dt), (dt * 2, dt / 2), (dt * 4, dt)]
        # Test using variable dt interval but using the same dt.

        self.T = self.t0 + 5 * dt
        self.ics = self.cell_model.initial_conditions()
示例#2
0
        def __init__(self):
            self.mesh = UnitCubeMesh(5, 5, 5)

            # Create time
            self.time = Constant(0.0)

            # Create stimulus
            self.stimulus = Expression("2.0*t", t=self.time, degree=1)

            # Create ac
            self.applied_current = Expression("sin(2*pi*x[0])*t",
                                              t=self.time,
                                              degree=3)

            # Create conductivity "tensors"
            self.M_i = 1.0
            self.M_e = 2.0

            self.cell_model = FitzHughNagumoManual()
            self.cardiac_model = CardiacModel(self.mesh, self.time, self.M_i,
                                              self.M_e, self.cell_model,
                                              self.stimulus,
                                              self.applied_current)

            dt = 0.1
            self.t0 = 0.0
            if Solver == SplittingSolver:
                # FIXME: Dolfin-adjoint fails with adaptive timestep and SplittingSolver
                self.dt = dt
            else:
                self.dt = [(0.0, dt), (dt * 2, dt / 2), (dt * 4, dt)]
            # Test using variable dt interval but using the same dt.

            self.T = self.t0 + 5 * dt

            # Create solver object
            params = Solver.default_parameters()

            if Solver == SplittingSolver:
                params.enable_adjoint = enable_adjoint
                params.BidomainSolver.linear_solver_type = solver_type
                params.BidomainSolver.petsc_krylov_solver.relative_tolerance = 1e-12
            else:
                params.BasicBidomainSolver.linear_variational_solver.linear_solver = \
                                "gmres" if solver_type == "iterative" else "lu"
                params.BasicBidomainSolver.linear_variational_solver.krylov_solver.relative_tolerance = 1e-12
                params.BasicBidomainSolver.linear_variational_solver.preconditioner = 'ilu'

            self.solver = Solver(self.cardiac_model, params=params)
            (vs_, vs, vur) = self.solver.solution_fields()

            if ics is None:
                self.ics = self.cell_model.initial_conditions()
                vs_.assign(self.ics)
            else:
                vs_.vector()[:] = ics.vector()
示例#3
0
def setup_model():
    "Set-up cardiac model based on a slightly non-standard set of parameters."

    # Define cell parameters
    k = 0.00004; Vrest = -85.; Vthreshold = -70.; Vpeak = 40.;
    v_amp = Vpeak - Vrest
    l = 0.63; b = 0.013;
    cell_parameters = {"c_1": k*v_amp**2, "c_2": k*v_amp, "c_3": b/l,
                       "a": (Vthreshold - Vrest)/v_amp, "b": l,
                       "v_rest":Vrest, "v_peak": Vpeak}
    cell = FitzHughNagumoManual(cell_parameters)

    # Define conductivities
    chi = 2000.0   # cm^{-1}
    s_il = 3.0/chi # mS
    s_it = 0.3/chi # mS
    s_el = 2.0/chi # mS
    s_et = 1.3/chi # mS
    M_i = as_tensor(((s_il, 0), (0, s_it)))
    M_e = as_tensor(((s_el, 0), (0, s_et)))

    # Define mesh
    domain = UnitSquareMesh(20, 20)
    time = Constant(0.0)

    heart = CardiacModel(domain, time, M_i, M_e, cell)
    return heart
def test_solver_with_domains():

    mesh = UnitCubeMesh(5, 5, 5)
    time = Constant(0.0)

    stimulus = Expression("2.0*t", t=time, degree=1)

    # Create ac
    applied_current = Expression("sin(2*pi*x[0])*t", t=time, degree=3)

    # Create conductivity "tensors"
    M_i = 1.0
    M_e = 2.0

    cell_model = FitzHughNagumoManual()
    cardiac_model = CardiacModel(mesh, time, M_i, M_e, cell_model,
                                 stimulus, applied_current)

    dt = 0.1
    t0 = 0.0
    dt = dt
    T = t0 + 5*dt

    ics = cell_model.initial_conditions()

    # Create basic solver
    params = SplittingSolver.default_parameters()
    params["ode_solver_choice"] = "BasicCardiacODESolver"
    solver = SplittingSolver(cardiac_model, params=params)

    (vs_, vs, vur) = solver.solution_fields()
    vs_.assign(ics)

    # Solve
    solutions = solver.solve((t0, T), dt)
    for (interval, fields) in solutions:
        (vs_, vs, vur) = fields
 def setup(self):
     self.mesh = UnitCubeMesh(2, 2, 2)
     self.cell_model = FitzHughNagumoManual()
     self.cardiac_model = CardiacModel(self.mesh, None,
                                       1.0, 2.0,
                                       self.cell_model)
示例#6
0
class TestSplittingSolver(object):
    "Test functionality for the splitting solvers."

    def setup(self):
        self.mesh = UnitCubeMesh(5, 5, 5)

        # Create time
        self.time = Constant(0.0)

        # Create stimulus
        self.stimulus = Expression("2.0*t", t=self.time, degree=1)

        # Create ac
        self.applied_current = Expression("sin(2*pi*x[0])*t",
                                          t=self.time,
                                          degree=3)

        # Create conductivity "tensors"
        self.M_i = 1.0
        self.M_e = 2.0

        self.cell_model = FitzHughNagumoManual()
        self.cardiac_model = CardiacModel(self.mesh, self.time, self.M_i,
                                          self.M_e, self.cell_model,
                                          self.stimulus, self.applied_current)

        dt = 0.1
        self.t0 = 0.0
        self.dt = [(0.0, dt), (dt * 2, dt / 2), (dt * 4, dt)]
        # Test using variable dt interval but using the same dt.

        self.T = self.t0 + 5 * dt
        self.ics = self.cell_model.initial_conditions()

    @medium
    @parametrize(("solver_type"), ["direct", "iterative"])
    def test_basic_and_optimised_splitting_solver_exact(self, solver_type):
        """Test that basic and optimised splitting solvers yield
        very comparative results when configured identically."""

        # Create basic solver
        params = BasicSplittingSolver.default_parameters()
        params["BasicCardiacODESolver"]["S_polynomial_family"] = "CG"
        params["BasicCardiacODESolver"]["S_polynomial_degree"] = 1
        solver = BasicSplittingSolver(self.cardiac_model, params=params)

        (vs_, vs, vur) = solver.solution_fields()
        vs_.assign(self.ics)

        # Solve
        solutions = solver.solve((self.t0, self.T), self.dt)
        for (interval, fields) in solutions:
            (vs_, vs, vur) = fields
        a = vs.vector().norm("l2")
        c = vur.vector().norm("l2")
        assert_almost_equal(interval[1], self.T, 1e-10)

        if dolfin_adjoint:
            adj_reset()

        # Create optimised solver with direct solution algorithm
        params = SplittingSolver.default_parameters()
        params["BidomainSolver"]["linear_solver_type"] = solver_type
        params["enable_adjoint"] = False
        if solver_type == "direct":
            params["BidomainSolver"]["use_avg_u_constraint"] = True
        solver = SplittingSolver(self.cardiac_model, params=params)

        (vs_, vs, vur) = solver.solution_fields()
        vs_.assign(self.ics)

        # Solve again
        solutions = solver.solve((self.t0, self.T), self.dt)
        for (interval, fields) in solutions:
            (vs_, vs, vur) = fields
        assert_almost_equal(interval[1], self.T, 1e-10)
        b = vs.vector().norm("l2")
        d = vur.vector().norm("l2")

        print "a, b = ", a, b
        print "c, d = ", c, d
        print "a - b = ", (a - b)
        print "c - d = ", (c - d)

        # Compare results, discrepancy is in difference in ODE
        # solves.
        assert_almost_equal(a, b, tolerance=1.)
        assert_almost_equal(c, d, tolerance=1.)
    def test_fitz_hugh_nagumo_modified(self):
        k = 0.00004
        Vrest = -85.
        Vthreshold = -70.
        Vpeak = 40.
        k = 0.00004
        l = 0.63
        b = 0.013

        class FHN2(CardiacCellModel):
            """ODE model:

            parameters(Vrest,Vthreshold,Vpeak,k,l,b,ist)

            input(u)
            output(g)
            default_states(v=-85, w=0)

            Vrest = -85;
            Vthreshold = -70;
            Vpeak = 40;
            k = 0.00004;
            l = 0.63;
            b = 0.013;
            ist = 0.0

            v = u[0]
            w = u[1]

            g[0] =  -k*(v-Vrest)*(w+(v-Vthreshold)*(v-Vpeak))-ist;
            g[1] = l*(v-Vrest) - b*w;

            [specified by G. T. Lines Sept 22 2012]

            Note the minus sign convention here in the specification of
            I (g[0]) !!
            """
            def __init__(self):
                CardiacCellModel.__init__(self)

            def default_parameters(self):
                parameters = Parameters("FHN2")
                parameters.add("Vrest", Vrest)
                parameters.add("Vthreshold", Vthreshold)
                parameters.add("Vpeak", Vpeak)
                parameters.add("k", k)
                parameters.add("l", l)
                parameters.add("b", b)
                parameters.add("ist", 0.0)
                return parameters

            def I(self, v, w, time=None):
                k = self._parameters["k"]
                Vrest = self._parameters["Vrest"]
                Vthreshold = self._parameters["Vthreshold"]
                Vpeak = self._parameters["Vpeak"]
                ist = self._parameters["ist"]
                i = -k * (v - Vrest) * (w + (v - Vthreshold) *
                                        (v - Vpeak)) - ist
                return -i

            def F(self, v, w, time=None):
                l = self._parameters["l"]
                b = self._parameters["b"]
                Vrest = self._parameters["Vrest"]
                return l * (v - Vrest) - b * w

            def num_states(self):
                return 1

            def __str__(self):
                return "Modified FitzHugh-Nagumo cardiac cell model"

        def _run(cell):
            if dolfin_adjoint:
                from dolfin_adjoint import adj_reset
                adj_reset()

            solver = BasicSingleCellSolver(cell, Constant(0.0))

            # Setup initial condition
            (vs_, vs) = solver.solution_fields()
            vs_.vector()[0] = 30.  # Non-resting state
            vs_.vector()[1] = 0.

            T = 2
            solutions = solver.solve((0, T), 0.25)
            times = []
            v_values = []
            s_values = []
            for ((t0, t1), vs) in solutions:
                times += [0.5 * (t0 + t1)]
                v_values.append(vs.vector()[0])
                s_values.append(vs.vector()[1])

            return (v_values, s_values, times)

        # Try the modified one
        cell_mod = FHN2()
        (v_values_mod, s_values_mod, times_mod) = _run(cell_mod)

        # Compare with our standard FitzHugh (reparametrized)
        v_amp = Vpeak - Vrest
        cell_parameters = {
            "c_1": k * v_amp**2,
            "c_2": k * v_amp,
            "c_3": b / l,
            "a": (Vthreshold - Vrest) / v_amp,
            "b": l,
            "v_rest": Vrest,
            "v_peak": Vpeak
        }
        cell = FitzHughNagumoManual(cell_parameters)
        (v_values, s_values, times) = _run(cell)

        msg = "Mismatch in %s value comparison, diff = %.16e"
        v_diff = abs(v_values[-1] - v_values_mod[-1])
        s_diff = abs(s_values[-1] - s_values_mod[-1])
        assert (v_diff < 1.e-12), msg % v_diff
        assert (s_diff < 1.e-12), msg % s_diff

        # Look at some plots
        import os
        if int(os.environ.get("DOLFIN_NOPLOT", 0)) != 1:
            import pylab
            pylab.title("Standard FitzHugh-Nagumo")
            pylab.plot(times, v_values, 'b*')
            pylab.plot(times, s_values, 'r-')

            pylab.figure()
            pylab.title("Modified FitzHugh-Nagumo")
            pylab.plot(times_mod, v_values_mod, 'b*')
            pylab.plot(times_mod, s_values_mod, 'r-')
    def test_fitzhugh_nagumo_manual(self):
        """Test that the manually written FitzHugh-Nagumo model gives
        comparable results to a given reference from Sundnes et al,
        2006."""
        class Stimulus(Expression):
            def __init__(self, **kwargs):
                self.t = kwargs["t"]

            def eval(self, value, x):
                if float(self.t) >= 50 and float(self.t) < 60:
                    v_amp = 125
                    value[0] = 0.05 * v_amp
                else:
                    value[0] = 0.0

        if dolfin_adjoint:
            from dolfin_adjoint import adj_reset
            adj_reset()

        cell = FitzHughNagumoManual()
        time = Constant(0.0)
        cell.stimulus = Stimulus(t=time, degree=0)
        solver = BasicSingleCellSolver(cell, time)

        # Setup initial condition
        (vs_, vs) = solver.solution_fields()
        ic = cell.initial_conditions()
        vs_.assign(ic)

        # Initial set-up
        interval = (0, 400)
        dt = 1.0

        times = []
        v_values = []
        s_values = []

        # Solve
        solutions = solver.solve(interval, dt=dt)
        for (timestep, vs) in solutions:
            (t0, t1) = timestep
            times += [(t0 + t1) / 2]

            v_values += [vs.vector()[0]]
            s_values += [vs.vector()[1]]

        # Regression test
        v_max_reference = 2.6883308148064152e+01
        s_max_reference = 6.8660144687023219e+01
        tolerance = 1.e-14
        print "max(v_values) %.16e" % max(v_values)
        print "max(s_values) %.16e" % max(s_values)
        msg = "Maximal %s value does not match reference: diff is %.16e"

        v_diff = abs(max(v_values) - v_max_reference)
        s_diff = abs(max(s_values) - s_max_reference)
        assert (v_diff < tolerance), msg % ("v", v_diff)
        assert (s_diff < tolerance), msg % ("s", s_diff)

        # Correctness test
        import os
        if int(os.environ.get("DOLFIN_NOPLOT", 0)) != 1:
            import pylab
            pylab.plot(times, v_values, 'b*')
            pylab.plot(times, s_values, 'r-')