Exemplo n.º 1
0
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
Exemplo n.º 2
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) == 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
Exemplo n.º 4
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)
        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)
Exemplo n.º 5
0
 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")
Exemplo n.º 6
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) == 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)
Exemplo n.º 7
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) == 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]
Exemplo n.º 8
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]
Exemplo n.º 9
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)
Exemplo n.º 10
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)
        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]
Exemplo n.º 11
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]
Exemplo n.º 12
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)
Exemplo n.º 13
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)
        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)
Exemplo n.º 14
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

        # 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]
Exemplo n.º 15
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]
Exemplo n.º 16
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)
Exemplo n.º 17
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) == 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]
Exemplo n.º 18
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)
Exemplo n.º 19
0
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)]))
Exemplo n.º 20
0
    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)
Exemplo n.º 21
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, 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
Exemplo n.º 22
0
  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()
Exemplo n.º 23
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) == 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]
Exemplo n.º 24
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
Exemplo n.º 25
0
  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")
Exemplo n.º 26
0
    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)
Exemplo n.º 27
0
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)]))
Exemplo n.º 28
0
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
Exemplo n.º 29
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_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)
Exemplo n.º 30
0
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
Exemplo n.º 31
0
    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)
Exemplo n.º 32
0
  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
Exemplo n.º 33
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) == 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)
Exemplo n.º 34
0
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
Exemplo n.º 35
0
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
Exemplo n.º 36
0
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
Exemplo n.º 37
0
    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]