def planar_wave(ode, domain, D, S1, threshold, d=5): ''' Finds the conduction velocity of a planar wave. First paces the 0D ode model for 50 cycles at a BCL of 1000, then initiates a single planar wave, measuring the conduction velocity half-way in the domain. ''' # Load the cell model from file cellmodel = load_ode(ode) cellmodel = dolfin_jit(cellmodel, field_states, field_parameters) # Create the CardiacModel for the given domain and cell model heart = CardiacModel(domain, Constant(0.0), D, None, cellmodel) # Create the solver solver = GOSSplittingSolver(heart, GOSSparams()) dolfin_solver = solver.ode_solver ode_solver = dolfin_solver._ode_system_solvers[0] BCL = 1000 try: sspath = "../data/steadystates/" steadystate = np.load(sspath+"steadystate_%s_BCL%d.npy" % (ode, BCL)) except: print "Did not find steadystate for %s at BCL: %g, pacing 0D model" % (ode, BCL) steadystate = find_steadystate(ODE, BCL, 0.01) # Load steadystate into 2D model (u, um) = solver.solution_fields() for node in range(domain.coordinates().shape[0]): ode_solver.states(node)[:] = steadystate u.vector()[node] = steadystate[0] # Define the planar wave stimulus V = VectorFunctionSpace(domain, 'CG', 1) S1 = interpolate(S1, V).vector().array() # Apply the stimulus ode_solver.set_field_parameters(S1) xp = 0; yp = 0; t0 = 0; t1 = 0; for timestep, (u, vm) in solver.solve((0, tstop), dt): #plot(u, **plot_args) x = u.vector()[N/2-d] y = u.vector()[N/2+d] print u.vector().max(), x, y if x > threshold and (x-threshold)*(xp-threshold) < 0: # X cell has activated t0 = timestep[0] if y > threshold and (y-threshold)*(yp-threshold) < 0 and t0 != 0: # Y cell has activated t1 = timestep[0] # Calculate conduction velocity print "CV: ", 2*d*h/(t1-t0)*1e3 break xp = x yp = y
def __init__(self, ode): # Create the domain domain = RectangleMesh(0, 0, L, L, N, N) # Load the cell model from file cellmodel = load_ode(ode) cellmodel = dolfin_jit(cellmodel, field_states, field_parameters) # Create the CardiacModel for the given domain and cell model heart = CardiacModel(domain, Constant(0.0), D, None, cellmodel) # Create the solver solver = GOSSplittingSolver(heart, self.GOSSparams()) # Get the solution fields and subsolvers dolfin_solver = solver.ode_solver ode_solver = dolfin_solver._ode_system_solvers[0] self.solver = solver self.ode = ode self.dolfin_solver = dolfin_solver self.ode_solver = ode_solver self.domain = domain
def pacing_cv(ode, BCL_range, D, dt, threshold=0, stim_amp=0, plot_args=None): D = Constant(D) # Must be adjusted with temporal and spatial resolution L = 20 h = 0.5 dt_low = 0.1 # Create dolfin mesh N = int(L / h) domain = IntervalMesh(N, 0, L) # Load the cell model from file ode = load_ode(ode) cellmodel = dolfin_jit(ode, field_states=["V"], field_parameters=["stim_period", "stim_amplitude"]) # Create the CardiacModel for the given mesh and cell model heart = CardiacModel(domain, Constant(0.0), D, None, cellmodel) # Create the solver solver = GOSSplittingSolver(heart, GOSSparams()) # Get the solution fields and subsolvers dolfin_solver = solver.ode_solver ode_solver = dolfin_solver._ode_system_solvers[0] results = np.zeros((4, len(BCL_range))) for i, BCL in enumerate(BCL_range): # Set the stimulus parameter field stim_field = np.zeros(2 * (N + 1), dtype=np.float_) stim_field[0] = BCL stim_field[1] = stim_amp ode_solver.set_field_parameters(stim_field) # Pace 0D cell model and find quasi steady state sspath = "../data/steadystates/" try: states = np.load(sspath + "steadystate_%s_BCL%d.npy" % (ode, BCL)) except: print "Did not find steadystate for %s at BCL: %g, pacing 0D model" % ( ode, BCL) find_steadystate(ODE, BCL, 0.01) # Load quasi steady state into 1D model (u, um) = solver.solution_fields() for node in range(N + 1): ode_solver.states(node)[:] = states u.vector()[node] = states[0] # Used for measuring cell activation xp = 0 yp = 0 results[0][i] = BCL print "BCL: %g" % BCL # Do 3 pulses for pulsenr in range(1, 4): # Solve the pulse in higher temporal resolution for timestep, (u, vm) in solver.solve((i * BCL, i * BCL + 50), dt): if plot_args: plot(u, **plot_args) x = u.vector()[20] y = u.vector()[35] if x > threshold and (x - threshold) * (xp - threshold) < 0: t0 = (threshold - xp) / (x - xp) * dt + tp if y > threshold and (y - threshold) * (yp - threshold) < 0: t1 = (threshold - yp) / (y - yp) * dt + tp # Calculate conduction velocity Cv = 15 * h / (t1 - t0) * 1e3 print "\tCv: %g" % Cv results[pulsenr][i] = Cv t0 = 0 t1 = 0 xp = x yp = y tp = timestep[0] # Wait for next pulse for timestep, (u, vm) in solver.solve( (i * BCL + 50, (i + 1) * BCL), dt_low): if plot_args: plot(u, **plot_args) np.save("../data/results/cv_%s" % ode, results)
def spiral(ode, domain, D, S1, S2, plot_args={}, save_fig=False, threshold=0, BCL=500): # Load the cell model from file cellmodel = load_ode(ode) cellmodel = dolfin_jit(cellmodel, field_states, field_parameters) # Create the CardiacModel for the given domain and cell model heart = CardiacModel(domain, Constant(0.0), D, None, cellmodel) # Create the solver solver = GOSSplittingSolver(heart, GOSSparams()) dolfin_solver = solver.ode_solver ode_solver = dolfin_solver._ode_system_solvers[0] # Calculate parameter fields V = VectorFunctionSpace(domain, 'CG', 1) S1 = interpolate(S1, V).vector().array() S2 = interpolate(S2, V).vector().array() nostim = np.zeros(S1.shape, dtype=np.float_) # Read in steady state from file try: sspath = "../data/steadystates/" steadystate = np.load(sspath + "steadystate_%s_BCL%d.npy" % (ode, BCL)) except: print "Did not find steadystate for %s at BCL: %g, pacing 0D model" % ( ode, BCL) steadystate = find_steadystate(ODE, BCL, 0.01) # Load steadystate into 2D model (u, um) = solver.solution_fields() for node in range(domain.coordinates().shape[0]): ode_solver.states(node)[:] = steadystate u.vector()[node] = steadystate[0] cnt = 0 # Stimulate S1 pulse plot(u, interactive=True, **plot_args) ode_solver.set_field_parameters(S1) for timestep, (u, vm) in solver.solve((0, S2_time), dt): fig = plot(u, interactive=False, **plot_args) if save_fig and cnt % 5 == 0: padded_index = '%08d' % cnt fig.write_png('../tmp/randfib2_spiral_%s' % ode + padded_index) cnt += 1 ode_solver.set_field_parameters(S2) # Stimulate S2 pulse for timestep, (u, vm) in solver.solve((S2_time, S2_time + 100), dt): fig = plot(u, interactive=False, **plot_args) if save_fig and cnt % 5 == 0: padded_index = '%08d' % cnt fig.write_png('../tmp/randfib2_spiral_%s' % ode + padded_index) cnt += 1 # Turn of all stimulus and iterate until simulation stop # We monitor the top right corner to find the randfib_spiral period ode_solver.set_field_parameters(nostim) trig_time = [] xp = 0 for timestep, (u, vm) in solver.solve((S2_time + 100, tstop), dt): fig = plot(u, interactive=False, **plot_args) x = u.vector()[-1] if x > threshold and (x - threshold) * (xp - threshold) < 0: trig_time.append(timestep[0]) print "Trigger: %g" % timestep[0] xp = x if save_fig and cnt % 5 == 0: padded_index = '%08d' % cnt fig.write_png('../tmp/randfib2_spiral_%s' % ode + padded_index) cnt += 1
cellmodel = load_ode(ode) cellmodel = dolfin_jit(cellmodel, field_states, field_parameters) def GOSSparams(): params = GOSSplittingSolver.default_parameters() params["pde_solver"] = "monodomain" params["MonodomainSolver"]["linear_solver_type"] = "iterative" params["MonodomainSolver"]["theta"] = 1.0 params["ode_solver"]["scheme"] = "RL1" params["apply_stimulus_current_to_pde"] = False return params # Create the CardiacModel for the given domain and cell model heart = CardiacModel(domain, Constant(0.0), D, None, cellmodel) # Create the solver solver = GOSSplittingSolver(heart, GOSSparams()) # Get the solution fields and subsolvers dolfin_solver = solver.ode_solver ode_solver = dolfin_solver._ode_system_solvers[0] # Define stimulus fields S1 = ("(x[2] > 15.1)*amp", "t", "10000") #S2 = ("(x[1] > 4.75)*amp", "t", "10000") S2 = ("(x[0] > 0.0 && x[0] < 2.0 && x[2] > 10.0)*amp", "t", "stim_period") #("(x[0] > 4.8 && x[0] < 5.3 && x[1] > 4.8 && x[1] < 5.3)*amp", "t", "10000") #("(x[2] > 14 && x[1] < 4)*amp", "t", "10000") S1 = Expression(S1, amp=stim_amp, t=0)