def extract_blocks(form, test_functions: typing.List[ufl.Argument], trial_functions: typing.List[ufl.Argument] = None): """Extract blocks from a monolithic UFL form. Parameters ---------- form test_functions trial_functions: optional Returns ------- Splitted UFL form in the order determined by the passed test and trial functions. If no `trial_functions` are provided returns a list, othwerwise returns list of lists. """ # Prepare empty block matrices list if trial_functions is not None: blocks = [[None for i in range(len(test_functions))] for j in range(len(trial_functions))] else: blocks = [None for i in range(len(test_functions))] for i, tef in enumerate(test_functions): if trial_functions is not None: for j, trf in enumerate(trial_functions): to_null = dict() # Dictionary mapping the other trial functions # to zero for item in trial_functions: if item != trf: to_null[item] = ufl.zero(item.ufl_shape) # Dictionary mapping the other test functions # to zero for item in test_functions: if item != tef: to_null[item] = ufl.zero(item.ufl_shape) blocks[i][j] = ufl.replace(form, to_null) else: to_null = dict() # Dictionary mapping the other test functions # to zero for item in test_functions: if item != tef: to_null[item] = ufl.zero(item.ufl_shape) blocks[i] = ufl.replace(form, to_null) return blocks
def F(self, v, s, time=None): """ Right hand side for ODE system """ time = time if time else Constant(0.0) # Assign states V = v assert (len(s) == 3) m, h, n = s # Assign parameters # Init return args F_expressions = [ufl.zero()] * 3 # Expressions for the m gate component alpha_m = (-5.0 - 0.1 * V) / (-1.0 + ufl.exp(-5.0 - V / 10.0)) beta_m = 4 * ufl.exp(-25.0 / 6.0 - V / 18.0) F_expressions[0] = (1 - m) * alpha_m - beta_m * m # Expressions for the h gate component alpha_h = 0.07 * ufl.exp(-15.0 / 4.0 - V / 20.0) beta_h = 1.0 / (1 + ufl.exp(-9.0 / 2.0 - V / 10.0)) F_expressions[1] = (1 - h) * alpha_h - beta_h * h # Expressions for the n gate component alpha_n = (-0.65 - 0.01 * V) / (-1.0 + ufl.exp(-13.0 / 2.0 - V / 10.0)) beta_n = 0.125 * ufl.exp(-15.0 / 16.0 - V / 80.0) F_expressions[2] = (1 - n) * alpha_n - beta_n * n # Return results return dolfin.as_vector(F_expressions)
def _rush_larsen_step(rhs_exprs, diff_rhs_exprs, linear_terms, system_size, y0, stage_solution, dt, time, a, c, v, DX, time_dep_expressions): # If we need to replace the original solution with stage solution repl = None if stage_solution is not None: if system_size > 1: repl = {y0: stage_solution} else: repl = {y0[0]: stage_solution} # If we have time dependent expressions if time_dep_expressions and abs(float(c)) > DOLFIN_EPS: time_ = time time = time + dt * float(c) repl.update(_replace_dict_time_dependent_expression(time_dep_expressions, time_, dt, float(c))) repl[time_] = time # If all terms are linear (using generalized=True) we add a safe # guard to the linearized term. See below safe_guard = sum(linear_terms) == system_size # Add componentwise contribution to rl form rl_ufl_form = ufl.zero() num_rl_steps = 0 for ind in range(system_size): # forward euler step fe_du_i = rhs_exprs[ind] * dt * float(a) # If exact integration if linear_terms[ind]: num_rl_steps += 1 # Rush Larsen step Safeguard the divisor: let's hope # diff_rhs_exprs[ind] is never 1.0e-16! Let's get rid of # this when the conditional fixes land properly in UFL. eps = Constant(1.0e-16) rl_du_i = rhs_exprs[ind] / (diff_rhs_exprs[ind] + eps) * ( ufl.exp(diff_rhs_exprs[ind] * dt) - 1.0) # If safe guard if safe_guard: du_i = ufl.conditional(ufl.lt(abs(diff_rhs_exprs[ind]), 1e-8), fe_du_i, rl_du_i) else: du_i = rl_du_i else: du_i = fe_du_i # If we should replace solution in form with stage solution if repl: du_i = ufl.replace(du_i, repl) rl_ufl_form += (y0[ind] + du_i) * v[ind] return rl_ufl_form * DX
def F(self, v, s, time=None): """ Right hand side for ODE system """ time = time if time else Constant(0.0) # Assign states V = v assert(len(s) == 2) m, h = s # Assign parameters E_h = self._parameters["E_h"] E_m = self._parameters["E_m"] delta_h = self._parameters["delta_h"] k_h = self._parameters["k_h"] k_m = self._parameters["k_m"] tau_h0 = self._parameters["tau_h0"] tau_m = self._parameters["tau_m"] # Init return args F_expressions = [ufl.zero()]*2 # Expressions for the m gate component m_inf = 1.0/(1.0 + ufl.exp((E_m - V)/k_m)) F_expressions[0] = (-m + m_inf)/tau_m # Expressions for the h gate component h_inf = 1.0/(1.0 + ufl.exp((-E_h + V)/k_h)) tau_h = 2*tau_h0*ufl.exp(delta_h*(-E_h + V)/k_h)/(1 + ufl.exp((-E_h +\ V)/k_h)) F_expressions[1] = (-h + h_inf)/tau_h # Return results return dolfin.as_vector(F_expressions)
def function_arg(self, g): '''Set the value of this boundary condition.''' if isinstance(g, firedrake.Function): if g.function_space() != self.function_space(): raise RuntimeError("%r is defined on incompatible FunctionSpace!" % g) self._function_arg = g elif isinstance(g, ufl.classes.Zero): if g.ufl_shape and g.ufl_shape != self.function_space().ufl_element().value_shape(): raise ValueError(f"Provided boundary value {g} does not match shape of space") # Special case. Scalar zero for direct Function.assign. self._function_arg = ufl.zero() elif isinstance(g, ufl.classes.Expr): if g.ufl_shape != self.function_space().ufl_element().value_shape(): raise RuntimeError(f"Provided boundary value {g} does not match shape of space") try: self._function_arg = firedrake.Function(self.function_space()) self._function_arg_update = firedrake.Interpolator(g, self._function_arg).interpolate except (NotImplementedError, AttributeError): # Element doesn't implement interpolation self._function_arg = firedrake.Function(self.function_space()).project(g) self._function_arg_update = firedrake.Projector(g, self._function_arg).project else: try: g = as_ufl(g) self._function_arg = g except UFLException: try: # Recurse to handle this through interpolation. self.function_arg = as_ufl(as_tensor(g)) except UFLException: raise ValueError(f"{g} is not a valid DirichletBC expression")
def F(self, v, s, time=None): """ Right hand side for ODE system """ time = time if time else Constant(0.0) # Assign states V = v assert(len(s) == 7) m, h, j, Cai, d, f, x1 = s # Assign parameters g_s = self._parameters["g_s"] # Init return args F_expressions = [ufl.zero()]*7 # Expressions for the Sodium current m gate component alpha_m = (-47 - V)/(-1 + 0.0090952771017*ufl.exp(-0.1*V)) beta_m = 0.709552672749*ufl.exp(-0.056*V) F_expressions[0] = -beta_m*m + (1 - m)*alpha_m # Expressions for the Sodium current h gate component alpha_h = 5.49796243871e-10*ufl.exp(-0.25*V) beta_h = 1.7/(1 + 0.15802532089*ufl.exp(-0.082*V)) F_expressions[1] = (1 - h)*alpha_h - beta_h*h # Expressions for the Sodium current j gate component alpha_j = 1.86904730072e-10*ufl.exp(-0.25*V)/(1 +\ 1.67882753e-07*ufl.exp(-0.2*V)) beta_j = 0.3/(1 + 0.0407622039784*ufl.exp(-0.1*V)) F_expressions[2] = (1 - j)*alpha_j - beta_j*j # Expressions for the Slow inward current component E_s = -82.3 - 13.0287*ufl.ln(0.001*Cai) i_s = g_s*(-E_s + V)*d*f F_expressions[3] = 7e-06 - 0.07*Cai - 0.01*i_s # Expressions for the Slow inward current d gate component alpha_d = 0.095*ufl.exp(1/20 - V/100)/(1 +\ 1.43328813857*ufl.exp(-0.0719942404608*V)) beta_d = 0.07*ufl.exp(-44/59 - V/59)/(1 + ufl.exp(11/5 + V/20)) F_expressions[4] = -beta_d*d + (1 - d)*alpha_d # Expressions for the Slow inward current f gate component alpha_f = 0.012*ufl.exp(-28/125 - V/125)/(1 +\ 66.5465065251*ufl.exp(0.149925037481*V)) beta_f = 0.0065*ufl.exp(-3/5 - V/50)/(1 + ufl.exp(-6 - V/5)) F_expressions[5] = (1 - f)*alpha_f - beta_f*f # Expressions for the Time dependent outward current x1 gate component alpha_x1 = 0.0311584109863*ufl.exp(0.0826446280992*V)/(1 +\ 17.4117080633*ufl.exp(0.0571428571429*V)) beta_x1 = 0.000391646440562*ufl.exp(-0.0599880023995*V)/(1 +\ ufl.exp(-4/5 - V/25)) F_expressions[6] = (1 - x1)*alpha_x1 - beta_x1*x1 # Return results return dolfin.as_vector(F_expressions)
def _I(self, v, s, time): """ Original gotran transmembrane current dV/dt """ time = time if time else Constant(0.0) # Assign states V = v assert(len(s) == 7) m, h, j, Cai, d, f, x1 = s # Assign parameters E_Na = self._parameters["E_Na"] g_Na = self._parameters["g_Na"] g_Nac = self._parameters["g_Nac"] g_s = self._parameters["g_s"] IstimAmplitude = self._parameters["IstimAmplitude"] IstimPulseDuration = self._parameters["IstimPulseDuration"] IstimStart = self._parameters["IstimStart"] C = self._parameters["C"] # Init return args current = [ufl.zero()]*1 # Expressions for the Sodium current component i_Na = (g_Nac + g_Na*(m*m*m)*h*j)*(-E_Na + V) # Expressions for the Slow inward current component E_s = -82.3 - 13.0287*ufl.ln(0.001*Cai) i_s = g_s*(-E_s + V)*d*f # Expressions for the Time dependent outward current component i_x1 = 0.00197277571153*(-1 +\ 21.7584023962*ufl.exp(0.04*V))*ufl.exp(-0.04*V)*x1 # Expressions for the Time independent outward current component i_K1 = 0.0035*(-4 +\ 119.85640019*ufl.exp(0.04*V))/(8.33113748769*ufl.exp(0.04*V) +\ 69.4078518388*ufl.exp(0.08*V)) + 0.0035*(4.6 + 0.2*V)/(1 -\ 0.398519041085*ufl.exp(-0.04*V)) # Expressions for the Stimulus protocol component Istim = ufl.conditional(ufl.And(ufl.ge(time, IstimStart),\ ufl.le(time, IstimPulseDuration + IstimStart)), IstimAmplitude,\ 0) # Expressions for the Membrane component current[0] = (-i_K1 + Istim - i_Na - i_x1 - i_s)/C # Return results return current[0]
def _I(self, v, s, time): """ Original gotran transmembrane current dV/dt """ time = time if time else Constant(0.0) # Assign states V = v assert (len(s) == 2) v, w = s # Assign parameters u_c = self._parameters["u_c"] g_fi_max = self._parameters["g_fi_max"] tau_0 = self._parameters["tau_0"] tau_r = self._parameters["tau_r"] k = self._parameters["k"] tau_si = self._parameters["tau_si"] u_csi = self._parameters["u_csi"] Cm = self._parameters["Cm"] V_0 = self._parameters["V_0"] V_fi = self._parameters["V_fi"] # Init return args current = [ufl.zero()] * 1 # Expressions for the p component p = ufl.conditional(ufl.lt((-V_0 + V) / (V_fi - V_0), u_c), 0, 1) # Expressions for the Fast inward current component tau_d = Cm / g_fi_max J_fi = -(1 - (-V_0 + V)/(V_fi - V_0))*(-u_c + (-V_0 + V)/(V_fi -\ V_0))*p*v/tau_d # Expressions for the Slow outward current component J_so = p / tau_r + (1 - p) * (-V_0 + V) / (tau_0 * (V_fi - V_0)) # Expressions for the Slow inward current component J_si = -(1 + ufl.tanh(k*(-u_csi + (-V_0 + V)/(V_fi -\ V_0))))*w/(2*tau_si) # Expressions for the Stimulus protocol component J_stim = 0 # Expressions for the Membrane component current[0] = (V_0 - V_fi) * (J_stim + J_fi + J_si + J_so) # Return results return current[0]
def __init__(self, mesh: df.Mesh, time: df.Constant, model: CellModel, I_s: tp.Union[df.Expression, tp.Dict[int, df.Expression]] = None, parameters: df.Parameters = None) -> None: """Initialise parameters.""" super().__init__(mesh=mesh, time=time, cell_model=model, parameters=parameters) import ufl.classes # TODO Why? self._I_s = I_s # Initialize scheme v, s = split_function(self.vs, self._num_states + 1) w, q = split_function(df.TestFunction(self.VS), self._num_states + 1) # Workaround to get algorithm in RL schemes working as it only works for scalar expressions F_exprs = self._F(v, s, self._time) # MER: This looks much more complicated than it needs to be! # If we have a as_vector expression F_exprs_q = ufl.zero() if isinstance(F_exprs, ufl.classes.ListTensor): for i, expr_i in enumerate(F_exprs.ufl_operands): F_exprs_q += expr_i * q[i] else: F_exprs_q = F_exprs * q rhs = F_exprs_q - self._I_ion(v, s, self._time) * w # Handle stimulus: only handle single function case for now if self._I_s: rhs += self._I_s * w self._rhs = rhs * df.dP() name = self._parameters["scheme"] Scheme = self._name_to_scheme(name) self._scheme = Scheme(self._rhs, self.vs, self._time) # Initialize solver and update its parameters self._pi_solver = df.PointIntegralSolver(self._scheme)
def _I(self, v, s, time): """ Original gotran transmembrane current dV/dt """ time = time if time else Constant(0.0) # Assign states V = v assert (len(s) == 2) s, m = s # Assign parameters Cm = self._parameters["Cm"] E_L = self._parameters["E_L"] g_L = self._parameters["g_L"] # synapse components alpha = self._parameters["alpha"] g_S = self._parameters["g_S"] t0 = self._parameters["t0"] v_eq = self._parameters["v_eq"] # Init return args current = [ufl.zero()] * 1 # Expressions for the Membrane component # FIXME: base on stim_type + add to Hodgkin # if # i_Stim = g_S*(-v_eq + V)*ufl.conditional(ufl.ge(time, t0), 1, 0)*ufl.exp((t0 - time)/alpha) # elif sss: # i_Stim = g_S*ufl.conditional(ufl.ge(time, t0), 1, 0) # else: # i_Stim = g_S*ufl.conditional(ufl.And(ufl.ge(time, t0), # ufl.le(time, t1), 1, 0)) i_Stim = g_S * (-v_eq + V) * ufl.conditional(ufl.ge( time, t0), 1, 0) * ufl.exp((t0 - time) / alpha) i_L = g_L * (-E_L + V) current[0] = (-i_L - i_Stim) / Cm # Return results return current[0]
def _I(self, v, s, time): """ Original gotran transmembrane current dV/dt """ time = time if time else Constant(0.0) # Assign states V = v assert (len(s) == 3) m, h, n = s # Assign parameters g_Na = self._parameters["g_Na"] g_K = self._parameters["g_K"] g_L = self._parameters["g_L"] Cm = self._parameters["Cm"] E_R = self._parameters["E_R"] # Init return args current = [ufl.zero()] * 1 # Expressions for the Sodium channel component E_Na = 115.0 + E_R i_Na = g_Na * (m * m * m) * (-E_Na + V) * h # Expressions for the Potassium channel component E_K = -12.0 + E_R i_K = g_K * ufl.elem_pow(n, 4) * (-E_K + V) # Expressions for the Leakage current component E_L = 10.613 + E_R i_L = g_L * (-E_L + V) # Expressions for the Membrane component # TODO can be defined outside i_Stim = 0.0 current[0] = (-i_K - i_L - i_Na + i_Stim) / Cm # Return results return current[0]
def F(self, v, s, time=None): """ Right hand side for ODE system """ time = time if time else Constant(0.0) # Assign states V = v assert (len(s) == 2) v, w = s # Assign parameters u_c = self._parameters["u_c"] u_v = self._parameters["u_v"] tau_v1_minus = self._parameters["tau_v1_minus"] tau_v2_minus = self._parameters["tau_v2_minus"] tau_v_plus = self._parameters["tau_v_plus"] tau_w_minus = self._parameters["tau_w_minus"] tau_w_plus = self._parameters["tau_w_plus"] V_0 = self._parameters["V_0"] V_fi = self._parameters["V_fi"] # Init return args F_expressions = [ufl.zero()] * 2 # Expressions for the p component p = ufl.conditional(ufl.lt((-V_0 + V) / (V_fi - V_0), u_c), 0, 1) # Expressions for the q component q = ufl.conditional(ufl.lt((-V_0 + V) / (V_fi - V_0), u_v), 0, 1) # Expressions for the v gate component tau_v_minus = tau_v1_minus * q + tau_v2_minus * (1 - q) F_expressions[0] = (1 - p) * (1 - v) / tau_v_minus - p * v / tau_v_plus # Expressions for the w gate component F_expressions[1] = (1 - p) * (1 - w) / tau_w_minus - p * w / tau_w_plus # Return results return dolfin.as_vector(F_expressions)
def F(self, v, s, time=None): """ Right hand side for ODE system """ time = time if time else Constant(0.0) # Assign states V = v assert (len(s) == 2) s, m = s # Assign parameters # Init return args F_expressions = [ufl.zero()] * 2 # Expressions for the Membrane component F_expressions[0] = -m F_expressions[1] = s # Return results return dolfin.as_vector(F_expressions)
def _I(self, v, s, time): """ Original gotran transmembrane current dV/dt """ time = time if time else Constant(0.0) # Assign states V = v # Assign parameters g_leak = self._parameters["g_L"] Cm = self._parameters["Cm"] E_leak = self._parameters["E_L"] stim_type = self._parameters["stim_type"] g_s = self._parameters["g_S"] alpha = self._parameters["alpha"] v_eq = self._parameters["v_eq"] t0 = self._parameters["t_start"] t1 = self._parameters["t_stop"] # Init return args current = [ufl.zero()] * 1 # Expressions for the Membrane component if stim_type == 0: i_stim = g_s * (-v_eq + V) * ufl.conditional( ufl.ge(time, t0), 1, 0) * ufl.exp((t0 - time) / alpha) elif stim_type == 1: i_stim = -g_s * ufl.conditional(ufl.ge(time, t0), 1, 0) elif stim_type == 2: i_stim = -g_s * ufl.conditional( ufl.And(ufl.ge(time, t0), ufl.le(time, t1)), 1, 0) i_leak = g_leak * (-E_leak + V) current[0] = (-i_leak - i_stim) / Cm # Return results return current[0]
def _I(self, v, s, time): """ Original gotran transmembrane current dV/dt """ time = time if time else Constant(0.0) # Assign states V = v assert(len(s) == 2) m, h = s # Assign parameters amp = self._parameters["amp"] duration = self._parameters["duration"] stimStart = self._parameters["stimStart"] E_Na = self._parameters["E_Na"] g_Na = self._parameters["g_Na"] E_K = self._parameters["E_K"] g_K = self._parameters["g_K"] k_r = self._parameters["k_r"] # Init return args current = [ufl.zero()]*1 # Expressions for the Fast sodium current component i_Na = g_Na*ufl.elem_pow(m, 3.0)*(-E_Na + V)*h # Expressions for the Potassium current component i_K = g_K*(-E_K + V)*ufl.exp((E_K - V)/k_r) # Expressions for the Membrane component i_stim = ufl.conditional(ufl.And(ufl.gt(time, stimStart),\ ufl.le(time, duration + stimStart)), amp, 0) current[0] = -i_K - i_Na - i_stim # Return results return current[0]
def F(self, v, s, time=None): """ Right hand side for ODE system """ time = time if time else Constant(0.0) # Assign states V = v assert (len(s) == 18) Xr1, Xr2, Xs, m, h, j, d, f, f2, fCass, s, r, Ca_SR, Ca_i, Ca_ss,\ R_prime, Na_i, K_i = s # Assign parameters P_kna = self._parameters["P_kna"] g_K1 = self._parameters["g_K1"] g_Kr = self._parameters["g_Kr"] g_Ks = self._parameters["g_Ks"] g_Na = self._parameters["g_Na"] g_bna = self._parameters["g_bna"] g_CaL = self._parameters["g_CaL"] g_bca = self._parameters["g_bca"] g_to = self._parameters["g_to"] K_mNa = self._parameters["K_mNa"] K_mk = self._parameters["K_mk"] P_NaK = self._parameters["P_NaK"] K_NaCa = self._parameters["K_NaCa"] K_sat = self._parameters["K_sat"] Km_Ca = self._parameters["Km_Ca"] Km_Nai = self._parameters["Km_Nai"] alpha = self._parameters["alpha"] gamma = self._parameters["gamma"] K_pCa = self._parameters["K_pCa"] g_pCa = self._parameters["g_pCa"] g_pK = self._parameters["g_pK"] Buf_c = self._parameters["Buf_c"] Buf_sr = self._parameters["Buf_sr"] Buf_ss = self._parameters["Buf_ss"] Ca_o = self._parameters["Ca_o"] EC = self._parameters["EC"] K_buf_c = self._parameters["K_buf_c"] K_buf_sr = self._parameters["K_buf_sr"] K_buf_ss = self._parameters["K_buf_ss"] K_up = self._parameters["K_up"] V_leak = self._parameters["V_leak"] V_rel = self._parameters["V_rel"] V_sr = self._parameters["V_sr"] V_ss = self._parameters["V_ss"] V_xfer = self._parameters["V_xfer"] Vmax_up = self._parameters["Vmax_up"] k1_prime = self._parameters["k1_prime"] k2_prime = self._parameters["k2_prime"] k3 = self._parameters["k3"] k4 = self._parameters["k4"] max_sr = self._parameters["max_sr"] min_sr = self._parameters["min_sr"] Na_o = self._parameters["Na_o"] Cm = self._parameters["Cm"] F = self._parameters["F"] R = self._parameters["R"] T = self._parameters["T"] V_c = self._parameters["V_c"] K_o = self._parameters["K_o"] # Init return args F_expressions = [ufl.zero()] * 18 # Expressions for the Reversal potentials component E_Na = R * T * ufl.ln(Na_o / Na_i) / F E_K = R * T * ufl.ln(K_o / K_i) / F E_Ks = R * T * ufl.ln((Na_o * P_kna + K_o) / (K_i + P_kna * Na_i)) / F E_Ca = 0.5 * R * T * ufl.ln(Ca_o / Ca_i) / F # Expressions for the Inward rectifier potassium current component alpha_K1 = 0.1 / (1 + 6.14421235333e-06 * ufl.exp(-0.06 * E_K + 0.06 * V)) beta_K1 = (3.06060402008*ufl.exp(0.0002*V - 0.0002*E_K) +\ 0.367879441171*ufl.exp(0.1*V - 0.1*E_K))/(1 + ufl.exp(0.5*E_K -\ 0.5*V)) xK1_inf = alpha_K1 / (alpha_K1 + beta_K1) i_K1 = 0.430331482912 * g_K1 * ufl.sqrt(K_o) * (-E_K + V) * xK1_inf # Expressions for the Rapid time dependent potassium current component i_Kr = 0.430331482912 * g_Kr * ufl.sqrt(K_o) * (-E_K + V) * Xr1 * Xr2 # Expressions for the Xr1 gate component xr1_inf = 1.0 / (1 + ufl.exp(-26 / 7 - V / 7)) alpha_xr1 = 450 / (1 + ufl.exp(-9 / 2 - V / 10)) beta_xr1 = 6 / (1 + 13.5813245226 * ufl.exp(0.0869565217391 * V)) tau_xr1 = alpha_xr1 * beta_xr1 F_expressions[0] = (xr1_inf - Xr1) / tau_xr1 # Expressions for the Xr2 gate component xr2_inf = 1.0 / (1 + ufl.exp(11 / 3 + V / 24)) alpha_xr2 = 3 / (1 + ufl.exp(-3 - V / 20)) beta_xr2 = 1.12 / (1 + ufl.exp(-3 + V / 20)) tau_xr2 = alpha_xr2 * beta_xr2 F_expressions[1] = (xr2_inf - Xr2) / tau_xr2 # Expressions for the Slow time dependent potassium current component i_Ks = g_Ks * (Xs * Xs) * (-E_Ks + V) # Expressions for the Xs gate component xs_inf = 1.0 / (1 + ufl.exp(-5 / 14 - V / 14)) alpha_xs = 1400 / ufl.sqrt(1 + ufl.exp(5 / 6 - V / 6)) beta_xs = 1.0 / (1 + ufl.exp(-7 / 3 + V / 15)) tau_xs = 80 + alpha_xs * beta_xs F_expressions[2] = (xs_inf - Xs) / tau_xs # Expressions for the Fast sodium current component i_Na = g_Na * (m * m * m) * (-E_Na + V) * h * j # Expressions for the m gate component m_inf = 1.0/((1 + 0.00184221158117*ufl.exp(-0.110741971207*V))*(1 +\ 0.00184221158117*ufl.exp(-0.110741971207*V))) alpha_m = 1.0 / (1 + ufl.exp(-12 - V / 5)) beta_m = 0.1 / (1 + ufl.exp(-1 / 4 + V / 200)) + 0.1 / ( 1 + ufl.exp(7 + V / 5)) tau_m = alpha_m * beta_m F_expressions[3] = (-m + m_inf) / tau_m # Expressions for the h gate component h_inf = 1.0/((1 + 15212.5932857*ufl.exp(0.134589502019*V))*(1 +\ 15212.5932857*ufl.exp(0.134589502019*V))) alpha_h = ufl.conditional(ufl.lt(V, -40),\ 4.43126792958e-07*ufl.exp(-0.147058823529*V), 0) beta_h = ufl.conditional(ufl.lt(V, -40), 2.7*ufl.exp(0.079*V) +\ 310000*ufl.exp(0.3485*V), 0.77/(0.13 +\ 0.0497581410839*ufl.exp(-0.0900900900901*V))) tau_h = 1.0 / (alpha_h + beta_h) F_expressions[4] = (-h + h_inf) / tau_h # Expressions for the j gate component j_inf = 1.0/((1 + 15212.5932857*ufl.exp(0.134589502019*V))*(1 +\ 15212.5932857*ufl.exp(0.134589502019*V))) alpha_j = ufl.conditional(ufl.lt(V, -40), (37.78 +\ V)*(-25428*ufl.exp(0.2444*V) - 6.948e-06*ufl.exp(-0.04391*V))/(1 +\ 50262745826.0*ufl.exp(0.311*V)), 0) beta_j = ufl.conditional(ufl.lt(V, -40),\ 0.02424*ufl.exp(-0.01052*V)/(1 +\ 0.0039608683399*ufl.exp(-0.1378*V)), 0.6*ufl.exp(0.057*V)/(1 +\ 0.0407622039784*ufl.exp(-0.1*V))) tau_j = 1.0 / (alpha_j + beta_j) F_expressions[5] = (-j + j_inf) / tau_j # Expressions for the Sodium background current component i_b_Na = g_bna * (-E_Na + V) # Expressions for the L_type Ca current component i_CaL = 4*g_CaL*(F*F)*(-15 + V)*(0.25*Ca_ss*ufl.exp(F*(-30 +\ 2*V)/(R*T)) - Ca_o)*d*f*f2*fCass/(R*T*(-1 + ufl.exp(F*(-30 +\ 2*V)/(R*T)))) # Expressions for the d gate component d_inf = 1.0 / (1 + 0.344153786865 * ufl.exp(-0.133333333333 * V)) alpha_d = 0.25 + 1.4 / (1 + ufl.exp(-35 / 13 - V / 13)) beta_d = 1.4 / (1 + ufl.exp(1 + V / 5)) gamma_d = 1.0 / (1 + ufl.exp(5 / 2 - V / 20)) tau_d = alpha_d * beta_d + gamma_d F_expressions[6] = (-d + d_inf) / tau_d # Expressions for the f gate component f_inf = 1.0 / (1 + ufl.exp(20 / 7 + V / 7)) tau_f = 20 + 1102.5*ufl.exp(-((27 + V)*(27 + V))/225) + 180/(1 +\ ufl.exp(3 + V/10)) + 200/(1 + ufl.exp(13/10 - V/10)) F_expressions[7] = (f_inf - f) / tau_f # Expressions for the F2 gate component f2_inf = 0.33 + 0.67 / (1 + ufl.exp(5 + V / 7)) tau_f2 = 80/(1 + ufl.exp(3 + V/10)) + 562*ufl.exp(-((27 + V)*(27 +\ V))/240) + 31/(1 + ufl.exp(5/2 - V/10)) F_expressions[8] = (-f2 + f2_inf) / tau_f2 # Expressions for the FCass gate component fCass_inf = 0.4 + 0.6 / (1 + 400.0 * (Ca_ss * Ca_ss)) tau_fCass = 2 + 80 / (1 + 400.0 * (Ca_ss * Ca_ss)) F_expressions[9] = (fCass_inf - fCass) / tau_fCass # Expressions for the Calcium background current component i_b_Ca = g_bca * (-E_Ca + V) # Expressions for the Transient outward current component i_to = g_to * (-E_K + V) * r * s # Expressions for the s gate component s_inf = 1.0 / (1 + ufl.exp(4 + V / 5)) tau_s = 3 + 5/(1 + ufl.exp(-4 + V/5)) + 85*ufl.exp(-((45 + V)*(45 +\ V))/320) F_expressions[10] = (s_inf - s) / tau_s # Expressions for the r gate component r_inf = 1.0 / (1 + ufl.exp(10 / 3 - V / 6)) tau_r = 0.8 + 9.5 * ufl.exp(-((40 + V) * (40 + V)) / 1800) F_expressions[11] = (r_inf - r) / tau_r # Expressions for the Sodium potassium pump current component i_NaK = K_o*P_NaK*Na_i/((K_mNa + Na_i)*(K_mk + K_o)*(1 +\ 0.0353*ufl.exp(-F*V/(R*T)) + 0.1245*ufl.exp(-0.1*F*V/(R*T)))) # Expressions for the Sodium calcium exchanger current component i_NaCa = K_NaCa*(-alpha*(Na_o*Na_o*Na_o)*Ca_i*ufl.exp(F*(-1 +\ gamma)*V/(R*T)) +\ Ca_o*(Na_i*Na_i*Na_i)*ufl.exp(F*gamma*V/(R*T)))/((1 +\ K_sat*ufl.exp(F*(-1 + gamma)*V/(R*T)))*(Km_Ca +\ Ca_o)*((Na_o*Na_o*Na_o) + (Km_Nai*Km_Nai*Km_Nai))) # Expressions for the Calcium pump current component i_p_Ca = g_pCa * Ca_i / (Ca_i + K_pCa) # Expressions for the Potassium pump current component i_p_K = g_pK * (-E_K + V) / (1 + 65.4052157419 * ufl.exp(-0.167224080268 * V)) # Expressions for the Calcium dynamics component i_up = Vmax_up / (1 + (K_up * K_up) / (Ca_i * Ca_i)) i_leak = V_leak * (Ca_SR - Ca_i) i_xfer = V_xfer * (Ca_ss - Ca_i) kcasr = max_sr - (-min_sr + max_sr) / (1 + (EC * EC) / (Ca_SR * Ca_SR)) Ca_i_bufc = 1.0 / (1 + Buf_c * K_buf_c / ((Ca_i + K_buf_c) * (Ca_i + K_buf_c))) Ca_sr_bufsr = 1.0/(1 + Buf_sr*K_buf_sr/((Ca_SR + K_buf_sr)*(Ca_SR +\ K_buf_sr))) Ca_ss_bufss = 1.0/(1 + Buf_ss*K_buf_ss/((Ca_ss + K_buf_ss)*(Ca_ss +\ K_buf_ss))) F_expressions[13] = (i_xfer - Cm*(i_b_Ca + i_p_Ca -\ 2*i_NaCa)/(2*F*V_c) + V_sr*(-i_up + i_leak)/V_c)*Ca_i_bufc k1 = k1_prime / kcasr k2 = k2_prime * kcasr O = (Ca_ss * Ca_ss) * R_prime * k1 / ((Ca_ss * Ca_ss) * k1 + k3) F_expressions[15] = -Ca_ss * R_prime * k2 + k4 * (1 - R_prime) i_rel = V_rel * (Ca_SR - Ca_ss) * O F_expressions[12] = (i_up - i_leak - i_rel) * Ca_sr_bufsr F_expressions[14] = (-Cm*i_CaL/(2*F*V_ss) - V_c*i_xfer/V_ss +\ V_sr*i_rel/V_ss)*Ca_ss_bufss # Expressions for the Sodium dynamics component F_expressions[16] = Cm * (-i_b_Na - i_Na - 3 * i_NaCa - 3 * i_NaK) / (F * V_c) # Expressions for the Membrane component i_Stim = 0 # Expressions for the Potassium dynamics component F_expressions[17] = Cm*(2*i_NaK - i_Ks - i_Stim - i_Kr - i_to - i_p_K\ - i_K1)/(F*V_c) # Return results return as_vector(F_expressions)
def _I(self, v, s, time): """ Original gotran transmembrane current dV/dt """ time = time if time else Constant(0.0) # Assign states V = v assert (len(s) == 17) m, h, j, d, f1, f2, fCa, Xr1, Xr2, Xs, Xf, q, r, Nai, g, Cai, Ca_SR = s # Assign parameters Chromanol_iKs30 = self._parameters["Chromanol_iKs30"] Chromanol_iKs50 = self._parameters["Chromanol_iKs50"] Chromanol_iKs70 = self._parameters["Chromanol_iKs70"] Chromanol_iKs90 = self._parameters["Chromanol_iKs90"] E4031_100nM = self._parameters["E4031_100nM"] E4031_30nM = self._parameters["E4031_30nM"] TTX_10uM = self._parameters["TTX_10uM"] TTX_30uM = self._parameters["TTX_30uM"] TTX_3uM = self._parameters["TTX_3uM"] nifed_100nM = self._parameters["nifed_100nM"] nifed_10nM = self._parameters["nifed_10nM"] nifed_30nM = self._parameters["nifed_30nM"] nifed_3nM = self._parameters["nifed_3nM"] PkNa = self._parameters["PkNa"] g_Na = self._parameters["g_Na"] g_CaL = self._parameters["g_CaL"] g_Kr = self._parameters["g_Kr"] g_Ks = self._parameters["g_Ks"] g_K1 = self._parameters["g_K1"] E_f = self._parameters["E_f"] g_f = self._parameters["g_f"] g_b_Na = self._parameters["g_b_Na"] g_b_Ca = self._parameters["g_b_Ca"] Km_K = self._parameters["Km_K"] Km_Na = self._parameters["Km_Na"] PNaK = self._parameters["PNaK"] KmCa = self._parameters["KmCa"] KmNai = self._parameters["KmNai"] Ksat = self._parameters["Ksat"] alpha = self._parameters["alpha"] gamma = self._parameters["gamma"] kNaCa = self._parameters["kNaCa"] KPCa = self._parameters["KPCa"] g_PCa = self._parameters["g_PCa"] g_to = self._parameters["g_to"] Cao = self._parameters["Cao"] F = self._parameters["F"] Ki = self._parameters["Ki"] Ko = self._parameters["Ko"] Nao = self._parameters["Nao"] R = self._parameters["R"] T = self._parameters["T"] # Init return args current = [ufl.zero()] * 1 # Expressions for the Electric potentials component E_Na = R * T * ufl.ln(Nao / Nai) / F E_K = R * T * ufl.ln(Ko / Ki) / F E_Ks = R * T * ufl.ln((Ko + Nao * PkNa) / (Ki + PkNa * Nai)) / F E_Ca = 0.5 * R * T * ufl.ln(Cao / Cai) / F # Expressions for the i_Na component TTX_coeff = ufl.conditional(ufl.eq(TTX_3uM, 1), 0.18,\ ufl.conditional(ufl.eq(TTX_10uM, 1), 0.06,\ ufl.conditional(ufl.eq(TTX_30uM, 1), 0.02, 1))) i_Na = g_Na * (m * m * m) * (-E_Na + V) * TTX_coeff * h * j # Expressions for the i_CaL component nifed_coeff = ufl.conditional(ufl.eq(nifed_3nM, 1), 0.93,\ ufl.conditional(ufl.eq(nifed_10nM, 1), 0.79,\ ufl.conditional(ufl.eq(nifed_30nM, 1), 0.56,\ ufl.conditional(ufl.eq(nifed_100nM, 1), 0.28, 1)))) i_CaL = 4*g_CaL*(F*F)*(-0.341*Cao +\ Cai*ufl.exp(2*F*V/(R*T)))*V*d*f1*f2*fCa*nifed_coeff/(R*T*(-1 +\ ufl.exp(2*F*V/(R*T)))) # Expressions for the i_Kr component E4031_coeff = ufl.conditional(ufl.eq(E4031_30nM, 1), 0.77,\ ufl.conditional(ufl.eq(E4031_100nM, 1), 0.5, 1)) i_Kr = 0.430331482912 * g_Kr * ufl.sqrt(Ko) * ( -E_K + V) * E4031_coeff * Xr1 * Xr2 # Expressions for the i_Ks component Chromanol_coeff = ufl.conditional(ufl.eq(Chromanol_iKs30, 1), 0.7,\ ufl.conditional(ufl.eq(Chromanol_iKs50, 1), 0.5,\ ufl.conditional(ufl.eq(Chromanol_iKs70, 1), 0.3,\ ufl.conditional(ufl.eq(Chromanol_iKs90, 1), 0.1, 1)))) i_Ks = g_Ks*(Xs*Xs)*(1 + 0.6/(1 +\ 6.48182102606e-07*ufl.elem_pow(1.0/Cai, 1.4)))*(-E_Ks +\ V)*Chromanol_coeff # Expressions for the i_K1 component alpha_K1 = 3.91 / ( 1 + 2.44592857399e-52 * ufl.exp(594.2 * V - 594.2 * E_K)) beta_K1 = (0.00277806676906*ufl.exp(588.6*V - 588.6*E_K) -\ 1.5394838221*ufl.exp(0.2*V - 0.2*E_K))/(1 + ufl.exp(454.7*V -\ 454.7*E_K)) XK1_inf = alpha_K1 / (alpha_K1 + beta_K1) i_K1 = 0.430331482912 * g_K1 * ufl.sqrt(Ko) * (-E_K + V) * XK1_inf # Expressions for the i_f component i_f = g_f * (-E_f + V) * Xf # Expressions for the i_b Na component i_b_Na = g_b_Na * (-E_Na + V) # Expressions for the i_b Ca component i_b_Ca = g_b_Ca * (-E_Ca + V) # Expressions for the i_NaK component i_NaK = Ko*PNaK*Nai/((Km_K + Ko)*(Km_Na + Nai)*(1 +\ 0.0353*ufl.exp(-F*V/(R*T)) + 0.1245*ufl.exp(-0.1*F*V/(R*T)))) # Expressions for the i_NaCa component i_NaCa = kNaCa*(Cao*(Nai*Nai*Nai)*ufl.exp(F*gamma*V/(R*T)) -\ alpha*(Nao*Nao*Nao)*Cai*ufl.exp(F*(-1 + gamma)*V/(R*T)))/((1 +\ Ksat*ufl.exp(F*(-1 + gamma)*V/(R*T)))*(Cao +\ KmCa)*((KmNai*KmNai*KmNai) + (Nao*Nao*Nao))) # Expressions for the i_PCa component i_PCa = g_PCa * Cai / (KPCa + Cai) # Expressions for the i_to component i_to = g_to * (-E_K + V) * q * r # Expressions for the Membrane component current[0] = -i_CaL - i_K1 - i_Kr - i_Ks - i_Na - i_NaCa - i_NaK -\ i_PCa - i_b_Ca - i_b_Na - i_f - i_to # Return results return current[0]
def F(self, v, s, time=None): """ Right hand side for ODE system """ time = time if time else Constant(0.0) # Assign states V = v assert (len(s) == 17) m, h, j, d, f1, f2, fCa, Xr1, Xr2, Xs, Xf, q, r, Nai, g, Cai, Ca_SR = s # Assign parameters TTX_10uM = self._parameters["TTX_10uM"] TTX_30uM = self._parameters["TTX_30uM"] TTX_3uM = self._parameters["TTX_3uM"] nifed_100nM = self._parameters["nifed_100nM"] nifed_10nM = self._parameters["nifed_10nM"] nifed_30nM = self._parameters["nifed_30nM"] nifed_3nM = self._parameters["nifed_3nM"] g_Na = self._parameters["g_Na"] g_CaL = self._parameters["g_CaL"] tau_fCa = self._parameters["tau_fCa"] L0 = self._parameters["L0"] Q = self._parameters["Q"] g_b_Na = self._parameters["g_b_Na"] g_b_Ca = self._parameters["g_b_Ca"] Km_K = self._parameters["Km_K"] Km_Na = self._parameters["Km_Na"] PNaK = self._parameters["PNaK"] KmCa = self._parameters["KmCa"] KmNai = self._parameters["KmNai"] Ksat = self._parameters["Ksat"] alpha = self._parameters["alpha"] gamma = self._parameters["gamma"] kNaCa = self._parameters["kNaCa"] KPCa = self._parameters["KPCa"] g_PCa = self._parameters["g_PCa"] Cao = self._parameters["Cao"] Cm = self._parameters["Cm"] F = self._parameters["F"] Ko = self._parameters["Ko"] Nao = self._parameters["Nao"] R = self._parameters["R"] T = self._parameters["T"] V_SR = self._parameters["V_SR"] Vc = self._parameters["Vc"] Buf_C = self._parameters["Buf_C"] Buf_SR = self._parameters["Buf_SR"] Kbuf_C = self._parameters["Kbuf_C"] Kbuf_SR = self._parameters["Kbuf_SR"] Kup = self._parameters["Kup"] V_leak = self._parameters["V_leak"] VmaxUp = self._parameters["VmaxUp"] a_rel = self._parameters["a_rel"] b_rel = self._parameters["b_rel"] c_rel = self._parameters["c_rel"] tau_g = self._parameters["tau_g"] # Init return args F_expressions = [ufl.zero()] * 17 # Expressions for the Electric potentials component E_Na = R * T * ufl.ln(Nao / Nai) / F E_Ca = 0.5 * R * T * ufl.ln(Cao / Cai) / F # Expressions for the i_Na component TTX_coeff = ufl.conditional(ufl.eq(TTX_3uM, 1), 0.18,\ ufl.conditional(ufl.eq(TTX_10uM, 1), 0.06,\ ufl.conditional(ufl.eq(TTX_30uM, 1), 0.02, 1))) i_Na = g_Na * (m * m * m) * (-E_Na + V) * TTX_coeff * h * j # Expressions for the m gate component m_inf = 1.0*ufl.elem_pow(1 +\ 0.00308976260789*ufl.exp(-169.491525424*V), -0.333333333333) alpha_m = 1.0 / (1 + 6.14421235333e-06 * ufl.exp(-200.0 * V)) beta_m = 0.1/(1 + 1096.63315843*ufl.exp(200.0*V)) + 0.1/(1 +\ 0.778800783071*ufl.exp(5.0*V)) tau_m = 0.001 * alpha_m * beta_m F_expressions[0] = (-m + m_inf) / tau_m # Expressions for the h gate component h_inf = 1.0 / ufl.sqrt(1 + 311490.091283 * ufl.exp(175.438596491 * V)) alpha_h = ufl.conditional(ufl.lt(V, -0.04),\ 4.43126792958e-07*ufl.exp(-147.058823529*V), 0) beta_h = ufl.conditional(ufl.lt(V, -0.04), 310000.0*ufl.exp(348.5*V)\ + 2.7*ufl.exp(79.0*V), 0.77/(0.13 +\ 0.0497581410839*ufl.exp(-90.0900900901*V))) tau_h = ufl.conditional(ufl.lt(V, -0.04), 1.5/(1000*alpha_h +\ 1000*beta_h), 0.002542) F_expressions[1] = (-h + h_inf) / tau_h # Expressions for the j gate component j_inf = 1.0 / ufl.sqrt(1 + 311490.091283 * ufl.exp(175.438596491 * V)) alpha_j = ufl.conditional(ufl.lt(V, -0.04), (37.78 +\ 1000*V)*(-25428*ufl.exp(244.4*V) -\ 6.948e-06*ufl.exp(-43.91*V))/(1 +\ 50262745826.0*ufl.exp(311.0*V)), 0) beta_j = ufl.conditional(ufl.lt(V, -0.04),\ 0.02424*ufl.exp(-10.52*V)/(1 +\ 0.0039608683399*ufl.exp(-137.8*V)), 0.6*ufl.exp(57.0*V)/(1 +\ 0.0407622039784*ufl.exp(-100.0*V))) tau_j = 7.0 / (1000 * alpha_j + 1000 * beta_j) F_expressions[2] = (-j + j_inf) / tau_j # Expressions for the i_CaL component nifed_coeff = ufl.conditional(ufl.eq(nifed_3nM, 1), 0.93,\ ufl.conditional(ufl.eq(nifed_10nM, 1), 0.79,\ ufl.conditional(ufl.eq(nifed_30nM, 1), 0.56,\ ufl.conditional(ufl.eq(nifed_100nM, 1), 0.28, 1)))) i_CaL = 4*g_CaL*(F*F)*(-0.341*Cao +\ Cai*ufl.exp(2*F*V/(R*T)))*V*d*f1*f2*fCa*nifed_coeff/(R*T*(-1 +\ ufl.exp(2*F*V/(R*T)))) # Expressions for the d gate component d_infinity = 1.0 / (1 + 0.272531793034 * ufl.exp(-1000 * V / 7)) alpha_d = 0.25 + 1.4 / (1 + ufl.exp(-35 / 13 - 1000 * V / 13)) beta_d = 1.4 / (1 + ufl.exp(1 + 200 * V)) gamma_d = 1.0 / (1 + ufl.exp(5 / 2 - 50 * V)) tau_d = 0.001 * gamma_d + 0.001 * alpha_d * beta_d F_expressions[3] = (-d + d_infinity) / tau_d # Expressions for the F1 gate component f1_inf = 1.0 / (1 + ufl.exp(26 / 3 + 1000 * V / 3)) constf1 = ufl.conditional(ufl.gt(-f1 + f1_inf, 0), 0.92835 +\ 1433*Cai, 1) tau_f1 = 0.001*(20 + 200.0/(1 + ufl.exp(13/10 - 100*V)) + 180.0/(1 +\ ufl.exp(3 + 100*V)) +\ 1102.5*ufl.exp(-0.00444444444444*ufl.elem_pow(27 + 1000*V,\ 4)))*constf1 F_expressions[4] = (-f1 + f1_inf) / tau_f1 # Expressions for the F2 gate component f2_inf = 0.33 + 0.67 / (1 + ufl.exp(35 / 4 + 250 * V)) constf2 = 1 tau_f2 = 0.001*constf2*(600*ufl.exp(-((25 + 1000*V)*(25 +\ 1000*V))/170) + 16.0/(1 + ufl.exp(3 + 100*V)) + 31.0/(1 +\ ufl.exp(5/2 - 100*V))) F_expressions[5] = (-f2 + f2_inf) / tau_f2 # Expressions for the FCa gate component alpha_fCa = 1.0 / (1 + 5.95374180765e+25 * ufl.elem_pow(Cai, 8)) beta_fCa = 0.1 / (1 + 0.000123409804087 * ufl.exp(10000.0 * Cai)) gamma_fCa = 0.3 / (1 + 0.391605626677 * ufl.exp(1250.0 * Cai)) fCa_inf = 0.760109455762*alpha_fCa + 0.760109455762*beta_fCa +\ 0.760109455762*gamma_fCa constfCa = ufl.conditional(ufl.And(ufl.gt(V, -0.06), ufl.gt(fCa_inf,\ fCa)), 0, 1) F_expressions[6] = (-fCa + fCa_inf) * constfCa / tau_fCa # Expressions for the Xr1 gate component V_half = -19.0 - 1000*R*T*ufl.ln(ufl.elem_pow(1 + 0.384615384615*Cao,\ 4)/(L0*ufl.elem_pow(1 + 1.72413793103*Cao, 4)))/(F*Q) Xr1_inf = 1.0 / (1 + ufl.exp(0.204081632653 * V_half - 204.081632653 * V)) alpha_Xr1 = 450.0 / (1 + ufl.exp(-9 / 2 - 100 * V)) beta_Xr1 = 6.0 / (1 + 13.5813245226 * ufl.exp(86.9565217391 * V)) tau_Xr1 = 0.001 * alpha_Xr1 * beta_Xr1 F_expressions[7] = (-Xr1 + Xr1_inf) / tau_Xr1 # Expressions for the Xr2 gate component Xr2_infinity = 1.0 / (1 + ufl.exp(44 / 25 + 20 * V)) alpha_Xr2 = 3.0 / (1 + ufl.exp(-3 - 50 * V)) beta_Xr2 = 1.12 / (1 + ufl.exp(-3 + 50 * V)) tau_Xr2 = 0.001 * alpha_Xr2 * beta_Xr2 F_expressions[8] = (-Xr2 + Xr2_infinity) / tau_Xr2 # Expressions for the Xs gate component Xs_infinity = 1.0 / (1 + ufl.exp(-5 / 4 - 125 * V / 2)) alpha_Xs = 1100.0 / ufl.sqrt(1 + ufl.exp(-5 / 3 - 500 * V / 3)) beta_Xs = 1.0 / (1 + ufl.exp(-3 + 50 * V)) tau_Xs = alpha_Xs * beta_Xs / 1000 F_expressions[9] = (-Xs + Xs_infinity) / tau_Xs # Expressions for the Xf gate component Xf_infinity = 1.0 / (1 + 5780495.71031 * ufl.exp(200 * V)) tau_Xf = 1.9 / (1 + ufl.exp(3 / 2 + 100 * V)) F_expressions[10] = (-Xf + Xf_infinity) / tau_Xf # Expressions for the i_b Na component i_b_Na = g_b_Na * (-E_Na + V) # Expressions for the i_b Ca component i_b_Ca = g_b_Ca * (-E_Ca + V) # Expressions for the i_NaK component i_NaK = Ko*PNaK*Nai/((Km_K + Ko)*(Km_Na + Nai)*(1 +\ 0.0353*ufl.exp(-F*V/(R*T)) + 0.1245*ufl.exp(-0.1*F*V/(R*T)))) # Expressions for the i_NaCa component i_NaCa = kNaCa*(Cao*(Nai*Nai*Nai)*ufl.exp(F*gamma*V/(R*T)) -\ alpha*(Nao*Nao*Nao)*Cai*ufl.exp(F*(-1 + gamma)*V/(R*T)))/((1 +\ Ksat*ufl.exp(F*(-1 + gamma)*V/(R*T)))*(Cao +\ KmCa)*((KmNai*KmNai*KmNai) + (Nao*Nao*Nao))) # Expressions for the i_PCa component i_PCa = g_PCa * Cai / (KPCa + Cai) # Expressions for the q gate component q_inf = 1.0 / (1 + ufl.exp(53 / 13 + 1000 * V / 13)) tau_q = 0.00606 + 0.039102/(0.0168716780457*ufl.exp(-80.0*V) +\ 6.42137321286*ufl.exp(100.0*V)) F_expressions[11] = (-q + q_inf) / tau_q # Expressions for the r gate component r_inf = 1.0 / (1 + 3.28489055021 * ufl.exp(-53.3333333333 * V)) tau_r = 0.00275352 + 0.01440516/(16.3010892258*ufl.exp(90.0*V) +\ 0.0211152735604*ufl.exp(-120.0*V)) F_expressions[12] = (-r + r_inf) / tau_r # Expressions for the Sodium dynamics component F_expressions[13] = -1e+18*Cm*(3*i_NaCa + 3*i_NaK + i_Na +\ i_b_Na)/(F*Vc) # Expressions for the Calcium dynamics component i_rel = 0.0411*(c_rel + a_rel*(Ca_SR*Ca_SR)/((b_rel*b_rel) +\ (Ca_SR*Ca_SR)))*d*g i_up = VmaxUp / (1 + (Kup * Kup) / (Cai * Cai)) i_leak = V_leak * (-Cai + Ca_SR) g_inf = ufl.conditional(ufl.le(Cai, 0.00035), 1.0/(1 +\ 5.43991024148e+20*ufl.elem_pow(Cai, 6)), 1.0/(1 +\ 1.9720198874e+55*ufl.elem_pow(Cai, 16))) const2 = ufl.conditional(ufl.And(ufl.gt(V, -0.06), ufl.gt(g_inf, g)),\ 0, 1) F_expressions[14] = (-g + g_inf) * const2 / tau_g Cai_bufc = 1.0 / (1 + Buf_C * Kbuf_C / ((Kbuf_C + Cai) * (Kbuf_C + Cai))) Ca_SR_bufSR = 1.0/(1 + Buf_SR*Kbuf_SR/((Kbuf_SR + Ca_SR)*(Kbuf_SR +\ Ca_SR))) F_expressions[15] = (-i_up - 5e+17*Cm*(-2*i_NaCa + i_CaL + i_PCa +\ i_b_Ca)/(F*Vc) + i_leak + i_rel)*Cai_bufc F_expressions[16] = Vc * (-i_leak - i_rel + i_up) * Ca_SR_bufSR / V_SR # Return results return dolfin.as_vector(F_expressions)
from dolfin import * from ufl import zero mesh = UnitSquareMesh(10, 10) V = FunctionSpace(mesh, 'CG', 1) u = TrialFunction(V) v = TestFunction(V) cs = map(Constant, range(4)) forms = [c*inner(u, v)*dx for c in cs] f0 = sum(forms) f1 = sum(forms, 0) f2 = sum(forms, zero()) f3 = sum(forms[1:], forms[0]) iforms = iter(forms) f4 = sum(iforms, next(iforms)) print len(set([f.signature() for f in (f0, f1, f2, f3, f4)]))
def __init__(self, F_form: typing.List, u: typing.List, lmbda: dolfinx.fem.Function, A_form=None, B_form=None, prefix=None): """SLEPc problem and solver wrapper. Wrapper for a generalised eigenvalue problem obtained from UFL residual forms. Parameters ---------- F_form Residual forms u Current solution vectors lmbda Eigenvalue function. Residual forms must be linear in lmbda for linear eigenvalue problems. A_form, optional Override automatically derived A B_form, optional Override automatically derived B Note ---- In general, eigenvalue problems have form T(lmbda) * x = 0, where T(lmbda) is a matrix-valued function. Linear eigenvalue problems have T(lmbda) = A + lmbda * B, and if B is not identity matrix then this problem is called generalized (linear) eigenvalue problem. """ self.F_form = F_form self.u = u self.lmbda = lmbda self.comm = u[0].function_space.mesh.comm self.ur = [] self.ui = [] for func in u: self.ur.append( dolfinx.fem.Function(func.function_space, name=func.name)) self.ui.append( dolfinx.fem.Function(func.function_space, name=func.name)) # Prepare tangent form M0 which has terms involving lambda self.M0 = [[None for i in range(len(self.u))] for j in range(len(self.u))] for i in range(len(self.u)): for j in range(len(self.u)): self.M0[i][j] = ufl.algorithms.expand_derivatives( ufl.derivative(F_form[i], self.u[j], ufl.TrialFunction( self.u[j].function_space))) if B_form is None: B0 = [[None for i in range(len(self.u))] for j in range(len(self.u))] for i in range(len(self.u)): for j in range(len(self.u)): # Differentiate wrt. lambda and replace all remaining lambda with Zero B0[i][j] = ufl.algorithms.expand_derivatives( ufl.diff(self.M0[i][j], lmbda)) B0[i][j] = ufl.replace(B0[i][j], {lmbda: ufl.zero()}) if B0[i][j].empty(): B0[i][j] = None self.B_form = B0 else: self.B_form = B_form if A_form is None: A0 = [[None for i in range(len(self.u))] for j in range(len(self.u))] for i in range(len(self.u)): for j in range(len(self.u)): A0[i][j] = ufl.replace(self.M0[i][j], {lmbda: ufl.zero()}) if A0[i][j].empty(): A0[i][j] = None continue self.A_form = A0 else: self.A_form = A_form self.eps = SLEPc.EPS().create(self.comm) self.eps.setOptionsPrefix(prefix) self.eps.setFromOptions() self.A_form = dolfinx.fem.form(self.A_form) self.B_form = dolfinx.fem.form(self.B_form) self.A = dolfinx.fem.petsc.create_matrix_block(self.A_form) self.B = None if not self.empty_B(): self.B = dolfinx.fem.petsc.create_matrix_block(self.B_form)
def _butcher_scheme_generator_tlm(a, b, c, time, solution, rhs_form, perturbation): """ Generates a list of forms and solutions for a given Butcher tableau *Arguments* a (2 dimensional numpy array) The a matrix of the Butcher tableau. b (1-2 dimensional numpy array) The b vector of the Butcher tableau. If b is 2 dimensional the scheme includes an error estimator and can be used in adaptive solvers. c (1 dimensional numpy array) The c vector the Butcher tableau. time (_Constant_) A Constant holding the time at the start of the time step solution (_Function_) The prognostic variable rhs_form (ufl.Form) A UFL form representing the rhs for a time differentiated equation perturbation (_Function_) The perturbation in the initial condition of the solution """ a = _check_abc(a, b, c) size = a.shape[0] DX = _check_form(rhs_form) # Get test function arguments, coefficients = ufl.algorithms.\ extract_arguments_and_coefficients(rhs_form) v = arguments[0] # Create time step dt = Constant(0.1) # rhs forms dolfin_stage_forms = [] ufl_stage_forms = [] # Stage solutions k = [ Function(solution.function_space(), name="k_%d" % i) for i in range(size) ] kdot = [Function(solution.function_space(), name="kdot_%d"%i) \ for i in range(size)] # Create the stage forms y_ = solution ydot = solution.copy() time_ = time time_dep_expressions = _time_dependent_expressions(rhs_form, time) zero_ = ufl.zero(*y_.shape()) forward_forms = [] stage_solutions = [] jacobian_indices = [] for i, ki in enumerate(k): # Check whether the stage is explicit explicit = a[i, i] == 0 # Evaluation arguments for the ith stage evalargs = y_ + dt * sum([float(a[i,j]) * k[j] \ for j in range(i+1)], zero_) time = time_ + dt * c[i] replace_dict = _replace_dict_time_dependent_expression(time_dep_expressions, \ time_, dt, c[i]) replace_dict[y_] = evalargs replace_dict[time_] = time stage_form = ufl.replace(rhs_form, replace_dict) forward_forms.append(stage_form) # The recomputation of the forward run: if explicit: stage_forms = [stage_form] jacobian_indices.append(-1) else: # Create a F=0 form and differentiate it stage_form_implicit = stage_form - ufl.inner(ki, v) * DX stage_forms = [ stage_form_implicit, derivative(stage_form_implicit, ki) ] jacobian_indices.append(0) ufl_stage_forms.append(stage_forms) dolfin_stage_forms.append([Form(form) for form in stage_forms]) stage_solutions.append(ki) # And now the tangent linearisation: stage_form_tlm = safe_action(derivative(stage_form, y_), perturbation) + \ sum([dt*float(a[i,j]) * safe_action(derivative(\ forward_forms[j], y_), kdot[j]) for j in range(i+1)]) if explicit: stage_forms_tlm = [stage_form_tlm] jacobian_indices.append(-1) else: # Create a F=0 form and differentiate it stage_form_tlm -= ufl.inner(kdot[i], v) * DX stage_forms_tlm = [ stage_form_tlm, derivative(stage_form_tlm, kdot[i]) ] jacobian_indices.append(1) ufl_stage_forms.append(stage_forms_tlm) dolfin_stage_forms.append([Form(form) for form in stage_forms_tlm]) stage_solutions.append(kdot[i]) # Only one last stage if len(b.shape) == 1: last_stage = Form(ufl.inner(perturbation + sum(\ [dt*float(bi)*kdoti for bi, kdoti in zip(b, kdot)], zero_), v)*DX) else: raise Exception("Not sure what to do here") human_form = [] for i in range(size): kterm = " + ".join("%sh*k_%s" % ("" if a[i,j] == 1.0 else \ "%s*"% a[i,j], j) \ for j in range(size) if a[i,j] != 0) if c[i] in [0.0, 1.0]: cih = " + h" if c[i] == 1.0 else "" else: cih = " + %s*h" % c[i] kdotterm = " + ".join("%(a)sh*action(derivative(f(t_n%(cih)s, y_n + "\ "%(kterm)s), kdot_%(i)s" % \ {"a": ("" if a[i,j] == 1.0 else "%s*"% a[i,j], j), "i": i, "cih": cih, "kterm": kterm} \ for j in range(size) if a[i,j] != 0) if len(kterm) == 0: human_form.append("k_%(i)s = f(t_n%(cih)s, y_n)" % { "i": i, "cih": cih }) human_form.append("kdot_%(i)s = action(derivative("\ "f(t_n%(cih)s, y_n), y_n), ydot_n)" % \ {"i": i, "cih": cih}) else: human_form.append("k_%(i)s = f(t_n%(cih)s, y_n + %(kterm)s)" % \ {"i": i, "cih": cih, "kterm": kterm}) human_form.append("kdot_%(i)s = action(derivative(f(t_n%(cih)s, "\ "y_n + %(kterm)s), y_n) + %(kdotterm)s" % \ {"i": i, "cih": cih, "kterm": kterm, "kdotterm": kdotterm}) parentheses = "(%s)" if np.sum(b > 0) > 1 else "%s" human_form.append("ydot_{n+1} = ydot_n + h*" + parentheses % (" + ".join(\ "%skdot_%s" % ("" if b[i] == 1.0 else "%s*" % b[i], i) \ for i in range(size) if b[i] > 0))) human_form = "\n".join(human_form) return ufl_stage_forms, dolfin_stage_forms, jacobian_indices, last_stage, \ stage_solutions, dt, human_form, perturbation
def __define_boundary_terms(self): if self.verb > 2: print0("Defining boundary terms") self.bnd_vector_form = numpy.empty(self.DD.G, dtype=object) self.bnd_matrix_form = numpy.empty(self.DD.G, dtype=object) n = FacetNormal(self.DD.mesh) i,p,q = ufl.indices(3) natural_boundaries = self.BC.vacuum_boundaries.union(self.BC.incoming_fluxes.keys()) nonzero = lambda x: numpy.all(x > 0) nonzero_inc_flux = any(map(nonzero, self.BC.incoming_fluxes.values())) if nonzero_inc_flux and not self.fixed_source_problem: coupled_solver_error(__file__, "define boundary terms", "Incoming flux specified for an eigenvalue problem"+\ "(Q must be given whenever phi_inc is; it may possibly be zero everywhere)") for g in range(self.DD.G): self.bnd_vector_form[g] = ufl.zero() self.bnd_matrix_form[g] = ufl.zero() if natural_boundaries: try: ds = Measure("ds")[self.DD.boundaries] except TypeError: coupled_solver_error(__file__, "define boundary terms", "File assigning boundary indices to facets required if vacuum or incoming flux boundaries " "are specified.") for bnd_idx in natural_boundaries: # NOTE: The following doesn't work because ufl.abs requires a function # #for g in range(self.DD.G): # self.bnd_matrix_form[g] += \ # abs(self.tensors.G[p,q,i]*n[i])*self.u[g][q]*self.v[g][p]*ds(bnd_idx) # # NOTE: Instead, the following explicit loop has to be used; this makes tensors.G unneccessary # for pp in range(self.DD.M): omega_p_dot_n = self.DD.ordinates_matrix[i,pp]*n[i] for g in range(self.DD.G): self.bnd_matrix_form[g] += \ abs(omega_p_dot_n)*self.tensors.Wp[pp]*self.u[g][pp]*self.v[g][pp]*ds(bnd_idx) if nonzero_inc_flux: for pp in range(self.DD.M): omega_p_dot_n = self.DD.ordinates_matrix[i,pp]*n[i] for bnd_idx, psi_inc in self.BC.incoming_fluxes.iteritems(): if psi_inc.shape != (self.DD.M, self.DD.G): coupled_solver_error(__file__, "define boundary terms", "Incoming flux with incorrect number of groups and directions specified: "+ "{}, expected ({}, {})".format(psi_inc.shape, self.DD.M, self.DD.G)) for g in range(self.DD.G): self.bnd_vector_form[g] += \ ufl.conditional(omega_p_dot_n < 0, omega_p_dot_n*self.tensors.Wp[pp]*psi_inc[pp,g]*self.v[g][pp]*ds(bnd_idx), ufl.zero()) # FIXME: This assumes zero adjoint outgoing flux else: # Apply vacuum b.c. everywhere ds = Measure("ds") for pp in range(self.DD.M): omega_p_dot_n = self.DD.ordinates_matrix[i,pp]*n[i] for g in range(self.DD.G): self.bnd_matrix_form[g] += abs(omega_p_dot_n)*self.tensors.Wp[pp]*self.u[g][pp]*self.v[g][pp]*ds()
def _I(self, v, s, time): """ Original gotran transmembrane current dV/dt """ time = time if time else Constant(0.0) # Assign states V = v assert (len(s) == 18) Xr1, Xr2, Xs, m, h, j, d, f, f2, fCass, s, r, Ca_SR, Ca_i, Ca_ss,\ R_prime, Na_i, K_i = s # Assign parameters P_kna = self._parameters["P_kna"] g_K1 = self._parameters["g_K1"] g_Kr = self._parameters["g_Kr"] g_Ks = self._parameters["g_Ks"] g_Na = self._parameters["g_Na"] g_bna = self._parameters["g_bna"] g_CaL = self._parameters["g_CaL"] g_bca = self._parameters["g_bca"] g_to = self._parameters["g_to"] K_mNa = self._parameters["K_mNa"] K_mk = self._parameters["K_mk"] P_NaK = self._parameters["P_NaK"] K_NaCa = self._parameters["K_NaCa"] K_sat = self._parameters["K_sat"] Km_Ca = self._parameters["Km_Ca"] Km_Nai = self._parameters["Km_Nai"] alpha = self._parameters["alpha"] gamma = self._parameters["gamma"] K_pCa = self._parameters["K_pCa"] g_pCa = self._parameters["g_pCa"] g_pK = self._parameters["g_pK"] Ca_o = self._parameters["Ca_o"] Na_o = self._parameters["Na_o"] F = self._parameters["F"] R = self._parameters["R"] T = self._parameters["T"] K_o = self._parameters["K_o"] # Init return args current = [ufl.zero()] * 1 # Expressions for the Reversal potentials component E_Na = R * T * ufl.ln(Na_o / Na_i) / F E_K = R * T * ufl.ln(K_o / K_i) / F E_Ks = R * T * ufl.ln((Na_o * P_kna + K_o) / (K_i + P_kna * Na_i)) / F E_Ca = 0.5 * R * T * ufl.ln(Ca_o / Ca_i) / F # Expressions for the Inward rectifier potassium current component alpha_K1 = 0.1 / (1 + 6.14421235333e-06 * ufl.exp(-0.06 * E_K + 0.06 * V)) beta_K1 = (3.06060402008*ufl.exp(0.0002*V - 0.0002*E_K) +\ 0.367879441171*ufl.exp(0.1*V - 0.1*E_K))/(1 + ufl.exp(0.5*E_K -\ 0.5*V)) xK1_inf = alpha_K1 / (alpha_K1 + beta_K1) i_K1 = 0.430331482912 * g_K1 * ufl.sqrt(K_o) * (-E_K + V) * xK1_inf # Expressions for the Rapid time dependent potassium current component i_Kr = 0.430331482912 * g_Kr * ufl.sqrt(K_o) * (-E_K + V) * Xr1 * Xr2 # Expressions for the Slow time dependent potassium current component i_Ks = g_Ks * (Xs * Xs) * (-E_Ks + V) # Expressions for the Fast sodium current component i_Na = g_Na * (m * m * m) * (-E_Na + V) * h * j # Expressions for the Sodium background current component i_b_Na = g_bna * (-E_Na + V) # Expressions for the L_type Ca current component i_CaL = 4*g_CaL*(F*F)*(-15 + V)*(0.25*Ca_ss*ufl.exp(F*(-30 +\ 2*V)/(R*T)) - Ca_o)*d*f*f2*fCass/(R*T*(-1 + ufl.exp(F*(-30 +\ 2*V)/(R*T)))) # Expressions for the Calcium background current component i_b_Ca = g_bca * (-E_Ca + V) # Expressions for the Transient outward current component i_to = g_to * (-E_K + V) * r * s # Expressions for the Sodium potassium pump current component i_NaK = K_o*P_NaK*Na_i/((K_mNa + Na_i)*(K_mk + K_o)*(1 +\ 0.0353*ufl.exp(-F*V/(R*T)) + 0.1245*ufl.exp(-0.1*F*V/(R*T)))) # Expressions for the Sodium calcium exchanger current component i_NaCa = K_NaCa*(-alpha*(Na_o*Na_o*Na_o)*Ca_i*ufl.exp(F*(-1 +\ gamma)*V/(R*T)) +\ Ca_o*(Na_i*Na_i*Na_i)*ufl.exp(F*gamma*V/(R*T)))/((1 +\ K_sat*ufl.exp(F*(-1 + gamma)*V/(R*T)))*(Km_Ca +\ Ca_o)*((Na_o*Na_o*Na_o) + (Km_Nai*Km_Nai*Km_Nai))) # Expressions for the Calcium pump current component i_p_Ca = g_pCa * Ca_i / (Ca_i + K_pCa) # Expressions for the Potassium pump current component i_p_K = g_pK * (-E_K + V) / (1 + 65.4052157419 * ufl.exp(-0.167224080268 * V)) # Expressions for the Membrane component i_Stim = 0 current[0] = -i_CaL - i_Ks - i_NaCa - i_b_Na - i_Stim - i_Kr - i_p_Ca\ - i_to - i_b_Ca - i_Na - i_p_K - i_NaK - i_K1 # Return results return current[0]
def _butcher_scheme_generator_tlm(a, b, c, time, solution, rhs_form, perturbation): """ Generates a list of forms and solutions for a given Butcher tableau *Arguments* a (2 dimensional numpy array) The a matrix of the Butcher tableau. b (1-2 dimensional numpy array) The b vector of the Butcher tableau. If b is 2 dimensional the scheme includes an error estimator and can be used in adaptive solvers. c (1 dimensional numpy array) The c vector the Butcher tableau. time (_Constant_) A Constant holding the time at the start of the time step solution (_Function_) The prognostic variable rhs_form (ufl.Form) A UFL form representing the rhs for a time differentiated equation perturbation (_Function_) The perturbation in the initial condition of the solution """ a = _check_abc(a, b, c) size = a.shape[0] DX = _check_form(rhs_form) # Get test function arguments = rhs_form.arguments() coefficients = rhs_form.coefficients() v = arguments[0] # Create time step dt = Constant(0.1) # rhs forms dolfin_stage_forms = [] ufl_stage_forms = [] # Stage solutions k = [Function(solution.function_space(), name="k_%d"%i) for i in range(size)] kdot = [Function(solution.function_space(), name="kdot_%d"%i) \ for i in range(size)] # Create the stage forms y_ = solution time_ = time time_dep_expressions = _time_dependent_expressions(rhs_form, time) zero_ = ufl.zero(*y_.ufl_shape) forward_forms = [] stage_solutions = [] jacobian_indices = [] for i, ki in enumerate(k): # Check whether the stage is explicit explicit = a[i,i] == 0 # Evaluation arguments for the ith stage evalargs = y_ + dt * sum([float(a[i,j]) * k[j] \ for j in range(i+1)], zero_) time = time_ + dt*c[i] replace_dict = _replace_dict_time_dependent_expression(time_dep_expressions, time_, dt, c[i]) replace_dict[y_] = evalargs replace_dict[time_] = time stage_form = ufl.replace(rhs_form, replace_dict) forward_forms.append(stage_form) # The recomputation of the forward run: if explicit: stage_forms = [stage_form] jacobian_indices.append(-1) else: # Create a F=0 form and differentiate it stage_form_implicit = stage_form - ufl.inner(ki, v)*DX stage_forms = [stage_form_implicit, derivative(stage_form_implicit, ki)] jacobian_indices.append(0) ufl_stage_forms.append(stage_forms) dolfin_stage_forms.append([Form(form) for form in stage_forms]) stage_solutions.append(ki) # And now the tangent linearisation: stage_form_tlm = safe_action(derivative(stage_form, y_), perturbation) + \ sum([dt*float(a[i,j]) * safe_action(derivative(\ forward_forms[j], y_), kdot[j]) for j in range(i+1)]) if explicit: stage_forms_tlm = [stage_form_tlm] jacobian_indices.append(-1) else: # Create a F=0 form and differentiate it stage_form_tlm -= ufl.inner(kdot[i], v)*DX stage_forms_tlm = [stage_form_tlm, derivative(stage_form_tlm, kdot[i])] jacobian_indices.append(1) ufl_stage_forms.append(stage_forms_tlm) dolfin_stage_forms.append([Form(form) for form in stage_forms_tlm]) stage_solutions.append(kdot[i]) # Only one last stage if len(b.shape) == 1: last_stage = Form(ufl.inner(perturbation + sum(\ [dt*float(bi)*kdoti for bi, kdoti in zip(b, kdot)], zero_), v)*DX) else: raise Exception("Not sure what to do here") human_form = [] for i in range(size): kterm = " + ".join("%sh*k_%s" % ("" if a[i,j] == 1.0 else \ "%s*"% a[i,j], j) \ for j in range(size) if a[i,j] != 0) if c[i] in [0.0, 1.0]: cih = " + h" if c[i] == 1.0 else "" else: cih = " + %s*h" % c[i] kdotterm = " + ".join("%(a)sh*action(derivative(f(t_n%(cih)s, y_n + "\ "%(kterm)s), kdot_%(i)s" % \ {"a": ("" if a[i,j] == 1.0 else "%s*"% a[i,j], j), "i": i, "cih": cih, "kterm": kterm} \ for j in range(size) if a[i,j] != 0) if len(kterm) == 0: human_form.append("k_%(i)s = f(t_n%(cih)s, y_n)" % {"i": i, "cih": cih}) human_form.append("kdot_%(i)s = action(derivative("\ "f(t_n%(cih)s, y_n), y_n), ydot_n)" % \ {"i": i, "cih": cih}) else: human_form.append("k_%(i)s = f(t_n%(cih)s, y_n + %(kterm)s)" % \ {"i": i, "cih": cih, "kterm": kterm}) human_form.append("kdot_%(i)s = action(derivative(f(t_n%(cih)s, "\ "y_n + %(kterm)s), y_n) + %(kdotterm)s" % \ {"i": i, "cih": cih, "kterm": kterm, "kdotterm": kdotterm}) parentheses = "(%s)" if np.sum(b>0) > 1 else "%s" human_form.append("ydot_{n+1} = ydot_n + h*" + parentheses % (" + ".join(\ "%skdot_%s" % ("" if b[i] == 1.0 else "%s*" % b[i], i) \ for i in range(size) if b[i] > 0))) human_form = "\n".join(human_form) return ufl_stage_forms, dolfin_stage_forms, jacobian_indices, last_stage, \ stage_solutions, dt, human_form, perturbation
def assemble_algebraic_system(self): if self.verb > 1: print0(self.print_prefix + "Assembling algebraic system.") mat_timer = Timer("---- MTX: Complete construction") ass_timer = Timer("---- MTX: Assembling") add_values_A = False add_values_B = False add_values_Q = False for gto in range(self.DD.G): #=============================== LOOP OVER GROUPS AND ASSEMBLE ================================ spc = self.print_prefix + " " if self.verb > 3 and self.DD.G > 1: print spc + 'GROUP [', gto, ',', gto, '] :' pres_fiss = self.PD.get_xs('chi', self.chi, gto) self.PD.get_xs('D', self.D, gto) self.PD.get_xs('St', self.R, gto) i,j,p,q,k1,k2 = ufl.indices(6) form = ( self.D*self.tensors.T[p,q,i,j]*self.u[gto][q].dx(j)*self.v[gto][p].dx(i) + self.R*self.tensors.W[p,q]*self.u[gto][q]*self.v[gto][p] ) * dx + self.bnd_matrix_form[gto] ass_timer.start() assemble(form, tensor=self.A, finalize_tensor=False, add_values=add_values_A) add_values_A = True ass_timer.stop() if self.fixed_source_problem: if self.PD.isotropic_source_everywhere: self.PD.get_Q(self.fixed_source, 0, gto) # FIXME: This assumes that adjoint source == forward source form = self.fixed_source * self.tensors.Wp[p] * self.v[gto][p] * dx + self.bnd_vector_form[gto] else: form = ufl.zero() for n in range(self.DD.M): self.PD.get_Q(self.fixed_source, n, gto) # FIXME: This assumes that adjoint source == forward source form += self.fixed_source[n,gto] * self.tensors.Wp[n] * self.v[gto][n] * dx + self.bnd_vector_form[gto] ass_timer.start() assemble(form, tensor=self.Q, finalize_tensor=False, add_values=add_values_Q) add_values_Q = True ass_timer.stop() for gfrom in range(self.DD.G): if self.verb > 3 and self.DD.G > 1: print spc + 'GROUP [', gto, ',', gfrom, '] :' pres_Ss = False # TODO: Enlarge self.S and self.C to (L+1)^2 (or 1./2.*(L+1)*(L+2) in 2D) to accomodate for anisotropic # scattering (lines below using CC, SS are correct only for L = 0, when the following inner loop runs only # once. for l in range(self.L+1): for m in range(-l, l+1): if self.DD.angular_quad.get_D() == 2 and divmod(l+m,2)[1] == 0: continue pres_Ss |= self.PD.get_xs('Ss', self.S[l], gto, gfrom, l) self.PD.get_xs('C', self.C[l], gto, gfrom, l) if pres_Ss: Sd = ufl.diag(self.S) SS = self.tensors.QT[p,k1]*Sd[k1,k2]*self.tensors.Q[k2,q] Cd = ufl.diag(self.C) CC = self.tensors.QtT[p,i,k1]*Cd[k1,k2]*self.tensors.Qt[k2,q,j] ass_timer.start() form = ( CC[p,i,q,j]*self.u[gfrom][q].dx(j)*self.v[gto][p].dx(i) - SS[q,p]*self.u[gfrom][q]*self.v[gto][p] ) * dx assemble(form, tensor=self.A, finalize_tensor=False, add_values=add_values_A) ass_timer.stop() if pres_fiss: pres_nSf = self.PD.get_xs('nSf', self.R, gfrom) if pres_nSf: ass_timer.start() if self.fixed_source_problem: form = -self.chi*self.R/(4*numpy.pi)*\ self.tensors.QT[p,0]*self.tensors.Q[0,q]*self.u[gfrom][q]*self.v[gto][p]*dx assemble(form, tensor=self.A, finalize_tensor=False, add_values=add_values_A) else: form = self.chi*self.R/(4*numpy.pi)*\ self.tensors.QT[p,0]*self.tensors.Q[0,q]*self.u[gfrom][q]*self.v[gto][p]*dx assemble(form, tensor=self.B, finalize_tensor=False, add_values=add_values_B) add_values_B = True ass_timer.stop() #============================= END LOOP OVER GROUPS AND ASSEMBLE =============================== self.A.apply("add") if self.fixed_source_problem: self.Q.apply("add") elif self.eigenproblem: self.B.apply("add")
def F(self, V, s, time=None): m, h, n, NKo, NKi, NNao, NNai, NClo, NCli, voli, O = s O = dolfin.conditional(dolfin.ge(O, 0), O, 0) G_K = self._parameters["G_K"] G_Na = self._parameters["G_Na"] G_ClL = self._parameters["G_ClL"] G_Kl = self._parameters["G_KL"] G_NaL = self._parameters["G_NaL"] C = self._parameters["C"] # Ion Concentration related Parameters eps_K = self._parameters["eps_K"] G_glia = self._parameters["G_glia"] eps_O = self._parameters["eps_O"] Ukcc2 = self._parameters["Ukcc2"] Unkcc1 = self._parameters["Unkcc1"] rho_max = self._parameters["rho_max"] # Volume vol = 1.4368e-15 # unit:m^3, when r=7 um,v=1.4368e-15 m^3 # TODO: add to parameters beta0 = self._parameters["beta0"] # Time Constant tau = self._parameters["tau"] KBath = self._parameters["KBath"] OBath = self._parameters["OBath"] gamma = self._gamma(voli) volo = (1 + 1 / beta0) * vol - voli # Extracellular volume beta = voli / volo # Ratio of intracelluar to extracelluar volume # Gating variables alpha_m = 0.32 * (54 + V) / (1 - exp(-(V + 54) / 4)) beta_m = 0.28 * (V + 27) / (exp((V + 27) / 5) - 1) alpha_h = 0.128 * exp(-(V + 50) / 18) beta_h = 4 / (1 + exp(-(V + 27) / 5)) alpha_n = 0.032 * (V + 52) / (1 - exp(-(V + 52) / 5)) beta_n = 0.5 * exp(-(V + 57) / 40) dotm = alpha_m * (1 - m) - beta_m * m doth = alpha_h * (1 - h) - beta_h * h dotn = alpha_n * (1 - n) - beta_n * n Ko, Ki, Nao, Nai, Clo, Cli = self._get_concentrations(V, s) fo = 1 / (1 + exp((2.5 - OBath) / 0.2)) fv = 1 / (1 + exp((beta - 20) / 2)) eps_K *= fo * fv G_glia *= fo rho = rho_max / (1 + exp((20 - O) / 3)) / gamma I_glia = G_glia / (1 + exp((18 - Ko) / 2.5)) Igliapump = rho / 3 / (1 + exp((25 - 18) / 3)) / (1 + exp(3.5 - Ko)) I_diff = eps_K * (Ko - KBath) + I_glia + 2 * Igliapump * gamma I_K = self._I_K(V, n, Ko, Ki) I_Na = self._I_Na(V, m, h, Nao, Nai) I_Cl = self._I_Cl(V, Clo, Cli) I_pump = self._I_pump(Nai, Ko, O, gamma) # Cloride transporter (mM/s) fKo = 1 / (1 + exp(16 - Ko)) FKCC2 = Ukcc2 * ln((Ki * Cli) / (Ko * Clo)) FNKCC1 = Unkcc1 * fKo * (ln((Ki * Cli) / (Ko * Clo)) + ln( (Nai * Cli) / (Nao * Clo))) dotNKo = tau * volo * (gamma * beta * (I_K - 2.0 * I_pump) - I_diff + FKCC2 * beta + FNKCC1 * beta) dotNKi = -tau * voli * (gamma * (I_K - 2.0 * I_pump) + FKCC2 + FNKCC1) dotNNao = tau * volo * beta * (gamma * (I_Na + 3.0 * I_pump) + FNKCC1) dotNNai = -tau * voli * (gamma * (I_Na + 3.0 * I_pump) + FNKCC1) dotNClo = beta * volo * tau * (FKCC2 - gamma * I_Cl + 2 * FNKCC1) dotNCli = voli * tau * (gamma * I_Cl - FKCC2 - 2 * FNKCC1) r1 = vol / voli r2 = 1 / beta0 * vol / ((1 + 1 / beta0) * vol - voli) pii = Nai + Cli + Ki + 132 * r1 pio = Nao + Ko + Clo + 18 * r2 vol_hat = vol * (1.1029 - 0.1029 * exp((pio - pii) / 20)) dotVoli = -(voli - vol_hat) / 0.25 * tau dotO = tau * (-5.3 * (I_pump + Igliapump) * gamma + eps_O * (OBath - O)) F_expressions = [ufl.zero()] * self.num_states() F_expressions[0] = dotm F_expressions[1] = doth F_expressions[2] = dotn F_expressions[3] = dotNKo F_expressions[4] = dotNKi F_expressions[5] = dotNNao F_expressions[6] = dotNNai F_expressions[7] = dotNClo F_expressions[8] = dotNCli F_expressions[9] = dotVoli F_expressions[10] = dotO return dolfin.as_vector(F_expressions)
from dolfin import * from ufl import zero mesh = UnitSquareMesh(10, 10) V = FunctionSpace(mesh, 'CG', 1) u = TrialFunction(V) v = TestFunction(V) cs = map(Constant, range(4)) forms = [c * inner(u, v) * dx for c in cs] f0 = sum(forms) f1 = sum(forms, 0) f2 = sum(forms, zero()) f3 = sum(forms[1:], forms[0]) iforms = iter(forms) f4 = sum(iforms, next(iforms)) print len(set([f.signature() for f in (f0, f1, f2, f3, f4)]))
def _butcher_scheme_generator(a, b, c, time, solution, rhs_form): """ Generates a list of forms and solutions for a given Butcher tableau *Arguments* a (2 dimensional numpy array) The a matrix of the Butcher tableau. b (1-2 dimensional numpy array) The b vector of the Butcher tableau. If b is 2 dimensional the scheme includes an error estimator and can be used in adaptive solvers. c (1 dimensional numpy array) The c vector the Butcher tableau. time (_Constant_) A Constant holding the time at the start of the time step solution (_Function_) The prognostic variable rhs_form (ufl.Form) A UFL form representing the rhs for a time differentiated equation """ a = _check_abc(a, b, c) size = a.shape[0] DX = _check_form(rhs_form) # Get test function arguments, coefficients = ufl.algorithms.\ extract_arguments_and_coefficients(rhs_form) v = arguments[0] # Create time step dt = Constant(0.1) # rhs forms dolfin_stage_forms = [] ufl_stage_forms = [] # Stage solutions k = [ Function(solution.function_space(), name="k_%d" % i) for i in range(size) ] jacobian_indices = [] # Create the stage forms y_ = solution time_ = time time_dep_expressions = _time_dependent_expressions(rhs_form, time) zero_ = ufl.zero(*y_.shape()) for i, ki in enumerate(k): # Check whether the stage is explicit explicit = a[i, i] == 0 # Evaluation arguments for the ith stage evalargs = y_ + dt * sum([float(a[i,j]) * k[j] \ for j in range(i+1)], zero_) time = time_ + dt * c[i] replace_dict = _replace_dict_time_dependent_expression(time_dep_expressions, \ time_, dt, c[i]) replace_dict[y_] = evalargs replace_dict[time_] = time stage_form = ufl.replace(rhs_form, replace_dict) if explicit: stage_forms = [stage_form] jacobian_indices.append(-1) else: # Create a F=0 form and differentiate it stage_form -= ufl.inner(ki, v) * DX stage_forms = [stage_form, derivative(stage_form, ki)] jacobian_indices.append(0) ufl_stage_forms.append(stage_forms) dolfin_stage_forms.append([Form(form) for form in stage_forms]) # Only one last stage if len(b.shape) == 1: last_stage = Form(ufl.inner(y_+sum([dt*float(bi)*ki for bi, ki in \ zip(b, k)], zero_), v)*DX) else: # FIXME: Add support for addaptivity in RKSolver and MultiStageScheme last_stage = [Form(ufl.inner(y_+sum([dt*float(bi)*ki for bi, ki in \ zip(b[0,:], k)], zero_), v)*DX), Form(ufl.inner(y_+sum([dt*float(bi)*ki for bi, ki in \ zip(b[1,:], k)], zero_), v)*DX)] # Create the Function holding the solution at end of time step #k.append(solution.copy()) # Generate human form of MultiStageScheme human_form = [] for i in range(size): kterm = " + ".join("%sh*k_%s" % ("" if a[i,j] == 1.0 else \ "%s*"% a[i,j], j) \ for j in range(size) if a[i,j] != 0) if c[i] in [0.0, 1.0]: cih = " + h" if c[i] == 1.0 else "" else: cih = " + %s*h" % c[i] if len(kterm) == 0: human_form.append("k_%(i)s = f(t_n%(cih)s, y_n)" % { "i": i, "cih": cih }) else: human_form.append("k_%(i)s = f(t_n%(cih)s, y_n + %(kterm)s)" % \ {"i": i, "cih": cih, "kterm": kterm}) parentheses = "(%s)" if np.sum(b > 0) > 1 else "%s" human_form.append("y_{n+1} = y_n + h*" + parentheses % (" + ".join(\ "%sk_%s" % ("" if b[i] == 1.0 else "%s*" % b[i], i) \ for i in range(size) if b[i] > 0))) human_form = "\n".join(human_form) return ufl_stage_forms, dolfin_stage_forms, jacobian_indices, last_stage, \ k, dt, human_form, None
def F(self, v, s, time=None): """ Right hand side for ODE system """ time = time if time else Constant(0.0) # Assign states V_m = v assert (len(s) == 38) h, j, m, x_kr, x_ks, x_to_f, x_to_s, y_to_f, y_to_s, d, f, f_Ca_Bj,\ f_Ca_Bsl, Ry_Ri, Ry_Ro, Ry_Rr, Na_Bj, Na_Bsl, CaM, Myo_c, Myo_m,\ SRB, Tn_CHc, Tn_CHm, Tn_CL, SLH_j, SLH_sl, SLL_j, SLL_sl, Ca_sr,\ Csqn_b, Na_i, Na_j, Na_sl, K_i, Ca_i, Ca_j, Ca_sl = s # Assign parameters Fjunc = self._parameters["Fjunc"] Fjunc_CaL = self._parameters["Fjunc_CaL"] cellLength = self._parameters["cellLength"] cellRadius = self._parameters["cellRadius"] GNa = self._parameters["GNa"] GNaB = self._parameters["GNaB"] IbarNaK = self._parameters["IbarNaK"] KmKo = self._parameters["KmKo"] KmNaip = self._parameters["KmNaip"] Q10CaL = self._parameters["Q10CaL"] pCa = self._parameters["pCa"] pNa = self._parameters["pNa"] IbarNCX = self._parameters["IbarNCX"] Kdact = self._parameters["Kdact"] KmCai = self._parameters["KmCai"] KmCao = self._parameters["KmCao"] KmNai = self._parameters["KmNai"] KmNao = self._parameters["KmNao"] Q10NCX = self._parameters["Q10NCX"] ksat = self._parameters["ksat"] nu = self._parameters["nu"] IbarSLCaP = self._parameters["IbarSLCaP"] KmPCa = self._parameters["KmPCa"] Q10SLCaP = self._parameters["Q10SLCaP"] GCaB = self._parameters["GCaB"] Kmf = self._parameters["Kmf"] Kmr = self._parameters["Kmr"] MaxSR = self._parameters["MaxSR"] MinSR = self._parameters["MinSR"] Q10SRCaP = self._parameters["Q10SRCaP"] Vmax_SRCaP = self._parameters["Vmax_SRCaP"] ec50SR = self._parameters["ec50SR"] hillSRCaP = self._parameters["hillSRCaP"] kiCa = self._parameters["kiCa"] kim = self._parameters["kim"] koCa = self._parameters["koCa"] kom = self._parameters["kom"] ks = self._parameters["ks"] Bmax_Naj = self._parameters["Bmax_Naj"] Bmax_Nasl = self._parameters["Bmax_Nasl"] koff_na = self._parameters["koff_na"] kon_na = self._parameters["kon_na"] Bmax_CaM = self._parameters["Bmax_CaM"] Bmax_SR = self._parameters["Bmax_SR"] Bmax_TnChigh = self._parameters["Bmax_TnChigh"] Bmax_TnClow = self._parameters["Bmax_TnClow"] Bmax_myosin = self._parameters["Bmax_myosin"] koff_cam = self._parameters["koff_cam"] koff_myoca = self._parameters["koff_myoca"] koff_myomg = self._parameters["koff_myomg"] koff_sr = self._parameters["koff_sr"] koff_tnchca = self._parameters["koff_tnchca"] koff_tnchmg = self._parameters["koff_tnchmg"] koff_tncl = self._parameters["koff_tncl"] kon_cam = self._parameters["kon_cam"] kon_myoca = self._parameters["kon_myoca"] kon_myomg = self._parameters["kon_myomg"] kon_sr = self._parameters["kon_sr"] kon_tnchca = self._parameters["kon_tnchca"] kon_tnchmg = self._parameters["kon_tnchmg"] kon_tncl = self._parameters["kon_tncl"] Bmax_SLhighj0 = self._parameters["Bmax_SLhighj0"] Bmax_SLhighsl0 = self._parameters["Bmax_SLhighsl0"] Bmax_SLlowj0 = self._parameters["Bmax_SLlowj0"] Bmax_SLlowsl0 = self._parameters["Bmax_SLlowsl0"] koff_slh = self._parameters["koff_slh"] koff_sll = self._parameters["koff_sll"] kon_slh = self._parameters["kon_slh"] kon_sll = self._parameters["kon_sll"] Bmax_Csqn0 = self._parameters["Bmax_Csqn0"] J_ca_juncsl = self._parameters["J_ca_juncsl"] J_ca_slmyo = self._parameters["J_ca_slmyo"] koff_csqn = self._parameters["koff_csqn"] kon_csqn = self._parameters["kon_csqn"] J_na_juncsl = self._parameters["J_na_juncsl"] J_na_slmyo = self._parameters["J_na_slmyo"] Nao = self._parameters["Nao"] Ko = self._parameters["Ko"] Cao = self._parameters["Cao"] Mgi = self._parameters["Mgi"] Cmem = self._parameters["Cmem"] Frdy = self._parameters["Frdy"] R = self._parameters["R"] Temp = self._parameters["Temp"] g_K1_factor = self._parameters["g_K1_factor"] g_CaL_factor = self._parameters["g_CaL_factor"] g_Kr_factor = self._parameters["g_Kr_factor"] g_Ks_factor = self._parameters["g_Ks_factor"] g_to_factor = self._parameters["g_to_factor"] SR_Ca_release_ks_factor = self._parameters["SR_Ca_release_ks_factor"] # Init return args F_expressions = [ufl.zero()] * 38 # Expressions for the Geometry component Vcell = 1e-15 * ufl.pi * cellLength * (cellRadius * cellRadius) Vmyo = 0.65 * Vcell Vsr = 0.035 * Vcell Vsl = 0.02 * Vcell Vjunc = 0.000539 * Vcell Fsl = 1 - Fjunc Fsl_CaL = 1 - Fjunc_CaL # Expressions for the Reversal potentials component FoRT = Frdy / (R * Temp) ena_junc = ufl.ln(Nao / Na_j) / FoRT ena_sl = ufl.ln(Nao / Na_sl) / FoRT eca_junc = ufl.ln(Cao / Ca_j) / (2 * FoRT) eca_sl = ufl.ln(Cao / Ca_sl) / (2 * FoRT) Qpow = -31 + Temp / 10 # Expressions for the I_Na component mss = 1.0/((1 + 0.00184221158117*ufl.exp(-0.110741971207*V_m))*(1 +\ 0.00184221158117*ufl.exp(-0.110741971207*V_m))) taum = 0.1292*ufl.exp(-((2.94658944659 +\ 0.0643500643501*V_m)*(2.94658944659 + 0.0643500643501*V_m))) +\ 0.06487*ufl.exp(-((-0.0943466353678 +\ 0.0195618153365*V_m)*(-0.0943466353678 + 0.0195618153365*V_m))) ah = ufl.conditional(ufl.ge(V_m, -40), 0,\ 4.43126792958e-07*ufl.exp(-0.147058823529*V_m)) bh = ufl.conditional(ufl.ge(V_m, -40), 0.77/(0.13 +\ 0.0497581410839*ufl.exp(-0.0900900900901*V_m)),\ 310000.0*ufl.exp(0.3485*V_m) + 2.7*ufl.exp(0.079*V_m)) tauh = 1.0 / (bh + ah) hss = 1.0/((1 + 15212.5932857*ufl.exp(0.134589502019*V_m))*(1 +\ 15212.5932857*ufl.exp(0.134589502019*V_m))) aj = ufl.conditional(ufl.ge(V_m, -40), 0, (37.78 +\ V_m)*(-25428.0*ufl.exp(0.2444*V_m) -\ 6.948e-06*ufl.exp(-0.04391*V_m))/(1 +\ 50262745826.0*ufl.exp(0.311*V_m))) bj = ufl.conditional(ufl.ge(V_m, -40), 0.6*ufl.exp(0.057*V_m)/(1 +\ 0.0407622039784*ufl.exp(-0.1*V_m)),\ 0.02424*ufl.exp(-0.01052*V_m)/(1 +\ 0.0039608683399*ufl.exp(-0.1378*V_m))) tauj = 1.0 / (bj + aj) jss = 1.0/((1 + 15212.5932857*ufl.exp(0.134589502019*V_m))*(1 +\ 15212.5932857*ufl.exp(0.134589502019*V_m))) F_expressions[2] = (-m + mss) / taum F_expressions[0] = (hss - h) / tauh F_expressions[1] = (-j + jss) / tauj I_Na_junc = Fjunc * GNa * (m * m * m) * (-ena_junc + V_m) * h * j I_Na_sl = GNa * (m * m * m) * (-ena_sl + V_m) * Fsl * h * j # Expressions for the I_NaBK component I_nabk_junc = Fjunc * GNaB * (-ena_junc + V_m) I_nabk_sl = GNaB * (-ena_sl + V_m) * Fsl # Expressions for the I_NaK component sigma = -1 / 7 + ufl.exp(0.0148588410104 * Nao) / 7 fnak = 1.0/(1 + 0.1245*ufl.exp(-0.1*FoRT*V_m) +\ 0.0365*ufl.exp(-FoRT*V_m)*sigma) I_nak_junc = Fjunc*IbarNaK*Ko*fnak/((1 + ufl.elem_pow(KmNaip,\ 4)/ufl.elem_pow(Na_j, 4))*(KmKo + Ko)) I_nak_sl = IbarNaK*Ko*Fsl*fnak/((1 + ufl.elem_pow(KmNaip,\ 4)/ufl.elem_pow(Na_sl, 4))*(KmKo + Ko)) # Expressions for the I_Kr component xrss = 1.0 / (1 + ufl.exp(-2 - V_m / 5)) tauxr = 230/(1 + ufl.exp(2 + V_m/20)) + 3300/((1 + ufl.exp(-22/9 -\ V_m/9))*(1 + ufl.exp(11/9 + V_m/9))) F_expressions[3] = (-x_kr + xrss) / tauxr # Expressions for the I_Ks component xsss = 1.0 / (1 + 0.765928338365 * ufl.exp(-0.0701754385965 * V_m)) tauxs = 990.1 / (1 + 0.841540408868 * ufl.exp(-0.070821529745 * V_m)) F_expressions[4] = (-x_ks + xsss) / tauxs # Expressions for the I_to component xtoss = 1.0 / (1 + ufl.exp(19 / 13 - V_m / 13)) ytoss = 1.0 / (1 + 49.4024491055 * ufl.exp(V_m / 5)) tauxtos = 0.5 + 9 / (1 + ufl.exp(1 / 5 + V_m / 15)) tauytos = 30 + 800 / (1 + ufl.exp(6 + V_m / 10)) F_expressions[6] = (-x_to_s + xtoss) / tauxtos F_expressions[8] = (ytoss - y_to_s) / tauytos tauxtof = 0.5 + 8.5 * ufl.exp(-((9 / 10 + V_m / 50) * (9 / 10 + V_m / 50))) tauytof = 7 + 85 * ufl.exp(-((40 + V_m) * (40 + V_m)) / 220) F_expressions[5] = (xtoss - x_to_f) / tauxtof F_expressions[7] = (ytoss - y_to_f) / tauytof # Expressions for the I_Ca component fss = 0.6 / (1 + ufl.exp(5 / 2 - V_m / 20)) + 1.0 / ( 1 + ufl.exp(35 / 9 + V_m / 9)) dss = 1.0 / (1 + ufl.exp(-5 / 6 - V_m / 6)) taud = (1 - ufl.exp(-5 / 6 - V_m / 6)) * dss / (0.175 + 0.035 * V_m) tauf = 1.0/(0.02 + 0.0197*ufl.exp(-((0.48865 + 0.0337*V_m)*(0.48865 +\ 0.0337*V_m)))) F_expressions[9] = (-d + dss) / taud F_expressions[10] = (fss - f) / tauf F_expressions[11] = 1.7 * (1 - f_Ca_Bj) * Ca_j - 0.0119 * f_Ca_Bj F_expressions[12] = -0.0119 * f_Ca_Bsl + 1.7 * (1 - f_Ca_Bsl) * Ca_sl fcaCaMSL = 0 fcaCaj = 0 ibarca_j = 4*Frdy*pCa*(-0.341*Cao +\ 0.341*Ca_j*ufl.exp(2*FoRT*V_m))*FoRT*V_m/(-1 +\ ufl.exp(2*FoRT*V_m)) ibarca_sl = 4*Frdy*pCa*(-0.341*Cao +\ 0.341*Ca_sl*ufl.exp(2*FoRT*V_m))*FoRT*V_m/(-1 +\ ufl.exp(2*FoRT*V_m)) ibarna_j = Frdy*pNa*(-0.75*Nao +\ 0.75*Na_j*ufl.exp(FoRT*V_m))*FoRT*V_m/(-1 + ufl.exp(FoRT*V_m)) ibarna_sl = Frdy*pNa*(0.75*Na_sl*ufl.exp(FoRT*V_m) -\ 0.75*Nao)*FoRT*V_m/(-1 + ufl.exp(FoRT*V_m)) I_Ca_junc = g_CaL_factor*0.45*Fjunc_CaL*ufl.elem_pow(Q10CaL, Qpow)*(1 - f_Ca_Bj +\ fcaCaj)*d*f*ibarca_j I_Ca_sl = g_CaL_factor*0.45*ufl.elem_pow(Q10CaL, Qpow)*(1 - f_Ca_Bsl +\ fcaCaMSL)*Fsl_CaL*d*f*ibarca_sl I_CaNa_junc = g_CaL_factor*0.45*Fjunc_CaL*ufl.elem_pow(Q10CaL, Qpow)*(1 - f_Ca_Bj\ + fcaCaj)*d*f*ibarna_j I_CaNa_sl = g_CaL_factor*0.45*ufl.elem_pow(Q10CaL, Qpow)*(1 - f_Ca_Bsl +\ fcaCaMSL)*Fsl_CaL*d*f*ibarna_sl # Expressions for the I_NCX component Ka_junc = 1.0 / (1 + (Kdact * Kdact) / (Ca_j * Ca_j)) Ka_sl = 1.0 / (1 + (Kdact * Kdact) / (Ca_sl * Ca_sl)) s1_junc = Cao * (Na_j * Na_j * Na_j) * ufl.exp(nu * FoRT * V_m) s1_sl = Cao * (Na_sl * Na_sl * Na_sl) * ufl.exp(nu * FoRT * V_m) s2_junc = (Nao * Nao * Nao) * Ca_j * ufl.exp((-1 + nu) * FoRT * V_m) s3_junc = KmCao*(Na_j*Na_j*Na_j) + (Nao*Nao*Nao)*Ca_j +\ Cao*(Na_j*Na_j*Na_j) + KmCai*(Nao*Nao*Nao)*(1 +\ (Na_j*Na_j*Na_j)/(KmNai*KmNai*KmNai)) + (KmNao*KmNao*KmNao)*(1 +\ Ca_j/KmCai)*Ca_j s2_sl = (Nao * Nao * Nao) * Ca_sl * ufl.exp((-1 + nu) * FoRT * V_m) s3_sl = KmCai*(Nao*Nao*Nao)*(1 +\ (Na_sl*Na_sl*Na_sl)/(KmNai*KmNai*KmNai)) + (Nao*Nao*Nao)*Ca_sl +\ (KmNao*KmNao*KmNao)*(1 + Ca_sl/KmCai)*Ca_sl +\ Cao*(Na_sl*Na_sl*Na_sl) + KmCao*(Na_sl*Na_sl*Na_sl) I_ncx_junc = Fjunc*IbarNCX*ufl.elem_pow(Q10NCX, Qpow)*(-s2_junc +\ s1_junc)*Ka_junc/((1 + ksat*ufl.exp((-1 + nu)*FoRT*V_m))*s3_junc) I_ncx_sl = IbarNCX*ufl.elem_pow(Q10NCX, Qpow)*(-s2_sl +\ s1_sl)*Fsl*Ka_sl/((1 + ksat*ufl.exp((-1 + nu)*FoRT*V_m))*s3_sl) # Expressions for the I_PCa component I_pca_junc = Fjunc*IbarSLCaP*ufl.elem_pow(Q10SLCaP,\ Qpow)*ufl.elem_pow(Ca_j, 1.6)/(ufl.elem_pow(Ca_j, 1.6) +\ ufl.elem_pow(KmPCa, 1.6)) I_pca_sl = IbarSLCaP*ufl.elem_pow(Q10SLCaP, Qpow)*ufl.elem_pow(Ca_sl,\ 1.6)*Fsl/(ufl.elem_pow(Ca_sl, 1.6) + ufl.elem_pow(KmPCa, 1.6)) # Expressions for the I_CaBK component I_cabk_junc = Fjunc * GCaB * (-eca_junc + V_m) I_cabk_sl = GCaB * (-eca_sl + V_m) * Fsl # Expressions for the SR Fluxes component kCaSR = MaxSR - (-MinSR + MaxSR) / (1 + ufl.elem_pow(ec50SR / Ca_sr, 2.5)) koSRCa = koCa / kCaSR kiSRCa = kiCa * kCaSR RI = 1 - Ry_Ro - Ry_Ri - Ry_Rr F_expressions[15] = -(Ca_j*Ca_j)*Ry_Rr*koSRCa + kom*Ry_Ro + kim*RI -\ Ca_j*Ry_Rr*kiSRCa F_expressions[14] = -kom*Ry_Ro - Ca_j*Ry_Ro*kiSRCa + kim*Ry_Ri +\ (Ca_j*Ca_j)*Ry_Rr*koSRCa F_expressions[13] = -kim*Ry_Ri + Ca_j*Ry_Ro*kiSRCa - kom*Ry_Ri +\ (Ca_j*Ca_j)*RI*koSRCa J_SRCarel = SR_Ca_release_ks_factor * ks * (Ca_sr - Ca_j) * Ry_Ro J_serca = Vmax_SRCaP*ufl.elem_pow(Q10SRCaP,\ Qpow)*(-ufl.elem_pow(Ca_sr/Kmr, hillSRCaP) +\ ufl.elem_pow(Ca_i/Kmf, hillSRCaP))/(1 + ufl.elem_pow(Ca_sr/Kmr,\ hillSRCaP) + ufl.elem_pow(Ca_i/Kmf, hillSRCaP)) J_SRleak = 5.348e-06 * Ca_sr - 5.348e-06 * Ca_j # Expressions for the Na Buffers component F_expressions[16] = -koff_na * Na_Bj + kon_na * (-Na_Bj + Bmax_Naj) * Na_j F_expressions[17] = kon_na * (-Na_Bsl + Bmax_Nasl) * Na_sl - koff_na * Na_Bsl # Expressions for the Cytosolic Ca Buffers component F_expressions[24] = kon_tncl*(Bmax_TnClow - Tn_CL)*Ca_i -\ koff_tncl*Tn_CL F_expressions[22] = -koff_tnchca*Tn_CHc + kon_tnchca*(-Tn_CHc +\ Bmax_TnChigh - Tn_CHm)*Ca_i F_expressions[23] = Mgi*kon_tnchmg*(-Tn_CHc + Bmax_TnChigh - Tn_CHm)\ - koff_tnchmg*Tn_CHm F_expressions[18] = kon_cam * (-CaM + Bmax_CaM) * Ca_i - koff_cam * CaM F_expressions[19] = -koff_myoca*Myo_c + kon_myoca*(-Myo_c +\ Bmax_myosin - Myo_m)*Ca_i F_expressions[20] = Mgi*kon_myomg*(-Myo_c + Bmax_myosin - Myo_m) -\ koff_myomg*Myo_m F_expressions[21] = kon_sr * (Bmax_SR - SRB) * Ca_i - koff_sr * SRB J_CaB_cytosol = -koff_tnchca*Tn_CHc - koff_myoca*Myo_c +\ Mgi*kon_myomg*(-Myo_c + Bmax_myosin - Myo_m) +\ Mgi*kon_tnchmg*(-Tn_CHc + Bmax_TnChigh - Tn_CHm) -\ koff_tnchmg*Tn_CHm + kon_tncl*(Bmax_TnClow - Tn_CL)*Ca_i +\ kon_sr*(Bmax_SR - SRB)*Ca_i - koff_myomg*Myo_m + kon_cam*(-CaM +\ Bmax_CaM)*Ca_i - koff_cam*CaM - koff_tncl*Tn_CL +\ kon_myoca*(-Myo_c + Bmax_myosin - Myo_m)*Ca_i +\ kon_tnchca*(-Tn_CHc + Bmax_TnChigh - Tn_CHm)*Ca_i - koff_sr*SRB # Expressions for the Junctional and SL Ca Buffers component Bmax_SLlowsl = Bmax_SLlowsl0 * Vmyo / Vsl Bmax_SLlowj = Bmax_SLlowj0 * Vmyo / Vjunc Bmax_SLhighsl = Bmax_SLhighsl0 * Vmyo / Vsl Bmax_SLhighj = Bmax_SLhighj0 * Vmyo / Vjunc F_expressions[27] = kon_sll * (Bmax_SLlowj - SLL_j) * Ca_j - koff_sll * SLL_j F_expressions[28] = kon_sll*(-SLL_sl + Bmax_SLlowsl)*Ca_sl -\ koff_sll*SLL_sl F_expressions[25] = kon_slh*(Bmax_SLhighj - SLH_j)*Ca_j -\ koff_slh*SLH_j F_expressions[26] = kon_slh*(-SLH_sl + Bmax_SLhighsl)*Ca_sl -\ koff_slh*SLH_sl J_CaB_junction = kon_slh*(Bmax_SLhighj - SLH_j)*Ca_j +\ kon_sll*(Bmax_SLlowj - SLL_j)*Ca_j - koff_slh*SLH_j -\ koff_sll*SLL_j J_CaB_sl = kon_sll*(-SLL_sl + Bmax_SLlowsl)*Ca_sl + kon_slh*(-SLH_sl\ + Bmax_SLhighsl)*Ca_sl - koff_sll*SLL_sl - koff_slh*SLH_sl # Expressions for the SR Ca Concentrations component Bmax_Csqn = Bmax_Csqn0 * Vmyo / Vsr F_expressions[30] = -koff_csqn*Csqn_b + kon_csqn*(Bmax_Csqn -\ Csqn_b)*Ca_sr F_expressions[29] = -kon_csqn*(Bmax_Csqn - Csqn_b)*Ca_sr -\ J_SRleak*Vmyo/Vsr + koff_csqn*Csqn_b - J_SRCarel + J_serca # Expressions for the Na Concentrations component I_Na_tot_junc = 3*I_nak_junc + 3*I_ncx_junc + I_CaNa_junc + I_Na_junc\ + I_nabk_junc I_Na_tot_sl = I_Na_sl + I_nabk_sl + 3 * I_nak_sl + I_CaNa_sl + 3 * I_ncx_sl F_expressions[32] = -Cmem*I_Na_tot_junc/(Frdy*Vjunc) +\ J_na_juncsl*(Na_sl - Na_j)/Vjunc - F_expressions[16] F_expressions[33] = -F_expressions[17] + J_na_slmyo*(-Na_sl +\ Na_i)/Vsl + J_na_juncsl*(-Na_sl + Na_j)/Vsl -\ Cmem*I_Na_tot_sl/(Frdy*Vsl) F_expressions[31] = J_na_slmyo * (Na_sl - Na_i) / Vmyo # Expressions for the K Concentration component F_expressions[34] = Constant(0.0) # Expressions for the Ca Concentrations component I_Ca_tot_junc = I_pca_junc + I_cabk_junc + I_Ca_junc - 2 * I_ncx_junc I_Ca_tot_sl = -2 * I_ncx_sl + I_pca_sl + I_cabk_sl + I_Ca_sl F_expressions[36] = J_ca_juncsl*(Ca_sl - Ca_j)/Vjunc +\ J_SRCarel*Vsr/Vjunc - J_CaB_junction -\ Cmem*I_Ca_tot_junc/(2*Frdy*Vjunc) + J_SRleak*Vmyo/Vjunc F_expressions[37] = -J_CaB_sl + J_ca_juncsl*(Ca_j - Ca_sl)/Vsl -\ Cmem*I_Ca_tot_sl/(2*Frdy*Vsl) + J_ca_slmyo*(Ca_i - Ca_sl)/Vsl F_expressions[35] = -J_CaB_cytosol + J_ca_slmyo*(Ca_sl - Ca_i)/Vmyo -\ J_serca*Vsr/Vmyo # Return results return dolfin.as_vector(F_expressions)
def _butcher_scheme_generator_adm(a, b, c, time, solution, rhs_form, adj): """ Generates a list of forms and solutions for a given Butcher tableau *Arguments* a (2 dimensional numpy array) The a matrix of the Butcher tableau. b (1-2 dimensional numpy array) The b vector of the Butcher tableau. If b is 2 dimensional the scheme includes an error estimator and can be used in adaptive solvers. c (1 dimensional numpy array) The c vector the Butcher tableau. time (_Constant_) A Constant holding the time at the start of the time step solution (_Function_) The prognostic variable rhs_form (ufl.Form) A UFL form representing the rhs for a time differentiated equation adj (_Function_) The derivative of the functional with respect to y_n+1 """ a = _check_abc(a, b, c) size = a.shape[0] DX = _check_form(rhs_form) # Get test function arguments, coefficients = ufl.algorithms.\ extract_arguments_and_coefficients(rhs_form) v = arguments[0] # Create time step dt = Constant(0.1) # rhs forms dolfin_stage_forms = [] ufl_stage_forms = [] # Stage solutions k = [ Function(solution.function_space(), name="k_%d" % i) for i in range(size) ] kbar = [Function(solution.function_space(), name="kbar_%d"%i) \ for i in range(size)] # Create the stage forms y_ = solution ydot = solution.copy() time_ = time time_dep_expressions = _time_dependent_expressions(rhs_form, time) zero_ = ufl.zero(*y_.shape()) forward_forms = [] stage_solutions = [] jacobian_indices = [] # The recomputation of the forward run: for i, ki in enumerate(k): # Check whether the stage is explicit explicit = a[i, i] == 0 # Evaluation arguments for the ith stage evalargs = y_ + dt * sum([float(a[i,j]) * k[j] \ for j in range(i+1)], zero_) time = time_ + dt * c[i] replace_dict = _replace_dict_time_dependent_expression(\ time_dep_expressions, time_, dt, c[i]) replace_dict[y_] = evalargs replace_dict[time_] = time stage_form = ufl.replace(rhs_form, replace_dict) forward_forms.append(stage_form) if explicit: stage_forms = [stage_form] jacobian_indices.append(-1) else: # Create a F=0 form and differentiate it stage_form_implicit = stage_form - ufl.inner(ki, v) * DX stage_forms = [stage_form_implicit, derivative(\ stage_form_implicit, ki)] jacobian_indices.append(0) ufl_stage_forms.append(stage_forms) dolfin_stage_forms.append([Form(form) for form in stage_forms]) stage_solutions.append(ki) for i, kbari in reversed(list(enumerate(kbar))): # Check whether the stage is explicit explicit = a[i, i] == 0 # And now the adjoint linearisation: stage_form_adm = ufl.inner(dt * b[i] * adj, v)*DX + sum(\ [dt * float(a[j,i]) * safe_action(safe_adjoint(derivative(\ forward_forms[j], y_)), kbar[j]) for j in range(i, size)]) if explicit: stage_forms_adm = [stage_form_adm] jacobian_indices.append(-1) else: # Create a F=0 form and differentiate it stage_form_adm -= ufl.inner(kbar[i], v) * DX stage_forms_adm = [ stage_form_adm, derivative(stage_form_adm, kbari) ] jacobian_indices.append(1) ufl_stage_forms.append(stage_forms_adm) dolfin_stage_forms.append([Form(form) for form in stage_forms_adm]) stage_solutions.append(kbari) # Only one last stage if len(b.shape) == 1: last_stage = Form(ufl.inner(adj, v)*DX + sum(\ [safe_action(safe_adjoint(derivative(forward_forms[i], y_)), kbar[i]) \ for i in range(size)])) else: raise Exception("Not sure what to do here") human_form = "unimplemented" return ufl_stage_forms, dolfin_stage_forms, jacobian_indices, last_stage,\ stage_solutions, dt, human_form, adj
def F(self, V, s, time=None): """ds/dt = F(v, s).""" GCa = self._parameters["GCa"] gamma1 = self._parameters["gamma1"] Gglia = self._parameters["Gglia"] tau = self._parameters["tau"] control = self._parameters["control"] GNa = self._parameters["GNa"] GNaL = self._parameters["GNaL"] GK = self._parameters["GK"] GKL = self._parameters["GKL"] GAHP = self._parameters["GAHP"] Koinf = self._parameters["Koinf"] # Define some parameters ECa = 120 phi = 3 rho = 1.25 eps0 = 1.2 beta0 = 7 Cli = 6 Clo = 130 Nao = 144 - beta0*(s[5] - 18) ENa = 26.64*df.ln(Nao/s[5]) Ki = 140 + (18 - s[5]) EK = 26.64*df.ln(control*s[4]/Ki) INa = GNa*s[0]**3*s[2]*(V - ENa) + GNaL*(V - ENa) IK = (GK*s[1]**4 + GAHP*s[3]/(1 + s[3]) + GKL)*(V - EK) a_m = (3.0 + (0.1)*V)*(1 - df.exp(-3 -1/10*V))**(-1) b_m = 4*df.exp(-55/18 - 1/18*V) ah = (0.07)*df.exp(-11/5 - 1/20*V) bh = (1 + df.exp(-7/5 - 1/10*V))**(-1) an = (0.34 + (0.01)*V)*(1 - df.exp(-17/5 - 1/10*V))**(-1) bn = (0.125)*df.exp(-11/20 - 1/80*V) taum = (a_m + b_m)**(-1) minf = a_m*(a_m + b_m)**(-1) h_inf = (bh + ah)**(-1)*ah tauh = (bh + ah)**(-1) ninf = (an + bn)**(-1)*an taun = (an + bn)**(-1) dot_m = phi*(minf - s[0])*taum**(-1) dot_h = phi*(ninf - s[1])/taun dot_n = phi*(h_inf - s[2])/tauh Ipump = rho*(1/(1 + df.exp((25 - s[5])/3)))*(1/(1 + df.exp(5.5 - s[4]))) IGlia = Gglia/(1 + df.exp((18 - s[4])/2.5)) Idiff = eps0*(s[4] - Koinf) dot_Ca = -s[3]/80 - 0.002*GCa*(V - ECa)/(1 + df.exp(-(V + 25)/2.5)) dot_K = (gamma1*beta0*IK - 2*beta0*Ipump - IGlia - Idiff)/tau # dot_Na = (gamma1*INa + 3*Ipump)/tau dot_Na = -(gamma1*INa + 3*Ipump)/tau # Pretty sure it should me minus F_expressions = [ufl.zero()]*self.num_states() F_expressions[0] = dot_m F_expressions[1] = dot_h F_expressions[2] = dot_n F_expressions[3] = dot_Ca F_expressions[4] = dot_K F_expressions[5] = dot_Na return df.as_vector(F_expressions)
def solve_group_GS(self, it=0, init_slns_ary=None): if self.verb > 1: print0(self.print_prefix + "Solving..." ) if self.eigenproblem: coupled_solver_error(__file__, "solve using group GS", "Group Gauss-Seidel for eigenproblem not yet supported") sol_timer = Timer("-- Complete solution") mat_timer = Timer("---- MTX: Complete construction") ass_timer = Timer("---- MTX: Assembling") sln_timer = Timer("---- SOL: Solving") # To simplify the weak forms u = self.u[0] v = self.v[0] if init_slns_ary is None: init_slns_ary = numpy.zeros((self.DD.G, self.local_sln_size)) for g in range(self.DD.G): self.slns_mg[g].vector()[:] = init_slns_ary[g] err = 0. for gsi in range(self.max_group_GS_it): #========================================== GAUSS-SEIDEL LOOP ============================================ if self.verb > 2: print self.print_prefix + 'Gauss-Seidel iteration {}'.format(gsi) for gto in range(self.DD.G): #========================================= LOOP OVER GROUPS =============================================== self.sln_vec = self.slns_mg[gto].vector() prev_slng_vec = self.aux_slng.vector() prev_slng_vec.zero() prev_slng_vec.axpy(1.0, self.sln_vec) prev_slng_vec.apply("insert") spc = self.print_prefix + " " if self.verb > 3 and self.DD.G > 1: print spc + 'GROUP [', gto, ',', gto, '] :' #==================================== ASSEMBLE WITHIN-GROUP PROBLEM ======================================== mat_timer.start() pres_fiss = self.PD.get_xs('chi', self.chi, gto) self.PD.get_xs('D', self.D, gto) self.PD.get_xs('St', self.R, gto) i,j,p,q,k1,k2 = ufl.indices(6) form = ( self.D*self.tensors.T[p,q,i,j]*u[q].dx(j)*v[p].dx(i) + self.R*self.tensors.W[p,q]*u[q]*v[p] ) * dx + self.bnd_matrix_form[gto] ass_timer.start() add_values_A = False add_values_Q = False assemble(form, tensor=self.A, finalize_tensor=False, add_values=add_values_A) add_values_A = True ass_timer.stop() if self.fixed_source_problem: if self.PD.isotropic_source_everywhere: self.PD.get_Q(self.fixed_source, 0, gto) # FIXME: This assumes that adjoint source == forward source form = self.fixed_source*self.tensors.Wp[p]*v[p]*dx + self.bnd_vector_form[gto] else: form = ufl.zero() for n in range(self.DD.M): self.PD.get_Q(self.fixed_source, n, gto) # FIXME: This assumes that adjoint source == forward source form += self.fixed_source[n,gto] * self.tensors.Wp[n] * v[n] * dx + self.bnd_vector_form[gto] ass_timer.start() assemble(form, tensor=self.Q, finalize_tensor=False, add_values=add_values_Q) add_values_Q = True ass_timer.stop() for gfrom in range(self.DD.G): if self.verb > 3 and self.DD.G > 1: print spc + 'GROUP [', gto, ',', gfrom, '] :' pres_Ss = False # TODO: Enlarge self.S and self.C to (L+1)^2 (or 1./2.*(L+1)*(L+2) in 2D) to accomodate for anisotropic # scattering (lines below using CC, SS are correct only for L = 0, when the following inner loop runs only # once. for l in range(self.L+1): for m in range(-l, l+1): if self.DD.angular_quad.get_D() == 2 and divmod(l+m,2)[1] == 0: continue pres_Ss |= self.PD.get_xs('Ss', self.S[l], gto, gfrom, l) self.PD.get_xs('C', self.C[l], gto, gfrom, l) if pres_Ss: Sd = ufl.diag(self.S) SS = self.tensors.QT[p,k1]*Sd[k1,k2]*self.tensors.Q[k2,q] Cd = ufl.diag(self.C) CC = self.tensors.QtT[p,i,k1]*Cd[k1,k2]*self.tensors.Qt[k2,q,j] ass_timer.start() if gfrom != gto: form = ( SS[p,q]*self.slns_mg[gfrom][q]*v[p] - CC[p,i,q,j]*self.slns_mg[gfrom][q].dx(j)*v[p].dx(i) ) * dx assemble(form, tensor=self.Q, finalize_tensor=False, add_values=add_values_Q) else: form = ( CC[p,i,q,j]*u[q].dx(j)*v[p].dx(i) - SS[q,p]*u[q]*v[p] ) * dx assemble(form, tensor=self.A, finalize_tensor=False, add_values=add_values_A) ass_timer.stop() if pres_fiss: pres_nSf = self.PD.get_xs('nSf', self.R, gfrom) if pres_nSf: ass_timer.start() if gfrom != gto: form = self.chi*self.R/(4*numpy.pi)*\ self.tensors.QT[p,0]*self.tensors.Q[0,q]*self.slns_mg[gfrom][q]*v[p]*dx assemble(form, tensor=self.Q, finalize_tensor=False, add_values=add_values_Q) else: # NOTE: Fixed-source case (eigenproblems can currently be solved only by the coupled-group scheme) if self.fixed_source_problem: form = -self.chi*self.R/(4*numpy.pi)*self.tensors.QT[p,0]*self.tensors.Q[0,q]*u[q]*v[p]*dx assemble(form, tensor=self.A, finalize_tensor=False, add_values=add_values_A) ass_timer.stop() #================================== END ASSEMBLE WITHIN-GROUP PROBLEM ======================================= self.A.apply("add") self.Q.apply("add") mat_timer.stop() self.save_algebraic_system({'A':'A_{}'.format(gto), 'Q':'Q_{}'.format(gto)}, it) #==================================== SOLVE WITHIN-GROUP PROBLEM ========================================== sln_timer.start() dolfin_solve(self.A, self.sln_vec, self.Q, "cg", "petsc_amg") sln_timer.stop() self.up_to_date["flux"] = False err = max(err, delta(self.sln_vec.array(), prev_slng_vec.array())) #==================================== END LOOP OVER GROUPS ==================================== if err < self.parameters["group_GS"]["tol"]: break
def F(self, v, s, time=None): """ Right hand side for ODE system """ time = time if time else Constant(0.0) # Assign states V = v assert(len(s) == 16) Xr1, Xr2, Xs, m, h, j, d, f, fCa, s, r, Ca_SR, Ca_i, g, Na_i, K_i = s # Assign parameters P_kna = self._parameters["P_kna"] g_K1 = self._parameters["g_K1"] g_Kr = self._parameters["g_Kr"] g_Ks = self._parameters["g_Ks"] g_Na = self._parameters["g_Na"] g_bna = self._parameters["g_bna"] g_CaL = self._parameters["g_CaL"] g_bca = self._parameters["g_bca"] g_to = self._parameters["g_to"] K_mNa = self._parameters["K_mNa"] K_mk = self._parameters["K_mk"] P_NaK = self._parameters["P_NaK"] K_NaCa = self._parameters["K_NaCa"] K_sat = self._parameters["K_sat"] Km_Ca = self._parameters["Km_Ca"] Km_Nai = self._parameters["Km_Nai"] alpha = self._parameters["alpha"] gamma = self._parameters["gamma"] K_pCa = self._parameters["K_pCa"] g_pCa = self._parameters["g_pCa"] g_pK = self._parameters["g_pK"] Buf_c = self._parameters["Buf_c"] Buf_sr = self._parameters["Buf_sr"] Ca_o = self._parameters["Ca_o"] K_buf_c = self._parameters["K_buf_c"] K_buf_sr = self._parameters["K_buf_sr"] K_up = self._parameters["K_up"] V_leak = self._parameters["V_leak"] V_sr = self._parameters["V_sr"] Vmax_up = self._parameters["Vmax_up"] a_rel = self._parameters["a_rel"] b_rel = self._parameters["b_rel"] c_rel = self._parameters["c_rel"] tau_g = self._parameters["tau_g"] Na_o = self._parameters["Na_o"] Cm = self._parameters["Cm"] F = self._parameters["F"] R = self._parameters["R"] T = self._parameters["T"] V_c = self._parameters["V_c"] stim_amplitude = self._parameters["stim_amplitude"] stim_duration = self._parameters["stim_duration"] stim_start = self._parameters["stim_start"] K_o = self._parameters["K_o"] # Init return args F_expressions = [ufl.zero()]*16 # Expressions for the Reversal potentials component E_Na = R*T*ufl.ln(Na_o/Na_i)/F E_K = R*T*ufl.ln(K_o/K_i)/F E_Ks = R*T*ufl.ln((Na_o*P_kna + K_o)/(K_i + P_kna*Na_i))/F E_Ca = 0.5*R*T*ufl.ln(Ca_o/Ca_i)/F # Expressions for the Inward rectifier potassium current component alpha_K1 = 0.1/(1 + 6.14421235333e-06*ufl.exp(-0.06*E_K + 0.06*V)) beta_K1 = (3.06060402008*ufl.exp(0.0002*V - 0.0002*E_K) +\ 0.367879441171*ufl.exp(0.1*V - 0.1*E_K))/(1 + ufl.exp(0.5*E_K -\ 0.5*V)) xK1_inf = alpha_K1/(alpha_K1 + beta_K1) i_K1 = 0.430331482912*g_K1*ufl.sqrt(K_o)*(-E_K + V)*xK1_inf # Expressions for the Rapid time dependent potassium current component i_Kr = 0.430331482912*g_Kr*ufl.sqrt(K_o)*(-E_K + V)*Xr1*Xr2 # Expressions for the Xr1 gate component xr1_inf = 1.0/(1 + ufl.exp(-26/7 - V/7)) alpha_xr1 = 450/(1 + ufl.exp(-9/2 - V/10)) beta_xr1 = 6/(1 + 13.5813245226*ufl.exp(0.0869565217391*V)) tau_xr1 = alpha_xr1*beta_xr1 F_expressions[0] = (xr1_inf - Xr1)/tau_xr1 # Expressions for the Xr2 gate component xr2_inf = 1.0/(1 + ufl.exp(11/3 + V/24)) alpha_xr2 = 3/(1 + ufl.exp(-3 - V/20)) beta_xr2 = 1.12/(1 + ufl.exp(-3 + V/20)) tau_xr2 = alpha_xr2*beta_xr2 F_expressions[1] = (xr2_inf - Xr2)/tau_xr2 # Expressions for the Slow time dependent potassium current component i_Ks = g_Ks*(Xs*Xs)*(-E_Ks + V) # Expressions for the Xs gate component xs_inf = 1.0/(1 + ufl.exp(-5/14 - V/14)) alpha_xs = 1100/ufl.sqrt(1 + ufl.exp(-5/3 - V/6)) beta_xs = 1.0/(1 + ufl.exp(-3 + V/20)) tau_xs = alpha_xs*beta_xs F_expressions[2] = (xs_inf - Xs)/tau_xs # Expressions for the Fast sodium current component i_Na = g_Na*(m*m*m)*(-E_Na + V)*h*j # Expressions for the m gate component m_inf = 1.0/((1 + 0.00184221158117*ufl.exp(-0.110741971207*V))*(1 +\ 0.00184221158117*ufl.exp(-0.110741971207*V))) alpha_m = 1.0/(1 + ufl.exp(-12 - V/5)) beta_m = 0.1/(1 + ufl.exp(-1/4 + V/200)) + 0.1/(1 + ufl.exp(7 + V/5)) tau_m = alpha_m*beta_m F_expressions[3] = (-m + m_inf)/tau_m # Expressions for the h gate component h_inf = 1.0/((1 + 15212.5932857*ufl.exp(0.134589502019*V))*(1 +\ 15212.5932857*ufl.exp(0.134589502019*V))) alpha_h = 4.43126792958e-07*ufl.exp(-0.147058823529*V)/(1 +\ 2.35385266837e+17*ufl.exp(1.0*V)) beta_h = (2.7*ufl.exp(0.079*V) + 310000*ufl.exp(0.3485*V))/(1 +\ 2.35385266837e+17*ufl.exp(1.0*V)) + 0.77*(1 - 1/(1 +\ 2.35385266837e+17*ufl.exp(1.0*V)))/(0.13 +\ 0.0497581410839*ufl.exp(-0.0900900900901*V)) tau_h = 1.0/(alpha_h + beta_h) F_expressions[4] = (-h + h_inf)/tau_h # Expressions for the j gate component j_inf = 1.0/((1 + 15212.5932857*ufl.exp(0.134589502019*V))*(1 +\ 15212.5932857*ufl.exp(0.134589502019*V))) alpha_j = (37.78 + V)*(-25428*ufl.exp(0.2444*V) -\ 6.948e-06*ufl.exp(-0.04391*V))/((1 +\ 2.35385266837e+17*ufl.exp(1.0*V))*(1 +\ 50262745826.0*ufl.exp(0.311*V))) beta_j = 0.6*(1 - 1/(1 +\ 2.35385266837e+17*ufl.exp(1.0*V)))*ufl.exp(0.057*V)/(1 +\ 0.0407622039784*ufl.exp(-0.1*V)) +\ 0.02424*ufl.exp(-0.01052*V)/((1 +\ 2.35385266837e+17*ufl.exp(1.0*V))*(1 +\ 0.0039608683399*ufl.exp(-0.1378*V))) tau_j = 1.0/(alpha_j + beta_j) F_expressions[5] = (-j + j_inf)/tau_j # Expressions for the Sodium background current component i_b_Na = g_bna*(-E_Na + V) # Expressions for the L_type Ca current component i_CaL = 4*g_CaL*(F*F)*(Ca_i*ufl.exp(2*F*V/(R*T)) -\ 0.341*Ca_o)*V*d*f*fCa/(R*T*(-1 + ufl.exp(2*F*V/(R*T)))) # Expressions for the d gate component d_inf = 1.0/(1 + 0.513417119033*ufl.exp(-0.133333333333*V)) alpha_d = 0.25 + 1.4/(1 + ufl.exp(-35/13 - V/13)) beta_d = 1.4/(1 + ufl.exp(1 + V/5)) gamma_d = 1.0/(1 + ufl.exp(5/2 - V/20)) tau_d = alpha_d*beta_d + gamma_d F_expressions[6] = (-d + d_inf)/tau_d # Expressions for the f gate component f_inf = 1.0/(1 + ufl.exp(20/7 + V/7)) tau_f = 80 + 1125*ufl.exp(-((27 + V)*(27 + V))/240) + 165/(1 +\ ufl.exp(5/2 - V/10)) F_expressions[7] = (f_inf - f)/tau_f # Expressions for the FCa gate component alpha_fCa = 1.0/(1 + 8.03402376702e+27*ufl.elem_pow(Ca_i, 8)) exp_arg_0 = -5.0 + 10000.0*Ca_i exp_arg_00 = ufl.conditional(ufl.lt(exp_arg_0, 500.0), exp_arg_0,\ 500.0) beta_fCa = 0.1/(1 + ufl.exp(exp_arg_00)) exp_arg_1 = -0.9375 + 1250.0*Ca_i exp_arg_11 = ufl.conditional(ufl.lt(exp_arg_1, 500.0), exp_arg_1,\ 500.0) gama_fCa = 0.2/(1 + ufl.exp(exp_arg_11)) fCa_inf = 0.157534246575 + 0.684931506849*gama_fCa +\ 0.684931506849*alpha_fCa + 0.684931506849*beta_fCa tau_fCa = 2 d_fCa = (-fCa + fCa_inf)/tau_fCa F_expressions[8] = ufl.conditional(ufl.And(ufl.gt(V, -60),\ ufl.gt(fCa_inf, fCa)), 0, d_fCa) # Expressions for the Calcium background current component i_b_Ca = g_bca*(-E_Ca + V) # Expressions for the Transient outward current component i_to = g_to*(-E_K + V)*r*s # Expressions for the s gate component s_inf = 1.0/(1 + ufl.exp(4 + V/5)) tau_s = 3 + 5/(1 + ufl.exp(-4 + V/5)) + 85*ufl.exp(-((45 + V)*(45 +\ V))/320) F_expressions[9] = (s_inf - s)/tau_s # Expressions for the r gate component r_inf = 1.0/(1 + ufl.exp(10/3 - V/6)) tau_r = 0.8 + 9.5*ufl.exp(-((40 + V)*(40 + V))/1800) F_expressions[10] = (r_inf - r)/tau_r # Expressions for the Sodium potassium pump current component i_NaK = K_o*P_NaK*Na_i/((K_mNa + Na_i)*(K_mk + K_o)*(1 +\ 0.0353*ufl.exp(-F*V/(R*T)) + 0.1245*ufl.exp(-0.1*F*V/(R*T)))) # Expressions for the Sodium calcium exchanger current component i_NaCa = K_NaCa*(-alpha*(Na_o*Na_o*Na_o)*Ca_i*ufl.exp(F*(-1 +\ gamma)*V/(R*T)) +\ Ca_o*(Na_i*Na_i*Na_i)*ufl.exp(F*gamma*V/(R*T)))/((1 +\ K_sat*ufl.exp(F*(-1 + gamma)*V/(R*T)))*(Km_Ca +\ Ca_o)*((Na_o*Na_o*Na_o) + (Km_Nai*Km_Nai*Km_Nai))) # Expressions for the Calcium pump current component i_p_Ca = g_pCa*Ca_i/(Ca_i + K_pCa) # Expressions for the Potassium pump current component i_p_K = g_pK*(-E_K + V)/(1 + 65.4052157419*ufl.exp(-0.167224080268*V)) # Expressions for the Calcium dynamics component i_rel = (c_rel + a_rel*(Ca_SR*Ca_SR)/((b_rel*b_rel) +\ (Ca_SR*Ca_SR)))*d*g i_up = Vmax_up/(1 + (K_up*K_up)/(Ca_i*Ca_i)) i_leak = V_leak*(Ca_SR - Ca_i) g_inf = 1/((1 + 0.0301973834223*ufl.exp(10000.0*Ca_i))*(1 +\ 5.43991024148e+20*ufl.elem_pow(Ca_i, 6))) + (1 - 1/(1 +\ 0.0301973834223*ufl.exp(10000.0*Ca_i)))/(1 +\ 1.9720198874e+55*ufl.elem_pow(Ca_i, 16)) d_g = (-g + g_inf)/tau_g F_expressions[13] = (1 - 1.0/((1 + ufl.exp(60 + V))*(1 +\ ufl.exp(10.0*g_inf - 10.0*g))))*d_g Ca_i_bufc = 1.0/(1 + Buf_c*K_buf_c/((Ca_i + K_buf_c)*(Ca_i + K_buf_c))) Ca_sr_bufsr = 1.0/(1 + Buf_sr*K_buf_sr/((Ca_SR + K_buf_sr)*(Ca_SR +\ K_buf_sr))) F_expressions[12] = (i_rel - i_up - Cm*(i_b_Ca + i_p_Ca - 2*i_NaCa +\ i_CaL)/(2*F*V_c) + i_leak)*Ca_i_bufc F_expressions[11] = V_c*(i_up - i_leak - i_rel)*Ca_sr_bufsr/V_sr # Expressions for the Sodium dynamics component F_expressions[14] = Cm*(-i_b_Na - i_Na - 3*i_NaCa - 3*i_NaK)/(F*V_c) # Expressions for the Membrane component i_Stim = -stim_amplitude*(1 - 1/(1 + ufl.exp(5.0*time -\ 5.0*stim_start)))/(1 + ufl.exp(5.0*time - 5.0*stim_start -\ 5.0*stim_duration)) # Expressions for the Potassium dynamics component F_expressions[15] = Cm*(2*i_NaK - i_Ks - i_Kr - i_to - i_Stim - i_p_K\ - i_K1)/(F*V_c) # Return results return dolfin.as_vector(F_expressions)
def _butcher_scheme_generator(a, b, c, time, solution, rhs_form): """ Generates a list of forms and solutions for a given Butcher tableau *Arguments* a (2 dimensional numpy array) The a matrix of the Butcher tableau. b (1-2 dimensional numpy array) The b vector of the Butcher tableau. If b is 2 dimensional the scheme includes an error estimator and can be used in adaptive solvers. c (1 dimensional numpy array) The c vector the Butcher tableau. time (_Constant_) A Constant holding the time at the start of the time step solution (_Function_) The prognostic variable rhs_form (ufl.Form) A UFL form representing the rhs for a time differentiated equation """ a = _check_abc(a, b, c) size = a.shape[0] DX = _check_form(rhs_form) # Get test function arguments = rhs_form.arguments() coefficients = rhs_form.coefficients() v = arguments[0] # Create time step dt = Constant(0.1) # rhs forms dolfin_stage_forms = [] ufl_stage_forms = [] # Stage solutions k = [Function(solution.function_space(), name="k_%d"%i) for i in range(size)] jacobian_indices = [] # Create the stage forms y_ = solution time_ = time time_dep_expressions = _time_dependent_expressions(rhs_form, time) zero_ = ufl.zero(*y_.ufl_shape) for i, ki in enumerate(k): # Check whether the stage is explicit explicit = a[i,i] == 0 # Evaluation arguments for the ith stage evalargs = y_ + dt * sum([float(a[i,j]) * k[j] \ for j in range(i+1)], zero_) time = time_ + dt*c[i] replace_dict = _replace_dict_time_dependent_expression(time_dep_expressions, time_, dt, c[i]) replace_dict[y_] = evalargs replace_dict[time_] = time stage_form = ufl.replace(rhs_form, replace_dict) if explicit: stage_forms = [stage_form] jacobian_indices.append(-1) else: # Create a F=0 form and differentiate it stage_form -= ufl.inner(ki, v)*DX stage_forms = [stage_form, derivative(stage_form, ki)] jacobian_indices.append(0) ufl_stage_forms.append(stage_forms) dolfin_stage_forms.append([Form(form) for form in stage_forms]) # Only one last stage if len(b.shape) == 1: last_stage = Form(ufl.inner(y_+sum([dt*float(bi)*ki for bi, ki in \ zip(b, k)], zero_), v)*DX) else: # FIXME: Add support for adaptivity in RKSolver and MultiStageScheme last_stage = [Form(ufl.inner(y_+sum([dt*float(bi)*ki for bi, ki in \ zip(b[0,:], k)], zero_), v)*DX), Form(ufl.inner(y_+sum([dt*float(bi)*ki for bi, ki in \ zip(b[1,:], k)], zero_), v)*DX)] # Create the Function holding the solution at end of time step #k.append(solution.copy()) # Generate human form of MultiStageScheme human_form = [] for i in range(size): kterm = " + ".join("%sh*k_%s" % ("" if a[i,j] == 1.0 else \ "%s*"% a[i,j], j) \ for j in range(size) if a[i,j] != 0) if c[i] in [0.0, 1.0]: cih = " + h" if c[i] == 1.0 else "" else: cih = " + %s*h" % c[i] if len(kterm) == 0: human_form.append("k_%(i)s = f(t_n%(cih)s, y_n)" % {"i": i, "cih": cih}) else: human_form.append("k_%(i)s = f(t_n%(cih)s, y_n + %(kterm)s)" % \ {"i": i, "cih": cih, "kterm": kterm}) parentheses = "(%s)" if np.sum(b>0) > 1 else "%s" human_form.append("y_{n+1} = y_n + h*" + parentheses % (" + ".join(\ "%sk_%s" % ("" if b[i] == 1.0 else "%s*" % b[i], i) \ for i in range(size) if b[i] > 0))) human_form = "\n".join(human_form) return ufl_stage_forms, dolfin_stage_forms, jacobian_indices, last_stage, \ k, dt, human_form, None
def _butcher_scheme_generator(a, b, c, solution, rhs_form): """ Generates a list of forms and solutions for a given Butcher tableau *Arguments* a (2 dimensional numpy array) The a matrix of the Butcher tableau. b (1-2 dimensional numpy array) The b vector of the Butcher tableau. If b is 2 dimensional the scheme includes an error estimator and can be used in adaptive solvers. c (1 dimensional numpy array) The c vector the Butcher tableau. solution (_Function_) The prognastic variable rhs_form (ufl.Form) A UFL form representing the rhs for a time differentiated equation """ if not (isinstance(a, np.ndarray) and (len(a) == 1 or \ (len(a.shape)==2 and a.shape[0] == a.shape[1]))): raise TypeError("Expected an m x m numpy array as the first argument") if not (isinstance(b, np.ndarray) and len(b.shape) in [1,2]): raise TypeError("Expected a 1 or 2 dimensional numpy array as the second argument") if not (isinstance(c, np.ndarray) and len(c.shape) == 1): raise TypeError("Expected a 1 dimensional numpy array as the third argument") # Make sure a is a "matrix" if len(a) == 1: a.shape = (1, 1) # Get size of system size = a.shape[0] # If b is a matrix we expect it to have two rows if len(b.shape) == 2: if not (b.shape[0] == 2 and b.shape[1] == size): raise ValueError("Expected a 2 row matrix with the same number "\ "of collumns as the first dimension of the a matrix.") elif len(b) != size: raise ValueError("Expected the length of the b vector to have the "\ "same size as the first dimension of the a matrix.") if len(c) != size: raise ValueError("Expected the length of the c vector to have the "\ "same size as the first dimension of the a matrix.") # Check if tableau is fully implicit for i in range(size): for j in range(i): if a[j, i] != 0: raise ValueError("Does not support fully implicit Butcher tableau.") if not isinstance(rhs_form, ufl.Form): raise TypeError("Expected a ufl.Form as the 5th argument.") # Check if form contains a cell or point integral if "cell" in rhs_form.integral_groups(): DX = ufl.dx elif "point" in rhs_form.integral_groups(): DX = ufl.dP else: raise ValueError("Expected either a cell or point integral in the form.") # Get test function arguments, coefficients = ufl.algorithms.extract_arguments_and_coefficients(rhs_form) if len(arguments) != 1: raise ValueError("Expected the form to have rank 1") v = arguments[0] # Create time step dt = Constant(0.1) # rhs forms dolfin_stage_forms = [] ufl_stage_forms = [] # Stage solutions k = [solution.copy(deepcopy=True) for i in range(size)] # Create the stage forms y_ = solution for i, ki in enumerate(k): # Check wether the stage is explicit explicit = a[i,i] == 0 # Evaluation arguments for the ith stage evalargs = y_ + dt * sum([float(a[i,j]) * k[j] \ for j in range(i+1)], ufl.zero(*y_.shape())) stage_form = ufl.replace(rhs_form, {y_:evalargs}) if explicit: stage_forms = [stage_form] else: # Create a F=0 form and differentiate it stage_form -= ufl.inner(ki, v)*DX stage_forms = [stage_form, derivative(stage_form, ki)] ufl_stage_forms.append(stage_forms) dolfin_stage_forms.append([Form(form) for form in stage_forms]) # Only one last stage if len(b.shape) == 1: last_stage = cpp.FunctionAXPY([(float(bi), ki) for bi, ki in zip(b, k)]) else: # FIXME: Add support for addaptivity in RKSolver and MultiStageScheme last_stage = [cpp.FunctionAXPY([(float(bi), ki) for bi, ki in zip(b[0,:], k)]), cpp.FunctionAXPY([(float(bi), ki) for bi, ki in zip(b[1,:], k)])] # Create the Function holding the solution at end of time step #k.append(solution.copy()) # Generate human form of MultiStageScheme human_form = [] for i in range(size): kterm = " + ".join("%sh*k_%s" % ("" if a[i,j] == 1.0 else \ "%s*"% a[i,j], j) \ for j in range(size) if a[i,j] != 0) if c[i] in [0.0, 1.0]: cih = " + h" if c[i] == 1.0 else "" else: cih = " + %s*h" % c[i] if len(kterm) == 0: human_form.append("k_%(i)s = f(t_n%(cih)s, y_n)" % {"i": i, "cih": cih}) else: human_form.append("k_%(i)s = f(t_n%(cih)s, y_n + %(kterm)s)" % \ {"i": i, "cih": cih, "kterm": kterm}) parentheses = "(%s)" if np.sum(b>0) > 1 else "%s" human_form.append("y_{n+1} = y_n + h*" + parentheses % (" + ".join(\ "%sk_%s" % ("" if b[i] == 1.0 else "%s*" % b[i], i) \ for i in range(size) if b[i] > 0))) human_form = "\n".join(human_form) return ufl_stage_forms, dolfin_stage_forms, last_stage, k, dt, human_form
def _butcher_scheme_generator_adm(a, b, c, time, solution, rhs_form, adj): """ Generates a list of forms and solutions for a given Butcher tableau *Arguments* a (2 dimensional numpy array) The a matrix of the Butcher tableau. b (1-2 dimensional numpy array) The b vector of the Butcher tableau. If b is 2 dimensional the scheme includes an error estimator and can be used in adaptive solvers. c (1 dimensional numpy array) The c vector the Butcher tableau. time (_Constant_) A Constant holding the time at the start of the time step solution (_Function_) The prognostic variable rhs_form (ufl.Form) A UFL form representing the rhs for a time differentiated equation adj (_Function_) The derivative of the functional with respect to y_n+1 """ a = _check_abc(a, b, c) size = a.shape[0] DX = _check_form(rhs_form) # Get test function arguments = rhs_form.arguments() coefficients = rhs_form.coefficients() v = arguments[0] # Create time step dt = Constant(0.1) # rhs forms dolfin_stage_forms = [] ufl_stage_forms = [] # Stage solutions k = [Function(solution.function_space(), name="k_%d"%i) for i in range(size)] kbar = [Function(solution.function_space(), name="kbar_%d"%i) \ for i in range(size)] # Create the stage forms y_ = solution time_ = time time_dep_expressions = _time_dependent_expressions(rhs_form, time) zero_ = ufl.zero(*y_.ufl_shape) forward_forms = [] stage_solutions = [] jacobian_indices = [] # The recomputation of the forward run: for i, ki in enumerate(k): # Check whether the stage is explicit explicit = a[i,i] == 0 # Evaluation arguments for the ith stage evalargs = y_ + dt * sum([float(a[i,j]) * k[j] \ for j in range(i+1)], zero_) time = time_ + dt*c[i] replace_dict = _replace_dict_time_dependent_expression(\ time_dep_expressions, time_, dt, c[i]) replace_dict[y_] = evalargs replace_dict[time_] = time stage_form = ufl.replace(rhs_form, replace_dict) forward_forms.append(stage_form) if explicit: stage_forms = [stage_form] jacobian_indices.append(-1) else: # Create a F=0 form and differentiate it stage_form_implicit = stage_form - ufl.inner(ki, v)*DX stage_forms = [stage_form_implicit, derivative(\ stage_form_implicit, ki)] jacobian_indices.append(0) ufl_stage_forms.append(stage_forms) dolfin_stage_forms.append([Form(form) for form in stage_forms]) stage_solutions.append(ki) for i, kbari in reversed(list(enumerate(kbar))): # Check whether the stage is explicit explicit = a[i,i] == 0 # And now the adjoint linearisation: stage_form_adm = ufl.inner(dt * b[i] * adj, v)*DX + sum(\ [dt * float(a[j,i]) * safe_action(safe_adjoint(derivative(\ forward_forms[j], y_)), kbar[j]) for j in range(i, size)]) if explicit: stage_forms_adm = [stage_form_adm] jacobian_indices.append(-1) else: # Create a F=0 form and differentiate it stage_form_adm -= ufl.inner(kbar[i], v)*DX stage_forms_adm = [stage_form_adm, derivative(stage_form_adm, kbari)] jacobian_indices.append(1) ufl_stage_forms.append(stage_forms_adm) dolfin_stage_forms.append([Form(form) for form in stage_forms_adm]) stage_solutions.append(kbari) # Only one last stage if len(b.shape) == 1: last_stage = Form(ufl.inner(adj, v)*DX + sum(\ [safe_action(safe_adjoint(derivative(forward_forms[i], y_)), kbar[i]) \ for i in range(size)])) else: raise Exception("Not sure what to do here") human_form = "unimplemented" return ufl_stage_forms, dolfin_stage_forms, jacobian_indices, last_stage,\ stage_solutions, dt, human_form, adj
def _I(self, v, s, time): """ Original gotran transmembrane current dV/dt """ time = time if time else Constant(0.0) # Assign states V_m = v assert (len(s) == 38) h, j, m, x_kr, x_ks, x_to_f, x_to_s, y_to_f, y_to_s, d, f, f_Ca_Bj,\ f_Ca_Bsl, Ry_Ri, Ry_Ro, Ry_Rr, Na_Bj, Na_Bsl, CaM, Myo_c, Myo_m,\ SRB, Tn_CHc, Tn_CHm, Tn_CL, SLH_j, SLH_sl, SLL_j, SLL_sl, Ca_sr,\ Csqn_b, Na_i, Na_j, Na_sl, K_i, Ca_i, Ca_j, Ca_sl = s # Assign parameters Fjunc = self._parameters["Fjunc"] Fjunc_CaL = self._parameters["Fjunc_CaL"] GNa = self._parameters["GNa"] GNaB = self._parameters["GNaB"] IbarNaK = self._parameters["IbarNaK"] KmKo = self._parameters["KmKo"] KmNaip = self._parameters["KmNaip"] gkp = self._parameters["gkp"] pNaK = self._parameters["pNaK"] epi = self._parameters["epi"] GClB = self._parameters["GClB"] GClCa = self._parameters["GClCa"] KdClCa = self._parameters["KdClCa"] Q10CaL = self._parameters["Q10CaL"] pCa = self._parameters["pCa"] pK = self._parameters["pK"] pNa = self._parameters["pNa"] IbarNCX = self._parameters["IbarNCX"] Kdact = self._parameters["Kdact"] KmCai = self._parameters["KmCai"] KmCao = self._parameters["KmCao"] KmNai = self._parameters["KmNai"] KmNao = self._parameters["KmNao"] Q10NCX = self._parameters["Q10NCX"] ksat = self._parameters["ksat"] nu = self._parameters["nu"] IbarSLCaP = self._parameters["IbarSLCaP"] KmPCa = self._parameters["KmPCa"] Q10SLCaP = self._parameters["Q10SLCaP"] GCaB = self._parameters["GCaB"] Nao = self._parameters["Nao"] Ko = self._parameters["Ko"] Cao = self._parameters["Cao"] Cli = self._parameters["Cli"] Clo = self._parameters["Clo"] Frdy = self._parameters["Frdy"] R = self._parameters["R"] Temp = self._parameters["Temp"] g_K1_factor = self._parameters["g_K1_factor"] g_CaL_factor = self._parameters["g_CaL_factor"] g_Kr_factor = self._parameters["g_Kr_factor"] g_Ks_factor = self._parameters["g_Ks_factor"] g_to_factor = self._parameters["g_to_factor"] SR_Ca_release_ks_factor = self._parameters["SR_Ca_release_ks_factor"] # Init return args current = [ufl.zero()] * 1 # Expressions for the Geometry component Fsl = 1 - Fjunc Fsl_CaL = 1 - Fjunc_CaL # Expressions for the Reversal potentials component FoRT = Frdy / (R * Temp) ena_junc = ufl.ln(Nao / Na_j) / FoRT ena_sl = ufl.ln(Nao / Na_sl) / FoRT ek = ufl.ln(Ko / K_i) / FoRT eca_junc = ufl.ln(Cao / Ca_j) / (2 * FoRT) eca_sl = ufl.ln(Cao / Ca_sl) / (2 * FoRT) ecl = ufl.ln(Cli / Clo) / FoRT Qpow = -31 + Temp / 10 # Expressions for the I_Na component I_Na_junc = Fjunc * GNa * (m * m * m) * (-ena_junc + V_m) * h * j I_Na_sl = GNa * (m * m * m) * (-ena_sl + V_m) * Fsl * h * j # Expressions for the I_NaBK component I_nabk_junc = Fjunc * GNaB * (-ena_junc + V_m) I_nabk_sl = GNaB * (-ena_sl + V_m) * Fsl # Expressions for the I_NaK component sigma = -1 / 7 + ufl.exp(0.0148588410104 * Nao) / 7 fnak = 1.0/(1 + 0.1245*ufl.exp(-0.1*FoRT*V_m) +\ 0.0365*ufl.exp(-FoRT*V_m)*sigma) I_nak_junc = Fjunc*IbarNaK*Ko*fnak/((1 + ufl.elem_pow(KmNaip,\ 4)/ufl.elem_pow(Na_j, 4))*(KmKo + Ko)) I_nak_sl = IbarNaK*Ko*Fsl*fnak/((1 + ufl.elem_pow(KmNaip,\ 4)/ufl.elem_pow(Na_sl, 4))*(KmKo + Ko)) I_nak = I_nak_junc + I_nak_sl # Expressions for the I_Kr component gkr = g_Kr_factor * 0.0150616019019 * ufl.sqrt(Ko) rkr = 1.0 / (1 + ufl.exp(37 / 12 + V_m / 24)) I_kr = (-ek + V_m) * gkr * rkr * x_kr # Expressions for the I_Kp component kp_kp = 1.0 / (1 + 1786.47556538 * ufl.exp(-0.167224080268 * V_m)) I_kp_junc = Fjunc * gkp * (-ek + V_m) * kp_kp I_kp_sl = gkp * (-ek + V_m) * Fsl * kp_kp I_kp = I_kp_sl + I_kp_junc # Expressions for the I_Ks component eks = ufl.ln((Nao * pNaK + Ko) / (pNaK * Na_i + K_i)) / FoRT gks_junc = g_Ks_factor * 0.0035 gks_sl = g_Ks_factor * 0.0035 I_ks_junc = Fjunc * gks_junc * (x_ks * x_ks) * (-eks + V_m) I_ks_sl = gks_sl * (x_ks * x_ks) * (-eks + V_m) * Fsl I_ks = I_ks_sl + I_ks_junc # Expressions for the I_to component GtoSlow = ufl.conditional(ufl.eq(epi, 1), 0.0156, 0.037596) GtoFast = ufl.conditional(ufl.eq(epi, 1), 0.1144, 0.001404) I_tos = (-ek + V_m) * GtoSlow * x_to_s * y_to_s I_tof = (-ek + V_m) * g_to_factor * GtoFast * x_to_f * y_to_f I_to = I_tos + I_tof # Expressions for the I_Ki component aki = 1.02 / (1 + 7.35454251046e-07 * ufl.exp(0.2385 * V_m - 0.2385 * ek)) bki = (0.762624006506*ufl.exp(0.08032*V_m - 0.08032*ek) +\ 1.15340563519e-16*ufl.exp(0.06175*V_m - 0.06175*ek))/(1 +\ 0.0867722941577*ufl.exp(-0.5143*V_m + 0.5143*ek)) kiss = aki / (aki + bki) I_ki = g_K1_factor * 0.150616019019 * ufl.sqrt(Ko) * (-ek + V_m) * kiss # Expressions for the I_ClCa component I_ClCa_junc = Fjunc * GClCa * (-ecl + V_m) / (1 + KdClCa / Ca_j) I_ClCa_sl = GClCa * (-ecl + V_m) * Fsl / (1 + KdClCa / Ca_sl) I_ClCa = I_ClCa_sl + I_ClCa_junc I_Clbk = GClB * (-ecl + V_m) # Expressions for the I_Ca component fcaCaMSL = 0 fcaCaj = 0 ibarca_j = 4*Frdy*pCa*(-0.341*Cao +\ 0.341*Ca_j*ufl.exp(2*FoRT*V_m))*FoRT*V_m/(-1 +\ ufl.exp(2*FoRT*V_m)) ibarca_sl = 4*Frdy*pCa*(-0.341*Cao +\ 0.341*Ca_sl*ufl.exp(2*FoRT*V_m))*FoRT*V_m/(-1 +\ ufl.exp(2*FoRT*V_m)) ibark = Frdy*pK*(-0.75*Ko + 0.75*K_i*ufl.exp(FoRT*V_m))*FoRT*V_m/(-1 +\ ufl.exp(FoRT*V_m)) ibarna_j = Frdy*pNa*(-0.75*Nao +\ 0.75*Na_j*ufl.exp(FoRT*V_m))*FoRT*V_m/(-1 + ufl.exp(FoRT*V_m)) ibarna_sl = Frdy*pNa*(0.75*Na_sl*ufl.exp(FoRT*V_m) -\ 0.75*Nao)*FoRT*V_m/(-1 + ufl.exp(FoRT*V_m)) I_Ca_junc = g_CaL_factor*0.45*Fjunc_CaL*ufl.elem_pow(Q10CaL, Qpow)*(1 - f_Ca_Bj +\ fcaCaj)*d*f*ibarca_j I_Ca_sl = g_CaL_factor*0.45*ufl.elem_pow(Q10CaL, Qpow)*(1 - f_Ca_Bsl +\ fcaCaMSL)*Fsl_CaL*d*f*ibarca_sl I_CaK = g_CaL_factor*0.45*ufl.elem_pow(Q10CaL, Qpow)*(Fjunc_CaL*(1 - f_Ca_Bj +\ fcaCaj) + (1 - f_Ca_Bsl + fcaCaMSL)*Fsl_CaL)*d*f*ibark I_CaNa_junc = g_CaL_factor*0.45*Fjunc_CaL*ufl.elem_pow(Q10CaL, Qpow)*(1 - f_Ca_Bj\ + fcaCaj)*d*f*ibarna_j I_CaNa_sl = g_CaL_factor*0.45*ufl.elem_pow(Q10CaL, Qpow)*(1 - f_Ca_Bsl +\ fcaCaMSL)*Fsl_CaL*d*f*ibarna_sl # Expressions for the I_NCX component Ka_junc = 1.0 / (1 + (Kdact * Kdact) / (Ca_j * Ca_j)) Ka_sl = 1.0 / (1 + (Kdact * Kdact) / (Ca_sl * Ca_sl)) s1_junc = Cao * (Na_j * Na_j * Na_j) * ufl.exp(nu * FoRT * V_m) s1_sl = Cao * (Na_sl * Na_sl * Na_sl) * ufl.exp(nu * FoRT * V_m) s2_junc = (Nao * Nao * Nao) * Ca_j * ufl.exp((-1 + nu) * FoRT * V_m) s3_junc = KmCao*(Na_j*Na_j*Na_j) + (Nao*Nao*Nao)*Ca_j +\ Cao*(Na_j*Na_j*Na_j) + KmCai*(Nao*Nao*Nao)*(1 +\ (Na_j*Na_j*Na_j)/(KmNai*KmNai*KmNai)) + (KmNao*KmNao*KmNao)*(1 +\ Ca_j/KmCai)*Ca_j s2_sl = (Nao * Nao * Nao) * Ca_sl * ufl.exp((-1 + nu) * FoRT * V_m) s3_sl = KmCai*(Nao*Nao*Nao)*(1 +\ (Na_sl*Na_sl*Na_sl)/(KmNai*KmNai*KmNai)) + (Nao*Nao*Nao)*Ca_sl +\ (KmNao*KmNao*KmNao)*(1 + Ca_sl/KmCai)*Ca_sl +\ Cao*(Na_sl*Na_sl*Na_sl) + KmCao*(Na_sl*Na_sl*Na_sl) I_ncx_junc = Fjunc*IbarNCX*ufl.elem_pow(Q10NCX, Qpow)*(-s2_junc +\ s1_junc)*Ka_junc/((1 + ksat*ufl.exp((-1 + nu)*FoRT*V_m))*s3_junc) I_ncx_sl = IbarNCX*ufl.elem_pow(Q10NCX, Qpow)*(-s2_sl +\ s1_sl)*Fsl*Ka_sl/((1 + ksat*ufl.exp((-1 + nu)*FoRT*V_m))*s3_sl) # Expressions for the I_PCa component I_pca_junc = Fjunc*IbarSLCaP*ufl.elem_pow(Q10SLCaP,\ Qpow)*ufl.elem_pow(Ca_j, 1.6)/(ufl.elem_pow(Ca_j, 1.6) +\ ufl.elem_pow(KmPCa, 1.6)) I_pca_sl = IbarSLCaP*ufl.elem_pow(Q10SLCaP, Qpow)*ufl.elem_pow(Ca_sl,\ 1.6)*Fsl/(ufl.elem_pow(Ca_sl, 1.6) + ufl.elem_pow(KmPCa, 1.6)) # Expressions for the I_CaBK component I_cabk_junc = Fjunc * GCaB * (-eca_junc + V_m) I_cabk_sl = GCaB * (-eca_sl + V_m) * Fsl # Expressions for the Na Concentrations component I_Na_tot_junc = 3*I_nak_junc + 3*I_ncx_junc + I_CaNa_junc + I_Na_junc\ + I_nabk_junc I_Na_tot_sl = I_Na_sl + I_nabk_sl + 3 * I_nak_sl + I_CaNa_sl + 3 * I_ncx_sl # Expressions for the K Concentration component I_K_tot = -2 * I_nak + I_ks + I_CaK + I_kr + I_kp + I_ki + I_to # Expressions for the Ca Concentrations component I_Ca_tot_junc = I_pca_junc + I_cabk_junc + I_Ca_junc - 2 * I_ncx_junc I_Ca_tot_sl = -2 * I_ncx_sl + I_pca_sl + I_cabk_sl + I_Ca_sl # Expressions for the Membrane potential component i_Stim = 0 I_Na_tot = I_Na_tot_junc + I_Na_tot_sl I_Cl_tot = I_Clbk + I_ClCa I_Ca_tot = I_Ca_tot_junc + I_Ca_tot_sl I_tot = I_Na_tot + I_K_tot + I_Cl_tot + I_Ca_tot current[0] = -I_tot - i_Stim # Return results return current[0]