예제 #1
0
    def test_default_basic_single_cell_solver(self, cell_model, theta):
        "Test basic single cell solver."
        time = Constant(0.0)
        model = cell_model
        Model = cell_model.__class__

        if Model == supported_cell_models[3] and theta > 0:
            pytest.xfail("failing configuration (but should work)")

        model.stimulus = Expression("1000*t", t=time, degree=1)

        info_green("\nTesting %s" % model)
        vec_solve = self._run_solve(model, time, theta)

        if Model == supported_cell_models[3] and theta == 0:
            pytest.xfail("failing configuration (but should work)")

        if Model in self.references and theta in self.references[Model]:
            ind, ref_value = self.references[Model][theta]
            print("vec_solve", vec_solve.get_local())
            print("ind", ind, "ref", ref_value)

            assert_almost_equal(vec_solve[ind], ref_value, 1e-10)
        else:
            info_red("Missing references for %r, %r" % (Model, theta))
예제 #2
0
    def test_compute_gradient(self):
        "Test that we can compute the gradient for some given functional"
        set_dolfin_parameters()
        model = Model()

        params = BasicSingleCellSolver.default_parameters()
        params["theta"] = theta
        time = Constant(0.0)
        solver = BasicSingleCellSolver(model, time, params=params)

        # Get initial conditions (Projection of expressions
        # don't get annotated, which is fine, because there is
        # no need.)
        ics = project(model.initial_conditions(), solver.VS)

        # Run forward model
        info_green("Running forward %s with theta %g" % (model, theta))
        self._run(solver, model, ics)

        # Define functional
        (vs_, vs) = solver.solution_fields()
        J = Functional(inner(vs, vs) * dx * dt[FINISH_TIME])

        # Compute gradient with respect to vs_. Highly unclear
        # why with respect to ics and vs fail.
        info_green("Computing gradient")
        dJdics = compute_gradient(J, Control(vs_))
        assert (dJdics is not None), "Gradient is None (#fail)."
        print(dJdics.vector().array())
예제 #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
예제 #4
0
    def test_compute_adjoint(self):
        "Test that we can compute the adjoint for some given functional"
        set_dolfin_parameters()
        model = Model()

        params = BasicSingleCellSolver.default_parameters()
        params["theta"] = theta
        time = Constant(0.0)
        solver = BasicSingleCellSolver(model, time, params=params)

        # Get initial conditions (Projection of expressions
        # don't get annotated, which is fine, because there is
        # no need.)
        ics = project(model.initial_conditions(), solver.VS)

        # Run forward model
        info_green("Running forward %s with theta %g" % (model, theta))
        self._run(solver, model, ics)

        (vs_, vs) = solver.solution_fields()

        # Define functional and compute gradient etc
        J = Functional(inner(vs_, vs_) * dx * dt[FINISH_TIME])

        # Compute adjoint
        info_green("Computing adjoint")
        z = compute_adjoint(J)

        # Check that no vs_ adjoint is None (== 0.0!)
        for (value, var) in z:
            if var.name == "vs_":
                msg = "Adjoint solution for vs_ is None (#fail)."
                assert (value is not None), msg
예제 #5
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()
예제 #6
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()
예제 #7
0
    def setUp(self):
        self.mesh = UnitCubeMesh(5, 5, 5)
        self.time = Constant(0.0)

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

        # Create conductivity "tensors"
        self.M_i = 1.0

        self.t0 = 0.0
        self.dt = 0.1
예제 #8
0
    def test_compare_against_reference(self, Model, Scheme):
        ''' Runs the given cell model with the numerical scheme
            and compares the result with the reference value. '''

        solver = self._setup_solver(Model, Scheme, time=Constant(0))
        (vs_, vs) = solver.solution_fields()

        next_dt = 0.01
        solver.step((0.0, next_dt))
        vs_.assign(vs)
        solver.step((next_dt, 2 * next_dt))

        self.compare_against_reference(vs.vector(), Model, Scheme)
    def test_taylor_remainder(self):
        "Run Taylor remainder tests for selection of models and solvers."
        set_dolfin_parameters()
        model = Model()

        params = BasicSingleCellSolver.default_parameters()
        params["theta"] = theta
        time = Constant(0.0)
        solver = BasicSingleCellSolver(model, time, params=params)

        # Get initial conditions (Projection of expressions
        # don't get annotated, which is fine, because there is
        # no need.)
        ics = project(model.initial_conditions(), solver.VS)

        # Run forward model
        info_green("Running forward %s with theta %g" % (model, theta))
        self._run(solver, model, ics)

        # Define functional
        (vs_, vs) = solver.solution_fields()
        form = lambda w: inner(w, w)*dx
        J = Functional(form(vs)*dt[FINISH_TIME])

        # Compute value of functional with current ics
        Jics = assemble(form(vs))

        # Compute gradient with respect to vs_ (ics?)
        dJdics = compute_gradient(J, Control(vs_),
                                  forget=False)

        # Stop annotating
        parameters["adjoint"]["stop_annotating"] = True

        # Set-up runner
        def Jhat(ics):
            self._run(solver, model, ics)
            (vs_, vs) = solver.solution_fields()
            return assemble(form(vs))

        # Run taylor test
        if isinstance(model, Tentusscher_2004_mcell):
            seed=1.e-5
        else:
            seed=None

        conv_rate = taylor_test(Jhat, Control(vs_),
                                Jics, dJdics, seed=seed)

        # Check that minimal rate is greater than some given number
        assert_greater(conv_rate, 1.8)
    def _setup_solver(self, model, Scheme, mesh):

        # Initialize time and stimulus (note t=time construction!)
        time = Constant(0.0)
        stim = Expression("(time >= stim_start) && (time < stim_start + stim_duration)"
                          " ? stim_amplitude : 0.0 ", time=time, stim_amplitude=52.0,
                          stim_start=0.0, stim_duration=1.0, name="stim", degree=1)

        # Initialize solver
        params = CardiacODESolver.default_parameters()
        params["scheme"] = Scheme
        solver = CardiacODESolver(mesh, time, model, I_s=stim, params=params)

        return solver
예제 #11
0
def main(N, dt, T, theta):

    if dolfin_adjoint:
        adj_reset()

    # Create cardiac model
    mesh = UnitSquareMesh(N, N)
    time = Constant(0.0)
    cell_model = NoCellModel()
    ac_str = "cos(t)*cos(2*pi*x[0])*cos(2*pi*x[1]) + 4*pow(pi, 2)*cos(2*pi*x[0])*cos(2*pi*x[1])*sin(t)"
    stimulus = Expression(ac_str, t=time, degree=3)
    heart = CardiacModel(mesh, time, 1.0, 1.0, cell_model, stimulus=stimulus)

    # Set-up solver
    ps = BasicSplittingSolver.default_parameters()
    ps["theta"] = theta
    ps["BasicBidomainSolver"]["linear_variational_solver"][
        "linear_solver"] = "direct"
    solver = BasicSplittingSolver(heart, params=ps)

    # Define exact solution (Note: v is returned at end of time
    # interval(s), u is computed at somewhere in the time interval
    # depending on theta)
    v_exact = Expression("cos(2*pi*x[0])*cos(2*pi*x[1])*sin(t)", t=T, degree=3)
    u_exact = Expression("-cos(2*pi*x[0])*cos(2*pi*x[1])*sin(t)/2.0",
                         t=T - (1 - theta) * dt,
                         degree=3)

    # Define initial condition(s)
    vs0 = Function(solver.VS)
    (vs_, vs, vur) = solver.solution_fields()
    vs_.assign(vs0)

    # Solve
    solutions = solver.solve((0, T), dt)
    for (timestep, (vs_, vs, vur)) in solutions:
        continue

    # Compute errors
    (v, s) = vs.split(deepcopy=True)
    v_error = errornorm(v_exact, v, "L2", degree_rise=2)
    (v, u, r) = vur.split(deepcopy=True)
    u_error = errornorm(u_exact, u, "L2", degree_rise=2)

    return (v_error, u_error, mesh.hmin(), dt, T)
예제 #12
0
    def setUp(self):
        self.mesh = UnitCubeMesh(5, 5, 5)
        self.time = Constant(0.0)

        # Create stimulus
        self.stimulus = Expression("2.0", 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.t0 = 0.0
        self.dt = 0.1
    def test_replay(self):
        "Test that replay reports success for basic single cell solver"
        set_dolfin_parameters()
        model = Model()

        # Initialize solver
        params = BasicSingleCellSolver.default_parameters()
        params["theta"] = theta
        time = Constant(0.0)
        solver = BasicSingleCellSolver(model, time, params=params)

        info_green("Running %s with theta %g" % (model, theta))

        ics = project(model.initial_conditions(), solver.VS).copy(deepcopy=True, name="ics")
        self._run(solver, model, ics)

        info_green("Replaying")
        success = replay_dolfin(tol=0.0, stop=True)
        assert_true(success)
예제 #14
0
    def test_compare_against_reference_constant(self, Model, Scheme):
        ''' Runs the given cell model with the numerical scheme
            and compares the result with the reference value. '''

        Model = eval(Model)
        params = Model.default_parameters()
        self.replace_with_constants(params)

        solver = self._setup_solver(Model,
                                    Scheme,
                                    time=Constant(0),
                                    params=params)
        (vs_, vs) = solver.solution_fields()

        next_dt = 0.01
        solver.step((0.0, next_dt))
        vs_.assign(vs)
        solver.step((next_dt, 2 * next_dt))

        self.compare_against_reference(vs.vector(), Model, Scheme)
    def tlm_adj_setup_cellmodel_parameters(self, cell_model, Scheme):
        mesh = UnitIntervalMesh(3)
        Model = cell_model.__class__

        # Initiate solver, with model and Scheme
        cell_params = Model.default_parameters()
        param_name = cellmodel_parameters_seeds[Model][0]
        cell_params[param_name] = Constant(cell_params[param_name],
                                           name=param_name)
        model = Model(params=cell_params)

        solver = self._setup_solver(model, Scheme, mesh)

        info_green("Running forward %s with %s (setup)" % (model, Scheme))
        ics = Function(project(model.initial_conditions(), solver.VS),
                       name="ics")
        self._run(solver, ics)

        # Define functional
        (vs_, vs) = solver.solution_fields()
        form = lambda w: inner(w, w) * dx
        J = Functional(form(vs) * dt[FINISH_TIME])

        # Compute value of functional with current ics
        Jics = assemble(form(vs))

        # Set-up runner
        def Jhat(val):
            cell_params[param_name].assign(val)
            ics = Function(project(model.initial_conditions(), solver.VS),
                           name="ics")
            self._run(solver, ics)
            (vs_, vs) = solver.solution_fields()
            return assemble(form(vs))

        # Stop annotating
        solver.parameters["enable_adjoint"] = False

        m = ConstantControl(cell_params[param_name])
        return J, Jhat, m, Jics
        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)
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
예제 #18
0
 def replace_with_constants(self, params):
     ''' Replace all float values in params by Constants. '''
     for param_name in params.keys():
         value = params[param_name]
         params[param_name] = Constant(value)
    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-')
예제 #20
0
    def long_run_compare(self):
        mesh = UnitIntervalMesh(5)

        # FIXME: We need to make this run in paralell.
        if MPI.size(mesh.mpi_comm()) > 1:
            return

        Model = Tentusscher_2004_mcell
        tstop = 10
        ind_V = 0
        dt_ref = 0.1
        time_ref = np.linspace(0, tstop, int(tstop/dt_ref)+1)
        dir_path = os.path.dirname(__file__)
        Vm_reference = np.fromfile(os.path.join(dir_path, "Vm_reference.npy"))
        params = Model.default_parameters()

        time = Constant(0.0)
        stim = Expression("(time >= stim_start) && (time < stim_start + stim_duration)"\
                             " ? stim_amplitude : 0.0 ", time=time, stim_amplitude=52.0, \
                             stim_start=1.0, stim_duration=1.0, degree=1)

        # Initiate solver, with model and Scheme
        if dolfin_adjoint:
            adj_reset()

        solver = self._setup_solver(Model, Scheme, mesh, time, stim, params)
        solver._pi_solver.parameters["newton_solver"]["relative_tolerance"] = 1e-8
        solver._pi_solver.parameters["newton_solver"]["maximum_iterations"] = 30
        solver._pi_solver.parameters["newton_solver"]["report"] = False

        scheme = solver._scheme
        (vs_, vs) = solver.solution_fields()

        vs.assign(vs_)

        dof_to_vertex_map_values = dof_to_vertex_map(vs.function_space())
        scheme.t().assign(0.0)

        vs_array = np.zeros(mesh.num_vertices()*\
                            vs.function_space().dofmap().num_entity_dofs(0))
        vs_array[dof_to_vertex_map_values] = vs.vector().array()
        output = [vs_array[ind_V]]
        time_output = [0.0]
        dt = dt_org

        # Time step
        next_dt = max(min(tstop-float(scheme.t()), dt), 0.0)
        t0 = 0.0

        while next_dt > 0.0:

            # Step solver
            solver.step((t0, t0 + next_dt))
            vs_.assign(vs)

            # Collect plt output data
            vs_array[dof_to_vertex_map_values] = vs.vector().array()
            output.append(vs_array[ind_V])
            time_output.append(float(scheme.t()))

            # Next time step
            t0 += next_dt
            next_dt = max(min(tstop-float(scheme.t()), dt), 0.0)

        # Compare solution from CellML run using opencell
        assert_almost_equal(output[-1], Vm_reference[-1], abs_tol)

        output = np.array(output)
        time_output = np.array(time_output)

        output = np.interp(time_ref, time_output, output)

        value = np.sqrt(np.sum(((Vm_reference-output)/Vm_reference)**2))/len(Vm_reference)
        assert_almost_equal(value, 0.0, rel_tol)