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
Ejemplo n.º 2
0
    class SolverWrapper(object):
        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()

        def run_forward_model(self):

            solutions = self.solver.solve((self.t0, self.T), self.dt)
            for (interval, fields) in solutions:
                pass
            (vs_, vs, vur) = self.solver.solution_fields()

            return vs_, vs
Ejemplo n.º 3
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_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-')