def main(N, dt, T, theta=0.5): """Run bidomain MMA.""" # Exact solutions u_exact_str = "-cos(pi*x[0])*cos(pi*x[1])*sin(t)/2.0" v_exact_str = "cos(pi*x[0])*cos(pi*x[1])*sin(t)" s_exact_str = "-cos(pi*x[0])*cos(pi*x[1])*cos(t)" # Source term ac_str = "cos(t)*cos(pi*x[0])*cos(pi*x[1]) + pow(pi, 2)*cos(pi*x[0])*cos(pi*x[1])*sin(t)" ac_str += " - " + s_exact_str # Create data mesh = UnitSquareMesh(N, N) time = Constant(0.0) # We choose the FHN parameters such that s=1 and I_s=v model = SimpleODEModel(mesh) model.set_initial_conditions(V=0, S=Expression(s_exact_str, degree=5, t=0)) # Set initial condition ps = SplittingSolver.default_parameters() ps["pde_solver"] = "bidomain" ps["theta"] = theta ps["CardiacODESolver"]["scheme"] = "RK4" ps["enable_adjoint"] = False ps["BidomainSolver"]["linear_solver_type"] = "direct" ps["BidomainSolver"]["use_avg_u_constraint"] = True ps["apply_stimulus_current_to_pde"] = True stimulus = Expression(ac_str, t=time, dt=dt, degree=5) M_i = 1.0 M_e = 1.0 heart = cbcbeat.CardiacModel(mesh, time, M_i, M_e, model, stimulus) splittingsolver = SplittingSolver(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(v_exact_str, t=T, degree=3) u_exact = Expression(u_exact_str, t=T - (1. - theta) * dt, degree=3) pde_vs_, pde_vs, vur = splittingsolver.solution_fields() pde_vs_.assign(model.initial_conditions()) solutions = splittingsolver.solve((0, T), dt) for (t0, t1), (vs_, vs, vur) in solutions: pass # Compute errors v = vs.split(deepcopy=True)[0] u = vur.split(deepcopy=True)[1] v_error = errornorm(v_exact, v, "L2", degree_rise=2) u_error = errornorm(u_exact, u, "L2", degree_rise=2) return v_error, u_error, mesh.hmin(), dt, T
def main(N, dt, T, theta): # Create data mesh = UnitSquareMesh(N, N) time = Constant(0.0) ac_str = "cos(t)*cos(pi*x[0])*cos(pi*x[1]) + pow(pi, 2)*cos(pi*x[0])*cos(pi*x[1])*sin(t)" stimulus = Expression(ac_str, t=time, degree=5) M_i = 1. M_e = 1.0 # Set-up solver params = BidomainSolver.default_parameters() params["theta"] = theta params["linear_solver_type"] = "direct" params["use_avg_u_constraint"] = True params["enable_adjoint"] = False solver = BidomainSolver(mesh, time, M_i, M_e, I_s=stimulus, params=params) # 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(pi*x[0])*cos(pi*x[1])*sin(t)", t=T, degree=3) u_exact = Expression("-cos(pi*x[0])*cos(pi*x[1])*sin(t)/2.0", t=T - (1. - theta) * dt, degree=3) # Define initial condition(s) (v_, vu) = solver.solution_fields() # Solve solutions = solver.solve((0, T), dt) for (interval, fields) in solutions: continue # Compute errors (v, u) = vu.split(deepcopy=True)[0:2] v_error = errornorm(v_exact, v, "L2", degree_rise=2) u_error = errornorm(u_exact, u, "L2", degree_rise=2) return [v_error, u_error, mesh.hmin(), dt, T]
def initial_conditions(self): "Return initial conditions for v and s as an Expression." return Expression(list(self._initial_conditions.keys()), degree=1, **self._initial_conditions)