From 0966d8e6b4b7f9bd7b39ffdeae91b46ff2cb319a Mon Sep 17 00:00:00 2001 From: Henrik Finsberg Date: Sun, 19 Jan 2025 09:38:22 +0100 Subject: [PATCH 1/5] Restructure 0D simulations - add numerical experiment folder and abstract out common code for 0D simulations --- .gitignore | 13 + numerical_experiments/0D/split_cai.py | 30 + numerical_experiments/0D/split_cai_catrpn.py | 30 + numerical_experiments/0D/split_zeta.py | 30 + numerical_experiments/0D/utils.py | 492 ++++++++++++ .../odefiles/ToRORd_dynCl_endo_caisplit.ode | 715 +++++++++++++++++ .../ToRORd_dynCl_endo_catrpnsplit.ode | 719 +++++++++++++++++ .../odefiles/ToRORd_dynCl_endo_zetasplit.ode | 722 ++++++++++++++++++ 8 files changed, 2751 insertions(+) create mode 100644 numerical_experiments/0D/split_cai.py create mode 100644 numerical_experiments/0D/split_cai_catrpn.py create mode 100644 numerical_experiments/0D/split_zeta.py create mode 100644 numerical_experiments/0D/utils.py create mode 100644 numerical_experiments/odefiles/ToRORd_dynCl_endo_caisplit.ode create mode 100644 numerical_experiments/odefiles/ToRORd_dynCl_endo_catrpnsplit.ode create mode 100644 numerical_experiments/odefiles/ToRORd_dynCl_endo_zetasplit.ode diff --git a/.gitignore b/.gitignore index 39a4721..d976608 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,16 @@ +numerical_experiments/0D/ToRORd_dynCl_endo_caisplit.py +numerical_experiments/0D/ToRORd_dynCl_endo_caisplit_ep.py +numerical_experiments/0D/ToRORd_dynCl_endo_caisplit_mechanics.py +numerical_experiments/0D/ToRORd_dynCl_endo_catrpnsplit.py +numerical_experiments/0D/ToRORd_dynCl_endo_catrpnsplit_ep.py +numerical_experiments/0D/ToRORd_dynCl_endo_catrpnsplit_mechanics.py +numerical_experiments/0D/ToRORd_dynCl_endo_zetasplit.py +numerical_experiments/0D/ToRORd_dynCl_endo_zetasplit_ep.py +numerical_experiments/0D/ToRORd_dynCl_endo_zetasplit_mechanics.py +numerical_experiments/0D/output-cai_catrpn/ +numerical_experiments/0D/output-split-cai/ +numerical_experiments/0D/output-split-zeta/ + *.vtu *.pvd *.h5 diff --git a/numerical_experiments/0D/split_cai.py b/numerical_experiments/0D/split_cai.py new file mode 100644 index 0000000..27454d1 --- /dev/null +++ b/numerical_experiments/0D/split_cai.py @@ -0,0 +1,30 @@ +"""Same as 0D but with varying lambda""" + +from pathlib import Path + + +import utils + +here = Path(__file__).absolute().parent +odefile = here / ".." / "odefiles" / "ToRORd_dynCl_endo_caisplit.ode" +track_names = ("v", "CaTrpn", "TmB", "XU", "J_TRPN", "lmbda", "dLambda", "Zetas", "XS", "cai", "Ta") +Ns = [1, 2, 10, 50] + + +# Mech step performed every Nth ep step +# Do a set of simulations with various N: +# Ns = np.array([1, 2, 4, 6, 8, 10, 20, 50, 100, 200]) + + +outdir = here / "output-split-cai" + +utils.run_0D( + odefile=odefile, + outdir=outdir, + track_names=track_names, + Ns=Ns, + save_traces=True, + run_full_model=True, + dt=0.05, + simdur=10.0, +) diff --git a/numerical_experiments/0D/split_cai_catrpn.py b/numerical_experiments/0D/split_cai_catrpn.py new file mode 100644 index 0000000..9195b27 --- /dev/null +++ b/numerical_experiments/0D/split_cai_catrpn.py @@ -0,0 +1,30 @@ +"""Same as 0D but with varying lambda""" + +from pathlib import Path + + +import utils + +here = Path(__file__).absolute().parent +odefile = here / ".." / "odefiles" / "ToRORd_dynCl_endo_catrpnsplit.ode" +track_names = ("v", "CaTrpn", "TmB", "XU", "J_TRPN", "lmbda", "dLambda", "Zetas", "XS", "cai", "Ta") +Ns = [1, 2, 10, 50] + + +# Mech step performed every Nth ep step +# Do a set of simulations with various N: +# Ns = np.array([1, 2, 4, 6, 8, 10, 20, 50, 100, 200]) + + +outdir = here / "output-cai_catrpn" + +utils.run_0D( + odefile=odefile, + outdir=outdir, + track_names=track_names, + Ns=Ns, + save_traces=True, + run_full_model=True, + dt=0.05, + simdur=10.0, +) diff --git a/numerical_experiments/0D/split_zeta.py b/numerical_experiments/0D/split_zeta.py new file mode 100644 index 0000000..c9e9337 --- /dev/null +++ b/numerical_experiments/0D/split_zeta.py @@ -0,0 +1,30 @@ +"""Same as 0D but with varying lambda""" + +from pathlib import Path + + +import utils + +here = Path(__file__).absolute().parent +odefile = here / ".." / "odefiles" / "ToRORd_dynCl_endo_zetasplit.ode" +track_names = ("v", "CaTrpn", "TmB", "XU", "J_TRPN", "lmbda", "dLambda", "Zetas", "XS", "cai", "Ta") +Ns = [1, 2, 10, 50] + + +# Mech step performed every Nth ep step +# Do a set of simulations with various N: +# Ns = np.array([1, 2, 4, 6, 8, 10, 20, 50, 100, 200]) + + +outdir = here / "output-split-zeta" + +utils.run_0D( + odefile=odefile, + outdir=outdir, + track_names=track_names, + Ns=Ns, + save_traces=True, + run_full_model=True, + dt=0.05, + simdur=10.0, +) diff --git a/numerical_experiments/0D/utils.py b/numerical_experiments/0D/utils.py new file mode 100644 index 0000000..cba769f --- /dev/null +++ b/numerical_experiments/0D/utils.py @@ -0,0 +1,492 @@ +from pathlib import Path +import time +import json + +from typing import NamedTuple, Literal, Sequence + + +import numpy as np +import matplotlib.pyplot as plt +import gotranx + + +class TrackedValue(NamedTuple): + ep_value: np.ndarray + mechanics_value: np.ndarray + full_value: np.ndarray + ep_type: Literal["state", "monitor", "parameter", "none"] + mechanics_type: Literal["state", "monitor", "parameter", "none"] + full_type: Literal["state", "monitor", "parameter", "none"] = "none" + full_index: int = -1 + ep_index: int = -1 + mechanics_index: int = -1 + + +def update_tracked_values( + index: int, + tracked_values: dict[str, TrackedValue], + model: Literal["mechanics", "ep", "full"], + y: np.ndarray, + monitor: np.ndarray, + p: np.ndarray, +) -> None: + for name, v in tracked_values.items(): + if model == "mechanics": + if v.mechanics_type == "state": + v.mechanics_value[index] = y[v.mechanics_index] + elif v.mechanics_type == "monitor": + v.mechanics_value[index] = monitor[v.mechanics_index] + elif v.mechanics_type == "parameter": + v.mechanics_value[index] = p[v.mechanics_index] + elif model == "ep": + if v.ep_type == "state": + v.ep_value[index] = y[v.ep_index] + elif v.ep_type == "monitor": + v.ep_value[index] = monitor[v.ep_index] + elif v.ep_type == "parameter": + v.ep_value[index] = p[v.ep_index] + elif model == "full": + if v.full_type == "state": + v.full_value[index] = y[v.full_index] + elif v.full_type == "monitor": + v.full_value[index] = monitor[v.full_index] + elif v.full_type == "parameter": + v.full_value[index] = p[v.full_index] + + +def setup_track_values( + mechanics_model, ep_model, full_model, track_names, N +) -> dict[str, TrackedValue]: + track_values = {} + for name in track_names: + if name in mechanics_model["state"]: + mechanics_index = mechanics_model["state_index"](name) + mechanics_type = "state" + elif name in mechanics_model["monitor"]: + mechanics_index = mechanics_model["monitor_index"](name) + mechanics_type = "monitor" + elif name in mechanics_model["parameter"]: + mechanics_index = mechanics_model["parameter_index"](name) + mechanics_type = "parameter" + else: + mechanics_index = -1 + mechanics_type = "none" + + if name in ep_model["state"]: + ep_index = ep_model["state_index"](name) + ep_type = "state" + elif name in ep_model["monitor"]: + ep_index = ep_model["monitor_index"](name) + ep_type = "monitor" + elif name in ep_model["parameter"]: + ep_index = ep_model["parameter_index"](name) + ep_type = "parameter" + else: + ep_index = -1 + ep_type = "none" + + if name in full_model["state"]: + full_index = full_model["state_index"](name) + full_type = "state" + elif name in full_model["monitor"]: + full_index = full_model["monitor_index"](name) + full_type = "monitor" + elif name in full_model["parameter"]: + full_index = full_model["parameter_index"](name) + full_type = "parameter" + else: + full_index = -1 + full_type = "none" + + track_values[name] = TrackedValue( + ep_value=np.zeros(N), + mechanics_value=np.zeros(N), + full_value=np.zeros(N), + ep_type=ep_type, + mechanics_type=mechanics_type, + full_type=full_type, + full_index=full_index, + ep_index=ep_index, + mechanics_index=mechanics_index, + ) + return track_values + + +class MissingValue(NamedTuple): + name: str # Name of the missing value + model: Literal["mechanics", "ep"] # Which model is missing the value + index: int # Index of the missing value in the other model + value: float # Default value of the missing value + type: Literal["state", "monitor"] # Type of the missing value + + +class MissingValueIndices(NamedTuple): + ep: list[MissingValue] + mechanics: list[MissingValue] + + @property + def mechanics_values(self): + return np.array([v.value for v in self.mechanics]) + + @property + def ep_values(self): + return np.array([v.value for v in self.ep]) + + +def setup_missing_values(mechanics_model, ep_model) -> MissingValueIndices: + missing_values_mech = [] + for k in mechanics_model.get("missing", {}): + if k in ep_model["state"]: + index = ep_model["state_index"](k) + type = "state" + value = ep_model["init_state_values"]()[index] + elif k in ep_model["monitor"]: + index = ep_model["monitor_index"](k) + type = "monitor" + value = 0.0 # FIXME + else: + raise ValueError(f"Missing variable {k} not found in state or monitor") + + missing_values_mech.append( + MissingValue(name=k, model="mechanics", index=index, value=value, type=type) + ) + + missing_values_ep = [] + for k in ep_model.get("missing", {}): + if k in mechanics_model["state"]: + index = mechanics_model["state_index"](k) + type = "state" + value = mechanics_model["init_state_values"]()[index] + elif k in mechanics_model["monitor"]: + index = mechanics_model["monitor_index"](k) + type = "monitor" + value = 0.0 # FIXME + else: + raise ValueError(f"Missing variable {k} not found in state or monitor") + missing_values_ep.append( + MissingValue(name=k, model="ep", index=index, value=value, type=type) + ) + + return MissingValueIndices(ep=missing_values_ep, mechanics=missing_values_mech) + + +def twitch(t, tstart=0.05, ca_ampl=-0.2): + tau1 = 0.05 * 1000 + tau2 = 0.110 * 1000 + + ca_diast = 0.0 + + beta = (tau1 / tau2) ** (-1 / (tau1 / tau2 - 1)) - (tau1 / tau2) ** (-1 / (1 - tau2 / tau1)) + ca = np.zeros_like(t) + + ca[t <= tstart] = ca_diast + + ca[t > tstart] = (ca_ampl - ca_diast) / beta * ( + np.exp(-(t[t > tstart] - tstart) / tau1) - np.exp(-(t[t > tstart] - tstart) / tau2) + ) + ca_diast + return ca + 1.0 + + +def plot_twitch(t, filename="twitch.png"): + fig, ax = plt.subplots() + ax.plot(t, twitch(t)) + ax.set_xlabel("Time (ms)") + ax.set_ylabel("Lambda") + fig.savefig(filename) + + +def run_0D( + odefile: Path, + outdir: Path, + track_names: Sequence[str], + Ns: Sequence[int], + save_traces: bool = False, + run_full_model: bool = False, + dt: float = 0.05, + simdur: float = 10.0, +): + outdir.mkdir(exist_ok=True) + + # Load the model + ode = gotranx.load_ode(odefile) + + mechanics_comp = ode.get_component("mechanics") + mechanics_ode = mechanics_comp.to_ode() + + ep_ode = ode - mechanics_comp + ep_file = Path(f"{odefile.stem}_ep.py") + mechanics_file = Path(f"{odefile.stem}_mechanics.py") + full_file = Path(f"{odefile.stem}.py") + + # Generate model code from .ode file + rebuild = False + if not ep_file.is_file() or rebuild: + # Generate code for full model. + code = gotranx.cli.gotran2py.get_code( + ode, + scheme=[gotranx.schemes.Scheme.forward_generalized_rush_larsen], + ) + + # Generate code for the electrophysiology model + code_ep = gotranx.cli.gotran2py.get_code( + ep_ode, + scheme=[gotranx.schemes.Scheme.forward_generalized_rush_larsen], + missing_values=mechanics_ode.missing_variables, + ) + + # Generate code for the mechanics model + code_mechanics = gotranx.cli.gotran2py.get_code( + mechanics_ode, + scheme=[gotranx.schemes.Scheme.forward_generalized_rush_larsen], + missing_values=ep_ode.missing_variables, + ) + + # Create ep, mechanics and full model to files: + ep_file.write_text(code_ep) + mechanics_file.write_text(code_mechanics) + full_file.write_text(code) + + # Import ep, mechanics and full model + + model = __import__(full_file.stem).__dict__ + ep_model = __import__(ep_file.stem).__dict__ + mechanics_model = __import__(mechanics_file.stem).__dict__ + + # Set time step + dt = 0.05 + simdur = 10 # Simulation duration + t = np.arange(0, simdur, dt) + + # Forwared generalized rush larsen scheme for the electrophysiology model + fgr_ep = ep_model["forward_generalized_rush_larsen"] + # Monitor function for the electrophysiology model + mon_ep = ep_model["monitor_values"] + # Missing values function for the electrophysiology model + mv_ep = ep_model["missing_values"] + + # Forwared generalized rush larsen scheme for the mechanics model + fgr_mechanics = mechanics_model["forward_generalized_rush_larsen"] + # Monitor function for the mechanics model + mon_mechanics = mechanics_model["monitor_values"] + # Missing values function for the mechanics model + mv_mechanics = mechanics_model["missing_values"] + + # Setup the track values + track_values = setup_track_values( + mechanics_model=mechanics_model, + ep_model=ep_model, + full_model=model, + track_names=track_names, + N=len(t), + ) + missing_value_indices = setup_missing_values(mechanics_model=mechanics_model, ep_model=ep_model) + + # Index of the stretch and stretch rate in the mechanics model + lmbda_index_mechanics = mechanics_model["parameter_index"]("lmbda") + dLambda_index_mechanics = mechanics_model["parameter_index"]("dLambda") + + # Forwared generalized rush larsen scheme for the full model + fgr = model["forward_generalized_rush_larsen"] + # Monitor function for the full model + mon = model["monitor_values"] + # Index of the stretch and stretch rate in the full model + lmbda_index = model["parameter_index"]("lmbda") + dLambda_index = model["parameter_index"]("dLambda") + + for N in Ns: + timing_init = time.perf_counter() + # Get initial values from the EP model + y_ep = ep_model["init_state_values"]() + p_ep = ep_model["init_parameter_values"]() + ep_missing_values = np.zeros(len(ep_ode.missing_variables)) + if len(ep_missing_values) > 0: + ep_missing_args = (ep_missing_values,) + else: + ep_missing_args = () + + # Get initial values from the mechanics model + y_mechanics = mechanics_model["init_state_values"]() + p_mechanics = mechanics_model["init_parameter_values"]() + + mechanics_missing_values = missing_value_indices.mechanics_values + + # Get the initial values from the full model + y = model["init_state_values"]() + p = model["init_parameter_values"]() # Used in lambda update + + # Get the default values of the missing values + # A little bit chicken and egg problem here, but in this specific case we know that + # the mechanics_missing_values is only the calcium concentration, which is a state variable + # and this doesn't require any additional information to be calculated. + mechanics_missing_values[:] = mv_ep(0, y_ep, p_ep, *ep_missing_args) + if ep_missing_args: + ep_missing_values[:] = mv_mechanics( + 0, y_mechanics, p_mechanics, mechanics_missing_values + ) + + # We will store the previous missing values to check for convergence and use for updating + prev_mechanics_missing_values = np.zeros_like(mechanics_missing_values) + prev_mechanics_missing_values[:] = mechanics_missing_values + + inds = [] + count = 1 + prev_lmbda = p[lmbda_index] + + timings_solveloop = [] + timings_ep_steps = [] + timings_mech_steps = [] + for i, ti in enumerate(t): + timing_loopstart = time.perf_counter() + # Set initial lambda + if ti == 0: + lmbda_ti = twitch(ti) + p[lmbda_index] = lmbda_ti + p_mechanics[lmbda_index_mechanics] = lmbda_ti + dLambda = 0 + p[dLambda_index] = dLambda + p_mechanics[dLambda_index_mechanics] = dLambda + + if run_full_model: + # Forward step for the full model + y[:] = fgr(y, ti, dt, p) + monitor = mon(ti, y, p) + update_tracked_values( + index=i, monitor=monitor, y=y, p=p, tracked_values=track_values, model="full" + ) + + timing_ep_start = time.perf_counter() + # Forward step for the EP model + y_ep[:] = fgr_ep(y_ep, ti, dt, p_ep, *ep_missing_args) + monitor_ep = mon_ep(ti, y_ep, p_ep, *ep_missing_args) + + update_tracked_values( + index=i, monitor=monitor_ep, y=y_ep, p=p_ep, tracked_values=track_values, model="ep" + ) + + timing_ep_end = time.perf_counter() + timings_ep_steps.append(timing_ep_end - timing_ep_start) + + # Update missing values for the mechanics model + # this function just outputs the value of the missing values + # straight from y_ep (does not calculate anything) + mechanics_missing_values[:] = mv_ep(t, y_ep, p_ep, *ep_missing_args) + + if i % N != 0: + count += 1 + # Lambda still needs to be updated: + lmbda_ti = twitch(ti + dt) + p[lmbda_index] = lmbda_ti + p_mechanics[lmbda_index_mechanics] = lmbda_ti + dLambda = (lmbda_ti - prev_lmbda) / dt + p[dLambda_index] = dLambda + p_mechanics[dLambda_index_mechanics] = dLambda + prev_lmbda = lmbda_ti + timings_solveloop.append(time.perf_counter() - timing_loopstart) + continue + + # Store the index of the time step where we performed a step + inds.append(i) + + timing_mech_start = time.perf_counter() + + # For consistency with other models: + y_mechanics[:] = fgr_mechanics( + y_mechanics, ti, count * dt, p_mechanics, prev_mechanics_missing_values + ) + + count = 1 + monitor_mechanics = mon_mechanics( + ti, + y_mechanics, + p_mechanics, + mechanics_missing_values, + ) + update_tracked_values( + index=i, + monitor=monitor_mechanics, + y=y_mechanics, + p=p_mechanics, + tracked_values=track_values, + model="mechanics", + ) + + timing_mech_end = time.perf_counter() + timings_mech_steps.append(timing_mech_end - timing_mech_start) + + # Update lambda + # Should be done after all calculations except ep_missing, + # which is used for next ep step + lmbda_ti = twitch(ti + dt) + p[lmbda_index] = lmbda_ti + p_mechanics[lmbda_index_mechanics] = lmbda_ti + dLambda = (lmbda_ti - prev_lmbda) / dt + p[dLambda_index] = dLambda + p_mechanics[dLambda_index_mechanics] = dLambda + prev_lmbda = lmbda_ti + + # Update missing values for the EP model # J_TRPN for cai split + if ep_missing_args: + ep_missing_values[:] = mv_mechanics( + t, y_mechanics, p_mechanics, mechanics_missing_values + ) + + prev_mechanics_missing_values[:] = mechanics_missing_values + + timings_solveloop.append(time.perf_counter() - timing_loopstart) + + # Plot the results + perc = 100 * len(inds) / len(t) + print(f"Solved on {perc}% of the time steps") + inds = np.array(inds) + timing_total = time.perf_counter() - timing_init + + (outdir / f"split_cai_N{N}.json").write_text( + json.dumps( + { + "init_time": timing_init, + "loop_times": timings_solveloop, + "ep_step_times": timings_ep_steps, + "mech_step_times": timings_mech_steps, + "total_time": timing_total, + } + ) + ) + + if save_traces: + mech_header = np.array( + [k for k, v in track_values.items() if v.mechanics_type != "none"] + ) + mech_values = np.array( + [v.mechanics_value for v in track_values.values() if v.mechanics_type != "none"] + ) + np.savetxt(outdir / f"mech_N{N}.txt", mech_values.T, header=" ".join(mech_header)) + + ep_header = np.array([k for k, v in track_values.items() if v.ep_type != "none"]) + ep_values = np.array([v.ep_value for v in track_values.values() if v.ep_type != "none"]) + np.savetxt(outdir / f"ep_N{N}.txt", ep_values.T, header=" ".join(ep_header)) + + if run_full_model: + full_header = np.array( + [k for k, v in track_values.items() if v.full_type != "none"] + ) + full_values = np.array( + [v.full_value for v in track_values.values() if v.full_type != "none"] + ) + np.savetxt(outdir / f"full_N{N}.txt", full_values.T, header=" ".join(full_header)) + + import matplotlib.pyplot as plt + + for name, values in track_values.items(): + fig, ax = plt.subplots() + if values.ep_type != "none": + ax.plot(t, values.ep_value, label="EP") + if values.mechanics_type != "none": + ax.plot(t, values.mechanics_value, label="Mechanics") + + if run_full_model and values.full_type != "none": + ax.plot(t, values.full_value, label="Full") + ax.set_title(name) + ax.legend() + ax.grid() + fig.savefig(outdir / f"{name}_N{N}.png") + plt.close(fig) diff --git a/numerical_experiments/odefiles/ToRORd_dynCl_endo_caisplit.ode b/numerical_experiments/odefiles/ToRORd_dynCl_endo_caisplit.ode new file mode 100644 index 0000000..bd24bc1 --- /dev/null +++ b/numerical_experiments/odefiles/ToRORd_dynCl_endo_caisplit.ode @@ -0,0 +1,715 @@ +states("IKr", +C1=ScalarParam(0.9982511, unit="1", description=""), +C2=ScalarParam( 7.93602000000000023e-4, unit="1", description=""), +C3=ScalarParam( 6.53214300000000045e-4, unit="1", description=""), +I_=ScalarParam( 9.80408300000000003e-6, unit="1", description=""), +O_=ScalarParam( 2.92244900000000025e-4, unit="1", description="") +) + +states("CaMK", +CaMKt=ScalarParam( 1.09502599999999999e-2, unit="mM", description="") +) + +states("ryr", +Jrel_np=ScalarParam( 1.80824799999999996e-22, unit="mM/ms", description=""), +Jrel_p=ScalarParam( 4.35860800000000030e-21, unit="mM/ms", description="") +) + +states("Ito", +a=ScalarParam( 8.89925900000000051e-4, unit="1", description=""), +ap=ScalarParam( 4.53416500000000005e-4, unit="1", description=""), +iF=ScalarParam(0.9996716, unit="1", description=""), +iFp=ScalarParam(0.9996716, unit="1", description=""), +iS=ScalarParam(0.5988908, unit="1", description=""), +iSp=ScalarParam(0.6620692, unit="1", description="") +) + +states("intracellular_ions", +cajsr=ScalarParam(1.525693, unit="mM", description=""), +cansr=ScalarParam(1.528001, unit="mM", description=""), +cass=ScalarParam( 6.49734100000000044e-5, unit="mM", description=""), +cli=ScalarParam(29.20698, unit="mM", description=""), +clss=ScalarParam(29.20696, unit="mM", description=""), +ki=ScalarParam(147.7115, unit="mM", description=""), +kss=ScalarParam(147.7114, unit="mM", description=""), +nai=ScalarParam(12.39736, unit="mM", description=""), +nass=ScalarParam(12.3977, unit="mM", description="") +) + +states("intracellular_ions", +cai=0.0001 +) + +states("ICaL", +d=ScalarParam( 1.58884100000000000e-31, unit="1", description=""), +fcaf=ScalarParam(1, unit="1", description=""), +fcafp=ScalarParam(1, unit="1", description=""), +fcas=ScalarParam(0.9999014, unit="1", description=""), +ff_=ScalarParam(1, unit="1", description=""), +ffp=ScalarParam(1, unit="1", description=""), +fs=ScalarParam(0.9401791, unit="1", description=""), +jca=ScalarParam(0.9999846, unit="1", description=""), +nca_i=ScalarParam( 8.32600900000000053e-4, unit="1", description=""), +nca_ss=ScalarParam( 4.89937800000000024e-4, unit="1", description="") +) + +states("INa", +h=ScalarParam(0.8473267, unit="1", description=""), +hp=ScalarParam(0.7018454, unit="1", description=""), +j=ScalarParam(0.8471657, unit="1", description=""), +jp=ScalarParam(0.8469014, unit="1", description=""), +m=ScalarParam( 6.51715400000000005e-4, unit="1", description="") +) + +states("INaL", +hL=ScalarParam(0.5566017, unit="1", description=""), +hLp=ScalarParam(0.3115491, unit="1", description=""), +mL=ScalarParam( 1.35120299999999988e-4, unit="1", description="") +) + +states("membrane", +v=ScalarParam(-89.74808, unit="mV", description="") +) + +states("IKs", +xs1=ScalarParam(0.243959, unit="1", description=""), +xs2=ScalarParam( 1.58616700000000009e-4, unit="1", description="") +) + +parameters("I_katp", +A_atp=ScalarParam(2.0, unit="mM", description=""), +K_atp=ScalarParam(0.25, unit="mM", description=""), +K_o_n=ScalarParam(5.0, unit="mM", description=""), +fkatp=ScalarParam(0.0, unit="1", description=""), +gkatp=ScalarParam(4.3195, unit="mS/uF", description="") +) + +parameters("ICaL", +Aff=ScalarParam(0.6, unit="1", description=""), +ICaL_fractionSS=ScalarParam(0.8, unit="1", description=""), +Kmn=ScalarParam(0.002, unit="mM", description=""), +PCa_b=ScalarParam(8.3757e-05, unit="1", description=""), +dielConstant=ScalarParam(74.0, unit="1/K", description=""), +k2n=ScalarParam(500.0, unit="mS/uF", description=""), +offset=ScalarParam(0.0, unit="ms", description=""), +tjca=ScalarParam(72.5, unit="ms", description=""), +vShift=ScalarParam(0.0, unit="mV", description="") +) + +parameters("intracellular_ions","mechanics", +BSLmax=ScalarParam(1.124, unit="mM", description=""), +BSRmax=ScalarParam(0.047, unit="mM", description=""), +KmBSL=ScalarParam(0.0087, unit="mM", description=""), +KmBSR=ScalarParam(0.00087, unit="mM", description=""), +cmdnmax_b=ScalarParam(0.05, unit="mM", description=""), +csqnmax=ScalarParam(10.0, unit="mM", description=""), +kmcmdn=ScalarParam(0.00238, unit="mM", description=""), +kmcsqn=ScalarParam(0.8, unit="mM", description=""), +kmtrpn=ScalarParam(0.0005, unit="mM", description=""), +trpnmax=ScalarParam(0.07, unit="mM", description="") +) + +parameters("CaMK", +CaMKo=ScalarParam(0.05, unit="1", description=""), +KmCaM=ScalarParam(0.0015, unit="mM", description=""), +KmCaMK=ScalarParam(0.15, unit="mM", description=""), +aCaMK=ScalarParam(0.05, unit="1/mM/ms", description=""), +bCaMK=ScalarParam(0.00068, unit="mS/uF", description="") +) + +parameters("Ito", +EKshift=ScalarParam(0.0, unit="mV", description=""), +Gto_b=ScalarParam(0.16, unit="mS/uF", description="") +) + +parameters("physical_constants","mechanics", +F=ScalarParam(96485.0, unit="C/mol", description=""), +R=ScalarParam(8314.0, unit="mJ/mol/K", description=""), +T=ScalarParam(310.0, unit="K", description=""), +zca=ScalarParam(2.0, unit="1", description=""), +zcl=ScalarParam(-1.0, unit="1", description=""), +zk=ScalarParam(1.0, unit="1", description=""), +zna=ScalarParam(1.0, unit="1", description="") +) + +parameters("ICl", +Fjunc=ScalarParam(1.0, unit="1", description=""), +GClCa=ScalarParam(0.2843, unit="mS/uF", description=""), +GClb=ScalarParam(0.00198, unit="mS/uF", description=""), +KdClCa=ScalarParam(0.1, unit="mM", description="") +) + +parameters("IK1", +GK1_b=ScalarParam(0.6992, unit="mS/uF", description="") +) + +parameters("IKb", +GKb_b=ScalarParam(0.0189, unit="mS/uF", description="") +) + +parameters("IKr", +GKr_b=ScalarParam(0.0321, unit="mS/uF", description=""), +alpha_1=ScalarParam(0.154375, unit="mS/uF", description=""), +beta_1=ScalarParam(0.1911, unit="mS/uF", description="") +) + +parameters("IKs", +GKs_b=ScalarParam(0.0011, unit="mS/uF", description="") +) + +parameters("INa", +GNa=ScalarParam(11.7802, unit="mS/uF", description="") +) + +parameters("INaL", +GNaL_b=ScalarParam(0.0279, unit="mS/uF", description=""), +thL=ScalarParam(200.0, unit="ms", description="") +) + +parameters("INaCa", +Gncx_b=ScalarParam(0.0034, unit="mS/uF", description=""), +INaCa_fractionSS=ScalarParam(0.35, unit="1", description=""), +KmCaAct=ScalarParam(0.00015, unit="mM", description=""), +kasymm=ScalarParam(12.5, unit="1", description=""), +kcaoff=ScalarParam(5000.0, unit="mS/uF", description=""), +kcaon=ScalarParam(1500000.0, unit="mS/uF", description=""), +kna1=ScalarParam(15.0, unit="mS/uF", description=""), +kna2=ScalarParam(5.0, unit="mS/uF", description=""), +kna3=ScalarParam(88.12, unit="mS/uF", description=""), +qca=ScalarParam(0.167, unit="1", description=""), +qna=ScalarParam(0.5224, unit="1", description=""), +wca=ScalarParam(60000.0, unit="1", description=""), +wna=ScalarParam(60000.0, unit="1", description=""), +wnaca=ScalarParam(5000.0, unit="1", description="") +) + +parameters("IpCa", +GpCa=ScalarParam(0.0005, unit="mS/uF", description=""), +KmCap=ScalarParam(0.0005, unit="mM", description="") +) + +parameters("INaK", +H=ScalarParam(1e-07, unit="mM", description=""), +Khp=ScalarParam(1.698e-07, unit="mM", description=""), +Kki=ScalarParam(0.5, unit="mS/uF", description=""), +Kko=ScalarParam(0.3582, unit="mS/uF", description=""), +Kmgatp=ScalarParam(1.698e-07, unit="mM", description=""), +Knai0=ScalarParam(9.073, unit="mM", description=""), +Knao0=ScalarParam(27.78, unit="mM", description=""), +Knap=ScalarParam(224.0, unit="mM", description=""), +Kxkur=ScalarParam(292.0, unit="mM", description=""), +MgADP=ScalarParam(0.05, unit="mM", description=""), +MgATP=ScalarParam(9.8, unit="mM", description=""), +Pnak_b=ScalarParam(15.4509, unit="mS/uF", description=""), +delta=ScalarParam(-0.155, unit="mV", description=""), +eP=ScalarParam(4.2, unit="1", description=""), +k1m=ScalarParam(182.4, unit="mS/uF", description=""), +k1p=ScalarParam(949.5, unit="mS/uF", description=""), +k2m=ScalarParam(39.4, unit="mS/uF", description=""), +k2p=ScalarParam(687.2, unit="mS/uF", description=""), +k3m=ScalarParam(79300.0, unit="mS/uF", description=""), +k3p=ScalarParam(1899.0, unit="mS/uF", description=""), +k4m=ScalarParam(40.0, unit="mS/uF", description=""), +k4p=ScalarParam(639.0, unit="mS/uF", description="") +) + +parameters("ryr", +Jrel_b=ScalarParam(1.5378, unit="1", description=""), +bt=ScalarParam(4.75, unit="ms", description=""), +cajsr_half=ScalarParam(1.7, unit="mM", description="") +) + +parameters("SERCA", +Jup_b=ScalarParam(1.0, unit="1", description="") +) + +parameters("cell_geometry","mechanics", +L=ScalarParam(0.01, unit="cm", description=""), +rad_=ScalarParam(0.0011, unit="cm", description="") +) + +parameters("ICab", +PCab=ScalarParam(5.9194e-08, unit="mS/uF", description="") +) + +parameters("reversal_potentials", +PKNa=ScalarParam(0.01833, unit="1", description="") +) + +parameters("INab", +PNab=ScalarParam(1.9239e-09, unit="mS/uF", description="") +) + +parameters("extracellular", +cao=ScalarParam(1.8, unit="mM", description=""), +clo=ScalarParam(150.0, unit="mM", description=""), +ko=ScalarParam(5.0, unit="mM", description=""), +nao=ScalarParam(140.0, unit="mM", description="") +) + +parameters("environment", +celltype=ScalarParam(0.0, unit="1", description="") +) + +parameters("membrane", +i_Stim_Amplitude=ScalarParam(-53.0, unit="A/F", description=""), +i_Stim_End=ScalarParam(1e+17, unit="ms", description=""), +i_Stim_Period=ScalarParam(1000.0, unit="ms", description=""), +i_Stim_PulseDuration=ScalarParam(1.0, unit="ms", description=""), +i_Stim_Start=ScalarParam(0.0, unit="ms", description="") +) + +parameters("diff", +tauCa=ScalarParam(0.2, unit="ms", description=""), +tauCl=ScalarParam(2.0, unit="ms", description=""), +tauK=ScalarParam(2.0, unit="ms", description=""), +tauNa=ScalarParam(2.0, unit="ms", description="") +) + +expressions("cell_geometry", "mechanics") +Acap = 2.0*Ageo # cm**2 +Ageo = L*((2.0*3.14)*rad_) + rad_*((2.0*3.14)*rad_) # cm**2 +vcell = L*(rad_*((1000.0*3.14)*rad_)) # uL +vjsr = 0.0048*vcell # uL +vmyo = 0.68*vcell # uL +vnsr = 0.0552*vcell # uL +vss = 0.02*vcell # uL + +expressions("ICaL") +Afcaf = 0.3 + 0.6/(exp((v - 1*10.0)/10.0) + 1.0) +Afcas = 1.0 - Afcaf +Afs = 1.0 - Aff +ICaK = ICaK_i + ICaK_ss # A/F +ICaK_i = (1.0 - ICaL_fractionSS)*((d*(PhiCaK_i*(PCaK*(1.0 - fICaLp))))*(f*(1.0 - nca_i) + nca_i*(fca*jca)) + (d*(PhiCaK_i*(PCaKp*fICaLp)))*(fp*(1.0 - nca_i) + nca_i*(fcap*jca))) # A/F +ICaK_ss = ICaL_fractionSS*((d*(PhiCaK_ss*(PCaK*(1.0 - fICaLp))))*(f*(1.0 - nca_ss) + nca_ss*(fca*jca)) + (d*(PhiCaK_ss*(PCaKp*fICaLp)))*(fp*(1.0 - nca_ss) + nca_ss*(fcap*jca))) # A/F +ICaL_ICaL = ICaL_i + ICaL_ss # A/F +ICaL_i = (1.0 - ICaL_fractionSS)*((d*(PhiCaL_i*(PCa*(1.0 - fICaLp))))*(f*(1.0 - nca_i) + nca_i*(fca*jca)) + (d*(PhiCaL_i*(PCap*fICaLp)))*(fp*(1.0 - nca_i) + nca_i*(fcap*jca))) # A/F +ICaL_ss = ICaL_fractionSS*((d*(PhiCaL_ss*(PCa*(1.0 - fICaLp))))*(f*(1.0 - nca_ss) + nca_ss*(fca*jca)) + (d*(PhiCaL_ss*(PCap*fICaLp)))*(fp*(1.0 - nca_ss) + nca_ss*(fcap*jca))) # A/F +ICaNa = ICaNa_i + ICaNa_ss # A/F +ICaNa_i = (1.0 - ICaL_fractionSS)*((d*(PhiCaNa_i*(PCaNa*(1.0 - fICaLp))))*(f*(1.0 - nca_i) + nca_i*(fca*jca)) + (d*(PhiCaNa_i*(PCaNap*fICaLp)))*(fp*(1.0 - nca_i) + nca_i*(fcap*jca))) # A/F +ICaNa_ss = ICaL_fractionSS*((d*(PhiCaNa_ss*(PCaNa*(1.0 - fICaLp))))*(f*(1.0 - nca_ss) + nca_ss*(fca*jca)) + (d*(PhiCaNa_ss*(PCaNap*fICaLp)))*(fp*(1.0 - nca_ss) + nca_ss*(fcap*jca))) # A/F +Ii = (0.5*(4.0*cai + (cli + (ki + nai))))/1000.0 +Io = (0.5*(4.0*cao + (clo + (ko + nao))))/1000.0 +Iss = (0.5*(4.0*cass + (clss + (kss + nass))))/1000.0 +PCa = Conditional(Eq(celltype, 1.0), 1.2*PCa_b, Conditional(Eq(celltype, 2.0), 2.0*PCa_b, PCa_b)) +PCaK = 0.0003574*PCa +PCaKp = 0.0003574*PCap +PCaNa = 0.00125*PCa +PCaNap = 0.00125*PCap +PCap = 1.1*PCa +PhiCaK_i = ((1.0*vffrt)*(-gamma_ko*ko + (gamma_ki*ki)*exp(1.0*vfrt)))/(exp(1.0*vfrt) - 1*1.0) +PhiCaK_ss = ((1.0*vffrt)*(-gamma_ko*ko + (gamma_kss*kss)*exp(1.0*vfrt)))/(exp(1.0*vfrt) - 1*1.0) +PhiCaL_i = ((4.0*vffrt)*(-cao*gamma_cao + (cai*gamma_cai)*exp(2.0*vfrt)))/(exp(2.0*vfrt) - 1*1.0) +PhiCaL_ss = ((4.0*vffrt)*(-cao*gamma_cao + (cass*gamma_cass)*exp(2.0*vfrt)))/(exp(2.0*vfrt) - 1*1.0) +PhiCaNa_i = ((1.0*vffrt)*(-gamma_nao*nao + (gamma_nai*nai)*exp(1.0*vfrt)))/(exp(1.0*vfrt) - 1*1.0) +PhiCaNa_ss = ((1.0*vffrt)*(-gamma_nao*nao + (gamma_nass*nass)*exp(1.0*vfrt)))/(exp(1.0*vfrt) - 1*1.0) +anca_i = 1.0/(k2n/km2n + (Kmn/cai + 1.0)**4.0) +anca_ss = 1.0/(k2n/km2n + (Kmn/cass + 1.0)**4.0) +constA = 1820000.0/(T*dielConstant)**1.5 +dss = Conditional(Ge(v, 31.4978), 1.0, 1.0763*exp(-1.007*exp(-0.0829*v))) +f = Aff*ff_ + Afs*fs +fICaLp = 1.0/(1.0 + KmCaMK/CaMKa) +fca = Afcaf*fcaf + Afcas*fcas +fcap = Afcaf*fcafp + Afcas*fcas +fcass = fss +fp = Aff*ffp + Afs*fs +fss = 1.0/(exp((v + 19.58)/3.696) + 1.0) +gamma_cai = exp((-constA*4.0)*(sqrt(Ii)/(sqrt(Ii) + 1.0) - 0.3*Ii)) +gamma_cao = exp((-constA*4.0)*(sqrt(Io)/(sqrt(Io) + 1.0) - 0.3*Io)) +gamma_cass = exp((-constA*4.0)*(sqrt(Iss)/(sqrt(Iss) + 1.0) - 0.3*Iss)) +gamma_ki = exp((-constA*1.0)*(sqrt(Ii)/(sqrt(Ii) + 1.0) - 0.3*Ii)) +gamma_ko = exp((-constA*1.0)*(sqrt(Io)/(sqrt(Io) + 1.0) - 0.3*Io)) +gamma_kss = exp((-constA*1.0)*(sqrt(Iss)/(sqrt(Iss) + 1.0) - 0.3*Iss)) +gamma_nai = exp((-constA*1.0)*(sqrt(Ii)/(sqrt(Ii) + 1.0) - 0.3*Ii)) +gamma_nao = exp((-constA*1.0)*(sqrt(Io)/(sqrt(Io) + 1.0) - 0.3*Io)) +gamma_nass = exp((-constA*1.0)*(sqrt(Iss)/(sqrt(Iss) + 1.0) - 0.3*Iss)) +jcass = 1.0/(exp((v + 18.08)/2.7916) + 1.0) +km2n = jca*1.0 # mS/uF +td = (offset + 0.6) + 1.0/(exp((-1*0.05)*((v + vShift) + 6.0)) + exp(0.09*((v + vShift) + 14.0))) # ms +tfcaf = 7.0 + 1.0/(0.04*exp((-(v - 1*4.0))/7.0) + 0.04*exp((v - 1*4.0)/7.0)) # ms +tfcafp = 2.5*tfcaf # ms +tfcas = 100.0 + 1.0/(0.00012*exp((-v)/3.0) + 0.00012*exp(v/7.0)) # ms +tff = 7.0 + 1.0/(0.0045*exp((-(v + 20.0))/10.0) + 0.0045*exp((v + 20.0)/10.0)) # ms +tffp = 2.5*tff # ms +tfs = 1000.0 + 1.0/(3.5e-5*exp((-(v + 5.0))/4.0) + 3.5e-5*exp((v + 5.0)/6.0)) # ms +dd_dt = (-d + dss)/td +dfcaf_dt = (-fcaf + fcass)/tfcaf +dfcafp_dt = (-fcafp + fcass)/tfcafp +dfcas_dt = (-fcas + fcass)/tfcas +dff__dt = (-ff_ + fss)/tff +dffp_dt = (-ffp + fss)/tffp +dfs_dt = (-fs + fss)/tfs +djca_dt = (-jca + jcass)/tjca +dnca_i_dt = anca_i*k2n - km2n*nca_i +dnca_ss_dt = anca_ss*k2n - km2n*nca_ss + +expressions("Ito") +AiF = 1.0/(exp(((EKshift + v) - 1*213.6)/151.2) + 1.0) +AiS = 1.0 - AiF +Gto = Conditional(Or(Eq(celltype, 1.0), Eq(celltype, 2.0)), 2.0*Gto_b, Gto_b) # mS/uF +Ito_Ito = (Gto*(-EK + v))*(i*(a*(1.0 - fItop)) + ip*(ap*fItop)) # A/F +ass = 1.0/(exp((-((EKshift + v) - 1*14.34))/14.82) + 1.0) +assp = 1.0/(exp((-((EKshift + v) - 1*24.34))/14.82) + 1.0) +delta_epi = Conditional(Eq(celltype, 1.0), 1.0 - 0.95/(exp(((EKshift + v) + 70.0)/5.0) + 1.0), 1.0) +dti_develop = 1.354 + 0.0001/(exp((-((EKshift + v) - 1*12.23))/0.2154) + exp(((EKshift + v) - 1*167.4)/15.89)) +dti_recover = 1.0 - 0.5/(exp(((EKshift + v) + 70.0)/20.0) + 1.0) +fItop = 1.0/(1.0 + KmCaMK/CaMKa) +i = AiF*iF + AiS*iS +ip = AiF*iFp + AiS*iSp +iss = 1.0/(exp(((EKshift + v) + 43.94)/5.711) + 1.0) +ta = 1.0515/(1.0/((1.2089*(exp((-((EKshift + v) - 1*18.4099))/29.3814) + 1.0))) + 3.5/(exp(((EKshift + v) + 100.0)/29.3814) + 1.0)) # ms +tiF = delta_epi*tiF_b # ms +tiF_b = 4.562 + 1.0/(0.3933*exp((-((EKshift + v) + 100.0))/100.0) + 0.08004*exp(((EKshift + v) + 50.0)/16.59)) # ms +tiFp = tiF*(dti_develop*dti_recover) # ms +tiS = delta_epi*tiS_b # ms +tiS_b = 23.62 + 1.0/(0.001416*exp((-((EKshift + v) + 96.52))/59.05) + 1.78e-8*exp(((EKshift + v) + 114.1)/8.079)) # ms +tiSp = tiS*(dti_develop*dti_recover) # ms +da_dt = (-a + ass)/ta +dap_dt = (-ap + assp)/ta +diF_dt = (-iF + iss)/tiF +diFp_dt = (-iFp + iss)/tiFp +diS_dt = (-iS + iss)/tiS +diSp_dt = (-iSp + iss)/tiSp + +expressions("intracellular_ions") +Bcajsr = 1.0/((csqnmax*kmcsqn)/((cajsr + kmcsqn)**2.0) + 1.0) +Bcass = 1.0/((BSLmax*KmBSL)/((KmBSL + cass)**2.0) + ((BSRmax*KmBSR)/((KmBSR + cass)**2.0) + 1.0)) +cmdnmax = Conditional(Eq(celltype, 1.0), 1.3*cmdnmax_b, cmdnmax_b) # mM +dcajsr_dt = Bcajsr*(-Jrel + Jtr) # mM +dcansr_dt = Jup - Jtr*vjsr/vnsr # mM +dcass_dt = Bcass*(-Jdiff + ((Acap*(-(ICaL_ss - 2.0*INaCa_ss)))/(((2.0*F)*vss)) + (Jrel*vjsr)/vss)) # mM +dcli_dt = (Acap*(IClCa_sl + IClb))/((F*vmyo)) + (JdiffCl*vss)/vmyo # mM +dclss_dt = -JdiffCl + (Acap*IClCa_junc)/((F*vss)) # mM +dki_dt = (Acap*(-(ICaK_i + (-2.0*INaK_INaK + (Istim + (I_katp_I_katp + (IKb_IKb + (IK1_IK1 + (IKs_IKs + (IKr_IKr + Ito_Ito))))))))))/((F*vmyo)) + (JdiffK*vss)/vmyo # mM +dkss_dt = -JdiffK + (Acap*(-ICaK_ss))/((F*vss)) # mM +dnai_dt = (Acap*(-(INab_INab + (3.0*INaK_INaK + (ICaNa_i + (3.0*INaCa_i + (INaL_INaL + INa_INa)))))))/((F*vmyo)) + (JdiffNa*vss)/vmyo # mM +dnass_dt = -JdiffNa + (Acap*(-(ICaNa_ss + 3.0*INaCa_ss)))/((F*vss)) # mM +Bcai=1.0/(1.0+cmdnmax*kmcmdn/(kmcmdn+cai)**2.0) +dcai_dt=Bcai*(-(IpCa_IpCa+ICab_ICab-2.0*INaCa_i/3)*Acap/(2.0*F*vmyo)-Jup*vnsr/vmyo+Jdiff*vss/vmyo - J_TRPN) + + +expressions("CaMK") +CaMKa = CaMKb + CaMKt # mM +CaMKb = (CaMKo*(1.0 - CaMKt))/(KmCaM/cass + 1.0) # mM +dCaMKt_dt = -CaMKt*bCaMK + (CaMKb*aCaMK)*(CaMKb + CaMKt) # mM + +expressions("INaK") +E1_ = x1/(x4 + (x3 + (x1 + x2))) +E2 = x2/(x4 + (x3 + (x1 + x2))) +E3 = x3/(x4 + (x3 + (x1 + x2))) +E4 = x4/(x4 + (x3 + (x1 + x2))) +INaK_INaK = Pnak*(JnakK*zk + JnakNa*zna) # A/F +JnakK = 2.0*(-E3*a1 + E4*b1) # mM/ms +JnakNa = 3.0*(E1_*a3 - E2*b3) # mM/ms +Knai = Knai0*exp((delta*vfrt)/3.0) # mM +Knao = Knao0*exp((vfrt*(1.0 - delta))/3.0) # mM +P = eP/(((H/Khp + 1.0) + nai/Knap) + ki/Kxkur) +Pnak = Conditional(Eq(celltype, 1.0), 0.9*Pnak_b, Conditional(Eq(celltype, 2.0), 0.7*Pnak_b, Pnak_b)) # mS/uF +a1 = (k1p*(nai/Knai)**3.0)/(((1.0 + ki/Kki)**2.0 + (1.0 + nai/Knai)**3.0) - 1*1.0) +a2 = k2p +a3 = (k3p*(ko/Kko)**2.0)/(((1.0 + ko/Kko)**2.0 + (1.0 + nao/Knao)**3.0) - 1*1.0) +a4 = ((MgATP*k4p)/Kmgatp)/(1.0 + MgATP/Kmgatp) +b1 = MgADP*k1m +b2 = (k2m*(nao/Knao)**3.0)/(((1.0 + ko/Kko)**2.0 + (1.0 + nao/Knao)**3.0) - 1*1.0) +b3 = (H*(P*k3m))/(1.0 + MgATP/Kmgatp) +b4 = (k4m*(ki/Kki)**2.0)/(((1.0 + ki/Kki)**2.0 + (1.0 + nai/Knai)**3.0) - 1*1.0) +x1 = a2*(a1*b3) + (b3*(a2*b4) + (a2*(a1*a4) + b3*(b2*b4))) +x2 = b4*(a2*a3) + (b4*(a3*b1) + (a3*(a1*a2) + b4*(b1*b2))) +x3 = b1*(a3*a4) + (a4*(b1*b2) + (a4*(a2*a3) + b1*(b2*b3))) +x4 = a1*(b2*b3) + (a1*(a4*b2) + (a1*(a3*a4) + b2*(b3*b4))) + +expressions("INaCa") +E1_i = x1_i/(x4_i + (x3_i + (x1_i + x2_i))) +E1_ss = x1_ss/(x4_ss + (x3_ss + (x1_ss + x2_ss))) +E2_i = x2_i/(x4_i + (x3_i + (x1_i + x2_i))) +E2_ss = x2_ss/(x4_ss + (x3_ss + (x1_ss + x2_ss))) +E3_i = x3_i/(x4_i + (x3_i + (x1_i + x2_i))) +E3_ss = x3_ss/(x4_ss + (x3_ss + (x1_ss + x2_ss))) +E4_i = x4_i/(x4_i + (x3_i + (x1_i + x2_i))) +E4_ss = x4_ss/(x4_ss + (x3_ss + (x1_ss + x2_ss))) +Gncx = Conditional(Eq(celltype, 1.0), 1.1*Gncx_b, Conditional(Eq(celltype, 2.0), 1.4*Gncx_b, Gncx_b)) # mS/uF +INaCa_i = (allo_i*(Gncx*(1.0 - INaCa_fractionSS)))*(JncxCa_i*zca + JncxNa_i*zna) # A/F +INaCa_ss = (allo_ss*(Gncx*INaCa_fractionSS))*(JncxCa_ss*zca + JncxNa_ss*zna) # A/F +JncxCa_i = -E1_i*k1_i + E2_i*k2_i # mM/ms +JncxCa_ss = -E1_ss*k1_ss + E2_ss*k2_ss # mM/ms +JncxNa_i = -E2_i*k3pp_i + (E3_i*k4pp_i + 3.0*(-E1_i*k8_i + E4_i*k7_i)) # mM/ms +JncxNa_ss = -E2_ss*k3pp_ss + (E3_ss*k4pp_ss + 3.0*(-E1_ss*k8_ss + E4_ss*k7_ss)) # mM/ms +allo_i = 1.0/((KmCaAct/cai)**2.0 + 1.0) +allo_ss = 1.0/((KmCaAct/cass)**2.0 + 1.0) +h10_i = (nao/kna1)*(1.0 + nao/kna2) + (kasymm + 1.0) +h10_ss = (nao/kna1)*(1.0 + nao/kna2) + (kasymm + 1.0) +h11_i = (nao*nao)/((kna2*(h10_i*kna1))) +h11_ss = (nao*nao)/((kna2*(h10_ss*kna1))) +h12_i = 1.0/h10_i +h12_ss = 1.0/h10_ss +h1_i = (nai/kna3)*(hna + 1.0) + 1.0 +h1_ss = (nass/kna3)*(hna + 1.0) + 1.0 +h2_i = (hna*nai)/((h1_i*kna3)) +h2_ss = (hna*nass)/((h1_ss*kna3)) +h3_i = 1.0/h1_i +h3_ss = 1.0/h1_ss +h4_i = (nai/kna1)*(1.0 + nai/kna2) + 1.0 +h4_ss = (nass/kna1)*(1.0 + nass/kna2) + 1.0 +h5_i = (nai*nai)/((kna2*(h4_i*kna1))) +h5_ss = (nass*nass)/((kna2*(h4_ss*kna1))) +h6_i = 1.0/h4_i +h6_ss = 1.0/h4_ss +h7_i = (nao/kna3)*(1.0 + 1.0/hna) + 1.0 +h7_ss = (nao/kna3)*(1.0 + 1.0/hna) + 1.0 +h8_i = nao/((h7_i*(hna*kna3))) +h8_ss = nao/((h7_ss*(hna*kna3))) +h9_i = 1.0/h7_i +h9_ss = 1.0/h7_ss +hca = exp(qca*vfrt) +hna = exp(qna*vfrt) +k1_i = kcaon*(cao*h12_i) +k1_ss = kcaon*(cao*h12_ss) +k2_i = kcaoff +k2_ss = kcaoff +k3_i = k3p_i + k3pp_i +k3_ss = k3p_ss + k3pp_ss +k3p_i = h9_i*wca +k3p_ss = h9_ss*wca +k3pp_i = h8_i*wnaca +k3pp_ss = h8_ss*wnaca +k4_i = k4p_i + k4pp_i +k4_ss = k4p_ss + k4pp_ss +k4p_i = (h3_i*wca)/hca +k4p_ss = (h3_ss*wca)/hca +k4pp_i = h2_i*wnaca +k4pp_ss = h2_ss*wnaca +k5_i = kcaoff +k5_ss = kcaoff +k6_i = kcaon*(cai*h6_i) +k6_ss = kcaon*(cass*h6_ss) +k7_i = wna*(h2_i*h5_i) +k7_ss = wna*(h2_ss*h5_ss) +k8_i = wna*(h11_i*h8_i) +k8_ss = wna*(h11_ss*h8_ss) +x1_i = (k2_i*k4_i)*(k6_i + k7_i) + (k5_i*k7_i)*(k2_i + k3_i) +x1_ss = (k2_ss*k4_ss)*(k6_ss + k7_ss) + (k5_ss*k7_ss)*(k2_ss + k3_ss) +x2_i = (k1_i*k7_i)*(k4_i + k5_i) + (k4_i*k6_i)*(k1_i + k8_i) +x2_ss = (k1_ss*k7_ss)*(k4_ss + k5_ss) + (k4_ss*k6_ss)*(k1_ss + k8_ss) +x3_i = (k1_i*k3_i)*(k6_i + k7_i) + (k6_i*k8_i)*(k2_i + k3_i) +x3_ss = (k1_ss*k3_ss)*(k6_ss + k7_ss) + (k6_ss*k8_ss)*(k2_ss + k3_ss) +x4_i = (k2_i*k8_i)*(k4_i + k5_i) + (k3_i*k5_i)*(k1_i + k8_i) +x4_ss = (k2_ss*k8_ss)*(k4_ss + k5_ss) + (k3_ss*k5_ss)*(k1_ss + k8_ss) + +expressions("reversal_potentials") +ECl = ((R*T)/((F*zcl)))*log(clo/cli) # mV +EClss = ((R*T)/((F*zcl)))*log(clo/clss) # mV +EK = ((R*T)/((F*zk)))*log(ko/ki) # mV +EKs = ((R*T)/((F*zk)))*log((PKNa*nao + ko)/(PKNa*nai + ki)) # mV +ENa = ((R*T)/((F*zna)))*log(nao/nai) # mV + +expressions("IK1") +GK1 = Conditional(Eq(celltype, 1.0), 1.2*GK1_b, Conditional(Eq(celltype, 2.0), 1.3*GK1_b, GK1_b)) # mS/uF +IK1_IK1 = (K1ss*(GK1*sqrt(ko/5.0)))*(-EK + v) # A/F +K1ss = aK1/(aK1 + bK1) +aK1 = 4.094/(exp(0.1217*((-EK + v) - 1*49.934)) + 1.0) +bK1 = (15.72*exp(0.0674*((-EK + v) - 1*3.257)) + exp(0.0618*((-EK + v) - 1*594.31)))/(exp((-1*0.1629)*((-EK + v) + 14.207)) + 1.0) + +expressions("IKb") +GKb = Conditional(Eq(celltype, 1.0), 0.6*GKb_b, GKb_b) # mS/uF +IKb_IKb = (GKb*xkb)*(-EK + v) # A/F +xkb = 1.0/(exp((-(v - 1*10.8968))/23.9871) + 1.0) + +expressions("IKr") +GKr = Conditional(Eq(celltype, 1.0), 1.3*GKr_b, Conditional(Eq(celltype, 2.0), 0.8*GKr_b, GKr_b)) # mS/uF +IKr_IKr = (O_*(GKr*sqrt(ko/5.0)))*(-EK + v) # A/F +alpha = 0.1161*exp(0.299*vfrt) # mS/uF +alpha_2 = 0.0578*exp(0.971*vfrt) # mS/uF +alpha_C2ToI = 5.2e-5*exp(1.525*vfrt) # mS/uF +alpha_i = 0.2533*exp(0.5953*vfrt) # mS/uF +beta_ = 0.2442*exp((-1*1.604)*vfrt) # mS/uF +beta_2 = 0.000349*exp((-1*1.062)*vfrt) # mS/uF +beta_ItoC2 = (alpha_C2ToI*(beta_2*beta_i))/((alpha_2*alpha_i)) # mS/uF +beta_i = 0.06525*exp((-1*0.8209)*vfrt) # mS/uF +dC1_dt = -C1*(alpha_C2ToI + (alpha_2 + beta_1)) + (I_*beta_ItoC2 + (C2*alpha_1 + O_*beta_2)) +dC2_dt = -C2*(alpha_1 + beta_) + (C1*beta_1 + C3*alpha) +dC3_dt = C2*beta_ - C3*alpha +dI__dt = -I_*(beta_ItoC2 + beta_i) + (C1*alpha_C2ToI + O_*alpha_i) +dO__dt = -O_*(alpha_i + beta_2) + (C1*alpha_2 + I_*beta_i) + +expressions("IKs") +GKs = Conditional(Eq(celltype, 1.0), 1.4*GKs_b, GKs_b) # mS/uF +IKs_IKs = (xs2*(xs1*(GKs*KsCa)))*(-EKs + v) # A/F +KsCa = 1.0 + 0.6/((3.8e-5/cai)**1.4 + 1.0) +txs1 = 817.3 + 1.0/(0.0002326*exp((v + 48.28)/17.8) + 0.001292*exp((-(v + 210.0))/230.0)) # ms +txs2 = 1.0/(0.01*exp((v - 1*50.0)/20.0) + 0.0193*exp((-(v + 66.54))/31.0)) # ms +xs1ss = 1.0/(exp((-(v + 11.6))/8.932) + 1.0) +xs2ss = xs1ss +dxs1_dt = (-xs1 + xs1ss)/txs1 +dxs2_dt = (-xs2 + xs2ss)/txs2 + +expressions("INaL") +GNaL = Conditional(Eq(celltype, 1.0), 0.6*GNaL_b, GNaL_b) # mS/uF +INaL_INaL = (mL*(GNaL*(-ENa + v)))*(fINaLp*hLp + hL*(1.0 - fINaLp)) # A/F +fINaLp = 1.0/(1.0 + KmCaMK/CaMKa) +hLss = 1.0/(exp((v + 87.61)/7.488) + 1.0) +hLssp = 1.0/(exp((v + 93.81)/7.488) + 1.0) +mLss = 1.0/(exp((-(v + 42.85))/5.264) + 1.0) +thLp = 3.0*thL # ms +tmL = 0.06487*exp(-((v - 1*4.823)/51.12)**2.0) + 0.1292*exp(-((v + 45.79)/15.54)**2.0) # ms +dhL_dt = (-hL + hLss)/thL +dhLp_dt = (-hLp + hLssp)/thLp +dmL_dt = (-mL + mLss)/tmL + +expressions("ICab") +ICab_ICab = ((vffrt*(PCab*4.0))*(-cao*gamma_cao + (cai*gamma_cai)*exp(2.0*vfrt)))/(exp(2.0*vfrt) - 1*1.0) # A/F + +expressions("ICl") +IClCa = IClCa_junc + IClCa_sl # A/F +IClCa_junc = ((Fjunc*GClCa)/(KdClCa/cass + 1.0))*(-EClss + v) # A/F +IClCa_sl = ((GClCa*(1.0 - Fjunc))/(KdClCa/cai + 1.0))*(-ECl + v) # A/F +IClb = GClb*(-ECl + v) # A/F + +expressions("INa") +INa_INa = (m**3.0*(GNa*(-ENa + v)))*(j*(h*(1.0 - fINap)) + jp*(fINap*hp)) # A/F +ah = Conditional(Gt(v, -1*40.0), 0.0, 4.43126792958051e-7*exp(-0.147058823529412*v)) +aj = Conditional(Gt(v, -1*40.0), 0.0, -(v + 37.78)*(25428.0*exp(0.28831*v) + 6.948e-6)*exp(-0.04391*v)/(50262745825.954*exp(0.311*v) + 1.0)) +bh = Conditional(Gt(v, -1*40.0), 0.77*exp(0.0900900900900901*v)/(0.13*exp(0.0900900900900901*v) + 0.0497581410839387), 2.7*exp(0.079*v) + 310000.0*exp(0.3485*v)) +bj = Conditional(Gt(v, -1*40.0), 0.6*exp(0.157*v)/(1.0*exp(0.1*v) + 0.0407622039783662), 0.02424*exp(0.12728*v)/(1.0*exp(0.1378*v) + 0.00396086833990426)) +fINap = 1.0/(1.0 + KmCaMK/CaMKa) +hss = 1.0/((exp((v + 71.55)/7.43) + 1.0)**2.0) +hssp = 1.0/((exp((v + 77.55)/7.43) + 1.0)**2.0) +jss = hss +mss = 1.0/((exp((-(v + 56.86))/9.03) + 1.0)**2.0) +th = 1.0/(ah + bh) # ms +tj = 1.0/(aj + bj) # ms +tjp = 1.46*tj # ms +tm = 0.06487*exp(-((v - 1*4.823)/51.12)**2.0) + 0.1292*exp(-((v + 45.79)/15.54)**2.0) # ms +dh_dt = (-h + hss)/th +dhp_dt = (-hp + hssp)/th +dj_dt = (-j + jss)/tj +djp_dt = (-jp + jss)/tjp +dm_dt = (-m + mss)/tm + +expressions("INab") +INab_INab = ((PNab*vffrt)*(nai*exp(vfrt) - nao))/(exp(vfrt) - 1*1.0) # A/F + +expressions("I_katp") +I_katp_I_katp = (bkik*(akik*(fkatp*gkatp)))*(-EK + v) # A/F +akik = (ko/K_o_n)**0.24 +bkik = 1.0/((A_atp/K_atp)**2.0 + 1.0) + +expressions("IpCa") +IpCa_IpCa = (GpCa*cai)/(KmCap + cai) # A/F + +expressions("membrane") +Istim = Conditional(And(Le(i_Stim_Start, time), Ge(i_Stim_PulseDuration, -i_Stim_Period*floor(-(i_Stim_Start - time)/i_Stim_Period) - i_Stim_Start + time)), i_Stim_Amplitude, 0.0) # A/F +vffrt = (F*(F*v))/((R*T)) # C/mol +vfrt = (F*v)/((R*T)) +dv_dt = -(Istim + (I_katp_I_katp + (IClb + (IClCa + (ICab_ICab + (IpCa_IpCa + (IKb_IKb + (INab_INab + (INaK_INaK + (INaCa_ss + (INaCa_i + (IK1_IK1 + (IKs_IKs + (IKr_IKr + (ICaK + (ICaNa + (ICaL_ICaL + (Ito_Ito + (INaL_INaL + INa_INa))))))))))))))))))) # mV + +expressions("diff") +Jdiff = (-cai + cass)/tauCa # mM/ms +JdiffCl = (-cli + clss)/tauNa # mM/ms +JdiffK = (-ki + kss)/tauK # mM/ms +JdiffNa = (-nai + nass)/tauNa # mM/ms + +expressions("SERCA") +Jleak = (0.0048825*cansr)/15.0 # mM/ms +Jup = Jup_b*(-Jleak + (Jupnp*(1.0 - fJupp) + Jupp*fJupp)) # mM/ms +Jupnp = (cai*(upScale*0.005425))/(cai + 0.00092) # mM/ms +Jupp = (cai*((upScale*2.75)*0.005425))/((cai + 0.00092) - 1*0.00017) # mM/ms +fJupp = 1.0/(1.0 + KmCaMK/CaMKa) +upScale = Conditional(Eq(celltype, 1.0), 1.3, 1.0) + +expressions("ryr") +Jrel = Jrel_b*(Jrel_np*(1.0 - fJrelp) + Jrel_p*fJrelp) # mM/ms +Jrel_inf = Conditional(Eq(celltype, 2.0), 1.7*Jrel_inf_b, Jrel_inf_b) # mM/ms +Jrel_inf_b = ((ICaL_ss*(-a_rel))/1.0)/((cajsr_half/cajsr)**8.0 + 1.0) # mM/ms +Jrel_infp = Conditional(Eq(celltype, 2.0), 1.7*Jrel_infp_b, Jrel_infp_b) # mM/ms +Jrel_infp_b = ((ICaL_ss*(-a_relp))/1.0)/((cajsr_half/cajsr)**8.0 + 1.0) # mM/ms +a_rel = (0.5*bt)/1.0 # mM/ms +a_relp = (0.5*btp)/1.0 # mM/ms +btp = 1.25*bt # ms +fJrelp = 1.0/(1.0 + KmCaMK/CaMKa) +tau_rel = Conditional(Lt(tau_rel_b, 0.001), 0.001, tau_rel_b) # ms +tau_rel_b = bt/(1.0 + 0.0123/cajsr) # ms +tau_relp = Conditional(Lt(tau_relp_b, 0.001), 0.001, tau_relp_b) # ms +tau_relp_b = btp/(1.0 + 0.0123/cajsr) # ms +dJrel_np_dt = (Jrel_inf - Jrel_np)/tau_rel # mM/ms +dJrel_p_dt = (Jrel_infp - Jrel_p)/tau_relp # mM/ms + +expressions("trans_flux") +Jtr = (-cajsr + cansr)/60.0 # mM/ms + + + +states("mechanics", +XS=0, +XW=0, +CaTrpn=1e-8, +TmB=1, +Zetas=0, +Zetaw=0, +Cd=0 +) + +parameters("mechanics", +emcoupling=1, +lmbda=1, +dLambda=0, +mode=1, +isacs=0, +calib=1, +ktrpn = 0.1, +ntrpn = 2, +Trpn50 = 0.35, +rw = 0.5, +rs = 0.25, +gammas = 0.0085, +gammaw = 0.615, +phi = 2.23, +Tot_A = 25, +Beta0 = 2.3, +Beta1 = -2.4, +cat50_ref = 0.805, +Tref = 120, +kuw = 0.182, +kws = 0.012, +ku=0.04, +ntm=2.4, +p_a = 2.1, +p_b = 9.1, +p_k = 7, +etal = 200, +etas = 20) + +expressions("mechanics") +XS_max = Conditional(Gt(XS, 0), XS, 0) +XW_max = Conditional(Gt(XW, 0), XW, 0) +CaTrpn_max = Conditional(Gt(CaTrpn, 0), CaTrpn, 0) +kwu = kuw*(1/rw-1)-kws +ksu = kws*rw*(1/rs-1) +Aw = Tot_A*rs/((1-rs)*rw+rs) +As = Aw +cw = phi*kuw*((1-rs)*(1-rw))/((1-rs)*rw) +cs = phi*kws*((1-rs)*rw)/rs +XU = (1-TmB)-XS-XW +gammawu = gammaw*Abs(Zetaw) +gammasu = gammas*Conditional(Gt(Gt(Zetas,0)*Zetas, Lt(Zetas, -1)*(-Zetas-1)), Gt(Zetas,0)*Zetas, Lt(Zetas, -1)*(-Zetas-1)) +dXS_dt = kws*XW - ksu*XS - gammasu*XS +dXW_dt = kuw*XU - kwu*XW - kws*XW - gammawu*XW +cat50 = (cat50_ref+Beta1*(lambda_min12-1)) +dCaTrpn_dt = ktrpn*(((cai*1000/cat50)**ntrpn)*(1-CaTrpn)-CaTrpn) +kb = ku*Trpn50**ntm/(1-rs-(1-rs)*rw) +dTmB_dt = kb*Conditional(Lt(CaTrpn**(-ntm/2), 100), CaTrpn**(-ntm/2), 100)*XU-ku*CaTrpn**(ntm/2)*TmB +J_TRPN = dCaTrpn_dt*trpnmax +lambda_min12 = Conditional(Lt(lmbda, 1.2), lmbda, 1.2) +dZetas_dt = As*dLambda - cs*Zetas +dZetaw_dt = Aw*dLambda - cw*Zetaw +lambda_min087 = Conditional(Lt(lambda_min12, 0.87), lambda_min12, 0.87) +h_lambda_prima = 1+Beta0*(lambda_min12+lambda_min087-1.87) +h_lambda = Conditional(Gt(h_lambda_prima, 0), h_lambda_prima, 0) +Ta = h_lambda*(Tref/rs)*(XS*(Zetas+1) + XW*Zetaw) +C = lambda_min12 - 1 +dCd = C - Cd +eta = Conditional(Lt(dCd, 0), etas, etal) +dCd_dt = p_k * (C - Cd) / eta +Fd = eta * dCd +F1 = (exp( p_b * C) - 1) +Tp = p_a * (F1 + Fd) +Ttot = Ta + Tp diff --git a/numerical_experiments/odefiles/ToRORd_dynCl_endo_catrpnsplit.ode b/numerical_experiments/odefiles/ToRORd_dynCl_endo_catrpnsplit.ode new file mode 100644 index 0000000..7f3afdc --- /dev/null +++ b/numerical_experiments/odefiles/ToRORd_dynCl_endo_catrpnsplit.ode @@ -0,0 +1,719 @@ +states("IKr", +C1=ScalarParam(0.9982511, unit="1", description=""), +C2=ScalarParam( 7.93602000000000023e-4, unit="1", description=""), +C3=ScalarParam( 6.53214300000000045e-4, unit="1", description=""), +I_=ScalarParam( 9.80408300000000003e-6, unit="1", description=""), +O_=ScalarParam( 2.92244900000000025e-4, unit="1", description="") +) + +states("CaMK", +CaMKt=ScalarParam( 1.09502599999999999e-2, unit="mM", description="") +) + +states("ryr", +Jrel_np=ScalarParam( 1.80824799999999996e-22, unit="mM/ms", description=""), +Jrel_p=ScalarParam( 4.35860800000000030e-21, unit="mM/ms", description="") +) + +states("Ito", +a=ScalarParam( 8.89925900000000051e-4, unit="1", description=""), +ap=ScalarParam( 4.53416500000000005e-4, unit="1", description=""), +iF=ScalarParam(0.9996716, unit="1", description=""), +iFp=ScalarParam(0.9996716, unit="1", description=""), +iS=ScalarParam(0.5988908, unit="1", description=""), +iSp=ScalarParam(0.6620692, unit="1", description="") +) + +states("intracellular_ions", +cajsr=ScalarParam(1.525693, unit="mM", description=""), +cansr=ScalarParam(1.528001, unit="mM", description=""), +cass=ScalarParam( 6.49734100000000044e-5, unit="mM", description=""), +cli=ScalarParam(29.20698, unit="mM", description=""), +clss=ScalarParam(29.20696, unit="mM", description=""), +ki=ScalarParam(147.7115, unit="mM", description=""), +kss=ScalarParam(147.7114, unit="mM", description=""), +nai=ScalarParam(12.39736, unit="mM", description=""), +nass=ScalarParam(12.3977, unit="mM", description="") +) + +states("ICaL", +d=ScalarParam( 1.58884100000000000e-31, unit="1", description=""), +fcaf=ScalarParam(1, unit="1", description=""), +fcafp=ScalarParam(1, unit="1", description=""), +fcas=ScalarParam(0.9999014, unit="1", description=""), +ff_=ScalarParam(1, unit="1", description=""), +ffp=ScalarParam(1, unit="1", description=""), +fs=ScalarParam(0.9401791, unit="1", description=""), +jca=ScalarParam(0.9999846, unit="1", description=""), +nca_i=ScalarParam( 8.32600900000000053e-4, unit="1", description=""), +nca_ss=ScalarParam( 4.89937800000000024e-4, unit="1", description="") +) + +states("INa", +h=ScalarParam(0.8473267, unit="1", description=""), +hp=ScalarParam(0.7018454, unit="1", description=""), +j=ScalarParam(0.8471657, unit="1", description=""), +jp=ScalarParam(0.8469014, unit="1", description=""), +m=ScalarParam( 6.51715400000000005e-4, unit="1", description="") +) + +states("INaL", +hL=ScalarParam(0.5566017, unit="1", description=""), +hLp=ScalarParam(0.3115491, unit="1", description=""), +mL=ScalarParam( 1.35120299999999988e-4, unit="1", description="") +) + +states("membrane", +v=ScalarParam(-89.74808, unit="mV", description="") +) + +states("IKs", +xs1=ScalarParam(0.243959, unit="1", description=""), +xs2=ScalarParam( 1.58616700000000009e-4, unit="1", description="") +) + +parameters("I_katp", +A_atp=ScalarParam(2.0, unit="mM", description=""), +K_atp=ScalarParam(0.25, unit="mM", description=""), +K_o_n=ScalarParam(5.0, unit="mM", description=""), +fkatp=ScalarParam(0.0, unit="1", description=""), +gkatp=ScalarParam(4.3195, unit="mS/uF", description="") +) + +parameters("ICaL", +Aff=ScalarParam(0.6, unit="1", description=""), +ICaL_fractionSS=ScalarParam(0.8, unit="1", description=""), +Kmn=ScalarParam(0.002, unit="mM", description=""), +PCa_b=ScalarParam(8.3757e-05, unit="1", description=""), +dielConstant=ScalarParam(74.0, unit="1/K", description=""), +k2n=ScalarParam(500.0, unit="mS/uF", description=""), +offset=ScalarParam(0.0, unit="ms", description=""), +tjca=ScalarParam(72.5, unit="ms", description=""), +vShift=ScalarParam(0.0, unit="mV", description="") +) + +parameters("intracellular_ions","mechanics", +BSLmax=ScalarParam(1.124, unit="mM", description=""), +BSRmax=ScalarParam(0.047, unit="mM", description=""), +KmBSL=ScalarParam(0.0087, unit="mM", description=""), +KmBSR=ScalarParam(0.00087, unit="mM", description=""), +cmdnmax_b=ScalarParam(0.05, unit="mM", description=""), +csqnmax=ScalarParam(10.0, unit="mM", description=""), +kmcmdn=ScalarParam(0.00238, unit="mM", description=""), +kmcsqn=ScalarParam(0.8, unit="mM", description=""), +kmtrpn=ScalarParam(0.0005, unit="mM", description=""), +trpnmax=ScalarParam(0.07, unit="mM", description=""), +lmbda=1, +ktrpn = 0.1, +ntrpn = 2, +Beta1 = -2.4, +cat50_ref = 0.805 +) + +parameters("CaMK", +CaMKo=ScalarParam(0.05, unit="1", description=""), +KmCaM=ScalarParam(0.0015, unit="mM", description=""), +KmCaMK=ScalarParam(0.15, unit="mM", description=""), +aCaMK=ScalarParam(0.05, unit="1/mM/ms", description=""), +bCaMK=ScalarParam(0.00068, unit="mS/uF", description="") +) + +parameters("Ito", +EKshift=ScalarParam(0.0, unit="mV", description=""), +Gto_b=ScalarParam(0.16, unit="mS/uF", description="") +) + +parameters("physical_constants", "mechanics", +F=ScalarParam(96485.0, unit="C/mol", description=""), +R=ScalarParam(8314.0, unit="mJ/mol/K", description=""), +T=ScalarParam(310.0, unit="K", description=""), +zca=ScalarParam(2.0, unit="1", description=""), +zcl=ScalarParam(-1.0, unit="1", description=""), +zk=ScalarParam(1.0, unit="1", description=""), +zna=ScalarParam(1.0, unit="1", description="") +) + +parameters("ICl", +Fjunc=ScalarParam(1.0, unit="1", description=""), +GClCa=ScalarParam(0.2843, unit="mS/uF", description=""), +GClb=ScalarParam(0.00198, unit="mS/uF", description=""), +KdClCa=ScalarParam(0.1, unit="mM", description="") +) + +parameters("IK1", +GK1_b=ScalarParam(0.6992, unit="mS/uF", description="") +) + +parameters("IKb", +GKb_b=ScalarParam(0.0189, unit="mS/uF", description="") +) + +parameters("IKr", +GKr_b=ScalarParam(0.0321, unit="mS/uF", description=""), +alpha_1=ScalarParam(0.154375, unit="mS/uF", description=""), +beta_1=ScalarParam(0.1911, unit="mS/uF", description="") +) + +parameters("IKs", +GKs_b=ScalarParam(0.0011, unit="mS/uF", description="") +) + +parameters("INa", +GNa=ScalarParam(11.7802, unit="mS/uF", description="") +) + +parameters("INaL", +GNaL_b=ScalarParam(0.0279, unit="mS/uF", description=""), +thL=ScalarParam(200.0, unit="ms", description="") +) + +parameters("INaCa", +Gncx_b=ScalarParam(0.0034, unit="mS/uF", description=""), +INaCa_fractionSS=ScalarParam(0.35, unit="1", description=""), +KmCaAct=ScalarParam(0.00015, unit="mM", description=""), +kasymm=ScalarParam(12.5, unit="1", description=""), +kcaoff=ScalarParam(5000.0, unit="mS/uF", description=""), +kcaon=ScalarParam(1500000.0, unit="mS/uF", description=""), +kna1=ScalarParam(15.0, unit="mS/uF", description=""), +kna2=ScalarParam(5.0, unit="mS/uF", description=""), +kna3=ScalarParam(88.12, unit="mS/uF", description=""), +qca=ScalarParam(0.167, unit="1", description=""), +qna=ScalarParam(0.5224, unit="1", description=""), +wca=ScalarParam(60000.0, unit="1", description=""), +wna=ScalarParam(60000.0, unit="1", description=""), +wnaca=ScalarParam(5000.0, unit="1", description="") +) + +parameters("IpCa", +GpCa=ScalarParam(0.0005, unit="mS/uF", description=""), +KmCap=ScalarParam(0.0005, unit="mM", description="") +) + +parameters("INaK", +H=ScalarParam(1e-07, unit="mM", description=""), +Khp=ScalarParam(1.698e-07, unit="mM", description=""), +Kki=ScalarParam(0.5, unit="mS/uF", description=""), +Kko=ScalarParam(0.3582, unit="mS/uF", description=""), +Kmgatp=ScalarParam(1.698e-07, unit="mM", description=""), +Knai0=ScalarParam(9.073, unit="mM", description=""), +Knao0=ScalarParam(27.78, unit="mM", description=""), +Knap=ScalarParam(224.0, unit="mM", description=""), +Kxkur=ScalarParam(292.0, unit="mM", description=""), +MgADP=ScalarParam(0.05, unit="mM", description=""), +MgATP=ScalarParam(9.8, unit="mM", description=""), +Pnak_b=ScalarParam(15.4509, unit="mS/uF", description=""), +delta=ScalarParam(-0.155, unit="mV", description=""), +eP=ScalarParam(4.2, unit="1", description=""), +k1m=ScalarParam(182.4, unit="mS/uF", description=""), +k1p=ScalarParam(949.5, unit="mS/uF", description=""), +k2m=ScalarParam(39.4, unit="mS/uF", description=""), +k2p=ScalarParam(687.2, unit="mS/uF", description=""), +k3m=ScalarParam(79300.0, unit="mS/uF", description=""), +k3p=ScalarParam(1899.0, unit="mS/uF", description=""), +k4m=ScalarParam(40.0, unit="mS/uF", description=""), +k4p=ScalarParam(639.0, unit="mS/uF", description="") +) + +parameters("ryr", +Jrel_b=ScalarParam(1.5378, unit="1", description=""), +bt=ScalarParam(4.75, unit="ms", description=""), +cajsr_half=ScalarParam(1.7, unit="mM", description="") +) + +parameters("SERCA", +Jup_b=ScalarParam(1.0, unit="1", description="") +) + +parameters("cell_geometry","mechanics", +L=ScalarParam(0.01, unit="cm", description=""), +rad_=ScalarParam(0.0011, unit="cm", description="") +) + +parameters("ICab", +PCab=ScalarParam(5.9194e-08, unit="mS/uF", description="") +) + +parameters("reversal_potentials", +PKNa=ScalarParam(0.01833, unit="1", description="") +) + +parameters("INab", +PNab=ScalarParam(1.9239e-09, unit="mS/uF", description="") +) + +parameters("extracellular", +cao=ScalarParam(1.8, unit="mM", description=""), +clo=ScalarParam(150.0, unit="mM", description=""), +ko=ScalarParam(5.0, unit="mM", description=""), +nao=ScalarParam(140.0, unit="mM", description="") +) + +parameters("environment", +celltype=ScalarParam(0.0, unit="1", description="") +) + +parameters("membrane", +i_Stim_Amplitude=ScalarParam(-53.0, unit="A/F", description=""), +i_Stim_End=ScalarParam(1e+17, unit="ms", description=""), +i_Stim_Period=ScalarParam(1000.0, unit="ms", description=""), +i_Stim_PulseDuration=ScalarParam(1.0, unit="ms", description=""), +i_Stim_Start=ScalarParam(0.0, unit="ms", description="") +) + +parameters("diff", +tauCa=ScalarParam(0.2, unit="ms", description=""), +tauCl=ScalarParam(2.0, unit="ms", description=""), +tauK=ScalarParam(2.0, unit="ms", description=""), +tauNa=ScalarParam(2.0, unit="ms", description="") +) + +expressions("cell_geometry","mechanics") +Acap = 2.0*Ageo # cm**2 +Ageo = L*((2.0*3.14)*rad_) + rad_*((2.0*3.14)*rad_) # cm**2 +vcell = L*(rad_*((1000.0*3.14)*rad_)) # uL +vjsr = 0.0048*vcell # uL +vmyo = 0.68*vcell # uL +vnsr = 0.0552*vcell # uL +vss = 0.02*vcell # uL + +expressions("ICaL") +Afcaf = 0.3 + 0.6/(exp((v - 1*10.0)/10.0) + 1.0) +Afcas = 1.0 - Afcaf +Afs = 1.0 - Aff +ICaK = ICaK_i + ICaK_ss # A/F +ICaK_i = (1.0 - ICaL_fractionSS)*((d*(PhiCaK_i*(PCaK*(1.0 - fICaLp))))*(f*(1.0 - nca_i) + nca_i*(fca*jca)) + (d*(PhiCaK_i*(PCaKp*fICaLp)))*(fp*(1.0 - nca_i) + nca_i*(fcap*jca))) # A/F +ICaK_ss = ICaL_fractionSS*((d*(PhiCaK_ss*(PCaK*(1.0 - fICaLp))))*(f*(1.0 - nca_ss) + nca_ss*(fca*jca)) + (d*(PhiCaK_ss*(PCaKp*fICaLp)))*(fp*(1.0 - nca_ss) + nca_ss*(fcap*jca))) # A/F +ICaL_ICaL = ICaL_i + ICaL_ss # A/F +ICaL_i = (1.0 - ICaL_fractionSS)*((d*(PhiCaL_i*(PCa*(1.0 - fICaLp))))*(f*(1.0 - nca_i) + nca_i*(fca*jca)) + (d*(PhiCaL_i*(PCap*fICaLp)))*(fp*(1.0 - nca_i) + nca_i*(fcap*jca))) # A/F +ICaL_ss = ICaL_fractionSS*((d*(PhiCaL_ss*(PCa*(1.0 - fICaLp))))*(f*(1.0 - nca_ss) + nca_ss*(fca*jca)) + (d*(PhiCaL_ss*(PCap*fICaLp)))*(fp*(1.0 - nca_ss) + nca_ss*(fcap*jca))) # A/F +ICaNa = ICaNa_i + ICaNa_ss # A/F +ICaNa_i = (1.0 - ICaL_fractionSS)*((d*(PhiCaNa_i*(PCaNa*(1.0 - fICaLp))))*(f*(1.0 - nca_i) + nca_i*(fca*jca)) + (d*(PhiCaNa_i*(PCaNap*fICaLp)))*(fp*(1.0 - nca_i) + nca_i*(fcap*jca))) # A/F +ICaNa_ss = ICaL_fractionSS*((d*(PhiCaNa_ss*(PCaNa*(1.0 - fICaLp))))*(f*(1.0 - nca_ss) + nca_ss*(fca*jca)) + (d*(PhiCaNa_ss*(PCaNap*fICaLp)))*(fp*(1.0 - nca_ss) + nca_ss*(fcap*jca))) # A/F +Ii = (0.5*(4.0*cai + (cli + (ki + nai))))/1000.0 +Io = (0.5*(4.0*cao + (clo + (ko + nao))))/1000.0 +Iss = (0.5*(4.0*cass + (clss + (kss + nass))))/1000.0 +PCa = Conditional(Eq(celltype, 1.0), 1.2*PCa_b, Conditional(Eq(celltype, 2.0), 2.0*PCa_b, PCa_b)) +PCaK = 0.0003574*PCa +PCaKp = 0.0003574*PCap +PCaNa = 0.00125*PCa +PCaNap = 0.00125*PCap +PCap = 1.1*PCa +PhiCaK_i = ((1.0*vffrt)*(-gamma_ko*ko + (gamma_ki*ki)*exp(1.0*vfrt)))/(exp(1.0*vfrt) - 1*1.0) +PhiCaK_ss = ((1.0*vffrt)*(-gamma_ko*ko + (gamma_kss*kss)*exp(1.0*vfrt)))/(exp(1.0*vfrt) - 1*1.0) +PhiCaL_i = ((4.0*vffrt)*(-cao*gamma_cao + (cai*gamma_cai)*exp(2.0*vfrt)))/(exp(2.0*vfrt) - 1*1.0) +PhiCaL_ss = ((4.0*vffrt)*(-cao*gamma_cao + (cass*gamma_cass)*exp(2.0*vfrt)))/(exp(2.0*vfrt) - 1*1.0) +PhiCaNa_i = ((1.0*vffrt)*(-gamma_nao*nao + (gamma_nai*nai)*exp(1.0*vfrt)))/(exp(1.0*vfrt) - 1*1.0) +PhiCaNa_ss = ((1.0*vffrt)*(-gamma_nao*nao + (gamma_nass*nass)*exp(1.0*vfrt)))/(exp(1.0*vfrt) - 1*1.0) +anca_i = 1.0/(k2n/km2n + (Kmn/cai + 1.0)**4.0) +anca_ss = 1.0/(k2n/km2n + (Kmn/cass + 1.0)**4.0) +constA = 1820000.0/(T*dielConstant)**1.5 +dss = Conditional(Ge(v, 31.4978), 1.0, 1.0763*exp(-1.007*exp(-0.0829*v))) +f = Aff*ff_ + Afs*fs +fICaLp = 1.0/(1.0 + KmCaMK/CaMKa) +fca = Afcaf*fcaf + Afcas*fcas +fcap = Afcaf*fcafp + Afcas*fcas +fcass = fss +fp = Aff*ffp + Afs*fs +fss = 1.0/(exp((v + 19.58)/3.696) + 1.0) +gamma_cai = exp((-constA*4.0)*(sqrt(Ii)/(sqrt(Ii) + 1.0) - 0.3*Ii)) +gamma_cao = exp((-constA*4.0)*(sqrt(Io)/(sqrt(Io) + 1.0) - 0.3*Io)) +gamma_cass = exp((-constA*4.0)*(sqrt(Iss)/(sqrt(Iss) + 1.0) - 0.3*Iss)) +gamma_ki = exp((-constA*1.0)*(sqrt(Ii)/(sqrt(Ii) + 1.0) - 0.3*Ii)) +gamma_ko = exp((-constA*1.0)*(sqrt(Io)/(sqrt(Io) + 1.0) - 0.3*Io)) +gamma_kss = exp((-constA*1.0)*(sqrt(Iss)/(sqrt(Iss) + 1.0) - 0.3*Iss)) +gamma_nai = exp((-constA*1.0)*(sqrt(Ii)/(sqrt(Ii) + 1.0) - 0.3*Ii)) +gamma_nao = exp((-constA*1.0)*(sqrt(Io)/(sqrt(Io) + 1.0) - 0.3*Io)) +gamma_nass = exp((-constA*1.0)*(sqrt(Iss)/(sqrt(Iss) + 1.0) - 0.3*Iss)) +jcass = 1.0/(exp((v + 18.08)/2.7916) + 1.0) +km2n = jca*1.0 # mS/uF +td = (offset + 0.6) + 1.0/(exp((-1*0.05)*((v + vShift) + 6.0)) + exp(0.09*((v + vShift) + 14.0))) # ms +tfcaf = 7.0 + 1.0/(0.04*exp((-(v - 1*4.0))/7.0) + 0.04*exp((v - 1*4.0)/7.0)) # ms +tfcafp = 2.5*tfcaf # ms +tfcas = 100.0 + 1.0/(0.00012*exp((-v)/3.0) + 0.00012*exp(v/7.0)) # ms +tff = 7.0 + 1.0/(0.0045*exp((-(v + 20.0))/10.0) + 0.0045*exp((v + 20.0)/10.0)) # ms +tffp = 2.5*tff # ms +tfs = 1000.0 + 1.0/(3.5e-5*exp((-(v + 5.0))/4.0) + 3.5e-5*exp((v + 5.0)/6.0)) # ms +dd_dt = (-d + dss)/td +dfcaf_dt = (-fcaf + fcass)/tfcaf +dfcafp_dt = (-fcafp + fcass)/tfcafp +dfcas_dt = (-fcas + fcass)/tfcas +dff__dt = (-ff_ + fss)/tff +dffp_dt = (-ffp + fss)/tffp +dfs_dt = (-fs + fss)/tfs +djca_dt = (-jca + jcass)/tjca +dnca_i_dt = anca_i*k2n - km2n*nca_i +dnca_ss_dt = anca_ss*k2n - km2n*nca_ss + +expressions("Ito") +AiF = 1.0/(exp(((EKshift + v) - 1*213.6)/151.2) + 1.0) +AiS = 1.0 - AiF +Gto = Conditional(Or(Eq(celltype, 1.0), Eq(celltype, 2.0)), 2.0*Gto_b, Gto_b) # mS/uF +Ito_Ito = (Gto*(-EK + v))*(i*(a*(1.0 - fItop)) + ip*(ap*fItop)) # A/F +ass = 1.0/(exp((-((EKshift + v) - 1*14.34))/14.82) + 1.0) +assp = 1.0/(exp((-((EKshift + v) - 1*24.34))/14.82) + 1.0) +delta_epi = Conditional(Eq(celltype, 1.0), 1.0 - 0.95/(exp(((EKshift + v) + 70.0)/5.0) + 1.0), 1.0) +dti_develop = 1.354 + 0.0001/(exp((-((EKshift + v) - 1*12.23))/0.2154) + exp(((EKshift + v) - 1*167.4)/15.89)) +dti_recover = 1.0 - 0.5/(exp(((EKshift + v) + 70.0)/20.0) + 1.0) +fItop = 1.0/(1.0 + KmCaMK/CaMKa) +i = AiF*iF + AiS*iS +ip = AiF*iFp + AiS*iSp +iss = 1.0/(exp(((EKshift + v) + 43.94)/5.711) + 1.0) +ta = 1.0515/(1.0/((1.2089*(exp((-((EKshift + v) - 1*18.4099))/29.3814) + 1.0))) + 3.5/(exp(((EKshift + v) + 100.0)/29.3814) + 1.0)) # ms +tiF = delta_epi*tiF_b # ms +tiF_b = 4.562 + 1.0/(0.3933*exp((-((EKshift + v) + 100.0))/100.0) + 0.08004*exp(((EKshift + v) + 50.0)/16.59)) # ms +tiFp = tiF*(dti_develop*dti_recover) # ms +tiS = delta_epi*tiS_b # ms +tiS_b = 23.62 + 1.0/(0.001416*exp((-((EKshift + v) + 96.52))/59.05) + 1.78e-8*exp(((EKshift + v) + 114.1)/8.079)) # ms +tiSp = tiS*(dti_develop*dti_recover) # ms +da_dt = (-a + ass)/ta +dap_dt = (-ap + assp)/ta +diF_dt = (-iF + iss)/tiF +diFp_dt = (-iFp + iss)/tiFp +diS_dt = (-iS + iss)/tiS +diSp_dt = (-iSp + iss)/tiSp + +expressions("intracellular_ions") +Bcajsr = 1.0/((csqnmax*kmcsqn)/((cajsr + kmcsqn)**2.0) + 1.0) +Bcass = 1.0/((BSLmax*KmBSL)/((KmBSL + cass)**2.0) + ((BSRmax*KmBSR)/((KmBSR + cass)**2.0) + 1.0)) +cmdnmax = Conditional(Eq(celltype, 1.0), 1.3*cmdnmax_b, cmdnmax_b) # mM +dcajsr_dt = Bcajsr*(-Jrel + Jtr) # mM +dcansr_dt = Jup - Jtr*vjsr/vnsr # mM +dcass_dt = Bcass*(-Jdiff + ((Acap*(-(ICaL_ss - 2.0*INaCa_ss)))/(((2.0*F)*vss)) + (Jrel*vjsr)/vss)) # mM +dcli_dt = (Acap*(IClCa_sl + IClb))/((F*vmyo)) + (JdiffCl*vss)/vmyo # mM +dclss_dt = -JdiffCl + (Acap*IClCa_junc)/((F*vss)) # mM +dki_dt = (Acap*(-(ICaK_i + (-2.0*INaK_INaK + (Istim + (I_katp_I_katp + (IKb_IKb + (IK1_IK1 + (IKs_IKs + (IKr_IKr + Ito_Ito))))))))))/((F*vmyo)) + (JdiffK*vss)/vmyo # mM +dkss_dt = -JdiffK + (Acap*(-ICaK_ss))/((F*vss)) # mM +dnai_dt = (Acap*(-(INab_INab + (3.0*INaK_INaK + (ICaNa_i + (3.0*INaCa_i + (INaL_INaL + INa_INa)))))))/((F*vmyo)) + (JdiffNa*vss)/vmyo # mM +dnass_dt = -JdiffNa + (Acap*(-(ICaNa_ss + 3.0*INaCa_ss)))/((F*vss)) # mM +lambda_min12 = Conditional(Lt(lmbda, 1.2), lmbda, 1.2) +dcai_dt=Bcai*(-(IpCa_IpCa+ICab_ICab-2.0*INaCa_i/3)*Acap/(2.0*F*vmyo)-Jup*vnsr/vmyo+Jdiff*vss/vmyo - J_TRPN) +cat50 = (cat50_ref+Beta1*(lambda_min12-1)) +dCaTrpn_dt = ktrpn*(((cai*1000/cat50)**ntrpn)*(1-CaTrpn)-CaTrpn) +Bcai=1.0/(1.0+cmdnmax*kmcmdn/(kmcmdn+cai)**2.0) +J_TRPN = dCaTrpn_dt*trpnmax + + +expressions("CaMK") +CaMKa = CaMKb + CaMKt # mM +CaMKb = (CaMKo*(1.0 - CaMKt))/(KmCaM/cass + 1.0) # mM +dCaMKt_dt = -CaMKt*bCaMK + (CaMKb*aCaMK)*(CaMKb + CaMKt) # mM + +expressions("INaK") +E1_ = x1/(x4 + (x3 + (x1 + x2))) +E2 = x2/(x4 + (x3 + (x1 + x2))) +E3 = x3/(x4 + (x3 + (x1 + x2))) +E4 = x4/(x4 + (x3 + (x1 + x2))) +INaK_INaK = Pnak*(JnakK*zk + JnakNa*zna) # A/F +JnakK = 2.0*(-E3*a1 + E4*b1) # mM/ms +JnakNa = 3.0*(E1_*a3 - E2*b3) # mM/ms +Knai = Knai0*exp((delta*vfrt)/3.0) # mM +Knao = Knao0*exp((vfrt*(1.0 - delta))/3.0) # mM +P = eP/(((H/Khp + 1.0) + nai/Knap) + ki/Kxkur) +Pnak = Conditional(Eq(celltype, 1.0), 0.9*Pnak_b, Conditional(Eq(celltype, 2.0), 0.7*Pnak_b, Pnak_b)) # mS/uF +a1 = (k1p*(nai/Knai)**3.0)/(((1.0 + ki/Kki)**2.0 + (1.0 + nai/Knai)**3.0) - 1*1.0) +a2 = k2p +a3 = (k3p*(ko/Kko)**2.0)/(((1.0 + ko/Kko)**2.0 + (1.0 + nao/Knao)**3.0) - 1*1.0) +a4 = ((MgATP*k4p)/Kmgatp)/(1.0 + MgATP/Kmgatp) +b1 = MgADP*k1m +b2 = (k2m*(nao/Knao)**3.0)/(((1.0 + ko/Kko)**2.0 + (1.0 + nao/Knao)**3.0) - 1*1.0) +b3 = (H*(P*k3m))/(1.0 + MgATP/Kmgatp) +b4 = (k4m*(ki/Kki)**2.0)/(((1.0 + ki/Kki)**2.0 + (1.0 + nai/Knai)**3.0) - 1*1.0) +x1 = a2*(a1*b3) + (b3*(a2*b4) + (a2*(a1*a4) + b3*(b2*b4))) +x2 = b4*(a2*a3) + (b4*(a3*b1) + (a3*(a1*a2) + b4*(b1*b2))) +x3 = b1*(a3*a4) + (a4*(b1*b2) + (a4*(a2*a3) + b1*(b2*b3))) +x4 = a1*(b2*b3) + (a1*(a4*b2) + (a1*(a3*a4) + b2*(b3*b4))) + +expressions("INaCa") +E1_i = x1_i/(x4_i + (x3_i + (x1_i + x2_i))) +E1_ss = x1_ss/(x4_ss + (x3_ss + (x1_ss + x2_ss))) +E2_i = x2_i/(x4_i + (x3_i + (x1_i + x2_i))) +E2_ss = x2_ss/(x4_ss + (x3_ss + (x1_ss + x2_ss))) +E3_i = x3_i/(x4_i + (x3_i + (x1_i + x2_i))) +E3_ss = x3_ss/(x4_ss + (x3_ss + (x1_ss + x2_ss))) +E4_i = x4_i/(x4_i + (x3_i + (x1_i + x2_i))) +E4_ss = x4_ss/(x4_ss + (x3_ss + (x1_ss + x2_ss))) +Gncx = Conditional(Eq(celltype, 1.0), 1.1*Gncx_b, Conditional(Eq(celltype, 2.0), 1.4*Gncx_b, Gncx_b)) # mS/uF +INaCa_i = (allo_i*(Gncx*(1.0 - INaCa_fractionSS)))*(JncxCa_i*zca + JncxNa_i*zna) # A/F +INaCa_ss = (allo_ss*(Gncx*INaCa_fractionSS))*(JncxCa_ss*zca + JncxNa_ss*zna) # A/F +JncxCa_i = -E1_i*k1_i + E2_i*k2_i # mM/ms +JncxCa_ss = -E1_ss*k1_ss + E2_ss*k2_ss # mM/ms +JncxNa_i = -E2_i*k3pp_i + (E3_i*k4pp_i + 3.0*(-E1_i*k8_i + E4_i*k7_i)) # mM/ms +JncxNa_ss = -E2_ss*k3pp_ss + (E3_ss*k4pp_ss + 3.0*(-E1_ss*k8_ss + E4_ss*k7_ss)) # mM/ms +allo_i = 1.0/((KmCaAct/cai)**2.0 + 1.0) +allo_ss = 1.0/((KmCaAct/cass)**2.0 + 1.0) +h10_i = (nao/kna1)*(1.0 + nao/kna2) + (kasymm + 1.0) +h10_ss = (nao/kna1)*(1.0 + nao/kna2) + (kasymm + 1.0) +h11_i = (nao*nao)/((kna2*(h10_i*kna1))) +h11_ss = (nao*nao)/((kna2*(h10_ss*kna1))) +h12_i = 1.0/h10_i +h12_ss = 1.0/h10_ss +h1_i = (nai/kna3)*(hna + 1.0) + 1.0 +h1_ss = (nass/kna3)*(hna + 1.0) + 1.0 +h2_i = (hna*nai)/((h1_i*kna3)) +h2_ss = (hna*nass)/((h1_ss*kna3)) +h3_i = 1.0/h1_i +h3_ss = 1.0/h1_ss +h4_i = (nai/kna1)*(1.0 + nai/kna2) + 1.0 +h4_ss = (nass/kna1)*(1.0 + nass/kna2) + 1.0 +h5_i = (nai*nai)/((kna2*(h4_i*kna1))) +h5_ss = (nass*nass)/((kna2*(h4_ss*kna1))) +h6_i = 1.0/h4_i +h6_ss = 1.0/h4_ss +h7_i = (nao/kna3)*(1.0 + 1.0/hna) + 1.0 +h7_ss = (nao/kna3)*(1.0 + 1.0/hna) + 1.0 +h8_i = nao/((h7_i*(hna*kna3))) +h8_ss = nao/((h7_ss*(hna*kna3))) +h9_i = 1.0/h7_i +h9_ss = 1.0/h7_ss +hca = exp(qca*vfrt) +hna = exp(qna*vfrt) +k1_i = kcaon*(cao*h12_i) +k1_ss = kcaon*(cao*h12_ss) +k2_i = kcaoff +k2_ss = kcaoff +k3_i = k3p_i + k3pp_i +k3_ss = k3p_ss + k3pp_ss +k3p_i = h9_i*wca +k3p_ss = h9_ss*wca +k3pp_i = h8_i*wnaca +k3pp_ss = h8_ss*wnaca +k4_i = k4p_i + k4pp_i +k4_ss = k4p_ss + k4pp_ss +k4p_i = (h3_i*wca)/hca +k4p_ss = (h3_ss*wca)/hca +k4pp_i = h2_i*wnaca +k4pp_ss = h2_ss*wnaca +k5_i = kcaoff +k5_ss = kcaoff +k6_i = kcaon*(cai*h6_i) +k6_ss = kcaon*(cass*h6_ss) +k7_i = wna*(h2_i*h5_i) +k7_ss = wna*(h2_ss*h5_ss) +k8_i = wna*(h11_i*h8_i) +k8_ss = wna*(h11_ss*h8_ss) +x1_i = (k2_i*k4_i)*(k6_i + k7_i) + (k5_i*k7_i)*(k2_i + k3_i) +x1_ss = (k2_ss*k4_ss)*(k6_ss + k7_ss) + (k5_ss*k7_ss)*(k2_ss + k3_ss) +x2_i = (k1_i*k7_i)*(k4_i + k5_i) + (k4_i*k6_i)*(k1_i + k8_i) +x2_ss = (k1_ss*k7_ss)*(k4_ss + k5_ss) + (k4_ss*k6_ss)*(k1_ss + k8_ss) +x3_i = (k1_i*k3_i)*(k6_i + k7_i) + (k6_i*k8_i)*(k2_i + k3_i) +x3_ss = (k1_ss*k3_ss)*(k6_ss + k7_ss) + (k6_ss*k8_ss)*(k2_ss + k3_ss) +x4_i = (k2_i*k8_i)*(k4_i + k5_i) + (k3_i*k5_i)*(k1_i + k8_i) +x4_ss = (k2_ss*k8_ss)*(k4_ss + k5_ss) + (k3_ss*k5_ss)*(k1_ss + k8_ss) + +expressions("reversal_potentials") +ECl = ((R*T)/((F*zcl)))*log(clo/cli) # mV +EClss = ((R*T)/((F*zcl)))*log(clo/clss) # mV +EK = ((R*T)/((F*zk)))*log(ko/ki) # mV +EKs = ((R*T)/((F*zk)))*log((PKNa*nao + ko)/(PKNa*nai + ki)) # mV +ENa = ((R*T)/((F*zna)))*log(nao/nai) # mV + +expressions("IK1") +GK1 = Conditional(Eq(celltype, 1.0), 1.2*GK1_b, Conditional(Eq(celltype, 2.0), 1.3*GK1_b, GK1_b)) # mS/uF +IK1_IK1 = (K1ss*(GK1*sqrt(ko/5.0)))*(-EK + v) # A/F +K1ss = aK1/(aK1 + bK1) +aK1 = 4.094/(exp(0.1217*((-EK + v) - 1*49.934)) + 1.0) +bK1 = (15.72*exp(0.0674*((-EK + v) - 1*3.257)) + exp(0.0618*((-EK + v) - 1*594.31)))/(exp((-1*0.1629)*((-EK + v) + 14.207)) + 1.0) + +expressions("IKb") +GKb = Conditional(Eq(celltype, 1.0), 0.6*GKb_b, GKb_b) # mS/uF +IKb_IKb = (GKb*xkb)*(-EK + v) # A/F +xkb = 1.0/(exp((-(v - 1*10.8968))/23.9871) + 1.0) + +expressions("IKr") +GKr = Conditional(Eq(celltype, 1.0), 1.3*GKr_b, Conditional(Eq(celltype, 2.0), 0.8*GKr_b, GKr_b)) # mS/uF +IKr_IKr = (O_*(GKr*sqrt(ko/5.0)))*(-EK + v) # A/F +alpha = 0.1161*exp(0.299*vfrt) # mS/uF +alpha_2 = 0.0578*exp(0.971*vfrt) # mS/uF +alpha_C2ToI = 5.2e-5*exp(1.525*vfrt) # mS/uF +alpha_i = 0.2533*exp(0.5953*vfrt) # mS/uF +beta_ = 0.2442*exp((-1*1.604)*vfrt) # mS/uF +beta_2 = 0.000349*exp((-1*1.062)*vfrt) # mS/uF +beta_ItoC2 = (alpha_C2ToI*(beta_2*beta_i))/((alpha_2*alpha_i)) # mS/uF +beta_i = 0.06525*exp((-1*0.8209)*vfrt) # mS/uF +dC1_dt = -C1*(alpha_C2ToI + (alpha_2 + beta_1)) + (I_*beta_ItoC2 + (C2*alpha_1 + O_*beta_2)) +dC2_dt = -C2*(alpha_1 + beta_) + (C1*beta_1 + C3*alpha) +dC3_dt = C2*beta_ - C3*alpha +dI__dt = -I_*(beta_ItoC2 + beta_i) + (C1*alpha_C2ToI + O_*alpha_i) +dO__dt = -O_*(alpha_i + beta_2) + (C1*alpha_2 + I_*beta_i) + +expressions("IKs") +GKs = Conditional(Eq(celltype, 1.0), 1.4*GKs_b, GKs_b) # mS/uF +IKs_IKs = (xs2*(xs1*(GKs*KsCa)))*(-EKs + v) # A/F +KsCa = 1.0 + 0.6/((3.8e-5/cai)**1.4 + 1.0) +txs1 = 817.3 + 1.0/(0.0002326*exp((v + 48.28)/17.8) + 0.001292*exp((-(v + 210.0))/230.0)) # ms +txs2 = 1.0/(0.01*exp((v - 1*50.0)/20.0) + 0.0193*exp((-(v + 66.54))/31.0)) # ms +xs1ss = 1.0/(exp((-(v + 11.6))/8.932) + 1.0) +xs2ss = xs1ss +dxs1_dt = (-xs1 + xs1ss)/txs1 +dxs2_dt = (-xs2 + xs2ss)/txs2 + +expressions("INaL") +GNaL = Conditional(Eq(celltype, 1.0), 0.6*GNaL_b, GNaL_b) # mS/uF +INaL_INaL = (mL*(GNaL*(-ENa + v)))*(fINaLp*hLp + hL*(1.0 - fINaLp)) # A/F +fINaLp = 1.0/(1.0 + KmCaMK/CaMKa) +hLss = 1.0/(exp((v + 87.61)/7.488) + 1.0) +hLssp = 1.0/(exp((v + 93.81)/7.488) + 1.0) +mLss = 1.0/(exp((-(v + 42.85))/5.264) + 1.0) +thLp = 3.0*thL # ms +tmL = 0.06487*exp(-((v - 1*4.823)/51.12)**2.0) + 0.1292*exp(-((v + 45.79)/15.54)**2.0) # ms +dhL_dt = (-hL + hLss)/thL +dhLp_dt = (-hLp + hLssp)/thLp +dmL_dt = (-mL + mLss)/tmL + +expressions("ICab") +ICab_ICab = ((vffrt*(PCab*4.0))*(-cao*gamma_cao + (cai*gamma_cai)*exp(2.0*vfrt)))/(exp(2.0*vfrt) - 1*1.0) # A/F + +expressions("ICl") +IClCa = IClCa_junc + IClCa_sl # A/F +IClCa_junc = ((Fjunc*GClCa)/(KdClCa/cass + 1.0))*(-EClss + v) # A/F +IClCa_sl = ((GClCa*(1.0 - Fjunc))/(KdClCa/cai + 1.0))*(-ECl + v) # A/F +IClb = GClb*(-ECl + v) # A/F + +expressions("INa") +INa_INa = (m**3.0*(GNa*(-ENa + v)))*(j*(h*(1.0 - fINap)) + jp*(fINap*hp)) # A/F +ah = Conditional(Gt(v, -1*40.0), 0.0, 4.43126792958051e-7*exp(-0.147058823529412*v)) +aj = Conditional(Gt(v, -1*40.0), 0.0, -(v + 37.78)*(25428.0*exp(0.28831*v) + 6.948e-6)*exp(-0.04391*v)/(50262745825.954*exp(0.311*v) + 1.0)) +bh = Conditional(Gt(v, -1*40.0), 0.77*exp(0.0900900900900901*v)/(0.13*exp(0.0900900900900901*v) + 0.0497581410839387), 2.7*exp(0.079*v) + 310000.0*exp(0.3485*v)) +bj = Conditional(Gt(v, -1*40.0), 0.6*exp(0.157*v)/(1.0*exp(0.1*v) + 0.0407622039783662), 0.02424*exp(0.12728*v)/(1.0*exp(0.1378*v) + 0.00396086833990426)) +fINap = 1.0/(1.0 + KmCaMK/CaMKa) +hss = 1.0/((exp((v + 71.55)/7.43) + 1.0)**2.0) +hssp = 1.0/((exp((v + 77.55)/7.43) + 1.0)**2.0) +jss = hss +mss = 1.0/((exp((-(v + 56.86))/9.03) + 1.0)**2.0) +th = 1.0/(ah + bh) # ms +tj = 1.0/(aj + bj) # ms +tjp = 1.46*tj # ms +tm = 0.06487*exp(-((v - 1*4.823)/51.12)**2.0) + 0.1292*exp(-((v + 45.79)/15.54)**2.0) # ms +dh_dt = (-h + hss)/th +dhp_dt = (-hp + hssp)/th +dj_dt = (-j + jss)/tj +djp_dt = (-jp + jss)/tjp +dm_dt = (-m + mss)/tm + +expressions("INab") +INab_INab = ((PNab*vffrt)*(nai*exp(vfrt) - nao))/(exp(vfrt) - 1*1.0) # A/F + +expressions("I_katp") +I_katp_I_katp = (bkik*(akik*(fkatp*gkatp)))*(-EK + v) # A/F +akik = (ko/K_o_n)**0.24 +bkik = 1.0/((A_atp/K_atp)**2.0 + 1.0) + +expressions("IpCa") +IpCa_IpCa = (GpCa*cai)/(KmCap + cai) # A/F + +expressions("membrane") +Istim = Conditional(And(Le(i_Stim_Start, time), Ge(i_Stim_PulseDuration, -i_Stim_Period*floor(-(i_Stim_Start - time)/i_Stim_Period) - i_Stim_Start + time)), i_Stim_Amplitude, 0.0) # A/F +vffrt = (F*(F*v))/((R*T)) # C/mol +vfrt = (F*v)/((R*T)) +dv_dt = -(Istim + (I_katp_I_katp + (IClb + (IClCa + (ICab_ICab + (IpCa_IpCa + (IKb_IKb + (INab_INab + (INaK_INaK + (INaCa_ss + (INaCa_i + (IK1_IK1 + (IKs_IKs + (IKr_IKr + (ICaK + (ICaNa + (ICaL_ICaL + (Ito_Ito + (INaL_INaL + INa_INa))))))))))))))))))) # mV + +expressions("diff") +Jdiff = (-cai + cass)/tauCa # mM/ms +JdiffCl = (-cli + clss)/tauNa # mM/ms +JdiffK = (-ki + kss)/tauK # mM/ms +JdiffNa = (-nai + nass)/tauNa # mM/ms + +expressions("SERCA") +Jleak = (0.0048825*cansr)/15.0 # mM/ms +Jup = Jup_b*(-Jleak + (Jupnp*(1.0 - fJupp) + Jupp*fJupp)) # mM/ms +Jupnp = (cai*(upScale*0.005425))/(cai + 0.00092) # mM/ms +Jupp = (cai*((upScale*2.75)*0.005425))/((cai + 0.00092) - 1*0.00017) # mM/ms +fJupp = 1.0/(1.0 + KmCaMK/CaMKa) +upScale = Conditional(Eq(celltype, 1.0), 1.3, 1.0) + +expressions("ryr") +Jrel = Jrel_b*(Jrel_np*(1.0 - fJrelp) + Jrel_p*fJrelp) # mM/ms +Jrel_inf = Conditional(Eq(celltype, 2.0), 1.7*Jrel_inf_b, Jrel_inf_b) # mM/ms +Jrel_inf_b = ((ICaL_ss*(-a_rel))/1.0)/((cajsr_half/cajsr)**8.0 + 1.0) # mM/ms +Jrel_infp = Conditional(Eq(celltype, 2.0), 1.7*Jrel_infp_b, Jrel_infp_b) # mM/ms +Jrel_infp_b = ((ICaL_ss*(-a_relp))/1.0)/((cajsr_half/cajsr)**8.0 + 1.0) # mM/ms +a_rel = (0.5*bt)/1.0 # mM/ms +a_relp = (0.5*btp)/1.0 # mM/ms +btp = 1.25*bt # ms +fJrelp = 1.0/(1.0 + KmCaMK/CaMKa) +tau_rel = Conditional(Lt(tau_rel_b, 0.001), 0.001, tau_rel_b) # ms +tau_rel_b = bt/(1.0 + 0.0123/cajsr) # ms +tau_relp = Conditional(Lt(tau_relp_b, 0.001), 0.001, tau_relp_b) # ms +tau_relp_b = btp/(1.0 + 0.0123/cajsr) # ms +dJrel_np_dt = (Jrel_inf - Jrel_np)/tau_rel # mM/ms +dJrel_p_dt = (Jrel_infp - Jrel_p)/tau_relp # mM/ms + +expressions("trans_flux") +Jtr = (-cajsr + cansr)/60.0 # mM/ms + + +states("intracellular_ions", +cai=0.0001, +CaTrpn=1e-8 +) + +states("mechanics", +XS=0, +XW=0, +TmB=1, +Zetas=0, +Zetaw=0, +Cd=0) + +parameters("mechanics", +emcoupling=1, +lmbda=1, +dLambda=0, +mode=1, +isacs=0, +calib=1, +ktrpn = 0.1, +ntrpn = 2, +Trpn50 = 0.35, +rw = 0.5, +rs = 0.25, +gammas = 0.0085, +gammaw = 0.615, +phi = 2.23, +Tot_A = 25, +Beta0 = 2.3, +Beta1 = -2.4, +cat50_ref = 0.805, +Tref = 120, +kuw = 0.182, +kws = 0.012, +ku=0.04, +ntm=2.4, +p_a = 2.1, +p_b = 9.1, +p_k = 7, +etal = 200, +etas = 20) + +expressions("mechanics") +XS_max = Conditional(Gt(XS, 0), XS, 0) +XW_max = Conditional(Gt(XW, 0), XW, 0) +CaTrpn_max = Conditional(Gt(CaTrpn, 0), CaTrpn, 0) +kwu = kuw*(1/rw-1)-kws +ksu = kws*rw*(1/rs-1) +Aw = Tot_A*rs/((1-rs)*rw+rs) +As = Aw +cw = phi*kuw*((1-rs)*(1-rw))/((1-rs)*rw) +cs = phi*kws*((1-rs)*rw)/rs +lambda_min12 = Conditional(Lt(lmbda, 1.2), lmbda, 1.2) +lambda_min087 = Conditional(Lt(lambda_min12, 0.87), lambda_min12, 0.87) +h_lambda_prima = 1+Beta0*(lambda_min12+lambda_min087-1.87) +h_lambda = Conditional(Gt(h_lambda_prima, 0), h_lambda_prima, 0) +XU = (1-TmB)-XS-XW +gammawu = gammaw*Abs(Zetaw) +gammasu = gammas*Conditional(Gt(Gt(Zetas,0)*Zetas, Lt(Zetas, -1)*(-Zetas-1)), Gt(Zetas,0)*Zetas, Lt(Zetas, -1)*(-Zetas-1)) +dXS_dt = kws*XW - ksu*XS - gammasu*XS +dXW_dt = kuw*XU - kwu*XW - kws*XW - gammawu*XW +kb = ku*Trpn50**ntm/(1-rs-(1-rs)*rw) +dTmB_dt = kb*Conditional(Lt(CaTrpn**(-ntm/2), 100), CaTrpn**(-ntm/2), 100)*XU-ku*CaTrpn**(ntm/2)*TmB +dZetas_dt = As*dLambda - cs*Zetas +dZetaw_dt = Aw*dLambda - cw*Zetaw +Ta = h_lambda*(Tref/rs)*(XS*(Zetas+1) + XW*Zetaw) +C = lambda_min12 - 1 +dCd = C - Cd +eta = Conditional(Lt(dCd, 0), etas, etal) +dCd_dt = p_k * (C - Cd) / eta +Fd = eta * dCd +F1 = (exp( p_b * C) - 1) +Tp = p_a * (F1 + Fd) +Ttot = Ta + Tp diff --git a/numerical_experiments/odefiles/ToRORd_dynCl_endo_zetasplit.ode b/numerical_experiments/odefiles/ToRORd_dynCl_endo_zetasplit.ode new file mode 100644 index 0000000..11e38f0 --- /dev/null +++ b/numerical_experiments/odefiles/ToRORd_dynCl_endo_zetasplit.ode @@ -0,0 +1,722 @@ +states("IKr", +C1=ScalarParam(0.9982511, unit="1", description=""), +C2=ScalarParam( 7.93602000000000023e-4, unit="1", description=""), +C3=ScalarParam( 6.53214300000000045e-4, unit="1", description=""), +I_=ScalarParam( 9.80408300000000003e-6, unit="1", description=""), +O_=ScalarParam( 2.92244900000000025e-4, unit="1", description="") +) + +states("CaMK", +CaMKt=ScalarParam( 1.09502599999999999e-2, unit="mM", description="") +) + +states("ryr", +Jrel_np=ScalarParam( 1.80824799999999996e-22, unit="mM/ms", description=""), +Jrel_p=ScalarParam( 4.35860800000000030e-21, unit="mM/ms", description="") +) + +states("Ito", +a=ScalarParam( 8.89925900000000051e-4, unit="1", description=""), +ap=ScalarParam( 4.53416500000000005e-4, unit="1", description=""), +iF=ScalarParam(0.9996716, unit="1", description=""), +iFp=ScalarParam(0.9996716, unit="1", description=""), +iS=ScalarParam(0.5988908, unit="1", description=""), +iSp=ScalarParam(0.6620692, unit="1", description="") +) + +states("intracellular_ions", +cajsr=ScalarParam(1.525693, unit="mM", description=""), +cansr=ScalarParam(1.528001, unit="mM", description=""), +cass=ScalarParam( 6.49734100000000044e-5, unit="mM", description=""), +cli=ScalarParam(29.20698, unit="mM", description=""), +clss=ScalarParam(29.20696, unit="mM", description=""), +ki=ScalarParam(147.7115, unit="mM", description=""), +kss=ScalarParam(147.7114, unit="mM", description=""), +nai=ScalarParam(12.39736, unit="mM", description=""), +nass=ScalarParam(12.3977, unit="mM", description="") +) + +states("ICaL", +d=ScalarParam( 1.58884100000000000e-31, unit="1", description=""), +fcaf=ScalarParam(1, unit="1", description=""), +fcafp=ScalarParam(1, unit="1", description=""), +fcas=ScalarParam(0.9999014, unit="1", description=""), +ff_=ScalarParam(1, unit="1", description=""), +ffp=ScalarParam(1, unit="1", description=""), +fs=ScalarParam(0.9401791, unit="1", description=""), +jca=ScalarParam(0.9999846, unit="1", description=""), +nca_i=ScalarParam( 8.32600900000000053e-4, unit="1", description=""), +nca_ss=ScalarParam( 4.89937800000000024e-4, unit="1", description="") +) + +states("INa", +h=ScalarParam(0.8473267, unit="1", description=""), +hp=ScalarParam(0.7018454, unit="1", description=""), +j=ScalarParam(0.8471657, unit="1", description=""), +jp=ScalarParam(0.8469014, unit="1", description=""), +m=ScalarParam( 6.51715400000000005e-4, unit="1", description="") +) + +states("INaL", +hL=ScalarParam(0.5566017, unit="1", description=""), +hLp=ScalarParam(0.3115491, unit="1", description=""), +mL=ScalarParam( 1.35120299999999988e-4, unit="1", description="") +) + +states("membrane", +v=ScalarParam(-89.74808, unit="mV", description="") +) + +states("IKs", +xs1=ScalarParam(0.243959, unit="1", description=""), +xs2=ScalarParam( 1.58616700000000009e-4, unit="1", description="") +) + +parameters("I_katp", +A_atp=ScalarParam(2.0, unit="mM", description=""), +K_atp=ScalarParam(0.25, unit="mM", description=""), +K_o_n=ScalarParam(5.0, unit="mM", description=""), +fkatp=ScalarParam(0.0, unit="1", description=""), +gkatp=ScalarParam(4.3195, unit="mS/uF", description="") +) + +parameters("ICaL", +Aff=ScalarParam(0.6, unit="1", description=""), +ICaL_fractionSS=ScalarParam(0.8, unit="1", description=""), +Kmn=ScalarParam(0.002, unit="mM", description=""), +PCa_b=ScalarParam(8.3757e-05, unit="1", description=""), +dielConstant=ScalarParam(74.0, unit="1/K", description=""), +k2n=ScalarParam(500.0, unit="mS/uF", description=""), +offset=ScalarParam(0.0, unit="ms", description=""), +tjca=ScalarParam(72.5, unit="ms", description=""), +vShift=ScalarParam(0.0, unit="mV", description="") +) + +parameters("intracellular_ions","mechanics", +BSLmax=ScalarParam(1.124, unit="mM", description=""), +BSRmax=ScalarParam(0.047, unit="mM", description=""), +KmBSL=ScalarParam(0.0087, unit="mM", description=""), +KmBSR=ScalarParam(0.00087, unit="mM", description=""), +cmdnmax_b=ScalarParam(0.05, unit="mM", description=""), +csqnmax=ScalarParam(10.0, unit="mM", description=""), +kmcmdn=ScalarParam(0.00238, unit="mM", description=""), +kmcsqn=ScalarParam(0.8, unit="mM", description=""), +kmtrpn=ScalarParam(0.0005, unit="mM", description=""), +trpnmax=ScalarParam(0.07, unit="mM", description="") +) + +parameters("CaMK", +CaMKo=ScalarParam(0.05, unit="1", description=""), +KmCaM=ScalarParam(0.0015, unit="mM", description=""), +KmCaMK=ScalarParam(0.15, unit="mM", description=""), +aCaMK=ScalarParam(0.05, unit="1/mM/ms", description=""), +bCaMK=ScalarParam(0.00068, unit="mS/uF", description="") +) + +parameters("Ito", +EKshift=ScalarParam(0.0, unit="mV", description=""), +Gto_b=ScalarParam(0.16, unit="mS/uF", description="") +) + +parameters("physical_constants","mechanics", +F=ScalarParam(96485.0, unit="C/mol", description=""), +R=ScalarParam(8314.0, unit="mJ/mol/K", description=""), +T=ScalarParam(310.0, unit="K", description=""), +zca=ScalarParam(2.0, unit="1", description=""), +zcl=ScalarParam(-1.0, unit="1", description=""), +zk=ScalarParam(1.0, unit="1", description=""), +zna=ScalarParam(1.0, unit="1", description="") +) + +parameters("ICl", +Fjunc=ScalarParam(1.0, unit="1", description=""), +GClCa=ScalarParam(0.2843, unit="mS/uF", description=""), +GClb=ScalarParam(0.00198, unit="mS/uF", description=""), +KdClCa=ScalarParam(0.1, unit="mM", description="") +) + +parameters("IK1", +GK1_b=ScalarParam(0.6992, unit="mS/uF", description="") +) + +parameters("IKb", +GKb_b=ScalarParam(0.0189, unit="mS/uF", description="") +) + +parameters("IKr", +GKr_b=ScalarParam(0.0321, unit="mS/uF", description=""), +alpha_1=ScalarParam(0.154375, unit="mS/uF", description=""), +beta_1=ScalarParam(0.1911, unit="mS/uF", description="") +) + +parameters("IKs", +GKs_b=ScalarParam(0.0011, unit="mS/uF", description="") +) + +parameters("INa", +GNa=ScalarParam(11.7802, unit="mS/uF", description="") +) + +parameters("INaL", +GNaL_b=ScalarParam(0.0279, unit="mS/uF", description=""), +thL=ScalarParam(200.0, unit="ms", description="") +) + +parameters("INaCa", +Gncx_b=ScalarParam(0.0034, unit="mS/uF", description=""), +INaCa_fractionSS=ScalarParam(0.35, unit="1", description=""), +KmCaAct=ScalarParam(0.00015, unit="mM", description=""), +kasymm=ScalarParam(12.5, unit="1", description=""), +kcaoff=ScalarParam(5000.0, unit="mS/uF", description=""), +kcaon=ScalarParam(1500000.0, unit="mS/uF", description=""), +kna1=ScalarParam(15.0, unit="mS/uF", description=""), +kna2=ScalarParam(5.0, unit="mS/uF", description=""), +kna3=ScalarParam(88.12, unit="mS/uF", description=""), +qca=ScalarParam(0.167, unit="1", description=""), +qna=ScalarParam(0.5224, unit="1", description=""), +wca=ScalarParam(60000.0, unit="1", description=""), +wna=ScalarParam(60000.0, unit="1", description=""), +wnaca=ScalarParam(5000.0, unit="1", description="") +) + +parameters("IpCa", +GpCa=ScalarParam(0.0005, unit="mS/uF", description=""), +KmCap=ScalarParam(0.0005, unit="mM", description="") +) + +parameters("INaK", +H=ScalarParam(1e-07, unit="mM", description=""), +Khp=ScalarParam(1.698e-07, unit="mM", description=""), +Kki=ScalarParam(0.5, unit="mS/uF", description=""), +Kko=ScalarParam(0.3582, unit="mS/uF", description=""), +Kmgatp=ScalarParam(1.698e-07, unit="mM", description=""), +Knai0=ScalarParam(9.073, unit="mM", description=""), +Knao0=ScalarParam(27.78, unit="mM", description=""), +Knap=ScalarParam(224.0, unit="mM", description=""), +Kxkur=ScalarParam(292.0, unit="mM", description=""), +MgADP=ScalarParam(0.05, unit="mM", description=""), +MgATP=ScalarParam(9.8, unit="mM", description=""), +Pnak_b=ScalarParam(15.4509, unit="mS/uF", description=""), +delta=ScalarParam(-0.155, unit="mV", description=""), +eP=ScalarParam(4.2, unit="1", description=""), +k1m=ScalarParam(182.4, unit="mS/uF", description=""), +k1p=ScalarParam(949.5, unit="mS/uF", description=""), +k2m=ScalarParam(39.4, unit="mS/uF", description=""), +k2p=ScalarParam(687.2, unit="mS/uF", description=""), +k3m=ScalarParam(79300.0, unit="mS/uF", description=""), +k3p=ScalarParam(1899.0, unit="mS/uF", description=""), +k4m=ScalarParam(40.0, unit="mS/uF", description=""), +k4p=ScalarParam(639.0, unit="mS/uF", description="") +) + +parameters("ryr", +Jrel_b=ScalarParam(1.5378, unit="1", description=""), +bt=ScalarParam(4.75, unit="ms", description=""), +cajsr_half=ScalarParam(1.7, unit="mM", description="") +) + +parameters("SERCA", +Jup_b=ScalarParam(1.0, unit="1", description="") +) + +parameters("cell_geometry","mechanics", +L=ScalarParam(0.01, unit="cm", description=""), +rad_=ScalarParam(0.0011, unit="cm", description="") +) + +parameters("ICab", +PCab=ScalarParam(5.9194e-08, unit="mS/uF", description="") +) + +parameters("reversal_potentials", +PKNa=ScalarParam(0.01833, unit="1", description="") +) + +parameters("INab", +PNab=ScalarParam(1.9239e-09, unit="mS/uF", description="") +) + +parameters("extracellular", +cao=ScalarParam(1.8, unit="mM", description=""), +clo=ScalarParam(150.0, unit="mM", description=""), +ko=ScalarParam(5.0, unit="mM", description=""), +nao=ScalarParam(140.0, unit="mM", description="") +) + +parameters("environment", +celltype=ScalarParam(0.0, unit="1", description="") +) + +parameters("membrane", +i_Stim_Amplitude=ScalarParam(-53.0, unit="A/F", description=""), +i_Stim_End=ScalarParam(1e+17, unit="ms", description=""), +i_Stim_Period=ScalarParam(1000.0, unit="ms", description=""), +i_Stim_PulseDuration=ScalarParam(1.0, unit="ms", description=""), +i_Stim_Start=ScalarParam(0.0, unit="ms", description="") +) + +parameters("diff", +tauCa=ScalarParam(0.2, unit="ms", description=""), +tauCl=ScalarParam(2.0, unit="ms", description=""), +tauK=ScalarParam(2.0, unit="ms", description=""), +tauNa=ScalarParam(2.0, unit="ms", description="") +) + +expressions("cell_geometry", "mechanics") +Acap = 2.0*Ageo # cm**2 +Ageo = L*((2.0*3.14)*rad_) + rad_*((2.0*3.14)*rad_) # cm**2 +vcell = L*(rad_*((1000.0*3.14)*rad_)) # uL +vjsr = 0.0048*vcell # uL +vmyo = 0.68*vcell # uL +vnsr = 0.0552*vcell # uL +vss = 0.02*vcell # uL + +expressions("ICaL") +Afcaf = 0.3 + 0.6/(exp((v - 1*10.0)/10.0) + 1.0) +Afcas = 1.0 - Afcaf +Afs = 1.0 - Aff +ICaK = ICaK_i + ICaK_ss # A/F +ICaK_i = (1.0 - ICaL_fractionSS)*((d*(PhiCaK_i*(PCaK*(1.0 - fICaLp))))*(f*(1.0 - nca_i) + nca_i*(fca*jca)) + (d*(PhiCaK_i*(PCaKp*fICaLp)))*(fp*(1.0 - nca_i) + nca_i*(fcap*jca))) # A/F +ICaK_ss = ICaL_fractionSS*((d*(PhiCaK_ss*(PCaK*(1.0 - fICaLp))))*(f*(1.0 - nca_ss) + nca_ss*(fca*jca)) + (d*(PhiCaK_ss*(PCaKp*fICaLp)))*(fp*(1.0 - nca_ss) + nca_ss*(fcap*jca))) # A/F +ICaL_ICaL = ICaL_i + ICaL_ss # A/F +ICaL_i = (1.0 - ICaL_fractionSS)*((d*(PhiCaL_i*(PCa*(1.0 - fICaLp))))*(f*(1.0 - nca_i) + nca_i*(fca*jca)) + (d*(PhiCaL_i*(PCap*fICaLp)))*(fp*(1.0 - nca_i) + nca_i*(fcap*jca))) # A/F +ICaL_ss = ICaL_fractionSS*((d*(PhiCaL_ss*(PCa*(1.0 - fICaLp))))*(f*(1.0 - nca_ss) + nca_ss*(fca*jca)) + (d*(PhiCaL_ss*(PCap*fICaLp)))*(fp*(1.0 - nca_ss) + nca_ss*(fcap*jca))) # A/F +ICaNa = ICaNa_i + ICaNa_ss # A/F +ICaNa_i = (1.0 - ICaL_fractionSS)*((d*(PhiCaNa_i*(PCaNa*(1.0 - fICaLp))))*(f*(1.0 - nca_i) + nca_i*(fca*jca)) + (d*(PhiCaNa_i*(PCaNap*fICaLp)))*(fp*(1.0 - nca_i) + nca_i*(fcap*jca))) # A/F +ICaNa_ss = ICaL_fractionSS*((d*(PhiCaNa_ss*(PCaNa*(1.0 - fICaLp))))*(f*(1.0 - nca_ss) + nca_ss*(fca*jca)) + (d*(PhiCaNa_ss*(PCaNap*fICaLp)))*(fp*(1.0 - nca_ss) + nca_ss*(fcap*jca))) # A/F +Ii = (0.5*(4.0*cai + (cli + (ki + nai))))/1000.0 +Io = (0.5*(4.0*cao + (clo + (ko + nao))))/1000.0 +Iss = (0.5*(4.0*cass + (clss + (kss + nass))))/1000.0 +PCa = Conditional(Eq(celltype, 1.0), 1.2*PCa_b, Conditional(Eq(celltype, 2.0), 2.0*PCa_b, PCa_b)) +PCaK = 0.0003574*PCa +PCaKp = 0.0003574*PCap +PCaNa = 0.00125*PCa +PCaNap = 0.00125*PCap +PCap = 1.1*PCa +PhiCaK_i = ((1.0*vffrt)*(-gamma_ko*ko + (gamma_ki*ki)*exp(1.0*vfrt)))/(exp(1.0*vfrt) - 1*1.0) +PhiCaK_ss = ((1.0*vffrt)*(-gamma_ko*ko + (gamma_kss*kss)*exp(1.0*vfrt)))/(exp(1.0*vfrt) - 1*1.0) +PhiCaL_i = ((4.0*vffrt)*(-cao*gamma_cao + (cai*gamma_cai)*exp(2.0*vfrt)))/(exp(2.0*vfrt) - 1*1.0) +PhiCaL_ss = ((4.0*vffrt)*(-cao*gamma_cao + (cass*gamma_cass)*exp(2.0*vfrt)))/(exp(2.0*vfrt) - 1*1.0) +PhiCaNa_i = ((1.0*vffrt)*(-gamma_nao*nao + (gamma_nai*nai)*exp(1.0*vfrt)))/(exp(1.0*vfrt) - 1*1.0) +PhiCaNa_ss = ((1.0*vffrt)*(-gamma_nao*nao + (gamma_nass*nass)*exp(1.0*vfrt)))/(exp(1.0*vfrt) - 1*1.0) +anca_i = 1.0/(k2n/km2n + (Kmn/cai + 1.0)**4.0) +anca_ss = 1.0/(k2n/km2n + (Kmn/cass + 1.0)**4.0) +constA = 1820000.0/(T*dielConstant)**1.5 +dss = Conditional(Ge(v, 31.4978), 1.0, 1.0763*exp(-1.007*exp(-0.0829*v))) +f = Aff*ff_ + Afs*fs +fICaLp = 1.0/(1.0 + KmCaMK/CaMKa) +fca = Afcaf*fcaf + Afcas*fcas +fcap = Afcaf*fcafp + Afcas*fcas +fcass = fss +fp = Aff*ffp + Afs*fs +fss = 1.0/(exp((v + 19.58)/3.696) + 1.0) +gamma_cai = exp((-constA*4.0)*(sqrt(Ii)/(sqrt(Ii) + 1.0) - 0.3*Ii)) +gamma_cao = exp((-constA*4.0)*(sqrt(Io)/(sqrt(Io) + 1.0) - 0.3*Io)) +gamma_cass = exp((-constA*4.0)*(sqrt(Iss)/(sqrt(Iss) + 1.0) - 0.3*Iss)) +gamma_ki = exp((-constA*1.0)*(sqrt(Ii)/(sqrt(Ii) + 1.0) - 0.3*Ii)) +gamma_ko = exp((-constA*1.0)*(sqrt(Io)/(sqrt(Io) + 1.0) - 0.3*Io)) +gamma_kss = exp((-constA*1.0)*(sqrt(Iss)/(sqrt(Iss) + 1.0) - 0.3*Iss)) +gamma_nai = exp((-constA*1.0)*(sqrt(Ii)/(sqrt(Ii) + 1.0) - 0.3*Ii)) +gamma_nao = exp((-constA*1.0)*(sqrt(Io)/(sqrt(Io) + 1.0) - 0.3*Io)) +gamma_nass = exp((-constA*1.0)*(sqrt(Iss)/(sqrt(Iss) + 1.0) - 0.3*Iss)) +jcass = 1.0/(exp((v + 18.08)/2.7916) + 1.0) +km2n = jca*1.0 # mS/uF +td = (offset + 0.6) + 1.0/(exp((-1*0.05)*((v + vShift) + 6.0)) + exp(0.09*((v + vShift) + 14.0))) # ms +tfcaf = 7.0 + 1.0/(0.04*exp((-(v - 1*4.0))/7.0) + 0.04*exp((v - 1*4.0)/7.0)) # ms +tfcafp = 2.5*tfcaf # ms +tfcas = 100.0 + 1.0/(0.00012*exp((-v)/3.0) + 0.00012*exp(v/7.0)) # ms +tff = 7.0 + 1.0/(0.0045*exp((-(v + 20.0))/10.0) + 0.0045*exp((v + 20.0)/10.0)) # ms +tffp = 2.5*tff # ms +tfs = 1000.0 + 1.0/(3.5e-5*exp((-(v + 5.0))/4.0) + 3.5e-5*exp((v + 5.0)/6.0)) # ms +dd_dt = (-d + dss)/td +dfcaf_dt = (-fcaf + fcass)/tfcaf +dfcafp_dt = (-fcafp + fcass)/tfcafp +dfcas_dt = (-fcas + fcass)/tfcas +dff__dt = (-ff_ + fss)/tff +dffp_dt = (-ffp + fss)/tffp +dfs_dt = (-fs + fss)/tfs +djca_dt = (-jca + jcass)/tjca +dnca_i_dt = anca_i*k2n - km2n*nca_i +dnca_ss_dt = anca_ss*k2n - km2n*nca_ss + +expressions("Ito") +AiF = 1.0/(exp(((EKshift + v) - 1*213.6)/151.2) + 1.0) +AiS = 1.0 - AiF +Gto = Conditional(Or(Eq(celltype, 1.0), Eq(celltype, 2.0)), 2.0*Gto_b, Gto_b) # mS/uF +Ito_Ito = (Gto*(-EK + v))*(i*(a*(1.0 - fItop)) + ip*(ap*fItop)) # A/F +ass = 1.0/(exp((-((EKshift + v) - 1*14.34))/14.82) + 1.0) +assp = 1.0/(exp((-((EKshift + v) - 1*24.34))/14.82) + 1.0) +delta_epi = Conditional(Eq(celltype, 1.0), 1.0 - 0.95/(exp(((EKshift + v) + 70.0)/5.0) + 1.0), 1.0) +dti_develop = 1.354 + 0.0001/(exp((-((EKshift + v) - 1*12.23))/0.2154) + exp(((EKshift + v) - 1*167.4)/15.89)) +dti_recover = 1.0 - 0.5/(exp(((EKshift + v) + 70.0)/20.0) + 1.0) +fItop = 1.0/(1.0 + KmCaMK/CaMKa) +i = AiF*iF + AiS*iS +ip = AiF*iFp + AiS*iSp +iss = 1.0/(exp(((EKshift + v) + 43.94)/5.711) + 1.0) +ta = 1.0515/(1.0/((1.2089*(exp((-((EKshift + v) - 1*18.4099))/29.3814) + 1.0))) + 3.5/(exp(((EKshift + v) + 100.0)/29.3814) + 1.0)) # ms +tiF = delta_epi*tiF_b # ms +tiF_b = 4.562 + 1.0/(0.3933*exp((-((EKshift + v) + 100.0))/100.0) + 0.08004*exp(((EKshift + v) + 50.0)/16.59)) # ms +tiFp = tiF*(dti_develop*dti_recover) # ms +tiS = delta_epi*tiS_b # ms +tiS_b = 23.62 + 1.0/(0.001416*exp((-((EKshift + v) + 96.52))/59.05) + 1.78e-8*exp(((EKshift + v) + 114.1)/8.079)) # ms +tiSp = tiS*(dti_develop*dti_recover) # ms +da_dt = (-a + ass)/ta +dap_dt = (-ap + assp)/ta +diF_dt = (-iF + iss)/tiF +diFp_dt = (-iFp + iss)/tiFp +diS_dt = (-iS + iss)/tiS +diSp_dt = (-iSp + iss)/tiSp + +expressions("intracellular_ions") +Bcajsr = 1.0/((csqnmax*kmcsqn)/((cajsr + kmcsqn)**2.0) + 1.0) +Bcass = 1.0/((BSLmax*KmBSL)/((KmBSL + cass)**2.0) + ((BSRmax*KmBSR)/((KmBSR + cass)**2.0) + 1.0)) +cmdnmax = Conditional(Eq(celltype, 1.0), 1.3*cmdnmax_b, cmdnmax_b) # mM +dcajsr_dt = Bcajsr*(-Jrel + Jtr) # mM +dcansr_dt = Jup - Jtr*vjsr/vnsr # mM +dcass_dt = Bcass*(-Jdiff + ((Acap*(-(ICaL_ss - 2.0*INaCa_ss)))/(((2.0*F)*vss)) + (Jrel*vjsr)/vss)) # mM +dcli_dt = (Acap*(IClCa_sl + IClb))/((F*vmyo)) + (JdiffCl*vss)/vmyo # mM +dclss_dt = -JdiffCl + (Acap*IClCa_junc)/((F*vss)) # mM +dki_dt = (Acap*(-(ICaK_i + (-2.0*INaK_INaK + (Istim + (I_katp_I_katp + (IKb_IKb + (IK1_IK1 + (IKs_IKs + (IKr_IKr + Ito_Ito))))))))))/((F*vmyo)) + (JdiffK*vss)/vmyo # mM +dkss_dt = -JdiffK + (Acap*(-ICaK_ss))/((F*vss)) # mM +dnai_dt = (Acap*(-(INab_INab + (3.0*INaK_INaK + (ICaNa_i + (3.0*INaCa_i + (INaL_INaL + INa_INa)))))))/((F*vmyo)) + (JdiffNa*vss)/vmyo # mM +dnass_dt = -JdiffNa + (Acap*(-(ICaNa_ss + 3.0*INaCa_ss)))/((F*vss)) # mM + +expressions("CaMK") +CaMKa = CaMKb + CaMKt # mM +CaMKb = (CaMKo*(1.0 - CaMKt))/(KmCaM/cass + 1.0) # mM +dCaMKt_dt = -CaMKt*bCaMK + (CaMKb*aCaMK)*(CaMKb + CaMKt) # mM + +expressions("INaK") +E1_ = x1/(x4 + (x3 + (x1 + x2))) +E2 = x2/(x4 + (x3 + (x1 + x2))) +E3 = x3/(x4 + (x3 + (x1 + x2))) +E4 = x4/(x4 + (x3 + (x1 + x2))) +INaK_INaK = Pnak*(JnakK*zk + JnakNa*zna) # A/F +JnakK = 2.0*(-E3*a1 + E4*b1) # mM/ms +JnakNa = 3.0*(E1_*a3 - E2*b3) # mM/ms +Knai = Knai0*exp((delta*vfrt)/3.0) # mM +Knao = Knao0*exp((vfrt*(1.0 - delta))/3.0) # mM +P = eP/(((H/Khp + 1.0) + nai/Knap) + ki/Kxkur) +Pnak = Conditional(Eq(celltype, 1.0), 0.9*Pnak_b, Conditional(Eq(celltype, 2.0), 0.7*Pnak_b, Pnak_b)) # mS/uF +a1 = (k1p*(nai/Knai)**3.0)/(((1.0 + ki/Kki)**2.0 + (1.0 + nai/Knai)**3.0) - 1*1.0) +a2 = k2p +a3 = (k3p*(ko/Kko)**2.0)/(((1.0 + ko/Kko)**2.0 + (1.0 + nao/Knao)**3.0) - 1*1.0) +a4 = ((MgATP*k4p)/Kmgatp)/(1.0 + MgATP/Kmgatp) +b1 = MgADP*k1m +b2 = (k2m*(nao/Knao)**3.0)/(((1.0 + ko/Kko)**2.0 + (1.0 + nao/Knao)**3.0) - 1*1.0) +b3 = (H*(P*k3m))/(1.0 + MgATP/Kmgatp) +b4 = (k4m*(ki/Kki)**2.0)/(((1.0 + ki/Kki)**2.0 + (1.0 + nai/Knai)**3.0) - 1*1.0) +x1 = a2*(a1*b3) + (b3*(a2*b4) + (a2*(a1*a4) + b3*(b2*b4))) +x2 = b4*(a2*a3) + (b4*(a3*b1) + (a3*(a1*a2) + b4*(b1*b2))) +x3 = b1*(a3*a4) + (a4*(b1*b2) + (a4*(a2*a3) + b1*(b2*b3))) +x4 = a1*(b2*b3) + (a1*(a4*b2) + (a1*(a3*a4) + b2*(b3*b4))) + +expressions("INaCa") +E1_i = x1_i/(x4_i + (x3_i + (x1_i + x2_i))) +E1_ss = x1_ss/(x4_ss + (x3_ss + (x1_ss + x2_ss))) +E2_i = x2_i/(x4_i + (x3_i + (x1_i + x2_i))) +E2_ss = x2_ss/(x4_ss + (x3_ss + (x1_ss + x2_ss))) +E3_i = x3_i/(x4_i + (x3_i + (x1_i + x2_i))) +E3_ss = x3_ss/(x4_ss + (x3_ss + (x1_ss + x2_ss))) +E4_i = x4_i/(x4_i + (x3_i + (x1_i + x2_i))) +E4_ss = x4_ss/(x4_ss + (x3_ss + (x1_ss + x2_ss))) +Gncx = Conditional(Eq(celltype, 1.0), 1.1*Gncx_b, Conditional(Eq(celltype, 2.0), 1.4*Gncx_b, Gncx_b)) # mS/uF +INaCa_i = (allo_i*(Gncx*(1.0 - INaCa_fractionSS)))*(JncxCa_i*zca + JncxNa_i*zna) # A/F +INaCa_ss = (allo_ss*(Gncx*INaCa_fractionSS))*(JncxCa_ss*zca + JncxNa_ss*zna) # A/F +JncxCa_i = -E1_i*k1_i + E2_i*k2_i # mM/ms +JncxCa_ss = -E1_ss*k1_ss + E2_ss*k2_ss # mM/ms +JncxNa_i = -E2_i*k3pp_i + (E3_i*k4pp_i + 3.0*(-E1_i*k8_i + E4_i*k7_i)) # mM/ms +JncxNa_ss = -E2_ss*k3pp_ss + (E3_ss*k4pp_ss + 3.0*(-E1_ss*k8_ss + E4_ss*k7_ss)) # mM/ms +allo_i = 1.0/((KmCaAct/cai)**2.0 + 1.0) +allo_ss = 1.0/((KmCaAct/cass)**2.0 + 1.0) +h10_i = (nao/kna1)*(1.0 + nao/kna2) + (kasymm + 1.0) +h10_ss = (nao/kna1)*(1.0 + nao/kna2) + (kasymm + 1.0) +h11_i = (nao*nao)/((kna2*(h10_i*kna1))) +h11_ss = (nao*nao)/((kna2*(h10_ss*kna1))) +h12_i = 1.0/h10_i +h12_ss = 1.0/h10_ss +h1_i = (nai/kna3)*(hna + 1.0) + 1.0 +h1_ss = (nass/kna3)*(hna + 1.0) + 1.0 +h2_i = (hna*nai)/((h1_i*kna3)) +h2_ss = (hna*nass)/((h1_ss*kna3)) +h3_i = 1.0/h1_i +h3_ss = 1.0/h1_ss +h4_i = (nai/kna1)*(1.0 + nai/kna2) + 1.0 +h4_ss = (nass/kna1)*(1.0 + nass/kna2) + 1.0 +h5_i = (nai*nai)/((kna2*(h4_i*kna1))) +h5_ss = (nass*nass)/((kna2*(h4_ss*kna1))) +h6_i = 1.0/h4_i +h6_ss = 1.0/h4_ss +h7_i = (nao/kna3)*(1.0 + 1.0/hna) + 1.0 +h7_ss = (nao/kna3)*(1.0 + 1.0/hna) + 1.0 +h8_i = nao/((h7_i*(hna*kna3))) +h8_ss = nao/((h7_ss*(hna*kna3))) +h9_i = 1.0/h7_i +h9_ss = 1.0/h7_ss +hca = exp(qca*vfrt) +hna = exp(qna*vfrt) +k1_i = kcaon*(cao*h12_i) +k1_ss = kcaon*(cao*h12_ss) +k2_i = kcaoff +k2_ss = kcaoff +k3_i = k3p_i + k3pp_i +k3_ss = k3p_ss + k3pp_ss +k3p_i = h9_i*wca +k3p_ss = h9_ss*wca +k3pp_i = h8_i*wnaca +k3pp_ss = h8_ss*wnaca +k4_i = k4p_i + k4pp_i +k4_ss = k4p_ss + k4pp_ss +k4p_i = (h3_i*wca)/hca +k4p_ss = (h3_ss*wca)/hca +k4pp_i = h2_i*wnaca +k4pp_ss = h2_ss*wnaca +k5_i = kcaoff +k5_ss = kcaoff +k6_i = kcaon*(cai*h6_i) +k6_ss = kcaon*(cass*h6_ss) +k7_i = wna*(h2_i*h5_i) +k7_ss = wna*(h2_ss*h5_ss) +k8_i = wna*(h11_i*h8_i) +k8_ss = wna*(h11_ss*h8_ss) +x1_i = (k2_i*k4_i)*(k6_i + k7_i) + (k5_i*k7_i)*(k2_i + k3_i) +x1_ss = (k2_ss*k4_ss)*(k6_ss + k7_ss) + (k5_ss*k7_ss)*(k2_ss + k3_ss) +x2_i = (k1_i*k7_i)*(k4_i + k5_i) + (k4_i*k6_i)*(k1_i + k8_i) +x2_ss = (k1_ss*k7_ss)*(k4_ss + k5_ss) + (k4_ss*k6_ss)*(k1_ss + k8_ss) +x3_i = (k1_i*k3_i)*(k6_i + k7_i) + (k6_i*k8_i)*(k2_i + k3_i) +x3_ss = (k1_ss*k3_ss)*(k6_ss + k7_ss) + (k6_ss*k8_ss)*(k2_ss + k3_ss) +x4_i = (k2_i*k8_i)*(k4_i + k5_i) + (k3_i*k5_i)*(k1_i + k8_i) +x4_ss = (k2_ss*k8_ss)*(k4_ss + k5_ss) + (k3_ss*k5_ss)*(k1_ss + k8_ss) + +expressions("reversal_potentials") +ECl = ((R*T)/((F*zcl)))*log(clo/cli) # mV +EClss = ((R*T)/((F*zcl)))*log(clo/clss) # mV +EK = ((R*T)/((F*zk)))*log(ko/ki) # mV +EKs = ((R*T)/((F*zk)))*log((PKNa*nao + ko)/(PKNa*nai + ki)) # mV +ENa = ((R*T)/((F*zna)))*log(nao/nai) # mV + +expressions("IK1") +GK1 = Conditional(Eq(celltype, 1.0), 1.2*GK1_b, Conditional(Eq(celltype, 2.0), 1.3*GK1_b, GK1_b)) # mS/uF +IK1_IK1 = (K1ss*(GK1*sqrt(ko/5.0)))*(-EK + v) # A/F +K1ss = aK1/(aK1 + bK1) +aK1 = 4.094/(exp(0.1217*((-EK + v) - 1*49.934)) + 1.0) +bK1 = (15.72*exp(0.0674*((-EK + v) - 1*3.257)) + exp(0.0618*((-EK + v) - 1*594.31)))/(exp((-1*0.1629)*((-EK + v) + 14.207)) + 1.0) + +expressions("IKb") +GKb = Conditional(Eq(celltype, 1.0), 0.6*GKb_b, GKb_b) # mS/uF +IKb_IKb = (GKb*xkb)*(-EK + v) # A/F +xkb = 1.0/(exp((-(v - 1*10.8968))/23.9871) + 1.0) + +expressions("IKr") +GKr = Conditional(Eq(celltype, 1.0), 1.3*GKr_b, Conditional(Eq(celltype, 2.0), 0.8*GKr_b, GKr_b)) # mS/uF +IKr_IKr = (O_*(GKr*sqrt(ko/5.0)))*(-EK + v) # A/F +alpha = 0.1161*exp(0.299*vfrt) # mS/uF +alpha_2 = 0.0578*exp(0.971*vfrt) # mS/uF +alpha_C2ToI = 5.2e-5*exp(1.525*vfrt) # mS/uF +alpha_i = 0.2533*exp(0.5953*vfrt) # mS/uF +beta_ = 0.2442*exp((-1*1.604)*vfrt) # mS/uF +beta_2 = 0.000349*exp((-1*1.062)*vfrt) # mS/uF +beta_ItoC2 = (alpha_C2ToI*(beta_2*beta_i))/((alpha_2*alpha_i)) # mS/uF +beta_i = 0.06525*exp((-1*0.8209)*vfrt) # mS/uF +dC1_dt = -C1*(alpha_C2ToI + (alpha_2 + beta_1)) + (I_*beta_ItoC2 + (C2*alpha_1 + O_*beta_2)) +dC2_dt = -C2*(alpha_1 + beta_) + (C1*beta_1 + C3*alpha) +dC3_dt = C2*beta_ - C3*alpha +dI__dt = -I_*(beta_ItoC2 + beta_i) + (C1*alpha_C2ToI + O_*alpha_i) +dO__dt = -O_*(alpha_i + beta_2) + (C1*alpha_2 + I_*beta_i) + +expressions("IKs") +GKs = Conditional(Eq(celltype, 1.0), 1.4*GKs_b, GKs_b) # mS/uF +IKs_IKs = (xs2*(xs1*(GKs*KsCa)))*(-EKs + v) # A/F +KsCa = 1.0 + 0.6/((3.8e-5/cai)**1.4 + 1.0) +txs1 = 817.3 + 1.0/(0.0002326*exp((v + 48.28)/17.8) + 0.001292*exp((-(v + 210.0))/230.0)) # ms +txs2 = 1.0/(0.01*exp((v - 1*50.0)/20.0) + 0.0193*exp((-(v + 66.54))/31.0)) # ms +xs1ss = 1.0/(exp((-(v + 11.6))/8.932) + 1.0) +xs2ss = xs1ss +dxs1_dt = (-xs1 + xs1ss)/txs1 +dxs2_dt = (-xs2 + xs2ss)/txs2 + +expressions("INaL") +GNaL = Conditional(Eq(celltype, 1.0), 0.6*GNaL_b, GNaL_b) # mS/uF +INaL_INaL = (mL*(GNaL*(-ENa + v)))*(fINaLp*hLp + hL*(1.0 - fINaLp)) # A/F +fINaLp = 1.0/(1.0 + KmCaMK/CaMKa) +hLss = 1.0/(exp((v + 87.61)/7.488) + 1.0) +hLssp = 1.0/(exp((v + 93.81)/7.488) + 1.0) +mLss = 1.0/(exp((-(v + 42.85))/5.264) + 1.0) +thLp = 3.0*thL # ms +tmL = 0.06487*exp(-((v - 1*4.823)/51.12)**2.0) + 0.1292*exp(-((v + 45.79)/15.54)**2.0) # ms +dhL_dt = (-hL + hLss)/thL +dhLp_dt = (-hLp + hLssp)/thLp +dmL_dt = (-mL + mLss)/tmL + +expressions("ICab") +ICab_ICab = ((vffrt*(PCab*4.0))*(-cao*gamma_cao + (cai*gamma_cai)*exp(2.0*vfrt)))/(exp(2.0*vfrt) - 1*1.0) # A/F + +expressions("ICl") +IClCa = IClCa_junc + IClCa_sl # A/F +IClCa_junc = ((Fjunc*GClCa)/(KdClCa/cass + 1.0))*(-EClss + v) # A/F +IClCa_sl = ((GClCa*(1.0 - Fjunc))/(KdClCa/cai + 1.0))*(-ECl + v) # A/F +IClb = GClb*(-ECl + v) # A/F + +expressions("INa") +INa_INa = (m**3.0*(GNa*(-ENa + v)))*(j*(h*(1.0 - fINap)) + jp*(fINap*hp)) # A/F +ah = Conditional(Gt(v, -1*40.0), 0.0, 4.43126792958051e-7*exp(-0.147058823529412*v)) +aj = Conditional(Gt(v, -1*40.0), 0.0, -(v + 37.78)*(25428.0*exp(0.28831*v) + 6.948e-6)*exp(-0.04391*v)/(50262745825.954*exp(0.311*v) + 1.0)) +bh = Conditional(Gt(v, -1*40.0), 0.77*exp(0.0900900900900901*v)/(0.13*exp(0.0900900900900901*v) + 0.0497581410839387), 2.7*exp(0.079*v) + 310000.0*exp(0.3485*v)) +bj = Conditional(Gt(v, -1*40.0), 0.6*exp(0.157*v)/(1.0*exp(0.1*v) + 0.0407622039783662), 0.02424*exp(0.12728*v)/(1.0*exp(0.1378*v) + 0.00396086833990426)) +fINap = 1.0/(1.0 + KmCaMK/CaMKa) +hss = 1.0/((exp((v + 71.55)/7.43) + 1.0)**2.0) +hssp = 1.0/((exp((v + 77.55)/7.43) + 1.0)**2.0) +jss = hss +mss = 1.0/((exp((-(v + 56.86))/9.03) + 1.0)**2.0) +th = 1.0/(ah + bh) # ms +tj = 1.0/(aj + bj) # ms +tjp = 1.46*tj # ms +tm = 0.06487*exp(-((v - 1*4.823)/51.12)**2.0) + 0.1292*exp(-((v + 45.79)/15.54)**2.0) # ms +dh_dt = (-h + hss)/th +dhp_dt = (-hp + hssp)/th +dj_dt = (-j + jss)/tj +djp_dt = (-jp + jss)/tjp +dm_dt = (-m + mss)/tm + +expressions("INab") +INab_INab = ((PNab*vffrt)*(nai*exp(vfrt) - nao))/(exp(vfrt) - 1*1.0) # A/F + +expressions("I_katp") +I_katp_I_katp = (bkik*(akik*(fkatp*gkatp)))*(-EK + v) # A/F +akik = (ko/K_o_n)**0.24 +bkik = 1.0/((A_atp/K_atp)**2.0 + 1.0) + +expressions("IpCa") +IpCa_IpCa = (GpCa*cai)/(KmCap + cai) # A/F + +expressions("membrane") +Istim = Conditional(And(Le(i_Stim_Start, time), Ge(i_Stim_PulseDuration, -i_Stim_Period*floor(-(i_Stim_Start - time)/i_Stim_Period) - i_Stim_Start + time)), i_Stim_Amplitude, 0.0) # A/F +vffrt = (F*(F*v))/((R*T)) # C/mol +vfrt = (F*v)/((R*T)) +dv_dt = -(Istim + (I_katp_I_katp + (IClb + (IClCa + (ICab_ICab + (IpCa_IpCa + (IKb_IKb + (INab_INab + (INaK_INaK + (INaCa_ss + (INaCa_i + (IK1_IK1 + (IKs_IKs + (IKr_IKr + (ICaK + (ICaNa + (ICaL_ICaL + (Ito_Ito + (INaL_INaL + INa_INa))))))))))))))))))) # mV + +expressions("diff") +Jdiff = (-cai + cass)/tauCa # mM/ms +JdiffCl = (-cli + clss)/tauNa # mM/ms +JdiffK = (-ki + kss)/tauK # mM/ms +JdiffNa = (-nai + nass)/tauNa # mM/ms + +expressions("SERCA") +Jleak = (0.0048825*cansr)/15.0 # mM/ms +Jup = Jup_b*(-Jleak + (Jupnp*(1.0 - fJupp) + Jupp*fJupp)) # mM/ms +Jupnp = (cai*(upScale*0.005425))/(cai + 0.00092) # mM/ms +Jupp = (cai*((upScale*2.75)*0.005425))/((cai + 0.00092) - 1*0.00017) # mM/ms +fJupp = 1.0/(1.0 + KmCaMK/CaMKa) +upScale = Conditional(Eq(celltype, 1.0), 1.3, 1.0) + +expressions("ryr") +Jrel = Jrel_b*(Jrel_np*(1.0 - fJrelp) + Jrel_p*fJrelp) # mM/ms +Jrel_inf = Conditional(Eq(celltype, 2.0), 1.7*Jrel_inf_b, Jrel_inf_b) # mM/ms +Jrel_inf_b = ((ICaL_ss*(-a_rel))/1.0)/((cajsr_half/cajsr)**8.0 + 1.0) # mM/ms +Jrel_infp = Conditional(Eq(celltype, 2.0), 1.7*Jrel_infp_b, Jrel_infp_b) # mM/ms +Jrel_infp_b = ((ICaL_ss*(-a_relp))/1.0)/((cajsr_half/cajsr)**8.0 + 1.0) # mM/ms +a_rel = (0.5*bt)/1.0 # mM/ms +a_relp = (0.5*btp)/1.0 # mM/ms +btp = 1.25*bt # ms +fJrelp = 1.0/(1.0 + KmCaMK/CaMKa) +tau_rel = Conditional(Lt(tau_rel_b, 0.001), 0.001, tau_rel_b) # ms +tau_rel_b = bt/(1.0 + 0.0123/cajsr) # ms +tau_relp = Conditional(Lt(tau_relp_b, 0.001), 0.001, tau_relp_b) # ms +tau_relp_b = btp/(1.0 + 0.0123/cajsr) # ms +dJrel_np_dt = (Jrel_inf - Jrel_np)/tau_rel # mM/ms +dJrel_p_dt = (Jrel_infp - Jrel_p)/tau_relp # mM/ms + +expressions("trans_flux") +Jtr = (-cajsr + cansr)/60.0 # mM/ms + + +states("mechanics-ep", +cai=0.0001, +XS=0, +XW=0, +CaTrpn=1e-8, +TmB=1 +) + +states("mechanics", +Zetas=0, +Zetaw=0, +Cd=0 +) + +parameters("mechanics-ep","mechanics", +emcoupling=1, +lmbda=1, +dLambda=0, +mode=1, +isacs=0, +calib=1, +ktrpn = 0.1, +ntrpn = 2, +Trpn50 = 0.35, +rw = 0.5, +rs = 0.25, +gammas = 0.0085, +gammaw = 0.615, +phi = 2.23, +Tot_A = 25, +Beta0 = 2.3, +Beta1 = -2.4, +cat50_ref = 0.805, +Tref = 120, +kuw = 0.182, +kws = 0.012, +ku=0.04, +ntm=2.4, +p_a = 2.1, +p_b = 9.1, +p_k = 7, +etal = 200, +etas = 20) + +expressions("mechanics-ep") +XS_max = Conditional(Gt(XS, 0), XS, 0) +XW_max = Conditional(Gt(XW, 0), XW, 0) +CaTrpn_max = Conditional(Gt(CaTrpn, 0), CaTrpn, 0) +kwu = kuw*(1/rw-1)-kws +ksu = kws*rw*(1/rs-1) +Aw = Tot_A*rs/((1-rs)*rw+rs) +As = Aw +cw = phi*kuw*((1-rs)*(1-rw))/((1-rs)*rw) +cs = phi*kws*((1-rs)*rw)/rs +XU = (1-TmB)-XS-XW +gammawu = gammaw*Abs(Zetaw) +gammasu = gammas*Conditional(Gt(Gt(Zetas,0)*Zetas, Lt(Zetas, -1)*(-Zetas-1)), Gt(Zetas,0)*Zetas, Lt(Zetas, -1)*(-Zetas-1)) +dXS_dt = kws*XW - ksu*XS - gammasu*XS +dXW_dt = kuw*XU - kwu*XW - kws*XW - gammawu*XW +cat50 = (cat50_ref+Beta1*(lambda_min12-1)) +dCaTrpn_dt = ktrpn*(((cai*1000/cat50)**ntrpn)*(1-CaTrpn)-CaTrpn) +kb = ku*Trpn50**ntm/(1-rs-(1-rs)*rw) +dTmB_dt = kb*Conditional(Lt(CaTrpn**(-ntm/2), 100), CaTrpn**(-ntm/2), 100)*XU-ku*CaTrpn**(ntm/2)*TmB +Bcai=1.0/(1.0+cmdnmax*kmcmdn/(kmcmdn+cai)**2.0) +J_TRPN = dCaTrpn_dt*trpnmax +dcai_dt=Bcai*(-(IpCa_IpCa+ICab_ICab-2.0*INaCa_i/3)*Acap/(2.0*F*vmyo)-Jup*vnsr/vmyo+Jdiff*vss/vmyo - J_TRPN) + + +expressions("mechanics-ep", "mechanics") +lambda_min12 = Conditional(Lt(lmbda, 1.2), lmbda, 1.2) + +expressions("mechanics") +Aw = Tot_A*rs/((1-rs)*rw+rs) +As = Aw +cw = phi*kuw*((1-rs)*(1-rw))/((1-rs)*rw) +cs = phi*kws*((1-rs)*rw)/rs +dZetas_dt = As*dLambda - cs*Zetas +dZetaw_dt = Aw*dLambda - cw*Zetaw +lambda_min087 = Conditional(Lt(lambda_min12, 0.87), lambda_min12, 0.87) +h_lambda_prima = 1+Beta0*(lambda_min12+lambda_min087-1.87) +h_lambda = Conditional(Gt(h_lambda_prima, 0), h_lambda_prima, 0) +Ta = h_lambda*(Tref/rs)*(XS*(Zetas+1) + XW*Zetaw) +C = lambda_min12 - 1 +dCd = C - Cd +eta = Conditional(Lt(dCd, 0), etas, etal) +dCd_dt = p_k * (C - Cd) / eta +Fd = eta * dCd +F1 = (exp( p_b * C) - 1) +Tp = p_a * (F1 + Fd) +Ttot = Ta + Tp From 1945d9dc831713a6fca2ba2aa53780f679352e92 Mon Sep 17 00:00:00 2001 From: Henrik Finsberg Date: Sun, 19 Jan 2025 12:33:41 +0100 Subject: [PATCH 2/5] Add workflow to run 0D examples --- .github/workflows/run0D.yml | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 .github/workflows/run0D.yml diff --git a/.github/workflows/run0D.yml b/.github/workflows/run0D.yml new file mode 100644 index 0000000..d9b4d00 --- /dev/null +++ b/.github/workflows/run0D.yml @@ -0,0 +1,34 @@ +name: Run 0D examples + +on: + pull_request: + push: + branches: [main] + + +jobs: + + run-0D: + # This code depends on the result of check-code + runs-on: ubuntu-24.04 + container: + image: ghcr.io/scientificcomputing/fenics-gmsh:2024-02-19 + + + steps: + - uses: actions/checkout@v4 + + - name: Install package + run: python3 -m pip install -e . + + - name: Run split-cai + working-directory: ./numerical_experiments/0D + run: python3 split_cai.py + + - name: Run split-cai-catrpn + working-directory: ./numerical_experiments/0D + run: python3 split_cai_catrpn.py + + - name: Run split-zeta + working-directory: ./numerical_experiments/0D + run: python3 split_zeta.py From ada3b9175b040ab92bbeffd65ab0ff567be01a21 Mon Sep 17 00:00:00 2001 From: Henrik Finsberg Date: Sun, 2 Feb 2025 21:35:05 +0100 Subject: [PATCH 3/5] Add 3D numerical experiments --- .../create_geometry_with_surface_markers.py | 110 ++ numerical_experiments/3D/split-cai.py | 32 + numerical_experiments/3D/split-cai_catrpn.py | 32 + numerical_experiments/3D/split-zeta.py | 32 + numerical_experiments/3D/utils.py | 956 ++++++++++++++++++ src/simcardems2/__init__.py | 12 +- src/simcardems2/land_CaTrpnsplit.py | 6 +- src/simcardems2/land_Zetasplit.py | 6 +- src/simcardems2/land_caisplit.py | 16 +- src/simcardems2/mechanicssolver.py | 6 +- 10 files changed, 1190 insertions(+), 18 deletions(-) create mode 100644 numerical_experiments/3D/create_geometry_with_surface_markers.py create mode 100644 numerical_experiments/3D/split-cai.py create mode 100644 numerical_experiments/3D/split-cai_catrpn.py create mode 100644 numerical_experiments/3D/split-zeta.py create mode 100644 numerical_experiments/3D/utils.py diff --git a/numerical_experiments/3D/create_geometry_with_surface_markers.py b/numerical_experiments/3D/create_geometry_with_surface_markers.py new file mode 100644 index 0000000..3615be5 --- /dev/null +++ b/numerical_experiments/3D/create_geometry_with_surface_markers.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Fri Jun 14 14:47:22 2024 + +@author: lenamyklebust +""" + +import argparse +import numpy as np +import dolfin +from pathlib import Path +from typing import Dict +from typing import Optional + + +def setup_geometry(dx: float, Lx: float, Ly: float, Lz: float) -> dolfin.Mesh: + mesh = dolfin.BoxMesh( + dolfin.MPI.comm_world, + dolfin.Point(0.0, 0.0, 0.0), + dolfin.Point(Lx, Ly, Lz), + int(np.rint((Lx / dx))), + int(np.rint((Ly / dx))), + int(np.rint((Lz / dx))), + ) + return mesh + + +def default_markers() -> Dict[str, int]: + return { + "X0": 1, + "X1": 2, + "Y0": 3, + "Y1": 4, + "Z0": 5, + "Z1": 6, + } + + +def assign_surface_markers( + mesh: dolfin.Mesh, + lx: float, + ly: float, + lz: float, + markers: Optional[Dict[str, int]] = None, +) -> dolfin.MeshFunction: + if markers is None: + markers = default_markers() + + # Define domains for each surface + x0 = dolfin.CompiledSubDomain("near(x[0], 0) && on_boundary") + x1 = dolfin.CompiledSubDomain("near(x[0], lx) && on_boundary", lx=lx) + y0 = dolfin.CompiledSubDomain("near(x[1], 0) && on_boundary") + y1 = dolfin.CompiledSubDomain("near(x[1], ly) && on_boundary", ly=ly) + z0 = dolfin.CompiledSubDomain("near(x[2], 0) && on_boundary") + z1 = dolfin.CompiledSubDomain("near(x[2], lz) && on_boundary", lz=lz) + + ffun = dolfin.MeshFunction("size_t", mesh, mesh.topology().dim() - 1) + ffun.set_all(0) + + x0.mark(ffun, markers["X0"]) + x1.mark(ffun, markers["X1"]) + + y0.mark(ffun, markers["Y0"]) + y1.mark(ffun, markers["Y1"]) + + z0.mark(ffun, markers["Z0"]) + z1.mark(ffun, markers["Z1"]) + return ffun, markers + + +def main(outdir: Path, dx: float = 0.5, Lx: float = 0.5, Ly: float = 1.0, Lz: float = 2.0): + print( + f"Creating geometry, mesh and surface markers " + f"with dx={dx}, Lx={Lx}, Ly={Ly}, Lz={Lz} in {outdir}" + ) + outdir.mkdir(exist_ok=True, parents=True) + mesh = setup_geometry(dx=dx, Lx=Lx, Ly=Ly, Lz=Lz) + mesh_file = outdir / f"mesh_mech_{dx}dx_{Lx}Lx_{Ly}Ly_{Lz}Lz.xdmf" + mesh_file.unlink(missing_ok=True) + mesh_file.with_suffix(".h5").unlink(missing_ok=True) + + surface_ffun, surface_markers = assign_surface_markers(mesh, lx=Lx, ly=Ly, lz=Lz) + surface_func_file = outdir / f"mesh_mech_{dx}dx_{Lx}Lx_{Ly}Ly_{Lz}Lz_surface_ffun.xdmf" + surface_func_file.unlink(missing_ok=True) + surface_func_file.with_suffix(".h5").unlink(missing_ok=True) + + with dolfin.XDMFFile(mesh_file.as_posix()) as file: + file.write(mesh) + with dolfin.XDMFFile(surface_func_file.as_posix()) as xdmf: + xdmf.write(surface_ffun) + print("Saved mesh and surface markers to", mesh_file, surface_func_file) + print(f"Surface markers: {surface_markers}") + + +def get_parser(): + parser = argparse.ArgumentParser() + parser.add_argument("-o", "--outdir", type=Path, default=Path("meshes")) + parser.add_argument("--dx", type=float, default=0.5) + parser.add_argument("--Lx", type=float, default=0.5) + parser.add_argument("--Ly", type=float, default=1.0) + parser.add_argument("--Lz", type=float, default=2.0) + + return parser + + +if __name__ == "__main__": + parser = get_parser() + args = parser.parse_args() + main(**vars(args)) diff --git a/numerical_experiments/3D/split-cai.py b/numerical_experiments/3D/split-cai.py new file mode 100644 index 0000000..84314df --- /dev/null +++ b/numerical_experiments/3D/split-cai.py @@ -0,0 +1,32 @@ +import utils + + +config = { + "sim": { + "N": 2, + "dt": 0.05, + "mech_mesh": "meshes/mesh_mech_0.5dx_0.5Lx_1.0Ly_2.0Lz", + "markerfile": "meshes/mesh_mech_0.5dx_0.5Lx_1.0Ly_2.0Lz_surface_ffun", + "modelfile": "../odefiles/ToRORd_dynCl_endo_caisplit.ode", + "outdir": "100ms_N1_cai_split_runcheck", + "split_scheme": "cai", + }, + "output": { + "all_ep": ["cai", "v"], + "all_mech": ["Ta", "lambda"], + "point_ep": [ + {"name": "cai", "x": 0.0, "y": 0, "z": 0}, + {"name": "v", "x": 0, "y": 0, "z": 0}, + ], + "point_mech": [ + {"name": "Ta", "x": 0, "y": 0, "z": 0}, + {"name": "Zetas", "x": 0, "y": 0, "z": 0}, + {"name": "XS", "x": 0, "y": 0, "z": 0}, + {"name": "TmB", "x": 0, "y": 0, "z": 0}, + {"name": "CaTrpn", "x": 0, "y": 0, "z": 0}, + {"name": "lambda", "x": 0, "y": 0, "z": 0}, + ], + }, +} + +utils.run_3D(config=config) diff --git a/numerical_experiments/3D/split-cai_catrpn.py b/numerical_experiments/3D/split-cai_catrpn.py new file mode 100644 index 0000000..0b1c2c7 --- /dev/null +++ b/numerical_experiments/3D/split-cai_catrpn.py @@ -0,0 +1,32 @@ +import utils + + +config = { + "sim": { + "N": 2, + "dt": 0.05, + "mech_mesh": "meshes/mesh_mech_0.5dx_0.5Lx_1.0Ly_2.0Lz", + "markerfile": "meshes/mesh_mech_0.5dx_0.5Lx_1.0Ly_2.0Lz_surface_ffun", + "modelfile": "../odefiles/ToRORd_dynCl_endo_catrpnsplit.ode", + "outdir": "100ms_N1_cai_catrpn_split_runcheck", + "split_scheme": "cai_catrpn", + }, + "output": { + "all_ep": ["cai", "v", "CaTrpn"], + "all_mech": ["Ta", "lambda"], + "point_ep": [ + {"name": "cai", "x": 0.0, "y": 0, "z": 0}, + {"name": "v", "x": 0, "y": 0, "z": 0}, + {"name": "CaTrpn", "x": 0, "y": 0, "z": 0}, + ], + "point_mech": [ + {"name": "Ta", "x": 0, "y": 0, "z": 0}, + {"name": "Zetas", "x": 0, "y": 0, "z": 0}, + {"name": "XS", "x": 0, "y": 0, "z": 0}, + {"name": "TmB", "x": 0, "y": 0, "z": 0}, + {"name": "lambda", "x": 0, "y": 0, "z": 0}, + ], + }, +} + +utils.run_3D(config=config) diff --git a/numerical_experiments/3D/split-zeta.py b/numerical_experiments/3D/split-zeta.py new file mode 100644 index 0000000..c5990bb --- /dev/null +++ b/numerical_experiments/3D/split-zeta.py @@ -0,0 +1,32 @@ +import utils + + +config = { + "sim": { + "N": 2, + "dt": 0.05, + "mech_mesh": "meshes/mesh_mech_0.5dx_0.5Lx_1.0Ly_2.0Lz", + "markerfile": "meshes/mesh_mech_0.5dx_0.5Lx_1.0Ly_2.0Lz_surface_ffun", + "modelfile": "../odefiles/ToRORd_dynCl_endo_zetasplit.ode", + "outdir": "100ms_N1_zeta_split_runcheck", + "split_scheme": "zeta", + }, + "output": { + "all_ep": ["cai", "v"], + "all_mech": ["Ta", "lambda"], + "point_ep": [ + {"name": "cai", "x": 0.0, "y": 0, "z": 0}, + {"name": "v", "x": 0, "y": 0, "z": 0}, + {"name": "CaTrpn", "x": 0, "y": 0, "z": 0}, + {"name": "XS", "x": 0, "y": 0, "z": 0}, + {"name": "TmB", "x": 0, "y": 0, "z": 0}, + ], + "point_mech": [ + {"name": "Ta", "x": 0, "y": 0, "z": 0}, + {"name": "Zetas", "x": 0, "y": 0, "z": 0}, + {"name": "lambda", "x": 0, "y": 0, "z": 0}, + ], + }, +} + +utils.run_3D(config=config) diff --git a/numerical_experiments/3D/utils.py b/numerical_experiments/3D/utils.py new file mode 100644 index 0000000..798b022 --- /dev/null +++ b/numerical_experiments/3D/utils.py @@ -0,0 +1,956 @@ +from dataclasses import dataclass, field +from copy import deepcopy +import logging +from typing import Sequence, Any +import argparse +from pathlib import Path +import toml +import json +import numpy as np +import gotranx +import dolfin +import beat +import pulse +import matplotlib.pyplot as plt +import simcardems2 +from simcardems2 import mechanicssolver + +try: + raise ImportError + from numba import jit +except ImportError: + + def jit(*args, **kwargs): + def wrapper(func): + return func + + return wrapper + + +cm2mm = 10.0 + + +def run_3D(config: dict[str, Any] | None = None): + dolfin.parameters["form_compiler"]["representation"] = "uflacs" + dolfin.parameters["form_compiler"]["cpp_optimize"] = True + dolfin.parameters["form_compiler"]["quadrature_degree"] = 4 + logging.getLogger("beat").setLevel(logging.ERROR) + + config = parse_parameters(config=config) + + mesh, ep_mesh = read_mesh(config) + + # Load the model + ep_model = setup_ep_ode_model(config["sim"]["modelfile"], label=config["sim"]["split_scheme"]) + + # Forwared generalized rush larsen scheme for the electrophysiology model + fgr_ep = jit(nopython=True)(ep_model["forward_generalized_rush_larsen"]) + + # Missing values function for the electrophysiology model + mv_ep = ep_model["missing_values"] + + # Get initial values from the EP model + y_ep_ = ep_model["init_state_values"]() + p_ep_ = ep_model["init_parameter_values"](i_Stim_Amplitude=0.0) + + if config["sim"]["split_scheme"] == "cai": + # Init value for J_TRPN = dCaTrpn_dt * trpnmax (to compare with zetasplit) + ep_missing_values_ = np.array([0.00010730972184715098]) + # Init value for cai + mechanics_missing_values_ = np.array([0.0001]) + elif config["sim"]["split_scheme"] == "zeta": + ep_missing_values_ = np.zeros(len(ep_model["missing"])) + mechanics_missing_values_ = np.zeros(2) + elif config["sim"]["split_scheme"] == "cai_catrpn": + ep_missing_values_ = np.array([]) + # Init value for cai + mechanics_missing_values_ = np.array([0.0001]) + else: + raise ValueError(f"Unknown split scheme: {config['sim']['split_scheme']}") + + ep_ode_space = dolfin.FunctionSpace(ep_mesh, "DG", 1) + v_ode = dolfin.Function(ep_ode_space) + num_points_ep = v_ode.vector().local_size() + + y_ep = np.zeros((len(y_ep_), num_points_ep)) + y_ep.T[:] = y_ep_ # Set to y_ep with initial values defined in ep_model + + # Set the activation + activation_space = dolfin.FunctionSpace(mesh, "DG", 1) + activation = dolfin.Function(activation_space) + + missing_mech = simcardems2.interpolation.MissingValue( + element=activation.ufl_element(), + interpolation_element=ep_ode_space.ufl_element(), + mechanics_mesh=mesh, + ep_mesh=ep_mesh, + num_values=len(mechanics_missing_values_), + ) + + if len(ep_missing_values_) > 0: + missing_ep = simcardems2.interpolation.MissingValue( + element=ep_ode_space.ufl_element(), + interpolation_element=activation.ufl_element(), + mechanics_mesh=mesh, + ep_mesh=ep_mesh, + num_values=len(ep_missing_values_), + ) + + missing_ep.values_mechanics.T[:] = ep_missing_values_ + missing_ep.values_ep.T[:] = ep_missing_values_ + ode_missing_variables = missing_ep.values_ep + missing_ep_args = (missing_ep.values_ep,) + else: + missing_ep = None + ode_missing_variables = None + missing_ep_args = () + + missing_mech.values_ep.T[:] = mechanics_missing_values_ + missing_mech.values_mechanics.T[:] = mechanics_missing_values_ + missing_mech.mechanics_values_to_function() # Assign initial values to mech functions + + # Use previous cai in mech to be consistent across splitting schemes + prev_missing_mech = simcardems2.interpolation.MissingValue( + element=activation.ufl_element(), + interpolation_element=ep_ode_space.ufl_element(), + mechanics_mesh=mesh, + ep_mesh=ep_mesh, + num_values=len(mechanics_missing_values_), + ) + for i in range(len(mechanics_missing_values_)): + prev_missing_mech.u_mechanics[i].vector().set_local(missing_mech.values_mechanics[i]) + + p_ep = np.zeros((len(p_ep_), num_points_ep)) + p_ep.T[:] = p_ep_ # Initialise p_ep with initial values defined in ep_model + + pde = setup_monodomain_model(config, ep_mesh) + + ode = beat.odesolver.DolfinODESolver( + v_ode=dolfin.Function(ep_ode_space), + v_pde=pde.state, + fun=fgr_ep, + parameters=p_ep, + init_states=y_ep, + num_states=len(y_ep), + v_index=ep_model["state_index"]("v"), + missing_variables=ode_missing_variables, + num_missing_variables=len(ep_missing_values_), + ) + ep_solver = beat.MonodomainSplittingSolver(pde=pde, ode=ode, theta=1) + + # TODO: do a different dirichlet/neumann check than this later. something smoother + t_bcs = dolfin.Constant(0) + + if config["sim"]["split_scheme"] == "cai": + land_params = {"cai": mechanics_missing_values_[0]} + LandModel = simcardems2.land_caisplit.LandModel + + elif config["sim"]["split_scheme"] == "zeta": + land_params = { + "XS": mechanics_missing_values_[0], + "XW": mechanics_missing_values_[1], + } + LandModel = simcardems2.land_Zetasplit.LandModel + elif config["sim"]["split_scheme"] == "cai_catrpn": + land_params = {"CaTrpn": mechanics_missing_values_[0]} + LandModel = simcardems2.land_CaTrpnsplit.LandModel + else: + raise ValueError(f"Unknown split scheme: {config['sim']['split_scheme']}") + + problem = setup_mechancis_model( + config, + mesh, + LandModel, + land_params=land_params, + t_bcs=t_bcs, + ) + + active_model = problem.material.active + + if config["sim"]["split_scheme"] == "cai": + mech_variables = { + "Ta": active_model.Ta_current, + "Zetas": active_model._Zetas, + "Zetaw": active_model._Zetaw, + "lambda": active_model.lmbda, + "XS": active_model._XS, + "XW": active_model._XW, + "TmB": active_model._TmB, + "CaTrpn": active_model._CaTrpn, + "J_TRPN": active_model._J_TRPN, + } + elif config["sim"]["split_scheme"] == "zeta": + mech_variables = { + "Ta": active_model.Ta_current, + "Zetas": active_model._Zetas, + "Zetaw": active_model._Zetaw, + "lambda": active_model.lmbda, + "XS": active_model.XS, + "XW": active_model.XW, + "dLambda": active_model._dLambda, + } + else: + mech_variables = { + "Ta": active_model.Ta_current, + "Zetas": active_model._Zetas, + "Zetaw": active_model._Zetaw, + "lambda": active_model.lmbda, + "XS": active_model._XS, + "XW": active_model._XW, + "TmB": active_model._TmB, + } + + collector = DataCollector( + problem=problem, + ep_ode_space=ep_ode_space, + config=config, + mech_variables=mech_variables, + ) + + inds = [] # Array with time-steps for which we solve mechanics + j = 0 + + for i, ti in enumerate(collector.t): + collector.timers.start_single_loop() + + print(f"Solving time {ti:.2f} ms") + t_bcs.assign(ti) # Use ti+ dt here instead? + + collector.timers.start_ep() + ep_solver.step((ti, ti + config["sim"]["dt"])) + collector.timers.stop_ep() + + # Assign values to ep function + for out_ep_var in collector.out_ep_names: + collector.out_ep_funcs[out_ep_var].vector()[:] = ode._values[ + ep_model["state_index"](out_ep_var) + ] + + collector.write_node_data_ep(i) + + if i % config["sim"]["N"] != 0: + collector.timers.stop_single_loop() + continue + + collector.timers.start_var_transfer() + # Extract missing values for the mechanics step from the ep model (ep function space) + missing_ep_values = mv_ep( + ti + config["sim"]["dt"], + ode._values, + ode.parameters, + *missing_ep_args, + ) + # Assign the extracted values as missing_mech for the mech step (ep function space) + for k in range(missing_mech.num_values): + missing_mech.u_ep_int[k].vector()[:] = missing_ep_values[k, :] + + # Interpolate missing variables from ep to mech function space + missing_mech.interpolate_ep_to_mechanics() + missing_mech.mechanics_function_to_values() + inds.append(i) + + collector.timers.stop_var_transfer() + + print("Solve mechanics") + collector.timers.start_mech() + + active_model.t.assign(ti + config["sim"]["N"] * config["sim"]["dt"]) # Addition! + nit, conv = problem.solve(ti, config["sim"]["N"] * config["sim"]["dt"]) + collector.timers.no_of_newton_iterations.append(nit) + print(f"No of iterations: {nit}") + active_model.update_prev() + collector.timers.stop_mech() + + collector.timers.start_var_transfer() + # Do we need to handle more cases here? + if config["sim"]["split_scheme"] == "cai": + missing_ep.u_mechanics_int[0].interpolate(active_model._J_TRPN) + if missing_ep is not None: + missing_ep.interpolate_mechanics_to_ep() + missing_ep.ep_function_to_values() + collector.timers.stop_var_transfer() + + collector.write_node_data_mech(i) + + collector.timers.start_var_transfer + # Use previous cai in mech to be consistent with zeta split + for i in range(len(mechanics_missing_values_)): + prev_missing_mech.u_mechanics[i].vector().set_local(missing_mech.values_mechanics[i]) + collector.timers.stop_var_transfer() + collector.timers.collect_var_transfer() + + collector.write_disp(j) + + j += 1 + collector.timers.stop_single_loop() + + collector.finalize(inds) + + +def default_config(): + return { + "ep": { + "conductivities": { + "sigma_el": 0.62, + "sigma_et": 0.24, + "sigma_il": 0.17, + "sigma_it": 0.019, + }, + "stimulus": { + "amplitude": 50000.0, + "duration": 2, + "start": 0.0, + "xmax": 1.5, + "xmin": 0.0, + "ymax": 1.5, + "ymin": 0.0, + "zmax": 1.5, + "zmin": 0.0, + }, + "chi": 140.0, + "C_m": 0.01, + }, + "mechanics": { + "material": { + "a": 2.28, + "a_f": 1.686, + "a_fs": 0.0, + "a_s": 0.0, + "b": 9.726, + "b_f": 15.779, + "b_fs": 0.0, + "b_s": 0.0, + }, + "bcs": [ + {"V": "u_x", "expression": 0, "marker": 1, "param_numbers": 0, "type": "Dirichlet"}, + {"V": "u_y", "expression": 0, "marker": 3, "param_numbers": 0, "type": "Dirichlet"}, + {"V": "u_z", "expression": 0, "marker": 5, "param_numbers": 0, "type": "Dirichlet"}, + ], + }, + "sim": { + "N": 2, + "dt": 0.05, + "mech_mesh": "meshes/mesh_mech_0.5dx_0.5Lx_1.0Ly_2.0Lz", + "markerfile": "meshes/mesh_mech_0.5dx_0.5Lx_1.0Ly_2.0Lz_surface_ffun", + "modelfile": "../odefiles/ToRORd_dynCl_endo_caisplit.ode", + "outdir": "100ms_N1_cai_split_runcheck", + "sim_dur": 4, + "split_scheme": "cai", + }, + "output": { + "all_ep": ["v"], + "all_mech": ["Ta", "lambda"], + "point_ep": [ + {"name": "v", "x": 0, "y": 0, "z": 0}, + ], + "point_mech": [ + {"name": "Ta", "x": 0, "y": 0, "z": 0}, + {"name": "lambda", "x": 0, "y": 0, "z": 0}, + ], + }, + } + + +def deep_update_dict(d, u): + for k, v in u.items(): + if isinstance(v, dict): + d[k] = deep_update_dict(d.get(k, {}), v) + else: + d[k] = v + return d + + +def parse_parameters( + argv: Sequence[str] | None = None, config: dict[str, Any] | None = None +) -> dict[str, Any]: + _config = default_config() + + if config is None: + # Parse config file from the command line + parser = argparse.ArgumentParser(description="Simcardems CLI") + parser.add_argument("config-file", type=Path, help="Config file") + + args = vars(parser.parse_args(argv)) + try: + config = toml.loads(args["config-file"].read_text()) + except toml.TomlDecodeError as e: + print(f"Error when parsing input parameters. Check config file. Error: {e}") + exit(1) + + return deep_update_dict(_config, config) + + +def setup_ep_ode_model(odefile, label): + module_file = Path(f"ep_model_{label}.py") + if not module_file.is_file(): + ode = gotranx.load_ode(odefile) + + mechanics_comp = ode.get_component("mechanics") + mechanics_ode = mechanics_comp.to_ode() + + ep_ode = ode - mechanics_comp + + # Generate code for the electrophysiology model + code_ep = gotranx.cli.gotran2py.get_code( + ep_ode, + scheme=[gotranx.schemes.Scheme.forward_generalized_rush_larsen], + missing_values=mechanics_ode.missing_variables, + ) + + Path(module_file).write_text(code_ep) + # Currently 3D mech needs to be written manually + + return __import__(str(module_file.stem)).__dict__ + + +def define_stimulus(mesh, chi, C_m, time, config): + stim_region = ( + [config["ep"]["stimulus"]["xmin"], config["ep"]["stimulus"]["xmax"]], + [config["ep"]["stimulus"]["ymin"], config["ep"]["stimulus"]["ymax"]], + [config["ep"]["stimulus"]["zmin"], config["ep"]["stimulus"]["zmax"]], + ) + stim_start = config["ep"]["stimulus"]["start"] + A = config["ep"]["stimulus"]["amplitude"] + duration = config["ep"]["stimulus"]["duration"] + # I_s = define_stimulus( + # mesh=ep_mesh, + # chi=chi, + # C_m=C_m, + # time=time, + # stim_region=stim_region, + # stim_start=config["stim"]["start"], + # A=config["stim"]["amplitude"], + # duration=config["stim"]["duration"], + # ) + + S1_marker = 1 + S1_subdomain = dolfin.CompiledSubDomain( + " ".join( + ( + f"x[0] >= {stim_region[0][0]}", + f"&& x[0] <= {stim_region[0][1]}", + f"&& x[1] >= {stim_region[1][0]}", + f"&& x[1] <= {stim_region[1][1]}", + f"&& x[2] >= {stim_region[2][0]}", + f"&& x[2] <= {stim_region[2][1]}", + ) + ) + ) + + S1_markers = dolfin.MeshFunction("size_t", mesh, mesh.topology().dim()) + S1_subdomain.mark(S1_markers, S1_marker) + # with dolfin.XDMFFile((outdir / "stim_region_markers.xdmf").as_posix()) as xdmf: + # xdmf.write(S1_markers) + + # Define stimulation (NB: region of interest carried by the mesh + # and assumptions in cbcbeat) + factor = 1.0 / (chi * C_m) # NB: cbcbeat convention + amplitude = factor * A * (1.0 / cm2mm) ** 3 # mV/ms + + I_s = dolfin.Expression( + "time >= start ? (time <= (duration + start) ? amplitude : 0.0) : 0.0", + time=time, + start=stim_start, + duration=duration, + amplitude=amplitude, + degree=0, + ) + + dx = dolfin.Measure("dx", domain=mesh, subdomain_data=S1_markers)(S1_marker) + return beat.base_model.Stimulus(dz=dx, expr=I_s) + + +def define_conductivity_tensor(sigma, chi, C_m): + # Compute monodomain approximation by taking harmonic mean in each + # direction of intracellular and extracellular part + def harmonic_mean(a, b): + return a * b / (a + b) + + sigma_l = harmonic_mean(sigma[0], sigma[2]) + sigma_t = harmonic_mean(sigma[1], sigma[3]) + + # Scale conducitivites by 1/(C_m * chi) + s_l = sigma_l / (C_m * chi) # mm^2 / ms + s_t = sigma_t / (C_m * chi) # mm^2 / ms + + # Define conductivity tensor + M = dolfin.as_tensor(((s_l, 0, 0), (0, s_t, 0), (0, 0, s_t))) + + return M + + +def create_boundary_conditions( + ffun_bcs, + bcs_dirichlet, + bcs_neumann, +): # TODO: update to not need separate dirichlet and neumann list + def dirichlet_bc(W): + bcs_W = { + "u_x": W.sub(0).sub(0), + "u_y": W.sub(0).sub(1), + "u_z": W.sub(0).sub(2), + # TODO: add the rest (check dolfin doc) + } + + bcs = [] + for bc in bcs_dirichlet: + bcs.append( + dolfin.DirichletBC( + bcs_W[bc["V"]], + bc["expression"], # TODO: use dolfin expression + ffun_bcs, + bc["marker"], + ) + ) + return bcs + + neumann_bc = [] + if bcs_neumann is not None: + for bc in bcs_neumann: + neumann_bc.append( + pulse.NeumannBC( + traction=simcardems2.utils.float_to_constant(bc["expression"]), + marker=bc["marker"], + ) + ) + + # Collect Boundary Conditions + bcs = pulse.BoundaryConditions(dirichlet=(dirichlet_bc,), neumann=neumann_bc) + return bcs + + +def handle_bcs(config, t_bcs): + bcs_dirichlet = [] + bcs_neumann = [] + for bc in deepcopy(config["mechanics"]["bcs"]): + if bc["type"] == "Dirichlet": + bcs_dirichlet.append(bc) + elif bc["type"] == "Neumann": + bcs_neumann.append(bc) + else: + raise KeyError( + f'{bc["type"]} is not a valid type of boundary ' + 'condition. Use Dirichlet or Neumann. Check config file' + ) + + if bc["param_numbers"] > 0: + bcs_parameters = {} + for param_nr in range(bc["param_numbers"]): + param_name = bc["param"][f"{param_nr}"]["name"] + param_value = bc["param"][f"{param_nr}"]["value"] + bcs_parameters[param_name] = param_value + bc["expression"] = dolfin.Expression( + bc["expression"], + **bcs_parameters, + t=t_bcs, + degree=bc["degree"], + ) + else: + bc["expression"] = dolfin.Constant(0) + return bcs_dirichlet, bcs_neumann + + +def read_mesh(config, refinement_level=0): + mesh = dolfin.Mesh() + with dolfin.XDMFFile(f'{config["sim"]["mech_mesh"]}.xdmf') as infile: + infile.read(mesh) + print(f'Loaded mesh: {config["sim"]["mech_mesh"]}') + + ep_mesh = mesh + if refinement_level > 0: + for i in range(refinement_level): + ep_mesh = dolfin.adapt(ep_mesh) + + return mesh, ep_mesh + + +def compute_function_average_over_mesh(func, mesh): + volume = dolfin.assemble(dolfin.Constant(1.0) * dolfin.dx(domain=mesh)) + return dolfin.assemble(func * dolfin.dx(domain=mesh)) / volume + + +def setup_monodomain_model(config, mesh): + sigma = [ + config["ep"]["conductivities"]["sigma_il"], + config["ep"]["conductivities"]["sigma_it"], + config["ep"]["conductivities"]["sigma_el"], + config["ep"]["conductivities"]["sigma_et"], + ] + chi = config["ep"]["chi"] + C_m = config["ep"]["C_m"] + time = dolfin.Constant(0.0) + I_s = define_stimulus(mesh, chi, C_m, time, config) + M = define_conductivity_tensor(sigma, chi, C_m) + params = {"preconditioner": "sor", "use_custom_preconditioner": False} + return beat.MonodomainModel(time=time, mesh=mesh, M=M, I_s=I_s, params=params) + + +def setup_mechancis_model(config, mesh, LandModel, land_params, t_bcs): + ffun_bcs = dolfin.MeshFunction("size_t", mesh, mesh.topology().dim() - 1) + marker_file = Path(f'{config["sim"]["markerfile"].rstrip(".xdmf")}.xdmf') + + with dolfin.XDMFFile(marker_file.as_posix()) as infile: + infile.read(ffun_bcs) + print(f"Loaded markerfile for bcs: {marker_file}") + + material_parameters = dict( + a=config["mechanics"]["material"]["a"], + a_f=config["mechanics"]["material"]["a_f"], + b=config["mechanics"]["material"]["b"], + b_f=config["mechanics"]["material"]["b_f"], + a_s=config["mechanics"]["material"]["a_s"], + b_s=config["mechanics"]["material"]["b_s"], + a_fs=config["mechanics"]["material"]["a_fs"], + b_fs=config["mechanics"]["material"]["b_fs"], + ) + marker_functions = pulse.MarkerFunctions(ffun=ffun_bcs) + + f0 = dolfin.as_vector([1.0, 0.0, 0.0]) + s0 = dolfin.as_vector([0.0, 1.0, 0.0]) + n0 = dolfin.as_vector([0.0, 0.0, 1.0]) + microstructure = pulse.Microstructure(f0=f0, s0=s0, n0=n0) + geometry = pulse.Geometry( + mesh=mesh, marker_functions=marker_functions, microstructure=microstructure + ) + + active_model = LandModel( + f0=f0, + s0=s0, + n0=n0, + mesh=mesh, + eta=0, # Fraction of transverse active tesion for active stress formulation. + # 0 = active only along fiber, 1 = equal forces in all directions + # (default=0.0). + dLambda_tol=1e-12, + **land_params, + ) + active_model.t = dolfin.Constant(0.0) + + # Validate mechanics variables to output + # for out_mech_var in list(set(out_mech_coord_names) | set(out_mech_var_names)): + # assert ( + # out_mech_var in mech_variables + # ), f"Error: '{out_mech_var}' is not a valid variable name. Check config file" + + material = pulse.HolzapfelOgden( + parameters=material_parameters, + active_model=active_model, + f0=f0, + s0=s0, + n0=n0, + ) + + bcs_dirichlet, bcs_neumann = handle_bcs(config, t_bcs) + + # Collect Boundary Conditions + bcs = create_boundary_conditions( + ffun_bcs, + bcs_dirichlet, + bcs_neumann, + ) + + problem = mechanicssolver.MechanicsProblem(geometry, material, bcs) + problem.solve(0.0, 0.0) + return problem + + +@dataclass +class DataCollector: + problem: mechanicssolver.MechanicsProblem + ep_ode_space: dolfin.FunctionSpace + config: dict + mech_variables: dict[str, dolfin.Function] + + def __post_init__(self): + self.outdir.mkdir(exist_ok=True, parents=True) + self._t = np.arange(0, self.config["sim"]["sim_dur"], self.config["sim"]["dt"]) + (self.outdir / "config.txt").write_text(toml.dumps(self.config)) + + self.out_ep_var_names = self.config["output"]["all_ep"] + self.out_mech_var_names = self.config["output"]["all_mech"] + + self.out_ep_coord_names = [f["name"] for f in self.config["output"]["point_ep"]] + self.ep_coords = [ + [f[f"{coord}"] for coord in ["x", "y", "z"]] for f in self.config["output"]["point_ep"] + ] + + self.out_mech_coord_names = [f["name"] for f in self.config["output"]["point_mech"]] + self.mech_coords = [ + [f[f"{coord}"] for coord in ["x", "y", "z"]] + for f in self.config["output"]["point_mech"] + ] + + # Create function spaces for ep variables to output + self.out_ep_funcs = {} + for out_ep_var in self.out_ep_names: + self.out_ep_funcs[out_ep_var] = dolfin.Function(self.ep_ode_space) + + self.out_ep_files = {} + for out_ep_var in self.out_ep_var_names: + self.out_ep_files[out_ep_var] = self.outdir / f"{out_ep_var}_out_ep.xdmf" + self.out_ep_files[out_ep_var].unlink(missing_ok=True) + self.out_ep_files[out_ep_var].with_suffix(".h5").unlink(missing_ok=True) + + self.out_mech_files = {} + for out_mech_var in self.out_mech_var_names: + self.out_mech_files[out_mech_var] = self.outdir / f"{out_mech_var}_out_mech.xdmf" + self.out_mech_files[out_mech_var].unlink(missing_ok=True) + self.out_mech_files[out_mech_var].with_suffix(".h5").unlink(missing_ok=True) + + self.out_ep_example_nodes = {} + self.out_ep_volume_average_timeseries = {} + for out_ep_var in self.out_ep_coord_names: + self.out_ep_example_nodes[out_ep_var] = np.zeros(len(self.t)) + self.out_ep_volume_average_timeseries[out_ep_var] = np.zeros(len(self.t)) + + self.out_mech_example_nodes = {} + self.out_mech_volume_average_timeseries = {} + for out_mech_var in self.out_mech_coord_names: + self.out_mech_example_nodes[out_mech_var] = np.zeros(len(self.t)) + self.out_mech_volume_average_timeseries[out_mech_var] = np.zeros(len(self.t)) + + self.timers = Timers() + + @property + def t(self): + return self._t + + @property + def out_ep_names(self): + return list(set(self.out_ep_var_names) | set(self.out_ep_coord_names)) + + @property + def outdir(self): + return Path(self.config["sim"]["outdir"]) + + @property + def disp_file(self): + return self.outdir / "displacement.xdmf" + + @property + def ep_mesh(self): + return self.ep_ode_space.mesh() + + def write_node_data_ep(self, i): + # Store values to plot time series for given coord + for var_nr, data in enumerate(self.config["output"]["point_ep"]): + # Trace variable in coordinate + out_ep_var = data["name"] + self.out_ep_example_nodes[out_ep_var][i] = self.out_ep_funcs[out_ep_var]( + self.ep_coords[var_nr] + ) + # Compute volume averages + self.out_ep_volume_average_timeseries[out_ep_var][i] = ( + compute_function_average_over_mesh(self.out_ep_funcs[out_ep_var], self.ep_mesh) + ) + + def write_node_data_mech(self, i): + for var_nr, data in enumerate(self.config["output"]["point_mech"]): + out_mech_var = data["name"] + # Trace variable in coordinate + self.out_mech_example_nodes[out_mech_var][i] = self.mech_variables[out_mech_var]( + self.mech_coords[var_nr] + ) + + # Compute volume averages + self.out_mech_volume_average_timeseries[out_mech_var][i] = ( + compute_function_average_over_mesh( + self.mech_variables[out_mech_var], self.problem.geometry.mesh + ) + ) + + def write_disp(self, j): + U, p = self.problem.state.split(deepcopy=True) + with dolfin.XDMFFile(self.disp_file.as_posix()) as file: + file.write_checkpoint(U, "disp", j, dolfin.XDMFFile.Encoding.HDF5, True) + + def write_ep(self, j): + for out_ep_var in self.out_ep_var_names: + with dolfin.XDMFFile(self.out_ep_files[out_ep_var].as_posix()) as file: + file.write_checkpoint( + self.out_ep_funcs[out_ep_var], + out_ep_var, + j, + dolfin.XDMFFile.Encoding.HDF5, + True, + ) + for out_mech_var in self.out_mech_var_names: + with dolfin.XDMFFile(self.out_mech_files[out_mech_var].as_posix()) as file: + file.write_checkpoint( + self.mech_variables[out_mech_var], + out_mech_var, + j, + dolfin.XDMFFile.Encoding.HDF5, + True, + ) + + def finalize(self, inds, plot_results=True): + self.timers.finalize(outdir=self.outdir) + # Write averaged results for later analysis + for out_ep_var in self.out_ep_coord_names: + # with open(Path(outdir / f"{out_ep_var}_out_ep_volume_average.txt"), "w") as f: + np.savetxt( + self.outdir / f"{out_ep_var}_out_ep_volume_average.txt", + self.out_ep_volume_average_timeseries[out_ep_var][inds], + ) + + for out_mech_var in self.out_mech_coord_names: + # with open(Path(outdir / f"{out_mech_var}_out_mech_volume_average.txt"), "w") as f: + np.savetxt( + self.outdir / f"{out_mech_var}_out_mech_volume_average.txt", + self.out_mech_volume_average_timeseries[out_mech_var][inds], + ) + + # Write point traces for later analysis + for var_nr, data in enumerate(self.config["output"]["point_ep"]): + out_ep_var = data["name"] + path = ( + self.outdir + / f"{out_ep_var}_ep_coord{self.ep_coords[var_nr][0]},{self.ep_coords[var_nr][1]},{self.ep_coords[var_nr][2]}.txt".replace( # noqa: E501 + " ", "" + ) + ) + np.savetxt(path, self.out_ep_example_nodes[out_ep_var][inds]) + + for var_nr, data in enumerate(self.config["output"]["point_mech"]): + out_mech_var = data["name"] + path = ( + self.outdir + / f"{out_mech_var}_mech_coord{self.mech_coords[var_nr][0]},{self.mech_coords[var_nr][1]},{self.mech_coords[var_nr][2]}.txt" # noqa: E501 + ) + np.savetxt(path, self.out_mech_example_nodes[out_mech_var][inds]) + + print(f"Solved on {100 * len(inds) / len(self.t)}% of the time steps") + inds = np.array(inds) + + if plot_results: + fig, ax = plt.subplots(len(self.out_ep_coord_names), 1, figsize=(10, 10)) + if len(self.out_ep_coord_names) == 1: + ax = np.array([ax]) + for i, out_ep_var in enumerate(self.out_ep_coord_names): + ax[i].plot(self.t[inds], self.out_ep_volume_average_timeseries[out_ep_var][inds]) + ax[i].set_title(f"{out_ep_var} volume average") + ax[i].set_xlabel("Time (ms)") + fig.tight_layout() + fig.savefig(self.outdir / "out_ep_volume_averages.png") + + fig, ax = plt.subplots(len(self.out_ep_coord_names), 1, figsize=(10, 10)) + if len(self.out_ep_coord_names) == 1: + ax = np.array([ax]) + for var_nr, data in enumerate(self.config["output"]["point_ep"]): + out_ep_var = data["name"] + ax[var_nr].plot(self.t[inds], self.out_ep_example_nodes[out_ep_var][inds]) + ax[var_nr].set_title(f"{out_ep_var} in coord {self.ep_coords[var_nr]}") + ax[var_nr].set_xlabel("Time (ms)") + fig.tight_layout() + fig.savefig(self.outdir / "out_ep_coord.png") + + fig, ax = plt.subplots(len(self.out_mech_coord_names), 1, figsize=(10, 10)) + if len(self.out_mech_coord_names) == 1: + ax = np.array([ax]) + for i, out_mech_var in enumerate(self.out_mech_coord_names): + ax[i].plot( + self.t[inds], self.out_mech_volume_average_timeseries[out_mech_var][inds] + ) + ax[i].set_title(f"{out_mech_var} volume average") + ax[i].set_xlabel("Time (ms)") + fig.tight_layout() + fig.savefig(self.outdir / "out_mech_volume_averages.png") + + fig, ax = plt.subplots(len(self.out_mech_coord_names), 1, figsize=(10, 10)) + if len(self.out_mech_coord_names) == 1: + ax = np.array([ax]) + + for var_nr, data in enumerate(self.config["output"]["point_mech"]): + out_mech_var = data["name"] + ax[var_nr].plot(self.t[inds], self.out_mech_example_nodes[out_mech_var][inds]) + ax[var_nr].set_title(f"{out_mech_var} in coord {self.mech_coords[var_nr]}") + ax[var_nr].set_xlabel("Time (ms)") + fig.tight_layout() + fig.savefig(self.outdir / "out_mech_coord.png") + + +@dataclass +class Timers: + timings_solveloop: list[float] = field(default_factory=list) + timings_ep_steps: list[float] = field(default_factory=list) + timings_mech_steps: list[float] = field(default_factory=list) + no_of_newton_iterations: list[float] = field(default_factory=list) + timings_var_transfer: list[float] = field(default_factory=list) + + def __post_init__(self): + self.start_total() + + def start_total(self): + self.total_timer = dolfin.Timer("total") + + def stop_total(self): + self.total_timer.stop() + self.timings_total = self.total_timer.elapsed + + def start_ep(self): + self.ep_timer = dolfin.Timer("ep") + + def stop_ep(self): + self.ep_timer.stop() + self.timings_ep_steps.append(self.ep_timer.elapsed()[0]) + + def start_single_loop(self): + self.timing_single_loop = dolfin.Timer("single_loop") + + def stop_single_loop(self): + self.timing_single_loop.stop() + self.timings_solveloop.append(self.timing_single_loop.elapsed()[0]) + + def start_var_transfer(self): + self.timing_var_transfer = dolfin.Timer("mv and lambda transfer time") + + def stop_var_transfer(self): + self.timing_var_transfer.stop() + + def collect_var_transfer(self): + self.timings_var_transfer.append(self.timing_var_transfer.elapsed()[0]) + + def start_mech(self): + self.mech_timer = dolfin.Timer("mech time") + + def stop_mech(self): + self.mech_timer.stop() + self.timings_mech_steps.append(self.mech_timer.elapsed()[0]) + + def finalize(self, outdir: Path): + self.stop_total() + timings = dolfin.timings( + dolfin.TimingClear.keep, + [dolfin.TimingType.wall, dolfin.TimingType.user, dolfin.TimingType.system], + ).str(True) + print(timings) + # with open(Path(outdir / "solve_timings.txt"), "w") as f: + # f.write("Loop total times\n") + # np.savetxt(f, self.timings_solveloop) + # f.write("Ep steps times\n") + # np.savetxt(f, self.timings_ep_steps) + # f.write("Mech steps times\n") + # np.savetxt(f, self.timings_mech_steps) + # f.write("No of mech iterations\n") + # np.savetxt(f, self.no_of_newton_iterations, fmt="%s") + # f.write("mv and lambda transfer time\n") + # np.savetxt(f, self.timings_var_transfer) + # f.write("Total time\n") + # f.write(f"{self.total_timer.elapsed()[0]}\n") + # f.write(timings) + + (outdir / "solve_timings.json").write_text( + json.dumps( + { + "Loop total times": self.timings_solveloop, + "Ep steps times": self.timings_ep_steps, + "Mech steps times": self.timings_mech_steps, + "No of mech iterations": self.no_of_newton_iterations, + "mv and lambda transfer time": self.timings_var_transfer, + "Total time": self.total_timer.elapsed()[0], + "timings": timings, + }, + indent=4, + ) + ) diff --git a/src/simcardems2/__init__.py b/src/simcardems2/__init__.py index 5a2c60f..39636a6 100644 --- a/src/simcardems2/__init__.py +++ b/src/simcardems2/__init__.py @@ -1,6 +1,16 @@ from . import interpolation from . import utils from . import mechanicssolver +from . import land_caisplit +from . import land_CaTrpnsplit +from . import land_Zetasplit -__all__ = ["interpolation", "utils", "mechanicssolver"] +__all__ = [ + "interpolation", + "utils", + "mechanicssolver", + "land_caisplit", + "land_CaTrpnsplit", + "land_Zetasplit", +] diff --git a/src/simcardems2/land_CaTrpnsplit.py b/src/simcardems2/land_CaTrpnsplit.py index 9c0efc9..42ff7f0 100644 --- a/src/simcardems2/land_CaTrpnsplit.py +++ b/src/simcardems2/land_CaTrpnsplit.py @@ -172,7 +172,7 @@ def __init__( self.Ta_current = dolfin.Function(self.function_space, name="Ta") self._projector = utils.Projector(self.function_space) self._dLambda_tol = dLambda_tol - self._t_prev = 0.0 + self._t_prev = dolfin.Constant(0.0) """ For CaTrpn split""" @@ -405,7 +405,7 @@ def Zetaw(self, lmbda): @property def dt(self) -> float: - return self.t - self._t_prev + return float(self.t - self._t_prev) def update_current(self, lmbda): self.update_Zetas(lmbda=lmbda) @@ -424,7 +424,7 @@ def update_prev(self): self.TmB_prev.vector()[:] = self._TmB.vector() self._projector.project(self.Ta_current, self.Ta(self.lmbda)) - self._t_prev = self.t + self._t_prev.assign(self.t) def Ta(self, lmbda): logger.debug("Evaluate Ta") diff --git a/src/simcardems2/land_Zetasplit.py b/src/simcardems2/land_Zetasplit.py index 74e57f7..49b0130 100644 --- a/src/simcardems2/land_Zetasplit.py +++ b/src/simcardems2/land_Zetasplit.py @@ -101,7 +101,7 @@ def __init__( self.Ta_current = dolfin.Function(self.function_space, name="Ta") self._projector = utils.Projector(self.function_space) self._dLambda_tol = dLambda_tol - self._t_prev = 0.0 + self._t_prev = dolfin.Constant(0.0) # @property # def lmbda_prev(self): @@ -221,7 +221,7 @@ def Zetaw(self, lmbda): @property def dt(self) -> float: - return self.t - self._t_prev + return float(self.t - self._t_prev) def update_current(self, lmbda): self.update_Zetas(lmbda=lmbda) @@ -233,7 +233,7 @@ def update_prev(self): self.Zetaw_prev.vector()[:] = self._Zetaw.vector() self.lmbda_prev.vector()[:] = self.lmbda.vector() # self.u_prev_prev.vector()[:] = self.u_prev.vector() - self._t_prev = self.t + self._t_prev.assign(self.t) def Ta(self, lmbda): logger.debug("Evaluate Ta") diff --git a/src/simcardems2/land_caisplit.py b/src/simcardems2/land_caisplit.py index 6f7f29b..0482817 100644 --- a/src/simcardems2/land_caisplit.py +++ b/src/simcardems2/land_caisplit.py @@ -211,7 +211,7 @@ def __init__( self.Ta_current = dolfin.Function(self.function_space, name="Ta") self._projector = utils.Projector(self.function_space) self._dLambda_tol = dLambda_tol - self._t_prev = 0.0 + self._t_prev = dolfin.Constant(0.0) """ From CaTrpn split""" @@ -355,9 +355,7 @@ def update_CaTrpn(self, lmbda): dt=self.dt, ), ) - print("Catrpn", self._CaTrpn.vector().get_local()[0]) - - """ """ + logger.debug("Catrpn", self._CaTrpn.vector().get_local()[0]) def dLambda(self, lmbda): logger.debug("Evaluate dLambda") @@ -508,7 +506,7 @@ def Zetaw(self, lmbda): @property def dt(self) -> float: - return self.t - self._t_prev + return float(self.t - self._t_prev) def update_current(self, lmbda): self.update_Zetas(lmbda=lmbda) @@ -524,7 +522,7 @@ def update_prev(self): self.Zetas_prev.vector()[:] = self._Zetas.vector() self.Zetaw_prev.vector()[:] = self._Zetaw.vector() self.lmbda_prev.vector()[:] = self.lmbda.vector() - print("lmbda", self.lmbda_prev.vector()[0]) + logger.debug("lmbda", self.lmbda_prev.vector()[0]) self.XS_prev.vector()[:] = self._XS.vector() self.XW_prev.vector()[:] = self._XW.vector() @@ -532,14 +530,14 @@ def update_prev(self): self.CaTrpn_prev.vector()[:] = self._CaTrpn.vector() self._projector.project(self.Ta_current, self.Ta(self.lmbda)) - self._t_prev = self.t + self._t_prev.assign(self.t) def Ta(self, lmbda): logger.debug("Evaluate Ta") Tref = self._parameters["Tref"] rs = self._parameters["rs"] - scale_popu_Tref = 1.0 # self._parameters["scale_popu_Tref"] - scale_popu_rs = 1.0 # self._parameters["scale_popu_rs"] + scale_popu_Tref = 1.0 + scale_popu_rs = 1.0 Beta0 = self._parameters["Beta0"] _min = ufl.min_value diff --git a/src/simcardems2/mechanicssolver.py b/src/simcardems2/mechanicssolver.py index 1abc66a..bcf291d 100644 --- a/src/simcardems2/mechanicssolver.py +++ b/src/simcardems2/mechanicssolver.py @@ -61,7 +61,7 @@ def __init__( logger.info(f"Initialize NewtonSolver with parameters: {parameters!r}") dolfin.PETScOptions.clear() self.dx = dolfin.Measure("dx", domain=state.function_space().mesh()) - self.volume = dolfin.assemble(dolfin.Constant(1) * self.dx) + # self.volume = dolfin.assemble(dolfin.Constant(1) * self.dx) self._problem = problem self._state = state self._update_cb = update_cb @@ -187,7 +187,9 @@ def solve(self, t0: float, dt: float) -> Tuple[int, bool]: self.active._dLambda, (lmbda - self.active.lmbda_prev) / self.active.dt ) - self.active._projector.project(self.active.Ta_current, self.active.Ta(lmbda)) + Ta = self.active.Ta(lmbda) + if not isinstance(Ta, ufl.constantvalue.Zero): + self.active._projector.project(self.active.Ta_current, self.active.Ta(lmbda)) self.active.update_current(lmbda=lmbda) self.active.update_prev() if not conv: From c3a3ea84f1b9f2ef578f83bfc2d0c405a239a7ca Mon Sep 17 00:00:00 2001 From: Henrik Finsberg Date: Sun, 2 Feb 2025 21:38:07 +0100 Subject: [PATCH 4/5] Remove demos --- .../CaTrpn_split/ORdmm_Land.ode | 663 ---------------- .../CaTrpn_split/config.toml | 118 --- ...d_CaTrpnsplit_consistent_with_zetasplit.py | 451 ----------- ...n_catrpnsplit_consistent_with_zetasplit.py | 683 ---------------- .../cai_split/ORdmm_Land.ode | 663 ---------------- .../cai_split/config.toml | 117 --- ...land_caisplit_consistent_with_zetasplit.py | 549 ------------- ...main_caisplit_consistent_with_zetasplit.py | 688 ---------------- demos/create_geometry_with_surface_markers.py | 93 --- demos/split-cai/0D/ORdmm_Land.ode | 663 ---------------- demos/split-cai/0D/main.py | 498 ------------ demos/split-cai/0D/main_time_and_Ns.py | 363 --------- .../0D_ToRORd/ToRORd_dynCl_endo_caisplit.ode | 715 ----------------- demos/split-cai/3D/ORdmm_Land.ode | 663 ---------------- .../3D/ToRORd_dynCl_endo_caisplit.ode | 715 ----------------- demos/split-cai/3D/config.toml | 117 --- demos/split-cai/3D/main_using_config.py | 700 ----------------- demos/split-cai/3D/main_using_config_time.py | 737 ------------------ demos/split-cai_catrpn/0D/ORdmm_Land.ode | 663 ---------------- demos/split-cai_catrpn/0D/main.py | 490 ------------ demos/split-cai_catrpn/0D/main_time_and_Ns.py | 342 -------- .../ToRORd_dynCl_endo_catrpnsplit.ode | 719 ----------------- demos/split-cai_catrpn/3D/ORdmm_Land.ode | 663 ---------------- .../3D/ToRORd_dynCl_endo_catrpnsplit.ode | 719 ----------------- demos/split-cai_catrpn/3D/config.toml | 118 --- .../split-cai_catrpn/3D/main_using_config.py | 681 ---------------- .../3D/main_using_config_time.py | 720 ----------------- demos/split-zeta/0D/ORdmm_Land.ode | 669 ---------------- demos/split-zeta/0D/main.py | 488 ------------ demos/split-zeta/0D/main_time_and_Ns.py | 339 -------- .../0D_ToRORd/ToRORd_dynCl_endo_zetasplit.ode | 722 ----------------- demos/split-zeta/3D/ORdmm_Land.ode | 669 ---------------- .../3D/ToRORd_dynCl_endo_zetasplit.ode | 722 ----------------- demos/split-zeta/3D/config.toml | 129 --- demos/split-zeta/3D/main_check_Ta.py | 243 ------ demos/split-zeta/3D/main_using_config.py | 684 ---------------- .../split-zeta/3D/main_using_config_no_ep.py | 234 ------ demos/split-zeta/3D/main_using_config_time.py | 720 ----------------- .../steady_state/main_full_to_steady_state.py | 134 ---- 39 files changed, 20064 deletions(-) delete mode 100644 demos/consistency_checks_across_split_schemes/CaTrpn_split/ORdmm_Land.ode delete mode 100644 demos/consistency_checks_across_split_schemes/CaTrpn_split/config.toml delete mode 100644 demos/consistency_checks_across_split_schemes/CaTrpn_split/land_CaTrpnsplit_consistent_with_zetasplit.py delete mode 100644 demos/consistency_checks_across_split_schemes/CaTrpn_split/main_catrpnsplit_consistent_with_zetasplit.py delete mode 100644 demos/consistency_checks_across_split_schemes/cai_split/ORdmm_Land.ode delete mode 100644 demos/consistency_checks_across_split_schemes/cai_split/config.toml delete mode 100644 demos/consistency_checks_across_split_schemes/cai_split/land_caisplit_consistent_with_zetasplit.py delete mode 100644 demos/consistency_checks_across_split_schemes/cai_split/main_caisplit_consistent_with_zetasplit.py delete mode 100644 demos/create_geometry_with_surface_markers.py delete mode 100644 demos/split-cai/0D/ORdmm_Land.ode delete mode 100644 demos/split-cai/0D/main.py delete mode 100644 demos/split-cai/0D/main_time_and_Ns.py delete mode 100644 demos/split-cai/0D_ToRORd/ToRORd_dynCl_endo_caisplit.ode delete mode 100644 demos/split-cai/3D/ORdmm_Land.ode delete mode 100644 demos/split-cai/3D/ToRORd_dynCl_endo_caisplit.ode delete mode 100644 demos/split-cai/3D/config.toml delete mode 100644 demos/split-cai/3D/main_using_config.py delete mode 100644 demos/split-cai/3D/main_using_config_time.py delete mode 100644 demos/split-cai_catrpn/0D/ORdmm_Land.ode delete mode 100644 demos/split-cai_catrpn/0D/main.py delete mode 100644 demos/split-cai_catrpn/0D/main_time_and_Ns.py delete mode 100644 demos/split-cai_catrpn/0D_ToRORd/ToRORd_dynCl_endo_catrpnsplit.ode delete mode 100644 demos/split-cai_catrpn/3D/ORdmm_Land.ode delete mode 100644 demos/split-cai_catrpn/3D/ToRORd_dynCl_endo_catrpnsplit.ode delete mode 100644 demos/split-cai_catrpn/3D/config.toml delete mode 100644 demos/split-cai_catrpn/3D/main_using_config.py delete mode 100644 demos/split-cai_catrpn/3D/main_using_config_time.py delete mode 100644 demos/split-zeta/0D/ORdmm_Land.ode delete mode 100644 demos/split-zeta/0D/main.py delete mode 100644 demos/split-zeta/0D/main_time_and_Ns.py delete mode 100644 demos/split-zeta/0D_ToRORd/ToRORd_dynCl_endo_zetasplit.ode delete mode 100644 demos/split-zeta/3D/ORdmm_Land.ode delete mode 100644 demos/split-zeta/3D/ToRORd_dynCl_endo_zetasplit.ode delete mode 100644 demos/split-zeta/3D/config.toml delete mode 100644 demos/split-zeta/3D/main_check_Ta.py delete mode 100644 demos/split-zeta/3D/main_using_config.py delete mode 100644 demos/split-zeta/3D/main_using_config_no_ep.py delete mode 100644 demos/split-zeta/3D/main_using_config_time.py delete mode 100644 demos/steady_state/main_full_to_steady_state.py diff --git a/demos/consistency_checks_across_split_schemes/CaTrpn_split/ORdmm_Land.ode b/demos/consistency_checks_across_split_schemes/CaTrpn_split/ORdmm_Land.ode deleted file mode 100644 index c753ce8..0000000 --- a/demos/consistency_checks_across_split_schemes/CaTrpn_split/ORdmm_Land.ode +++ /dev/null @@ -1,663 +0,0 @@ -# ORd modified by MMora (October-2016) -# Modifications in INa. The original formulation of INa has been -# optimised, according to Passini, in order to look like TT04. -# Modifications: -# 1) mss,hss,jss and hssp -# 2) gNa -# + -# Re-scaled conductances (Dutta et al 2016 CinC) -# + -# -# Land 2017(mechanical model)- Introduced by MMora (Jan2020) -# Tension -# Changes in Cai effect of troponin -# + -# -# Isacs -# -# -# In this version we fix mech.emcoupling=1, -# mode="intact", isacs=0 and celltype = 0 -# -# -# Modifications by Ilse (January 2023) -# Add scaling facotrs for heart failure and drugs - - -parameters("Scales", -scale_IKr = 1.119, -scale_IKs = 1.648, -scale_IK1 = 1.414, -scale_ICaL = 1.018, -scale_INaL = 2.274) - - - -parameters("settings", -celltype=0) - -parameters("extracellular ionic concentrations", -nao=140.0, -cao=1.8, -ko=5.4) - -parameters("physical constants", "mechanics", -R=8314.0, -T=310.0, -F=96485.0) - - -parameters("cell geometry", "mechanics", -L=0.01, -rad=0.0011) - - -expressions("cell geometry", "mechanics") -vcell=1000*3.14*rad*rad*L -Ageo=2*3.14*rad*rad+2*3.14*rad*L -Acap=2*Ageo -vmyo=0.68*vcell -vnsr=0.0552*vcell -vjsr=0.0048*vcell -vss=0.02*vcell - - -# Scaling factors for heart failure -parameters("scaling factors HF", -scale_HF_CaMKa=1.0, -scale_HF_Jrel_inf=1.0, -scale_HF_Jleak=1.0, -scale_HF_Jup=1.0, -scale_HF_GNaL=1.0, -scale_HF_GK1=1.0, -scale_HF_thL=1.0, -scale_HF_Gto=1.0, -scale_HF_Gncx=1.0, -scale_HF_Pnak=1.0) - -# Scaling factors for drug effects -parameters("scaling factors drug", -scale_drug_INa=1.0, -scale_drug_INaL=1.0, -scale_drug_Ito=1.0, -scale_drug_ICaL=1.0, -scale_drug_IKr=1.0, -scale_drug_IKs=1.0, -scale_drug_IK1=1.0, -scale_drug_IKb=1.0, -scale_drug_INab=1.0, -scale_drug_ICab=1.0, -scale_drug_IpCa=1.0, -scale_drug_Isacns=1.0, -scale_drug_Isack=1.0) - -######## EP states -states("CaMKt", -CaMKt=0 -) - -states("I_Na", -m=0, -hf=1, -hs=1, -j=1, -hsp=1, -jp=1) - -states("INaL", -mL=0, -hL=1, -hLp=1) - -states("Ito", -a=0, -iF=1, -iS=1, -ap=0, -iFp=1, -iSp=1) - -states("ICaL ICaNa ICaK", -d=0, -ff=1, -fs=1, -fcaf=1, -fcas=1, -jca=1, -nca=0, -ffp=1, -fcafp=1) - - -states("IKr", -xrf=0, -xrs=0) - - -states("IKs", -xs1=0, -xs2=0, -xk1=1) - -states("membrane potential", -v=-87) - - -states("ryanodione receptor", -Jrelnp=0, -Jrelp=0) - - -states("intracellular concentrations", -cai=0.0001, -nai=7, -nass=7, -ki=145, -kss=145, -cass=0.0001, -cansr=1.2, -CaTrpn=0.0001, -cajsr=1.2) - -states("mechanics", -XS=0, -XW=0, -TmB=1, -Zetas=0, -Zetaw=0, -Cd=0) - - -############################## - -parameters("CaMK constants", -KmCaMK=0.15, -aCaMK=0.05, -bCaMK=0.00068, -CaMKo=0.05, -KmCaM=0.0015) - -expressions("CaMKt") -CaMKb=CaMKo*(1.0-CaMKt)/(1.0+KmCaM/cass) -CaMKa=(CaMKb+CaMKt)*scale_HF_CaMKa -dCaMKt_dt=aCaMK*CaMKb*(CaMKb+CaMKt)-bCaMK*CaMKt - -parameters("reversal potentials", -PKNa=0.01833) - -expressions("reversal potentials") -ENa=(R*T/F)*log(nao/nai) -EK=(R*T/F)*log(ko/ki) -EKs=(R*T/F)*log((ko+PKNa*nao)/(ki+PKNa*nai)) -vffrt=v*F*F/(R*T) -vfrt=v*F/(R*T) - -parameters("I_Na", -Ahf=0.99, -GNa=31) - -expressions("I_Na") -mss=1.0/(1.0+exp((-(v+39.57+9.4))/7.5)) -tm=1.0/(6.765*exp((v+11.64)/34.77)+8.552*exp(-(v+77.42)/5.955)) -dm_dt=(mss-m)/tm -hss=1.0/(1+exp((v+78.5)/6.22)) -thf=1.0/(1.432e-5*exp(-(v+1.196)/6.285)+6.149*exp((v+0.5096)/20.27)) -ths=1.0/(0.009794*exp(-(v+17.95)/28.05)+0.3343*exp((v+5.730)/56.66)) -Ahs=1.0-Ahf -dhf_dt=(hss-hf)/thf -dhs_dt=(hss-hs)/ths -h=Ahf*hf+Ahs*hs -jss=hss -tj=2.038+1.0/(0.02136*exp(-(v+100.6)/8.281)+0.3052*exp((v+0.9941)/38.45)) -dj_dt=(jss-j)/tj -hssp=1.0/(1+exp((v+78.5+6.2)/6.22)) -thsp=3.0*ths -dhsp_dt=(hssp-hsp)/thsp -hp=Ahf*hf+Ahs*hsp -tjp=1.46*tj -djp_dt=(jss-jp)/tjp -fINap=(1.0/(1.0+KmCaMK/CaMKa)) -INa=GNa*scale_drug_INa*(v-ENa)*m**3.0*((1.0-fINap)*h*j+fINap*hp*jp) - -parameters("INaL", -thL=200.0) - -expressions("INaL") -mLss=1.0/(1.0+exp((-(v+42.85))/5.264)) -tmL=tm -dmL_dt=(mLss-mL)/tmL -hLss=1.0/(1.0+exp((v+87.61)/7.488)) -dhL_dt=(hLss-hL)/(thL*scale_HF_thL) -hLssp=1.0/(1.0+exp((v+93.81)/7.488)) -thLp=3.0*thL*scale_HF_thL -dhLp_dt=(hLssp-hLp)/thLp -GNaL=0.0075*scale_INaL*scale_drug_INaL*scale_HF_GNaL -fINaLp=(1.0/(1.0+KmCaMK/CaMKa)) -INaL=GNaL*(v-ENa)*mL*((1.0-fINaLp)*hL+fINaLp*hLp) - -parameters("Ito", -delta_epi=1.0, -Gto=0.02) - -expressions("Ito") -ass=1.0/(1.0+exp((-(v-14.34))/14.82)) -ta=1.0515/(1.0/(1.2089*(1.0+exp(-(v-18.4099)/29.3814)))+3.5/(1.0+exp((v+100.0)/29.3814))) -da_dt=(ass-a)/ta -iss=1.0/(1.0+exp((v+43.94)/5.711)) -tiF=4.562+1/(0.3933*exp((-(v+100.0))/100.0)+0.08004*exp((v+50.0)/16.59)) * delta_epi -tiS=23.62+1/(0.001416*exp((-(v+96.52))/59.05)+1.780e-8*exp((v+114.1)/8.079)) * delta_epi -AiF=1.0/(1.0+exp((v-213.6)/151.2)) -AiS=1.0-AiF -diF_dt=(iss-iF)/tiF -diS_dt=(iss-iS)/tiS -i=AiF*iF+AiS*iS -assp=1.0/(1.0+exp((-(v-24.34))/14.82)) -dap_dt=(assp-ap)/ta -dti_develop=1.354+1.0e-4/(exp((v-167.4)/15.89)+exp(-(v-12.23)/0.2154)) -dti_recover=1.0-0.5/(1.0+exp((v+70.0)/20.0)) -tiFp=dti_develop*dti_recover*tiF -tiSp=dti_develop*dti_recover*tiS -diFp_dt=(iss-iFp)/tiFp -diSp_dt=(iss-iSp)/tiSp -ip=AiF*iFp+AiS*iSp -fItop=(1.0/(1.0+KmCaMK/CaMKa)) -Ito=Gto*scale_drug_Ito*scale_HF_Gto*(v-EK)*((1.0-fItop)*a*i+fItop*ap*ip) - - -parameters("ICaL ICaNa ICaK", -Aff=0.6, -tjca=75.0, -Kmn=0.002, -k2n=1000.0, -zca=2.0) - -expressions("ICaL ICaNa ICaK") -dss=1.0/(1.0+exp((-(v+3.940))/4.230)) -td=0.6+1.0/(exp(-0.05*(v+6.0))+exp(0.09*(v+14.0))) -dd_dt=(dss-d)/td -fss=1.0/(1.0+exp((v+19.58)/3.696)) -tff=7.0+1.0/(0.0045*exp(-(v+20.0)/10.0)+0.0045*exp((v+20.0)/10.0)) -tfs=1000.0+1.0/(0.000035*exp(-(v+5.0)/4.0)+0.000035*exp((v+5.0)/6.0)) -Afs=1.0-Aff -dff_dt=(fss-ff)/tff -dfs_dt=(fss-fs)/tfs -f=Aff*ff+Afs*fs -fcass=fss -tfcaf=7.0+1.0/(0.04*exp(-(v-4.0)/7.0)+0.04*exp((v-4.0)/7.0)) -tfcas=100.0+1.0/(0.00012*exp(-v/3.0)+0.00012*exp(v/7.0)) -Afcaf=0.3+0.6/(1.0+exp((v-10.0)/10.0)) -Afcas=1.0-Afcaf -dfcaf_dt=(fcass-fcaf)/tfcaf -dfcas_dt=(fcass-fcas)/tfcas -fca=Afcaf*fcaf+Afcas*fcas -djca_dt=(fcass-jca)/tjca -tffp=2.5*tff -dffp_dt=(fss-ffp)/tffp -fp=Aff*ffp+Afs*fs -tfcafp=2.5*tfcaf -dfcafp_dt=(fcass-fcafp)/tfcafp -fcap=Afcaf*fcafp+Afcas*fcas -km2n=jca*1.0 -anca=1.0/(k2n/km2n+(1.0+Kmn/cass)**4.0) -dnca_dt=anca*k2n-nca*km2n -PhiCaL=4.0*vffrt*(cass*exp(2.0*vfrt)-0.341*cao)/(exp(2.0*vfrt)-1.0) -PhiCaNa=1.0*vffrt*(0.75*nass*exp(1.0*vfrt)-0.75*nao)/(exp(1.0*vfrt)-1.0) -PhiCaK=1.0*vffrt*(0.75*kss*exp(1.0*vfrt)-0.75*ko)/(exp(1.0*vfrt)-1.0) -PCa=0.0001*scale_ICaL*scale_drug_ICaL -PCap=1.1*PCa -PCaNa=0.00125*PCa -PCaK=3.574e-4*PCa -PCaNap=0.00125*PCap -PCaKp=3.574e-4*PCap -fICaLp=(1.0/(1.0+KmCaMK/CaMKa)) -ICaL=(1.0-fICaLp)*PCa*PhiCaL*d*(f*(1.0-nca)+jca*fca*nca)+fICaLp*PCap*PhiCaL*d*(fp*(1.0-nca)+jca*fcap*nca) -ICaNa=(1.0-fICaLp)*PCaNa*PhiCaNa*d*(f*(1.0-nca)+jca*fca*nca)+fICaLp*PCaNap*PhiCaNa*d*(fp*(1.0-nca)+jca*fcap*nca) -ICaK=(1.0-fICaLp)*PCaK*PhiCaK*d*(f*(1.0-nca)+jca*fca*nca)+fICaLp*PCaKp*PhiCaK*d*(fp*(1.0-nca)+jca*fcap*nca) - -expressions("IKr") -xrss=1.0/(1.0+exp((-(v+8.337))/6.789)) -txrf=12.98+1.0/(0.3652*exp((v-31.66)/3.869)+4.123e-5*exp((-(v-47.78))/20.38)) -txrs=1.865+1.0/(0.06629*exp((v-34.70)/7.355)+1.128e-5*exp((-(v-29.74))/25.94)) -Axrf=1.0/(1.0+exp((v+54.81)/38.21)) -Axrs=1.0-Axrf -dxrf_dt=(xrss-xrf)/txrf -dxrs_dt=(xrss-xrs)/txrs -xr=Axrf*xrf+Axrs*xrs -rkr=1.0/(1.0+exp((v+55.0)/75.0))*1.0/(1.0+exp((v-10.0)/30.0)) -GKr=0.046*scale_IKr*scale_drug_IKr -IKr=GKr*sqrt(ko/5.4)*xr*rkr*(v-EK) - -expressions("IKs") -xs1ss=1.0/(1.0+exp((-(v+11.60))/8.932)) -txs1=817.3+1.0/(2.326e-4*exp((v+48.28)/17.80)+0.001292*exp((-(v+210.0))/230.0)) -dxs1_dt=(xs1ss-xs1)/txs1 -xs2ss=xs1ss -txs2=1.0/(0.01*exp((v-50.0)/20.0)+0.0193*exp((-(v+66.54))/31.0)) -dxs2_dt=(xs2ss-xs2)/txs2 -KsCa=1.0+0.6/(1.0+(3.8e-5/cai)**1.4) -GKs=0.0034*scale_IKs*scale_drug_IKs -IKs=GKs*KsCa*xs1*xs2*(v-EKs) -xk1ss=1.0/(1.0+exp(-(v+2.5538*ko+144.59)/(1.5692*ko+3.8115))) -txk1=122.2/(exp((-(v+127.2))/20.36)+exp((v+236.8)/69.33)) -dxk1_dt=(xk1ss-xk1)/txk1 -rk1=1.0/(1.0+exp((v+105.8-2.6*ko)/9.493)) -GK1=0.1908*scale_IK1*scale_drug_IK1*scale_HF_GK1 -IK1=GK1*sqrt(ko)*rk1*xk1*(v-EK) - - -parameters("INaCa_i", -kna1=15.0, -kna2=5.0, -kna3=88.12, -kasymm=12.5, -wna=6.0e4, -wca=6.0e4, -wnaca=5.0e3, -kcaon=1.5e6, -kcaoff=5.0e3, -qna=0.5224, -qca=0.1670, -KmCaAct=150.0e-6, -Gncx=0.0008) - -expressions("INaCa_i") -hca=exp((qca*v*F)/(R*T)) -hna=exp((qna*v*F)/(R*T)) -h1_i=1+nai/kna3*(1+hna) -h2_i=(nai*hna)/(kna3*h1_i) -h3_i=1.0/h1_i -h4_i=1.0+nai/kna1*(1+nai/kna2) -h5_i=nai*nai/(h4_i*kna1*kna2) -h6_i=1.0/h4_i -h7_i=1.0+nao/kna3*(1.0+1.0/hna) -h8_i=nao/(kna3*hna*h7_i) -h9_i=1.0/h7_i -h10_i=kasymm+1.0+nao/kna1*(1.0+nao/kna2) -h11_i=nao*nao/(h10_i*kna1*kna2) -h12_i=1.0/h10_i -k1_i=h12_i*cao*kcaon -k2_i=kcaoff -k3p_i=h9_i*wca -k3pp_i=h8_i*wnaca -k3_i=k3p_i+k3pp_i -k4p_i=h3_i*wca/hca -k4pp_i=h2_i*wnaca -k4_i=k4p_i+k4pp_i -k5_i=kcaoff -k6_i=h6_i*cai*kcaon -k7_i=h5_i*h2_i*wna -k8_i=h8_i*h11_i*wna -x1_i=k2_i*k4_i*(k7_i+k6_i)+k5_i*k7_i*(k2_i+k3_i) -x2_i=k1_i*k7_i*(k4_i+k5_i)+k4_i*k6_i*(k1_i+k8_i) -x3_i=k1_i*k3_i*(k7_i+k6_i)+k8_i*k6_i*(k2_i+k3_i) -x4_i=k2_i*k8_i*(k4_i+k5_i)+k3_i*k5_i*(k1_i+k8_i) -E1_i=x1_i/(x1_i+x2_i+x3_i+x4_i) -E2_i=x2_i/(x1_i+x2_i+x3_i+x4_i) -E3_i=x3_i/(x1_i+x2_i+x3_i+x4_i) -E4_i=x4_i/(x1_i+x2_i+x3_i+x4_i) -allo_i=1.0/(1.0+(KmCaAct/cai)**2.0) -zna=1.0 -JncxNa_i=3.0*(E4_i*k7_i-E1_i*k8_i)+E3_i*k4pp_i-E2_i*k3pp_i -JncxCa_i=E2_i*k2_i-E1_i*k1_i -INaCa_i=0.8*Gncx*scale_HF_Gncx*allo_i*(zna*JncxNa_i+zca*JncxCa_i) - -expressions("INaCa_ss") -h1=1+nass/kna3*(1+hna) -h2=(nass*hna)/(kna3*h1) -h3=1.0/h1 -h4=1.0+nass/kna1*(1+nass/kna2) -h5=nass*nass/(h4*kna1*kna2) -h6=1.0/h4 -h7=1.0+nao/kna3*(1.0+1.0/hna) -h8=nao/(kna3*hna*h7) -h9=1.0/h7 -h10=kasymm+1.0+nao/kna1*(1+nao/kna2) -h11=nao*nao/(h10*kna1*kna2) -h12=1.0/h10 -k1=h12*cao*kcaon -k2=kcaoff -k3p_ss=h9*wca -k3pp=h8*wnaca -k3=k3p_ss+k3pp -k4p_ss=h3*wca/hca -k4pp=h2*wnaca -k4=k4p_ss+k4pp -k5=kcaoff -k6=h6*cass*kcaon -k7=h5*h2*wna -k8=h8*h11*wna -x1_ss=k2*k4*(k7+k6)+k5*k7*(k2+k3) -x2_ss=k1*k7*(k4+k5)+k4*k6*(k1+k8) -x3_ss=k1*k3*(k7+k6)+k8*k6*(k2+k3) -x4_ss=k2*k8*(k4+k5)+k3*k5*(k1+k8) -E1_ss=x1_ss/(x1_ss+x2_ss+x3_ss+x4_ss) -E2_ss=x2_ss/(x1_ss+x2_ss+x3_ss+x4_ss) -E3_ss=x3_ss/(x1_ss+x2_ss+x3_ss+x4_ss) -E4_ss=x4_ss/(x1_ss+x2_ss+x3_ss+x4_ss) -allo_ss=1.0/(1.0+(KmCaAct/cass)**2.0) -JncxNa_ss=3.0*(E4_ss*k7-E1_ss*k8)+E3_ss*k4pp-E2_ss*k3pp -JncxCa_ss=E2_ss*k2-E1_ss*k1 -INaCa_ss=0.2*Gncx*scale_HF_Gncx*allo_ss*(zna*JncxNa_ss+zca*JncxCa_ss) - - -parameters("INaK", -k1p=949.5, -k1m=182.4, -k2p=687.2, -k2m=39.4, -k3p=1899.0, -k3m=79300.0, -k4p=639.0, -k4m=40.0, -Knai0=9.073, -Knao0=27.78, -delta=-0.1550, -Kki=0.5, -Kko=0.3582, -MgADP=0.05, -MgATP=9.8, -Kmgatp=1.698e-7, -H=1.0e-7, -eP=4.2, -Khp=1.698e-7, -Knap=224.0, -Kxkur=292.0, -zk=1.0, -Pnak=30) - -expressions("INaK") -Knai=Knai0*exp((delta*v*F)/(3.0*R*T)) -Knao=Knao0*exp(((1.0-delta)*v*F)/(3.0*R*T)) -P=eP/(1.0+H/Khp+nai/Knap+ki/Kxkur) -a1=(k1p*(nai/Knai)**3.0)/((1.0+nai/Knai)**3.0+(1.0+ki/Kki)**2.0-1.0) -b1=k1m*MgADP -a2=k2p -b2=(k2m*(nao/Knao)**3.0)/((1.0+nao/Knao)**3.0+(1.0+ko/Kko)**2.0-1.0) -a3=(k3p*(ko/Kko)**2.0)/((1.0+nao/Knao)**3.0+(1.0+ko/Kko)**2.0-1.0) -b3=(k3m*P*H)/(1.0+MgATP/Kmgatp) -a4=(k4p*MgATP/Kmgatp)/(1.0+MgATP/Kmgatp) -b4=(k4m*(ki/Kki)**2.0)/((1.0+nai/Knai)**3.0+(1.0+ki/Kki)**2.0-1.0) -x1=a4*a1*a2+b2*b4*b3+a2*b4*b3+b3*a1*a2 -x2=b2*b1*b4+a1*a2*a3+a3*b1*b4+a2*a3*b4 -x3=a2*a3*a4+b3*b2*b1+b2*b1*a4+a3*a4*b1 -x4=b4*b3*b2+a3*a4*a1+b2*a4*a1+b3*b2*a1 -E1=x1/(x1+x2+x3+x4) -E2=x2/(x1+x2+x3+x4) -E3=x3/(x1+x2+x3+x4) -E4=x4/(x1+x2+x3+x4) -JnakNa=3.0*(E1*a3-E2*b3) -JnakK=2.0*(E4*b1-E3*a1) -INaK=Pnak*scale_HF_Pnak*(zna*JnakNa+zk*JnakK) - - -parameters("IKb", -GKb=0.003) - -expressions("IKb") -xkb=1.0/(1.0+exp(-(v-14.48)/18.34)) -IKb=GKb*scale_drug_IKb*xkb*(v-EK) - -parameters("INab", -PNab=3.75e-10) - -expressions("INab") -INab=PNab*scale_drug_INab*vffrt*(nai*exp(vfrt)-nao)/(exp(vfrt)-1.0) - - -parameters("ICab", -PCab=2.5e-8) - -expressions("ICab") -ICab=PCab*scale_drug_ICab*4.0*vffrt*(cai*exp(2.0*vfrt)-0.341*cao)/(exp(2.0*vfrt)-1.0) - -parameters("IpCa", -GpCa=0.0005) - -expressions("IpCa") -IpCa=GpCa*scale_drug_IpCa*cai/(0.0005+cai) - - -parameters("Isac (Pueyo)--> ns + k", -Gsac_ns=0.006, -Esac_ns=-10, -lambda_max=1.1, -Gsac_k=0.2882*800/210) - -expressions("Isac (Pueyo)--> ns + k") -Isac_P_ns=0 -Isac_P_k=0 - - -parameters("Istim", -amp=-80.0, -duration=0.5) - -expressions("Istim") -Istim = Conditional(Le(t, duration), amp, 0) - -expressions("membrane potential") -dv_dt=-(INa+INaL+Ito+ICaL+ICaNa+ICaK+IKr+IKs+IK1+INaCa_i+INaCa_ss+INaK+INab+IKb+IpCa+ICab+Istim+Isac_P_ns+Isac_P_k) - -expressions("diffusion fluxes") -JdiffNa=(nass-nai)/2.0 -JdiffK=(kss-ki)/2.0 -Jdiff=(cass-cai)/0.2 - -parameters("ryanodione receptor", -bt=4.75) - -expressions("ryanodione receptor") -a_rel=0.5*bt -Jrel_inf=a_rel*(-ICaL)/(1.0+(1.5*scale_HF_Jrel_inf/cajsr)**8.0) -tau_rel_tmp=bt/(1.0+0.0123/cajsr) -tau_rel=Conditional(Lt(tau_rel_tmp, 0.001), 0.001, tau_rel_tmp) -dJrelnp_dt=(Jrel_inf-Jrelnp)/tau_rel -btp=1.25*bt -a_relp=0.5*btp -Jrel_infp=a_relp*(-ICaL)/(1.0+(1.5*scale_HF_Jrel_inf/cajsr)**8.0) -tau_relp_tmp=btp/(1.0+0.0123/cajsr) -tau_relp=Conditional(Lt(tau_relp_tmp, 0.001), 0.001, tau_relp_tmp) -dJrelp_dt=(Jrel_infp-Jrelp)/tau_relp -fJrelp=(1.0/(1.0+KmCaMK/CaMKa)) -Jrel=(1.0-fJrelp)*Jrelnp+fJrelp*Jrelp - -expressions("calcium buffers") -Jupnp=0.004375*cai/(cai+0.00092) -Jupp=2.75*0.004375*cai/(cai+0.00092-0.00017) -fJupp=(1.0/(1.0+KmCaMK/CaMKa)) -Jleak=0.0039375*cansr*scale_HF_Jleak/15.0 -Jup=(1.0-fJupp)*Jupnp+fJupp*Jupp*scale_HF_Jup-Jleak -Jtr=(cansr-cajsr)/100.0 - -parameters("calcium buffers", "mechanics", -cmdnmax=0.05, -kmcmdn=0.00238, -trpnmax=0.07, -kmtrpn=0.0005, -BSRmax=0.047, -KmBSR=0.00087, -BSLmax=1.124, -KmBSL=0.0087, -csqnmax=10.0, -Beta1 = -2.4, -ktrpn = 0.1, -cat50_ref = 0.805, -ntrpn = 2, -lmbda=1, -scale_HF_cat50_ref=1.0, -kmcsqn=0.8) - -expressions("intracellular concentrations") -dnai_dt=-(INa+INaL+3.0*INaCa_i+3.0*INaK+INab+Isac_P_ns/3)*Acap/(F*vmyo)+JdiffNa*vss/vmyo -dnass_dt=-(ICaNa+3.0*INaCa_ss)*Acap/(F*vss)-JdiffNa -dki_dt=-(Ito+IKr+IKs+IK1+IKb+Isac_P_k+Isac_P_ns/3+Istim-2.0*INaK)*Acap/(F*vmyo)+JdiffK*vss/vmyo -dkss_dt=-(ICaK)*Acap/(F*vss)-JdiffK -Bcass=1.0/(1.0+BSRmax*KmBSR/(KmBSR+cass)**2.0+BSLmax*KmBSL/(KmBSL+cass)**2.0) -dcass_dt=Bcass*(-(ICaL-2.0*INaCa_ss)*Acap/(2.0*F*vss)+Jrel*vjsr/vss-Jdiff) -dcansr_dt=Jup-Jtr*vjsr/vnsr -Bcajsr=1.0/(1.0+csqnmax*kmcsqn/(kmcsqn+cajsr)**2.0) -dcajsr_dt=Bcajsr*(Jtr-Jrel) -Bcai=1.0/(1.0+cmdnmax*kmcmdn/(kmcmdn+cai)**2.0) -lambda_min12 = Conditional(Lt(lmbda, 1.2), lmbda, 1.2) -dcai_dt=Bcai*(-(IpCa+ICab-2.0*INaCa_i+Isac_P_ns/3)*Acap/(2.0*F*vmyo)-Jup*vnsr/vmyo+Jdiff*vss/vmyo - J_TRPN) -cat50 = (cat50_ref+Beta1*(lambda_min12-1))*scale_HF_cat50_ref -dCaTrpn_dt = ktrpn*(((cai*1000/cat50)**ntrpn)*(1-CaTrpn)-CaTrpn) -J_TRPN = dCaTrpn_dt*trpnmax - -parameters("mechanics", -emcoupling=1, -dLambda=0, -mode=1, -isacs=0, -calib=1, -Trpn50 = 0.35, -rw = 0.5, -rs = 0.25, -gammas = 0.0085, -gammaw = 0.615, -phi = 2.23, -Tot_A = 25, -Beta0 = 2.3, -Tref = 120, -kuw = 0.182, -kws = 0.012, -ku=0.04, -ntm=2.4, -p_a = 2.1, -p_b = 9.1, -p_k = 7, -etal = 200, -etas = 20) - -expressions("mechanics") -XS_max = Conditional(Gt(XS, 0), XS, 0) -XW_max = Conditional(Gt(XW, 0), XW, 0) -CaTrpn_max = Conditional(Gt(CaTrpn, 0), CaTrpn, 0) -kwu = kuw*(1/rw-1)-kws -ksu = kws*rw*(1/rs-1) -Aw = Tot_A*rs/((1-rs)*rw+rs) -As = Aw -cw = phi*kuw*((1-rs)*(1-rw))/((1-rs)*rw) -cs = phi*kws*((1-rs)*rw)/rs -lambda_min12 = Conditional(Lt(lmbda, 1.2), lmbda, 1.2) -lambda_min087 = Conditional(Lt(lambda_min12, 0.87), lambda_min12, 0.87) -h_lambda_prima = 1+Beta0*(lambda_min12+lambda_min087-1.87) -h_lambda = Conditional(Gt(h_lambda_prima, 0), h_lambda_prima, 0) -XU = (1-TmB)-XS-XW -gammawu = gammaw*abs(Zetaw) -gammasu = gammas*Conditional(Gt(Gt(Zetas,0)*Zetas, Lt(Zetas, -1)*(-Zetas-1)), Gt(Zetas,0)*Zetas, Lt(Zetas, -1)*(-Zetas-1)) -dXS_dt = kws*XW - ksu*XS - gammasu*XS -dXW_dt = kuw*XU - kwu*XW - kws*XW - gammawu*XW -kb = ku*Trpn50**ntm/(1-rs-(1-rs)*rw) -dTmB_dt = kb*Conditional(Lt(CaTrpn**(-ntm/2), 100), CaTrpn**(-ntm/2), 100)*XU-ku*CaTrpn**(ntm/2)*TmB -dZetas_dt = As*dLambda - cs*Zetas -dZetaw_dt = Aw*dLambda - cw*Zetaw -Ta = h_lambda*(Tref/rs)*(XS*(Zetas+1) + XW*Zetaw) -C = lambda_min12 - 1 -dCd = C - Cd -eta = Conditional(Lt(dCd, 0), etas, etal) -dCd_dt = p_k * (C - Cd) / eta -Fd = eta * dCd -F1 = (exp( p_b * C) - 1) -Tp = p_a * (F1 + Fd) -Ttot = Ta + Tp diff --git a/demos/consistency_checks_across_split_schemes/CaTrpn_split/config.toml b/demos/consistency_checks_across_split_schemes/CaTrpn_split/config.toml deleted file mode 100644 index 8e2391a..0000000 --- a/demos/consistency_checks_across_split_schemes/CaTrpn_split/config.toml +++ /dev/null @@ -1,118 +0,0 @@ -# Configuration file for running a simulation - -# SIMULATION PARAMETERS -sim.mech_mesh = "mesh_mech_0.5dx_0.5Lx_1Ly_2Lz" # mechanics mesh filepath without extension -sim.outdir = "50ms_N1_cai_catrpn_split_consistent_with_zeta_runcheck_with_111stim" # Output directory -sim.sim_dur = 50 # Duration of simulation. Integer -sim.dt = 0.05 # Timestep for ep solve -sim.N = 1 # Solve mechanics step every nth ep solve - -# MODEL PARAMETERS -sim.modelfile = "ORdmm_Land.ode" - -# OUTPUT PARAMETERS -write_all_ep.numbers = 2 -write_all_ep.0.name = "cai" -write_all_ep.1.name = "v" - -write_all_mech.numbers = 2 -write_all_mech.0.name = "Ta" -write_all_mech.1.name = "lambda" - -# Currently also outputting volume averages for these: -write_point_ep.numbers = 3 -write_point_ep.0.name = "cai" -write_point_ep.0.x = 0.0 -write_point_ep.0.y = 0 -write_point_ep.0.z = 0 -write_point_ep.1.name = "v" -write_point_ep.1.x = 0 -write_point_ep.1.y = 0 -write_point_ep.1.z = 0 -write_point_ep.2.name = "CaTrpn" -write_point_ep.2.x = 0 -write_point_ep.2.y = 0 -write_point_ep.2.z = 0 - -write_point_mech.numbers = 5 -write_point_mech.0.name = "Ta" -write_point_mech.0.x = 0 -write_point_mech.0.y = 0 -write_point_mech.0.z = 0 -write_point_mech.1.name = "Zetas" -write_point_mech.1.x = 0 -write_point_mech.1.y = 0 -write_point_mech.1.z = 0 -write_point_mech.2.name = "XS" -write_point_mech.2.x = 0 -write_point_mech.2.y = 0 -write_point_mech.2.z = 0 -write_point_mech.3.name = "TmB" -write_point_mech.3.x = 0 -write_point_mech.3.y = 0 -write_point_mech.3.z = 0 -write_point_mech.4.name = "lambda" -write_point_mech.4.x = 0 -write_point_mech.4.y = 0 -write_point_mech.4.z = 0 - - - -# Tissue conductivity values. Currently only a single region, from p.4339 of Niederer benchmark -ep.sigma_il = 0.17 # mS / mm -ep.sigma_it = 0.019 # mS / mm -ep.sigma_el = 0.62 # mS / mm -ep.sigma_et = 0.24 # mS / mm - -# Material parameters -# TODO: make material parameters more generic -mech.a=2.28 -mech.a_f=1.686 -mech.b=9.726 -mech.b_f=15.779 -mech.a_s=0.0 -mech.b_s=0.0 -mech.a_fs=0.0 -mech.b_fs=0.0 - -# STIMULUS PARAMETERS -stim.start = 0.0 -stim.amplitude = 50000.0 # mu A/cm^3 -stim.duration = 2 # ms -stim.xmin = 0.0 -stim.xmax = 1.0 -stim.ymin = 0.0 -stim.ymax = 1.0 -stim.zmin = 0.0 -stim.zmax = 1.0 - -# BOUNDARY CONDITIONS -bcs.numbers = 3 -bcs.markerfile = "mesh_mech_0.5dx_0.5Lx_1Ly_2Lz_surface_ffun" - -# Mesh markers used for assigning bcs -bcs.0.marker = 1 -bcs.0.type = "Dirichlet" -bcs.0.V = "u_x" -bcs.0.expression = 0 -bcs.0.param_numbers = 0 - -bcs.1.marker = 3 # if same marker for ux,uy,uz, (e.g. marker = 1), then fixes the entire plane (plane with marker == 1) -bcs.1.type = "Dirichlet" -bcs.1.V = "u_y" -bcs.1.expression = 0 -bcs.1.param_numbers = 0 - -bcs.2.marker = 5 -bcs.2.type = "Dirichlet" -bcs.2.V = "u_z" -bcs.2.expression = 0 -bcs.2.param_numbers = 0 - -#bcs.3.marker = 2 -#bcs.3.type = "Neumann" -#bcs.3.expression = 'a*t' # Value can be a function of t -#bcs.3.param_numbers = 1 -#bcs.3.param.0.name = 'a' -#bcs.3.param.0.value = -0.2 -#bcs.3.degree = 1 diff --git a/demos/consistency_checks_across_split_schemes/CaTrpn_split/land_CaTrpnsplit_consistent_with_zetasplit.py b/demos/consistency_checks_across_split_schemes/CaTrpn_split/land_CaTrpnsplit_consistent_with_zetasplit.py deleted file mode 100644 index 4032120..0000000 --- a/demos/consistency_checks_across_split_schemes/CaTrpn_split/land_CaTrpnsplit_consistent_with_zetasplit.py +++ /dev/null @@ -1,451 +0,0 @@ -import pulse -import dolfin -import ufl_legacy as ufl -import logging -import numpy as np -from enum import Enum - -from simcardems2 import utils - -logger = logging.getLogger(__name__) - - -class Scheme(str, Enum): - fd = "fd" - bd = "bd" - analytic = "analytic" - - -def _Zeta(Zeta_prev, A, c, dLambda, dt, scheme: Scheme): - # if scheme == Scheme.analytic: - dZetas_dt = A * dLambda - Zeta_prev * c - dZetas_dt_linearized = -c - if abs(c) > 1e-8: - return Zeta_prev + dZetas_dt * (np.exp(-c * dt) - 1.0) / dZetas_dt_linearized - else: - # Forward euler - return Zeta_prev + dZetas_dt * dt - - -# For CaTrpn split -def _XS(XS_prev, XW, gammasu, ksu, kws, dt): - dXS_dt_linearized = -gammasu - ksu - dXS_dt = -XS_prev * gammasu - XS_prev * ksu + XW * kws - return XS_prev + np.where( - (np.abs(dXS_dt_linearized) > 1e-8), - dXS_dt * (np.exp(dXS_dt_linearized * dt) - 1) / dXS_dt_linearized, - dXS_dt * dt, - ) - - -def _XW(XW_prev, XU, gammawu, kws, kuw, kwu, dt): - dXW_dt_linearized = -gammawu - kws - kwu - dXW_dt = -XW_prev * gammawu - XW_prev * kws + XU * kuw - XW_prev * kwu - return XW_prev + np.where( - (np.abs(dXW_dt_linearized) > 1e-8), - dXW_dt * (np.exp(dXW_dt_linearized * dt) - 1) / dXW_dt_linearized, - dXW_dt * dt, - ) - - -def _TmB(TmB_prev, CaTrpn, XU, ntm, kb, ku, dt): - dTmB_dt_linearized = -(CaTrpn ** (ntm / 2)) * ku - dTmB_dt = -TmB_prev * CaTrpn ** (ntm / 2) * ku + XU * ( - kb * np.where((CaTrpn ** (-1 / 2 * ntm) < 100), CaTrpn ** (-1 / 2 * ntm), 100) - ) - - return TmB_prev + np.where( - (np.abs(dTmB_dt_linearized) > 1e-8), - dTmB_dt * (np.exp(dTmB_dt_linearized * dt) - 1) / dTmB_dt_linearized, - dTmB_dt * dt, - ) - - -def _XU(XW, XS, TmB): - return -XW - XS + 1 - TmB - - -def _gammawu(Zetaw, gammaw): - return gammaw * np.abs(Zetaw) - - -def _gammasu(Zetas, gammas): - return gammas * np.where((Zetas > 0), Zetas, np.where((Zetas < -1), -Zetas - 1, 0)) - - -_parameters = { - "Beta0": 2.3, - "Tot_A": 25.0, - "Tref": 120, - "kuw": 0.182, - "kws": 0.012, - "phi": 2.23, - "rs": 0.25, - "rw": 0.5, - "gammas": 0.0085, # New parameters CaTrpn split - "gammaw": 0.615, # New parameters CaTrpn split - "Trpn50": 0.35, # New parameters CaTrpn split - "ntm": 2.4, # New parameters CaTrpn split. - "ku": 0.04, # New parameters CaTrpn split. -} - - -class LandModel(pulse.ActiveModel): - def __init__( - self, - f0, - s0, - n0, - CaTrpn, # New variables CaTrpn split (missing) - mesh, - TmB=None, # New variables CaTrpn split - XS=None, - XW=None, - parameters=None, - Zetas=None, - Zetaw=None, - lmbda=None, - eta=0, - scheme: Scheme = Scheme.analytic, - dLambda_tol: float = 1e-12, - **kwargs, - ): - logger.debug("Initialize Land Model") - super().__init__(f0=f0, s0=s0, n0=n0) - - self._eta = eta - self.function_space = dolfin.FunctionSpace(mesh, "DG", 1) - - """ For Catrpn split""" - self.CaTrpn = CaTrpn - - self._XS = dolfin.Function(self.function_space) - self.XS_prev = dolfin.Function(self.function_space) - if XS is not None: - self.XS_prev.assign(XS) - - self._XW = dolfin.Function(self.function_space) - self.XW_prev = dolfin.Function(self.function_space) - if XW is not None: - self.XW_prev.assign(XW) - - self._XU = dolfin.Function(self.function_space) - self._gammasu = dolfin.Function(self.function_space) - self._gammawu = dolfin.Function(self.function_space) - - self._TmB = dolfin.Function(self.function_space) - self.TmB_prev = dolfin.Function(self.function_space) - if TmB is not None: - self.TmB_prev.assign(TmB) - else: # Set initial TmB value - self._TmB.interpolate(dolfin.Constant(1)) - self.TmB_prev.interpolate(dolfin.Constant(1)) - """ """ - - if parameters is None: - parameters = _parameters - self._parameters = parameters - - self._scheme = scheme - - self._dLambda = dolfin.Function(self.function_space) - self.lmbda_prev = dolfin.Function(self.function_space) - self.lmbda_prev.vector()[:] = 1.0 - if lmbda is not None: - self.lmbda_prev.assign(lmbda) - self.lmbda = dolfin.Function(self.function_space) - - self._Zetas = dolfin.Function(self.function_space) - self.Zetas_prev = dolfin.Function(self.function_space) - if Zetas is not None: - self.Zetas_prev.assign(Zetas) - - self._Zetaw = dolfin.Function(self.function_space) - self.Zetaw_prev = dolfin.Function(self.function_space) - if Zetaw is not None: - self.Zetaw_prev.assign(Zetaw) - - self.Ta_current = dolfin.Function(self.function_space, name="Ta") - self._projector = utils.Projector(self.function_space) - self._dLambda_tol = dLambda_tol - self._t_prev = 0.0 - - """ For CaTrpn split""" - - @property - def ksu(self): - kws = self._parameters["kws"] - rw = self._parameters["rw"] - rs = self._parameters["rs"] - return (kws * rw) * (-1 + 1 / rs) - - @property - def kwu(self): - kuw = self._parameters["kuw"] - rw = self._parameters["rw"] - kws = self._parameters["kws"] - return kuw * (-1 + 1 / rw) - kws - - @property - def kb(self): - Trpn50 = self._parameters["Trpn50"] - ntm = self._parameters["ntm"] - ku = self._parameters["ku"] - rs = self._parameters["rs"] - rw = self._parameters["rw"] - return (Trpn50**ntm * ku) / (-rw * (1 - rs) + 1 - rs) - - @property - def XS(self): - return self._XS - - @property - def XW(self): - return self._XW - - @property - def TmB(self): - return self._TmB - - @property - def XU(self): - return self._XU - - @property - def gammawu(self): - return self._gammawu - - @property - def gammasu(self): - return self._gammasu - - def update_TmB(self): - logger.debug("update TmB") - self._TmB.vector()[:] = _TmB( - self.TmB_prev.vector().get_local(), - self.CaTrpn.vector().get_local(), - self.XU.vector().get_local(), - self._parameters["ntm"], - self.kb, - self._parameters["ku"], - self.dt, - ) - - def update_XS(self): - logger.debug("update XS") - self._XS.vector()[:] = _XS( - self.XS_prev.vector().get_local(), - self.XW_prev.vector().get_local(), - self.gammasu.vector().get_local(), - self.ksu, - self._parameters["kws"], - self.dt, - ) - - def update_XW(self): - logger.debug("update XW") - self._XW.vector()[:] = _XW( - self.XW_prev.vector().get_local(), - self.XU.vector().get_local(), - self.gammawu.vector().get_local(), - self._parameters["kws"], - self._parameters["kuw"], - self.kwu, - self.dt, - ) - - # Calculate monitors - def calculate_XU(self): - logger.debug("update XU") - self._XU.vector()[:] = _XU( - self.XW_prev.vector().get_local(), - self.XS_prev.vector().get_local(), - self.TmB_prev.vector().get_local(), - ) - - def calculate_gammasu(self): - logger.debug("update gammasu") - self._gammasu.vector()[:] = _gammasu( - self.Zetas_prev.vector().get_local(), - self._parameters["gammas"], - ) - - def calculate_gammawu(self): - logger.debug("update gammawu") - self._gammawu.vector()[:] = _gammawu( - self.Zetaw_prev.vector().get_local(), - self._parameters["gammaw"], - ) - - def dLambda(self, lmbda): - logger.debug("Evaluate dLambda") - if self.dt == 0: - return self._dLambda - else: - return (lmbda - self.lmbda_prev) / self.dt - - @property - def Aw(self): - Tot_A = self._parameters["Tot_A"] - rs = self._parameters["rs"] - rw = self._parameters["rw"] - scale_popu_rw = 1.0 # self._parameters["scale_popu_rw"] - scale_popu_rs = 1.0 # self._parameters["scale_popu_rs"] - return ( - Tot_A - * rs - * scale_popu_rs - / (rs * scale_popu_rs + rw * scale_popu_rw * (1.0 - (rs * scale_popu_rs))) - ) - - @property - def As(self): - return self.Aw - - @property - def cw(self): - phi = self._parameters["phi"] - kuw = self._parameters["kuw"] - rw = self._parameters["rw"] - - scale_popu_kuw = 1.0 # self._parameters["scale_popu_kuw"] - scale_popu_rw = 1.0 # self._parameters["scale_popu_rw"] - return kuw * scale_popu_kuw * phi * (1.0 - (rw * scale_popu_rw)) / (rw * scale_popu_rw) - - @property - def cs(self): - phi = self._parameters["phi"] - kws = self._parameters["kws"] - rs = self._parameters["rs"] - rw = self._parameters["rw"] - scale_popu_kws = 1.0 # self._parameters["scale_popu_kws"] - scale_popu_rw = 1.0 # self._parameters["scale_popu_rw"] - scale_popu_rs = 1.0 # self._parameters["scale_popu_rs"] - return ( - kws - * scale_popu_kws - * phi - * rw - * scale_popu_rw - * (1.0 - (rs * scale_popu_rs)) - / (rs * scale_popu_rs) - ) - - def update_Zetas(self, lmbda): - logger.debug("update Zetas") - self._projector( - self._Zetas, - _Zeta( - self.Zetas_prev, - self.As, - self.cs, - self.dLambda(lmbda), - self.dt, - self._scheme, - ), - ) - - def Zetas(self, lmbda): - return _Zeta( - self.Zetas_prev, - self.As, - self.cs, - self.dLambda(lmbda), - self.dt, - self._scheme, - ) - - def update_Zetaw(self, lmbda): - logger.debug("update Zetaw") - self._projector( - self._Zetaw, - _Zeta( - self.Zetaw_prev, - self.Aw, - self.cw, - self.dLambda(lmbda), - self.dt, - self._scheme, - ), - ) - - def Zetaw(self, lmbda): - return _Zeta( - self.Zetaw_prev, - self.Aw, - self.cw, - self.dLambda(lmbda), - self.dt, - self._scheme, - ) - - @property - def dt(self) -> float: - return self.t - self._t_prev - - def update_prev(self): - logger.debug("update previous") - self.Zetas_prev.vector()[:] = self._Zetas.vector() - self.Zetaw_prev.vector()[:] = self._Zetaw.vector() - self.lmbda_prev.vector()[:] = self.lmbda.vector() - - """ For CaTrpn split""" - self.XS_prev.vector()[:] = self._XS.vector() - self.XW_prev.vector()[:] = self._XW.vector() - self.TmB_prev.vector()[:] = self._TmB.vector() - """ """ - - self._projector.project(self.Ta_current, self.Ta(self.lmbda)) - self._t_prev = self.t - - def Ta(self, lmbda): - logger.debug("Evaluate Ta") - Tref = self._parameters["Tref"] - rs = self._parameters["rs"] - scale_popu_Tref = 1.0 # self._parameters["scale_popu_Tref"] - scale_popu_rs = 1.0 # self._parameters["scale_popu_rs"] - Beta0 = self._parameters["Beta0"] - - _min = ufl.min_value - _max = ufl.max_value - if isinstance(lmbda, (int, float)): - _min = min - _max = max - lmbda = _min(1.2, lmbda) - h_lambda_prima = 1.0 + Beta0 * (lmbda + _min(lmbda, 0.87) - 1.87) - h_lambda = _max(0, h_lambda_prima) - - return ( - h_lambda - * (Tref * scale_popu_Tref / (rs * scale_popu_rs)) - * (self._XS * (self.Zetas(lmbda) + 1.0) + self._XW * self.Zetaw(lmbda)) - ) - - def Wactive(self, F, **kwargs): - """Active stress energy""" - logger.debug("Compute active stress energy") - C = F.T * F - C = F.T * F - f = F * self.f0 - lmbda = dolfin.sqrt(f**2) - self._projector.project(self.lmbda, lmbda) - - # Used to update for next iteration, but not used to calculate Ta, - # since Ta takes lmda directly - self.update_Zetas(lmbda=lmbda) - self.update_Zetaw(lmbda=lmbda) - - """ For Catrpn split""" - self.calculate_XU() - self.calculate_gammasu() - self.calculate_gammawu() - self.update_XS() - self.update_XW() - self.update_TmB() - - return pulse.material.active_model.Wactive_transversally( - Ta=self.Ta(lmbda), - C=C, - f0=self.f0, - eta=self.eta, - ) diff --git a/demos/consistency_checks_across_split_schemes/CaTrpn_split/main_catrpnsplit_consistent_with_zetasplit.py b/demos/consistency_checks_across_split_schemes/CaTrpn_split/main_catrpnsplit_consistent_with_zetasplit.py deleted file mode 100644 index 6703138..0000000 --- a/demos/consistency_checks_across_split_schemes/CaTrpn_split/main_catrpnsplit_consistent_with_zetasplit.py +++ /dev/null @@ -1,683 +0,0 @@ -import logging -import gotranx -from pathlib import Path -from typing import Sequence -import numpy as np -import dolfin -import pulse -import beat -import argparse -import toml -import matplotlib.pyplot as plt - - -from simcardems2 import utils -from simcardems2 import mechanicssolver -from simcardems2 import interpolation -from land_CaTrpnsplit_consistent_with_zetasplit import LandModel -from simcardems2.validate_input_types import validate_input_types - - -try: - raise ImportError - from numba import jit -except ImportError: - - def jit(*args, **kwargs): - def wrapper(func): - return func - - return wrapper - - -logging.getLogger("beat").setLevel(logging.ERROR) - - -def parse_parameters(argv: Sequence[str] | None = None) -> int: - parser = argparse.ArgumentParser(description="Simcardems CLI") - parser.add_argument("config-file", type=Path, help="Config file") - - args = vars(parser.parse_args(argv)) - try: - config = toml.loads(args["config-file"].read_text()) - except toml.TomlDecodeError as e: - print(f"Error when parsing input parameters. Check config file. Error: {e}") - exit(1) - return config - - -config = parse_parameters() - -validate_input_types(config) - -stim_region = ( - [config["stim"]["xmin"], config["stim"]["xmax"]], - [config["stim"]["ymin"], config["stim"]["ymax"]], - [config["stim"]["zmin"], config["stim"]["zmax"]], -) -out_ep_var_names = [ - config["write_all_ep"][f"{i}"]["name"] for i in range(config["write_all_ep"]["numbers"]) -] -out_mech_var_names = [ - config["write_all_mech"][f"{i}"]["name"] for i in range(config["write_all_mech"]["numbers"]) -] -out_ep_coord_names = [ - config["write_point_ep"][f"{i}"]["name"] for i in range(config["write_point_ep"]["numbers"]) -] -ep_coords = [ - [config["write_point_ep"][f"{varnr}"][f"{coord}"] for coord in ["x", "y", "z"]] - for varnr in range(config["write_point_ep"]["numbers"]) -] -out_mech_coord_names = [ - config["write_point_mech"][f"{i}"]["name"] for i in range(config["write_point_mech"]["numbers"]) -] -mech_coords = [ - [config["write_point_mech"][f"{varnr}"][f"{coord}"] for coord in ["x", "y", "z"]] - for varnr in range(config["write_point_mech"]["numbers"]) -] - - -outdir = Path(config["sim"]["outdir"]) -outdir.mkdir(parents=True, exist_ok=True) - -with open(Path(outdir / "config.txt"), "w") as f: - f.write(toml.dumps(config)) - - -# TODO: do a different dirichlet/neumann check than this later. something smoother -t_bcs = dolfin.Constant(0) -bcs_dirichlet = [] -bcs_neumann = [] -bcs_expressions = {} -for bc in range(config["bcs"]["numbers"]): - if config["bcs"][f"{bc}"]["type"] == "Dirichlet": - bcs_dirichlet.append(bc) - elif config["bcs"][f"{bc}"]["type"] == "Neumann": - bcs_neumann.append(bc) - else: - raise KeyError( - f'{config["bcs"][str(bc)]["type"]} is not a valid type of boundary ' - 'condition. Use Dirichlet or Neumann. Check config file' - ) - - if config["bcs"][f"{bc}"]["param_numbers"] > 0: - bcs_parameters = {} - for param_nr in range(config["bcs"][f"{bc}"]["param_numbers"]): - param_name = config["bcs"][f"{bc}"]["param"][f"{param_nr}"]["name"] - param_value = config["bcs"][f"{bc}"]["param"][f"{param_nr}"]["value"] - bcs_parameters[param_name] = param_value - bcs_expressions[f"{bc}"] = dolfin.Expression( - config["bcs"][f"{bc}"]["expression"], - **bcs_parameters, - t=t_bcs, - degree=config["bcs"][f"{bc}"]["degree"], - ) - else: - bcs_expressions[f"{bc}"] = dolfin.Constant(0) - - -mesh = dolfin.Mesh() -with dolfin.XDMFFile(f'{config["sim"]["mech_mesh"]}.xdmf') as infile: - infile.read(mesh) -print(f'Loaded mesh: {config["sim"]["mech_mesh"]}') - - -ffun_bcs = dolfin.MeshFunction("size_t", mesh, mesh.topology().dim() - 1) -with dolfin.XDMFFile(f'{config["bcs"]["markerfile"]}.xdmf') as infile: - infile.read(ffun_bcs) -print(f'Loaded markerfile for bcs: {config["bcs"]["markerfile"]}') - - -tol = 5e-4 -# Surface to volume ratio -chi = 140.0 # mm^{-1} -# Membrane capacitance -C_m = 0.01 # mu F / mm^2 -cm2mm = 10.0 - -t = np.arange(0, config["sim"]["sim_dur"], config["sim"]["dt"]) -sigma = [ - config["ep"]["sigma_il"], - config["ep"]["sigma_it"], - config["ep"]["sigma_el"], - config["ep"]["sigma_et"], -] -material_parameters = dict( - a=config["mech"]["a"], - a_f=config["mech"]["a_f"], - b=config["mech"]["b"], - b_f=config["mech"]["b_f"], - a_s=config["mech"]["a_s"], - b_s=config["mech"]["b_s"], - a_fs=config["mech"]["a_fs"], - b_fs=config["mech"]["b_fs"], -) - - -dolfin.parameters["form_compiler"]["representation"] = "uflacs" -dolfin.parameters["form_compiler"]["cpp_optimize"] = True -dolfin.parameters["form_compiler"]["quadrature_degree"] = 4 - - -def define_conductivity_tensor(sigma, chi, C_m): - # Compute monodomain approximation by taking harmonic mean in each - # direction of intracellular and extracellular part - def harmonic_mean(a, b): - return a * b / (a + b) - - sigma_l = harmonic_mean(sigma[0], sigma[2]) - sigma_t = harmonic_mean(sigma[1], sigma[3]) - - # Scale conducitivites by 1/(C_m * chi) - s_l = sigma_l / (C_m * chi) # mm^2 / ms - s_t = sigma_t / (C_m * chi) # mm^2 / ms - - # Define conductivity tensor - M = dolfin.as_tensor(((s_l, 0, 0), (0, s_t, 0), (0, 0, s_t))) - - return M - - -def define_stimulus( - mesh, - chi, - C_m, - time, - stim_region=stim_region, - stim_start=config["stim"]["start"], - A=config["stim"]["amplitude"], - duration=config["stim"]["duration"], -): - S1_marker = 1 - S1_subdomain = dolfin.CompiledSubDomain( - " ".join( - ( - f"x[0] >= {stim_region[0][0]}", - f"&& x[0] <= {stim_region[0][1]}", - f"&& x[1] >= {stim_region[1][0]}", - f"&& x[1] <= {stim_region[1][1]}", - f"&& x[2] >= {stim_region[2][0]}", - f"&& x[2] <= {stim_region[2][1]}", - ) - ) - ) - - S1_markers = dolfin.MeshFunction("size_t", mesh, mesh.topology().dim()) - S1_subdomain.mark(S1_markers, S1_marker) - with dolfin.XDMFFile((outdir / "stim_region_markers.xdmf").as_posix()) as xdmf: - xdmf.write(S1_markers) - - # Define stimulation (NB: region of interest carried by the mesh - # and assumptions in cbcbeat) - factor = 1.0 / (chi * C_m) # NB: cbcbeat convention - amplitude = factor * A * (1.0 / cm2mm) ** 3 # mV/ms - - I_s = dolfin.Expression( - "time >= start ? (time <= (duration + start) ? amplitude : 0.0) : 0.0", - time=time, - start=config["stim"]["start"], - duration=duration, - amplitude=amplitude, - degree=0, - ) - - dx = dolfin.Measure("dx", domain=mesh, subdomain_data=S1_markers)(S1_marker) - return beat.base_model.Stimulus(dz=dx, expr=I_s) - - -# Load the model -if not Path("ep_model.py").exists(): - ode = gotranx.load_ode(config["sim"]["modelfile"]) - - mechanics_comp = ode.get_component("mechanics") - mechanics_ode = mechanics_comp.to_ode() - - ep_ode = ode - mechanics_comp - - # Generate code for the electrophysiology model - code_ep = gotranx.cli.gotran2py.get_code( - ep_ode, - scheme=[gotranx.schemes.Scheme.forward_generalized_rush_larsen], - missing_values=mechanics_ode.missing_variables, - ) - # Generate code for the mechanics model - code_mechanics = gotranx.cli.gotran2py.get_code( - mechanics_ode, - scheme=[gotranx.schemes.Scheme.forward_generalized_rush_larsen], - missing_values=ep_ode.missing_variables, - ) - - Path("ep_model.py").write_text(code_ep) - # Currently 3D mech needs to be written manually - -import ep_model as _ep_model - -ep_model = _ep_model.__dict__ - - -# Validate ep variables to output -for i in list(set(out_ep_coord_names) | set(out_ep_var_names)): - try: - var = ep_model["state_index"](i) - except KeyError: - print(f"{i} is not an ep state. Check config file") - raise - -# Forwared generalized rush larsen scheme for the electrophysiology model -fgr_ep = jit(nopython=True)(ep_model["forward_generalized_rush_larsen"]) -# Monitor function for the electrophysiology model -mon_ep = ep_model["monitor_values"] -# Missing values function for the electrophysiology model -mv_ep = ep_model["missing_values"] -lmbda_index_ep = ep_model["parameter_index"]("lmbda") - - -# Get initial values from the EP model -y_ep_ = ep_model["init_state_values"]() -p_ep_ = ep_model["init_parameter_values"](amp=0.0) - - -# ep_mesh = dolfin.adapt(dolfin.adapt(dolfin.adapt(mesh))) -ep_mesh = mesh # TEST: For when checking consistency across splits - -time = dolfin.Constant(0.0) -I_s = define_stimulus( - mesh=ep_mesh, - chi=chi, - C_m=C_m, - time=time, - stim_region=stim_region, - stim_start=config["stim"]["start"], - A=config["stim"]["amplitude"], - duration=config["stim"]["duration"], -) -M = define_conductivity_tensor(sigma, chi, C_m) -params = {"preconditioner": "sor", "use_custom_preconditioner": False} -ep_ode_space = dolfin.FunctionSpace(ep_mesh, "DG", 1) -v_ode = dolfin.Function(ep_ode_space) -num_points_ep = v_ode.vector().local_size() -lmbda = dolfin.Function(ep_ode_space) - - -y_ep = np.zeros((len(y_ep_), num_points_ep)) -y_ep.T[:] = y_ep_ # Set to y_ep with initial values defined in ep_model - - -# mechanics_missing_values_ = np.zeros(1) -mechanics_missing_values_ = np.array([0.0001]) - - -# Set the activation -activation_space = dolfin.FunctionSpace(mesh, "DG", 1) -activation = dolfin.Function(activation_space) -num_points_mech = activation.vector().local_size() - -missing_mech = interpolation.MissingValue( - element=activation.ufl_element(), - interpolation_element=ep_ode_space.ufl_element(), - mechanics_mesh=mesh, - ep_mesh=ep_mesh, - num_values=len(mechanics_missing_values_), -) - -missing_mech.values_ep.T[:] = mechanics_missing_values_ -missing_mech.values_mechanics.T[:] = mechanics_missing_values_ -missing_mech.mechanics_values_to_function() # Assign initial values to mech functions - - -# Use previous Catrpn in mech to be consistent with zeta split -prev_missing_mech = interpolation.MissingValue( - element=activation.ufl_element(), - interpolation_element=ep_ode_space.ufl_element(), - mechanics_mesh=mesh, - ep_mesh=ep_mesh, - num_values=len(mechanics_missing_values_), -) -for i in range(len(mechanics_missing_values_)): - prev_missing_mech.u_mechanics[i].vector().set_local(missing_mech.values_mechanics[i]) - - -# Create function spaces for ep variables to output -out_ep_funcs = {} -for out_ep_var in list(set(out_ep_var_names) | set(out_ep_coord_names)): - out_ep_funcs[out_ep_var] = dolfin.Function(ep_ode_space) - -p_ep = np.zeros((len(p_ep_), num_points_ep)) -p_ep.T[:] = p_ep_ # Initialise p_ep with initial values defined in ep_model - -pde = beat.MonodomainModel(time=time, mesh=ep_mesh, M=M, I_s=I_s, params=params) -ode = beat.odesolver.DolfinODESolver( - v_ode=dolfin.Function(ep_ode_space), - v_pde=pde.state, - fun=fgr_ep, - parameters=p_ep, - init_states=y_ep, - num_states=len(y_ep), - v_index=ep_model["state_index"]("v"), - missing_variables=None, - num_missing_variables=0, -) - -# ep_solver = beat.MonodomainSplittingSolver(pde=pde, ode=ode, theta=0.5) -ep_solver = beat.MonodomainSplittingSolver(pde=pde, ode=ode, theta=1) - -marker_functions = pulse.MarkerFunctions(ffun=ffun_bcs) - - -def create_boundary_conditions( - ffun_bcs, bcs_dirichlet, bcs_neumann, bcs_dict, bcs_expressions -): # TODO: update to not need separate dirichlet and neumann list - def dirichlet_bc(W): - bcs_W = { - "u_x": W.sub(0).sub(0), - "u_y": W.sub(0).sub(1), - "u_z": W.sub(0).sub(2), - # TODO: add the rest (check dolfin doc) - } - - bcs = [] - for bc in bcs_dirichlet: - bcs.append( - dolfin.DirichletBC( - bcs_W[bcs_dict[f"{bc}"]["V"]], - bcs_expressions[f"{bc}"], # TODO: use dolfin expression - ffun_bcs, - bcs_dict[f"{bc}"]["marker"], - ) - ) - return bcs - - neumann_bc = [] - if bcs_neumann is not None: - for bc in bcs_neumann: - neumann_bc.append( - pulse.NeumannBC( - traction=utils.float_to_constant(bcs_expressions[f"{bc}"]), - marker=bcs_dict[f"{bc}"]["marker"], - ) - ) - - # Collect Boundary Conditions - bcs = pulse.BoundaryConditions(dirichlet=(dirichlet_bc,), neumann=neumann_bc) - return bcs - - -f0 = dolfin.as_vector([1.0, 0.0, 0.0]) -s0 = dolfin.as_vector([0.0, 1.0, 0.0]) -n0 = dolfin.as_vector([0.0, 0.0, 1.0]) -microstructure = pulse.Microstructure(f0=f0, s0=s0, n0=n0) -geometry = pulse.Geometry( - mesh=mesh, marker_functions=marker_functions, microstructure=microstructure -) - -active_model = LandModel( - f0=f0, - s0=s0, - n0=n0, - # CaTrpn=missing_mech.u_mechanics[0], - CaTrpn=prev_missing_mech.u_mechanics[ - 0 - ], # Use prev Catrpn in mech to be consistent with zeta split - mesh=mesh, - eta=0, # Fraction of transverse active tension for active stress formulation. - # 0 = active only along fiber, 1 = equal forces in all directions - # (default=0.0). - dLambda_tol=1e-12, -) -active_model.t = 0.0 - - -mech_variables = { - "Ta": active_model.Ta_current, - "Zetas": active_model._Zetas, - "Zetaw": active_model._Zetaw, - "lambda": active_model.lmbda, - "XS": active_model._XS, - "XW": active_model._XW, - "TmB": active_model._TmB, -} - -# Validate mechanics variables to output -for out_mech_var in list(set(out_mech_coord_names) | set(out_mech_var_names)): - assert ( - out_mech_var in mech_variables - ), f"Error: '{out_mech_var}' is not a valid variable name. Check config file" - -material = pulse.HolzapfelOgden( - parameters=material_parameters, - active_model=active_model, - f0=f0, - s0=s0, - n0=n0, -) - - -def compute_function_average_over_mesh(func, mesh): - volume = dolfin.assemble(dolfin.Constant(1.0) * dolfin.dx(domain=mesh)) - return dolfin.assemble(func * dolfin.dx(domain=mesh)) / volume - - -# Collect Boundary Conditions -bcs = create_boundary_conditions( - ffun_bcs, bcs_dirichlet, bcs_neumann, config["bcs"], bcs_expressions -) - -problem = mechanicssolver.MechanicsProblem(geometry, material, bcs) -print("problem set up") -problem.solve(0.0, 0.0) - -disp_file = Path(outdir / "disp.xdmf") -disp_file.unlink(missing_ok=True) -disp_file.with_suffix(".h5").unlink(missing_ok=True) - -out_ep_files = {} -for out_ep_var in out_ep_var_names: - out_ep_files[out_ep_var] = Path(outdir / f"{out_ep_var}_out_ep.xdmf") - out_ep_files[out_ep_var].unlink(missing_ok=True) - out_ep_files[out_ep_var].with_suffix(".h5").unlink(missing_ok=True) - -out_mech_files = {} -for out_mech_var in out_mech_var_names: - out_mech_files[out_mech_var] = Path(outdir / f"{out_mech_var}_out_mech.xdmf") - out_mech_files[out_mech_var].unlink(missing_ok=True) - out_mech_files[out_mech_var].with_suffix(".h5").unlink(missing_ok=True) - - -# Create arrays for storing values to plot time series for example nodes -out_ep_example_nodes = {} -for out_ep_var in out_ep_coord_names: - out_ep_example_nodes[out_ep_var] = np.zeros(len(t)) - -out_mech_example_nodes = {} -for out_mech_var in out_mech_coord_names: - out_mech_example_nodes[out_mech_var] = np.zeros(len(t)) - -# Create arrays for storing values to plot time series for volume averages -out_ep_volume_average_timeseries = {} -for out_ep_var in out_ep_coord_names: - out_ep_volume_average_timeseries[out_ep_var] = np.zeros(len(t)) - -out_mech_volume_average_timeseries = {} -for out_mech_var in out_mech_coord_names: - out_mech_volume_average_timeseries[out_mech_var] = np.zeros(len(t)) - - -inds = [] # Array with time-steps for which we solve mechanics -j = 0 -timer = dolfin.Timer("solve_loop") - - -for i, ti in enumerate(t): - print(f"Solving time {ti:.2f} ms") - t_bcs.assign(ti) # Use ti+ dt here instead? - ep_solver.step((ti, ti + config["sim"]["dt"])) - - # Assign values to ep function - for out_ep_var in list(set(out_ep_var_names) | set(out_ep_coord_names)): - out_ep_funcs[out_ep_var].vector()[:] = ode._values[ep_model["state_index"](out_ep_var)] - - # Store values to plot time series for given coord - for var_nr in range(config["write_point_ep"]["numbers"]): - # Trace variable in coordinate - out_ep_var = config["write_point_ep"][f"{var_nr}"]["name"] - out_ep_example_nodes[out_ep_var][i] = out_ep_funcs[out_ep_var](ep_coords[var_nr]) - # Compute volume averages - out_ep_volume_average_timeseries[out_ep_var][i] = compute_function_average_over_mesh( - out_ep_funcs[out_ep_var], ep_mesh - ) - - if i % config["sim"]["N"] != 0: - continue - - # Extract missing values for the mechanics step from the ep model (ep function space) - missing_ep_values = mv_ep(ti + config["sim"]["dt"], ode._values, ode.parameters) - # Assign the extracted values as missing_mech for the mech step (ep function space) - for k in range(missing_mech.num_values): - missing_mech.u_ep_int[k].vector()[:] = missing_ep_values[k, :] - - # Interpolate missing variables from ep to mech function space - missing_mech.interpolate_ep_to_mechanics() - missing_mech.mechanics_function_to_values() - inds.append(i) - - print("Solve mechanics") - active_model.t = ti + config["sim"]["N"] * config["sim"]["dt"] # Addition! - problem.solve(ti, config["sim"]["N"] * config["sim"]["dt"]) - active_model.update_prev() - - lmbda.interpolate(active_model.lmbda) - - p_ep[lmbda_index_ep, :] = lmbda.vector().get_local() # p_ep are the ep parameters - print( - active_model.lmbda.vector().get_local().min(), - active_model.lmbda.vector().get_local().max(), - ) - - U, p = problem.state.split(deepcopy=True) - - for var_nr in range(config["write_point_mech"]["numbers"]): - # Trace variable in coordinate - out_mech_var = config["write_point_mech"][f"{var_nr}"]["name"] - - out_mech_example_nodes[out_mech_var][i] = mech_variables[out_mech_var](mech_coords[var_nr]) - - # Compute volume averages - out_mech_volume_average_timeseries[out_mech_var][i] = compute_function_average_over_mesh( - mech_variables[out_mech_var], mesh - ) - - # Use previous Catrpn in mech to be consistent with zeta split - for i in range(len(mechanics_missing_values_)): - prev_missing_mech.u_mechanics[i].vector().set_local(missing_mech.values_mechanics[i]) - - with dolfin.XDMFFile(disp_file.as_posix()) as file: - file.write_checkpoint(U, "disp", j, dolfin.XDMFFile.Encoding.HDF5, True) - for out_ep_var in out_ep_var_names: - with dolfin.XDMFFile(out_ep_files[out_ep_var].as_posix()) as file: - file.write_checkpoint( - out_ep_funcs[out_ep_var], - out_ep_var, - j, - dolfin.XDMFFile.Encoding.HDF5, - True, - ) - for out_mech_var in out_mech_var_names: - with dolfin.XDMFFile(out_mech_files[out_mech_var].as_posix()) as file: - file.write_checkpoint( - mech_variables[out_mech_var], - out_mech_var, - j, - dolfin.XDMFFile.Encoding.HDF5, - True, - ) - - j += 1 -timer.stop() -timings = dolfin.timings( - dolfin.TimingClear.keep, - [dolfin.TimingType.wall, dolfin.TimingType.user, dolfin.TimingType.system], -).str(True) -print(timings) -with open(Path(outdir / "solve_timings.txt"), "w") as f: - f.write(timings) - -# Write averaged results for later analysis -for out_ep_var in out_ep_coord_names: - with open(Path(outdir / f"{out_ep_var}_out_ep_volume_average.txt"), "w") as f: - np.savetxt(f, out_ep_volume_average_timeseries[out_ep_var][inds]) - -for out_mech_var in out_mech_coord_names: - with open(Path(outdir / f"{out_mech_var}_out_mech_volume_average.txt"), "w") as f: - np.savetxt(f, out_mech_volume_average_timeseries[out_mech_var][inds]) - -# Write point traces for later analysis -for var_nr in range(config["write_point_ep"]["numbers"]): - out_ep_var = config["write_point_ep"][f"{var_nr}"]["name"] - with open( - Path( - outdir - / f"{out_ep_var}_ep_coord{ep_coords[var_nr][0]},{ep_coords[var_nr][1]},{ep_coords[var_nr][2]}.txt".replace( - " ", "" - ) - ), - "w", - ) as f: - np.savetxt(f, out_ep_example_nodes[out_ep_var][inds]) - -for var_nr in range(config["write_point_mech"]["numbers"]): - out_mech_var = config["write_point_mech"][f"{var_nr}"]["name"] - with open( - Path( - outdir - / f"{out_mech_var}_mech_coord{mech_coords[var_nr][0]},{mech_coords[var_nr][1]},{mech_coords[var_nr][2]}.txt" - ), - "w", - ) as f: - np.savetxt(f, out_mech_example_nodes[out_mech_var][inds]) - -print(f"Solved on {100 * len(inds) / len(t)}% of the time steps") -inds = np.array(inds) - -# Plot the results -fig, ax = plt.subplots(len(out_ep_coord_names), 1, figsize=(10, 10)) -if len(out_ep_coord_names) == 1: - ax = np.array([ax]) -for i, out_ep_var in enumerate(out_ep_coord_names): - ax[i].plot(t[inds], out_ep_volume_average_timeseries[out_ep_var][inds]) - ax[i].set_title(f"{out_ep_var} volume average") - ax[i].set_xlabel("Time (ms)") -fig.tight_layout() -fig.savefig(Path(outdir / "out_ep_volume_averages.png")) - -fig, ax = plt.subplots(len(out_ep_coord_names), 1, figsize=(10, 10)) -if len(out_ep_coord_names) == 1: - ax = np.array([ax]) -for var_nr in range(config["write_point_ep"]["numbers"]): - out_ep_var = config["write_point_ep"][f"{var_nr}"]["name"] - ax[var_nr].plot(t[inds], out_ep_example_nodes[out_ep_var][inds]) - ax[var_nr].set_title(f"{out_ep_var} in coord {ep_coords[var_nr]}") - ax[var_nr].set_xlabel("Time (ms)") -fig.tight_layout() -fig.savefig(Path(outdir / "out_ep_coord.png")) - -fig, ax = plt.subplots(len(out_mech_coord_names), 1, figsize=(10, 10)) -if len(out_mech_coord_names) == 1: - ax = np.array([ax]) -for i, out_mech_var in enumerate(out_mech_coord_names): - ax[i].plot(t[inds], out_mech_volume_average_timeseries[out_mech_var][inds]) - ax[i].set_title(f"{out_mech_var} volume average") - ax[i].set_xlabel("Time (ms)") -fig.tight_layout() -fig.savefig(Path(outdir / "out_mech_volume_averages.png")) - -fig, ax = plt.subplots(len(out_mech_coord_names), 1, figsize=(10, 10)) -if len(out_mech_coord_names) == 1: - ax = np.array([ax]) - -for var_nr in range(config["write_point_mech"]["numbers"]): - out_mech_var = config["write_point_mech"][f"{var_nr}"]["name"] - ax[var_nr].plot(t[inds], out_mech_example_nodes[out_mech_var][inds]) - ax[var_nr].set_title(f"{out_mech_var} in coord {mech_coords[var_nr]}") - ax[var_nr].set_xlabel("Time (ms)") -fig.tight_layout() -fig.savefig(Path(outdir / "out_mech_coord.png")) diff --git a/demos/consistency_checks_across_split_schemes/cai_split/ORdmm_Land.ode b/demos/consistency_checks_across_split_schemes/cai_split/ORdmm_Land.ode deleted file mode 100644 index 2e79499..0000000 --- a/demos/consistency_checks_across_split_schemes/cai_split/ORdmm_Land.ode +++ /dev/null @@ -1,663 +0,0 @@ -# ORd modified by MMora (October-2016) -# Modifications in INa. The original formulation of INa has been -# optimised, according to Passini, in order to look like TT04. -# Modifications: -# 1) mss,hss,jss and hssp -# 2) gNa -# + -# Re-scaled conductances (Dutta et al 2016 CinC) -# + -# -# Land 2017(mechanical model)- Introduced by MMora (Jan2020) -# Tension -# Changes in Cai effect of troponin -# + -# -# Isacs -# -# -# In this version we fix mech.emcoupling=1, -# mode="intact", isacs=0 and celltype = 0 -# -# -# Modifications by Ilse (January 2023) -# Add scaling facotrs for heart failure and drugs - - -parameters("Scales", -scale_IKr = 1.119, -scale_IKs = 1.648, -scale_IK1 = 1.414, -scale_ICaL = 1.018, -scale_INaL = 2.274) - - - -parameters("settings", -celltype=0) - -parameters("extracellular ionic concentrations", -nao=140.0, -cao=1.8, -ko=5.4) - -parameters("physical constants", "mechanics", -R=8314.0, -T=310.0, -F=96485.0) - - -parameters("cell geometry", "mechanics", -L=0.01, -rad=0.0011) - - -expressions("cell geometry", "mechanics") -vcell=1000*3.14*rad*rad*L -Ageo=2*3.14*rad*rad+2*3.14*rad*L -Acap=2*Ageo -vmyo=0.68*vcell -vnsr=0.0552*vcell -vjsr=0.0048*vcell -vss=0.02*vcell - - -# Scaling factors for heart failure -parameters("scaling factors HF", -scale_HF_CaMKa=1.0, -scale_HF_Jrel_inf=1.0, -scale_HF_Jleak=1.0, -scale_HF_Jup=1.0, -scale_HF_GNaL=1.0, -scale_HF_GK1=1.0, -scale_HF_thL=1.0, -scale_HF_Gto=1.0, -scale_HF_Gncx=1.0, -scale_HF_Pnak=1.0) - -# Scaling factors for drug effects -parameters("scaling factors drug", -scale_drug_INa=1.0, -scale_drug_INaL=1.0, -scale_drug_Ito=1.0, -scale_drug_ICaL=1.0, -scale_drug_IKr=1.0, -scale_drug_IKs=1.0, -scale_drug_IK1=1.0, -scale_drug_IKb=1.0, -scale_drug_INab=1.0, -scale_drug_ICab=1.0, -scale_drug_IpCa=1.0, -scale_drug_Isacns=1.0, -scale_drug_Isack=1.0) - -######## EP states -states("CaMKt", -CaMKt=0 -) - -states("I_Na", -m=0, -hf=1, -hs=1, -j=1, -hsp=1, -jp=1) - -states("INaL", -mL=0, -hL=1, -hLp=1) - -states("Ito", -a=0, -iF=1, -iS=1, -ap=0, -iFp=1, -iSp=1) - -states("ICaL ICaNa ICaK", -d=0, -ff=1, -fs=1, -fcaf=1, -fcas=1, -jca=1, -nca=0, -ffp=1, -fcafp=1) - - -states("IKr", -xrf=0, -xrs=0) - - -states("IKs", -xs1=0, -xs2=0, -xk1=1) - -states("membrane potential", -v=-87) - - -states("ryanodione receptor", -Jrelnp=0, -Jrelp=0) - - -states("intracellular concentrations", -cai=0.0001, -nai=7, -nass=7, -ki=145, -kss=145, -cass=0.0001, -cansr=1.2, -cajsr=1.2) - -states("mechanics", -XS=0, -XW=0, -CaTrpn=0.0001, -TmB=1, -Zetas=0, -Zetaw=0, -Cd=0) - - -############################## - -parameters("CaMK constants", -KmCaMK=0.15, -aCaMK=0.05, -bCaMK=0.00068, -CaMKo=0.05, -KmCaM=0.0015) - -expressions("CaMKt") -CaMKb=CaMKo*(1.0-CaMKt)/(1.0+KmCaM/cass) -CaMKa=(CaMKb+CaMKt)*scale_HF_CaMKa -dCaMKt_dt=aCaMK*CaMKb*(CaMKb+CaMKt)-bCaMK*CaMKt - -parameters("reversal potentials", -PKNa=0.01833) - -expressions("reversal potentials") -ENa=(R*T/F)*log(nao/nai) -EK=(R*T/F)*log(ko/ki) -EKs=(R*T/F)*log((ko+PKNa*nao)/(ki+PKNa*nai)) -vffrt=v*F*F/(R*T) -vfrt=v*F/(R*T) - -parameters("I_Na", -Ahf=0.99, -GNa=31) - -expressions("I_Na") -mss=1.0/(1.0+exp((-(v+39.57+9.4))/7.5)) -tm=1.0/(6.765*exp((v+11.64)/34.77)+8.552*exp(-(v+77.42)/5.955)) -dm_dt=(mss-m)/tm -hss=1.0/(1+exp((v+78.5)/6.22)) -thf=1.0/(1.432e-5*exp(-(v+1.196)/6.285)+6.149*exp((v+0.5096)/20.27)) -ths=1.0/(0.009794*exp(-(v+17.95)/28.05)+0.3343*exp((v+5.730)/56.66)) -Ahs=1.0-Ahf -dhf_dt=(hss-hf)/thf -dhs_dt=(hss-hs)/ths -h=Ahf*hf+Ahs*hs -jss=hss -tj=2.038+1.0/(0.02136*exp(-(v+100.6)/8.281)+0.3052*exp((v+0.9941)/38.45)) -dj_dt=(jss-j)/tj -hssp=1.0/(1+exp((v+78.5+6.2)/6.22)) -thsp=3.0*ths -dhsp_dt=(hssp-hsp)/thsp -hp=Ahf*hf+Ahs*hsp -tjp=1.46*tj -djp_dt=(jss-jp)/tjp -fINap=(1.0/(1.0+KmCaMK/CaMKa)) -INa=GNa*scale_drug_INa*(v-ENa)*m**3.0*((1.0-fINap)*h*j+fINap*hp*jp) - -parameters("INaL", -thL=200.0) - -expressions("INaL") -mLss=1.0/(1.0+exp((-(v+42.85))/5.264)) -tmL=tm -dmL_dt=(mLss-mL)/tmL -hLss=1.0/(1.0+exp((v+87.61)/7.488)) -dhL_dt=(hLss-hL)/(thL*scale_HF_thL) -hLssp=1.0/(1.0+exp((v+93.81)/7.488)) -thLp=3.0*thL*scale_HF_thL -dhLp_dt=(hLssp-hLp)/thLp -GNaL=0.0075*scale_INaL*scale_drug_INaL*scale_HF_GNaL -fINaLp=(1.0/(1.0+KmCaMK/CaMKa)) -INaL=GNaL*(v-ENa)*mL*((1.0-fINaLp)*hL+fINaLp*hLp) - -parameters("Ito", -delta_epi=1.0, -Gto=0.02) - -expressions("Ito") -ass=1.0/(1.0+exp((-(v-14.34))/14.82)) -ta=1.0515/(1.0/(1.2089*(1.0+exp(-(v-18.4099)/29.3814)))+3.5/(1.0+exp((v+100.0)/29.3814))) -da_dt=(ass-a)/ta -iss=1.0/(1.0+exp((v+43.94)/5.711)) -tiF=4.562+1/(0.3933*exp((-(v+100.0))/100.0)+0.08004*exp((v+50.0)/16.59)) * delta_epi -tiS=23.62+1/(0.001416*exp((-(v+96.52))/59.05)+1.780e-8*exp((v+114.1)/8.079)) * delta_epi -AiF=1.0/(1.0+exp((v-213.6)/151.2)) -AiS=1.0-AiF -diF_dt=(iss-iF)/tiF -diS_dt=(iss-iS)/tiS -i=AiF*iF+AiS*iS -assp=1.0/(1.0+exp((-(v-24.34))/14.82)) -dap_dt=(assp-ap)/ta -dti_develop=1.354+1.0e-4/(exp((v-167.4)/15.89)+exp(-(v-12.23)/0.2154)) -dti_recover=1.0-0.5/(1.0+exp((v+70.0)/20.0)) -tiFp=dti_develop*dti_recover*tiF -tiSp=dti_develop*dti_recover*tiS -diFp_dt=(iss-iFp)/tiFp -diSp_dt=(iss-iSp)/tiSp -ip=AiF*iFp+AiS*iSp -fItop=(1.0/(1.0+KmCaMK/CaMKa)) -Ito=Gto*scale_drug_Ito*scale_HF_Gto*(v-EK)*((1.0-fItop)*a*i+fItop*ap*ip) - - -parameters("ICaL ICaNa ICaK", -Aff=0.6, -tjca=75.0, -Kmn=0.002, -k2n=1000.0, -zca=2.0) - -expressions("ICaL ICaNa ICaK") -dss=1.0/(1.0+exp((-(v+3.940))/4.230)) -td=0.6+1.0/(exp(-0.05*(v+6.0))+exp(0.09*(v+14.0))) -dd_dt=(dss-d)/td -fss=1.0/(1.0+exp((v+19.58)/3.696)) -tff=7.0+1.0/(0.0045*exp(-(v+20.0)/10.0)+0.0045*exp((v+20.0)/10.0)) -tfs=1000.0+1.0/(0.000035*exp(-(v+5.0)/4.0)+0.000035*exp((v+5.0)/6.0)) -Afs=1.0-Aff -dff_dt=(fss-ff)/tff -dfs_dt=(fss-fs)/tfs -f=Aff*ff+Afs*fs -fcass=fss -tfcaf=7.0+1.0/(0.04*exp(-(v-4.0)/7.0)+0.04*exp((v-4.0)/7.0)) -tfcas=100.0+1.0/(0.00012*exp(-v/3.0)+0.00012*exp(v/7.0)) -Afcaf=0.3+0.6/(1.0+exp((v-10.0)/10.0)) -Afcas=1.0-Afcaf -dfcaf_dt=(fcass-fcaf)/tfcaf -dfcas_dt=(fcass-fcas)/tfcas -fca=Afcaf*fcaf+Afcas*fcas -djca_dt=(fcass-jca)/tjca -tffp=2.5*tff -dffp_dt=(fss-ffp)/tffp -fp=Aff*ffp+Afs*fs -tfcafp=2.5*tfcaf -dfcafp_dt=(fcass-fcafp)/tfcafp -fcap=Afcaf*fcafp+Afcas*fcas -km2n=jca*1.0 -anca=1.0/(k2n/km2n+(1.0+Kmn/cass)**4.0) -dnca_dt=anca*k2n-nca*km2n -PhiCaL=4.0*vffrt*(cass*exp(2.0*vfrt)-0.341*cao)/(exp(2.0*vfrt)-1.0) -PhiCaNa=1.0*vffrt*(0.75*nass*exp(1.0*vfrt)-0.75*nao)/(exp(1.0*vfrt)-1.0) -PhiCaK=1.0*vffrt*(0.75*kss*exp(1.0*vfrt)-0.75*ko)/(exp(1.0*vfrt)-1.0) -PCa=0.0001*scale_ICaL*scale_drug_ICaL -PCap=1.1*PCa -PCaNa=0.00125*PCa -PCaK=3.574e-4*PCa -PCaNap=0.00125*PCap -PCaKp=3.574e-4*PCap -fICaLp=(1.0/(1.0+KmCaMK/CaMKa)) -ICaL=(1.0-fICaLp)*PCa*PhiCaL*d*(f*(1.0-nca)+jca*fca*nca)+fICaLp*PCap*PhiCaL*d*(fp*(1.0-nca)+jca*fcap*nca) -ICaNa=(1.0-fICaLp)*PCaNa*PhiCaNa*d*(f*(1.0-nca)+jca*fca*nca)+fICaLp*PCaNap*PhiCaNa*d*(fp*(1.0-nca)+jca*fcap*nca) -ICaK=(1.0-fICaLp)*PCaK*PhiCaK*d*(f*(1.0-nca)+jca*fca*nca)+fICaLp*PCaKp*PhiCaK*d*(fp*(1.0-nca)+jca*fcap*nca) - -expressions("IKr") -xrss=1.0/(1.0+exp((-(v+8.337))/6.789)) -txrf=12.98+1.0/(0.3652*exp((v-31.66)/3.869)+4.123e-5*exp((-(v-47.78))/20.38)) -txrs=1.865+1.0/(0.06629*exp((v-34.70)/7.355)+1.128e-5*exp((-(v-29.74))/25.94)) -Axrf=1.0/(1.0+exp((v+54.81)/38.21)) -Axrs=1.0-Axrf -dxrf_dt=(xrss-xrf)/txrf -dxrs_dt=(xrss-xrs)/txrs -xr=Axrf*xrf+Axrs*xrs -rkr=1.0/(1.0+exp((v+55.0)/75.0))*1.0/(1.0+exp((v-10.0)/30.0)) -GKr=0.046*scale_IKr*scale_drug_IKr -IKr=GKr*sqrt(ko/5.4)*xr*rkr*(v-EK) - -expressions("IKs") -xs1ss=1.0/(1.0+exp((-(v+11.60))/8.932)) -txs1=817.3+1.0/(2.326e-4*exp((v+48.28)/17.80)+0.001292*exp((-(v+210.0))/230.0)) -dxs1_dt=(xs1ss-xs1)/txs1 -xs2ss=xs1ss -txs2=1.0/(0.01*exp((v-50.0)/20.0)+0.0193*exp((-(v+66.54))/31.0)) -dxs2_dt=(xs2ss-xs2)/txs2 -KsCa=1.0+0.6/(1.0+(3.8e-5/cai)**1.4) -GKs=0.0034*scale_IKs*scale_drug_IKs -IKs=GKs*KsCa*xs1*xs2*(v-EKs) -xk1ss=1.0/(1.0+exp(-(v+2.5538*ko+144.59)/(1.5692*ko+3.8115))) -txk1=122.2/(exp((-(v+127.2))/20.36)+exp((v+236.8)/69.33)) -dxk1_dt=(xk1ss-xk1)/txk1 -rk1=1.0/(1.0+exp((v+105.8-2.6*ko)/9.493)) -GK1=0.1908*scale_IK1*scale_drug_IK1*scale_HF_GK1 -IK1=GK1*sqrt(ko)*rk1*xk1*(v-EK) - - -parameters("INaCa_i", -kna1=15.0, -kna2=5.0, -kna3=88.12, -kasymm=12.5, -wna=6.0e4, -wca=6.0e4, -wnaca=5.0e3, -kcaon=1.5e6, -kcaoff=5.0e3, -qna=0.5224, -qca=0.1670, -KmCaAct=150.0e-6, -Gncx=0.0008) - -expressions("INaCa_i") -hca=exp((qca*v*F)/(R*T)) -hna=exp((qna*v*F)/(R*T)) -h1_i=1+nai/kna3*(1+hna) -h2_i=(nai*hna)/(kna3*h1_i) -h3_i=1.0/h1_i -h4_i=1.0+nai/kna1*(1+nai/kna2) -h5_i=nai*nai/(h4_i*kna1*kna2) -h6_i=1.0/h4_i -h7_i=1.0+nao/kna3*(1.0+1.0/hna) -h8_i=nao/(kna3*hna*h7_i) -h9_i=1.0/h7_i -h10_i=kasymm+1.0+nao/kna1*(1.0+nao/kna2) -h11_i=nao*nao/(h10_i*kna1*kna2) -h12_i=1.0/h10_i -k1_i=h12_i*cao*kcaon -k2_i=kcaoff -k3p_i=h9_i*wca -k3pp_i=h8_i*wnaca -k3_i=k3p_i+k3pp_i -k4p_i=h3_i*wca/hca -k4pp_i=h2_i*wnaca -k4_i=k4p_i+k4pp_i -k5_i=kcaoff -k6_i=h6_i*cai*kcaon -k7_i=h5_i*h2_i*wna -k8_i=h8_i*h11_i*wna -x1_i=k2_i*k4_i*(k7_i+k6_i)+k5_i*k7_i*(k2_i+k3_i) -x2_i=k1_i*k7_i*(k4_i+k5_i)+k4_i*k6_i*(k1_i+k8_i) -x3_i=k1_i*k3_i*(k7_i+k6_i)+k8_i*k6_i*(k2_i+k3_i) -x4_i=k2_i*k8_i*(k4_i+k5_i)+k3_i*k5_i*(k1_i+k8_i) -E1_i=x1_i/(x1_i+x2_i+x3_i+x4_i) -E2_i=x2_i/(x1_i+x2_i+x3_i+x4_i) -E3_i=x3_i/(x1_i+x2_i+x3_i+x4_i) -E4_i=x4_i/(x1_i+x2_i+x3_i+x4_i) -allo_i=1.0/(1.0+(KmCaAct/cai)**2.0) -zna=1.0 -JncxNa_i=3.0*(E4_i*k7_i-E1_i*k8_i)+E3_i*k4pp_i-E2_i*k3pp_i -JncxCa_i=E2_i*k2_i-E1_i*k1_i -INaCa_i=0.8*Gncx*scale_HF_Gncx*allo_i*(zna*JncxNa_i+zca*JncxCa_i) - -expressions("INaCa_ss") -h1=1+nass/kna3*(1+hna) -h2=(nass*hna)/(kna3*h1) -h3=1.0/h1 -h4=1.0+nass/kna1*(1+nass/kna2) -h5=nass*nass/(h4*kna1*kna2) -h6=1.0/h4 -h7=1.0+nao/kna3*(1.0+1.0/hna) -h8=nao/(kna3*hna*h7) -h9=1.0/h7 -h10=kasymm+1.0+nao/kna1*(1+nao/kna2) -h11=nao*nao/(h10*kna1*kna2) -h12=1.0/h10 -k1=h12*cao*kcaon -k2=kcaoff -k3p_ss=h9*wca -k3pp=h8*wnaca -k3=k3p_ss+k3pp -k4p_ss=h3*wca/hca -k4pp=h2*wnaca -k4=k4p_ss+k4pp -k5=kcaoff -k6=h6*cass*kcaon -k7=h5*h2*wna -k8=h8*h11*wna -x1_ss=k2*k4*(k7+k6)+k5*k7*(k2+k3) -x2_ss=k1*k7*(k4+k5)+k4*k6*(k1+k8) -x3_ss=k1*k3*(k7+k6)+k8*k6*(k2+k3) -x4_ss=k2*k8*(k4+k5)+k3*k5*(k1+k8) -E1_ss=x1_ss/(x1_ss+x2_ss+x3_ss+x4_ss) -E2_ss=x2_ss/(x1_ss+x2_ss+x3_ss+x4_ss) -E3_ss=x3_ss/(x1_ss+x2_ss+x3_ss+x4_ss) -E4_ss=x4_ss/(x1_ss+x2_ss+x3_ss+x4_ss) -allo_ss=1.0/(1.0+(KmCaAct/cass)**2.0) -JncxNa_ss=3.0*(E4_ss*k7-E1_ss*k8)+E3_ss*k4pp-E2_ss*k3pp -JncxCa_ss=E2_ss*k2-E1_ss*k1 -INaCa_ss=0.2*Gncx*scale_HF_Gncx*allo_ss*(zna*JncxNa_ss+zca*JncxCa_ss) - - -parameters("INaK", -k1p=949.5, -k1m=182.4, -k2p=687.2, -k2m=39.4, -k3p=1899.0, -k3m=79300.0, -k4p=639.0, -k4m=40.0, -Knai0=9.073, -Knao0=27.78, -delta=-0.1550, -Kki=0.5, -Kko=0.3582, -MgADP=0.05, -MgATP=9.8, -Kmgatp=1.698e-7, -H=1.0e-7, -eP=4.2, -Khp=1.698e-7, -Knap=224.0, -Kxkur=292.0, -zk=1.0, -Pnak=30) - -expressions("INaK") -Knai=Knai0*exp((delta*v*F)/(3.0*R*T)) -Knao=Knao0*exp(((1.0-delta)*v*F)/(3.0*R*T)) -P=eP/(1.0+H/Khp+nai/Knap+ki/Kxkur) -a1=(k1p*(nai/Knai)**3.0)/((1.0+nai/Knai)**3.0+(1.0+ki/Kki)**2.0-1.0) -b1=k1m*MgADP -a2=k2p -b2=(k2m*(nao/Knao)**3.0)/((1.0+nao/Knao)**3.0+(1.0+ko/Kko)**2.0-1.0) -a3=(k3p*(ko/Kko)**2.0)/((1.0+nao/Knao)**3.0+(1.0+ko/Kko)**2.0-1.0) -b3=(k3m*P*H)/(1.0+MgATP/Kmgatp) -a4=(k4p*MgATP/Kmgatp)/(1.0+MgATP/Kmgatp) -b4=(k4m*(ki/Kki)**2.0)/((1.0+nai/Knai)**3.0+(1.0+ki/Kki)**2.0-1.0) -x1=a4*a1*a2+b2*b4*b3+a2*b4*b3+b3*a1*a2 -x2=b2*b1*b4+a1*a2*a3+a3*b1*b4+a2*a3*b4 -x3=a2*a3*a4+b3*b2*b1+b2*b1*a4+a3*a4*b1 -x4=b4*b3*b2+a3*a4*a1+b2*a4*a1+b3*b2*a1 -E1=x1/(x1+x2+x3+x4) -E2=x2/(x1+x2+x3+x4) -E3=x3/(x1+x2+x3+x4) -E4=x4/(x1+x2+x3+x4) -JnakNa=3.0*(E1*a3-E2*b3) -JnakK=2.0*(E4*b1-E3*a1) -INaK=Pnak*scale_HF_Pnak*(zna*JnakNa+zk*JnakK) - - -parameters("IKb", -GKb=0.003) - -expressions("IKb") -xkb=1.0/(1.0+exp(-(v-14.48)/18.34)) -IKb=GKb*scale_drug_IKb*xkb*(v-EK) - -parameters("INab", -PNab=3.75e-10) - -expressions("INab") -INab=PNab*scale_drug_INab*vffrt*(nai*exp(vfrt)-nao)/(exp(vfrt)-1.0) - - -parameters("ICab", -PCab=2.5e-8) - -expressions("ICab") -ICab=PCab*scale_drug_ICab*4.0*vffrt*(cai*exp(2.0*vfrt)-0.341*cao)/(exp(2.0*vfrt)-1.0) - -parameters("IpCa", -GpCa=0.0005) - -expressions("IpCa") -IpCa=GpCa*scale_drug_IpCa*cai/(0.0005+cai) - - -parameters("Isac (Pueyo)--> ns + k", -Gsac_ns=0.006, -Esac_ns=-10, -lambda_max=1.1, -Gsac_k=0.2882*800/210) - -expressions("Isac (Pueyo)--> ns + k") -Isac_P_ns=0 -Isac_P_k=0 - - -parameters("Istim", -amp=-80.0, -duration=0.5) - -expressions("Istim") -Istim = Conditional(Le(t, duration), amp, 0) - -expressions("membrane potential") -dv_dt=-(INa+INaL+Ito+ICaL+ICaNa+ICaK+IKr+IKs+IK1+INaCa_i+INaCa_ss+INaK+INab+IKb+IpCa+ICab+Istim+Isac_P_ns+Isac_P_k) - -expressions("diffusion fluxes") -JdiffNa=(nass-nai)/2.0 -JdiffK=(kss-ki)/2.0 -Jdiff=(cass-cai)/0.2 - -parameters("ryanodione receptor", -bt=4.75) - -expressions("ryanodione receptor") -a_rel=0.5*bt -Jrel_inf=a_rel*(-ICaL)/(1.0+(1.5*scale_HF_Jrel_inf/cajsr)**8.0) -tau_rel_tmp=bt/(1.0+0.0123/cajsr) -tau_rel=Conditional(Lt(tau_rel_tmp, 0.001), 0.001, tau_rel_tmp) -dJrelnp_dt=(Jrel_inf-Jrelnp)/tau_rel -btp=1.25*bt -a_relp=0.5*btp -Jrel_infp=a_relp*(-ICaL)/(1.0+(1.5*scale_HF_Jrel_inf/cajsr)**8.0) -tau_relp_tmp=btp/(1.0+0.0123/cajsr) -tau_relp=Conditional(Lt(tau_relp_tmp, 0.001), 0.001, tau_relp_tmp) -dJrelp_dt=(Jrel_infp-Jrelp)/tau_relp -fJrelp=(1.0/(1.0+KmCaMK/CaMKa)) -Jrel=(1.0-fJrelp)*Jrelnp+fJrelp*Jrelp - -expressions("calcium buffers") -Jupnp=0.004375*cai/(cai+0.00092) -Jupp=2.75*0.004375*cai/(cai+0.00092-0.00017) -fJupp=(1.0/(1.0+KmCaMK/CaMKa)) -Jleak=0.0039375*cansr*scale_HF_Jleak/15.0 -Jup=(1.0-fJupp)*Jupnp+fJupp*Jupp*scale_HF_Jup-Jleak -Jtr=(cansr-cajsr)/100.0 - -parameters("calcium buffers", "mechanics", -cmdnmax=0.05, -kmcmdn=0.00238, -trpnmax=0.07, -kmtrpn=0.0005, -BSRmax=0.047, -KmBSR=0.00087, -BSLmax=1.124, -KmBSL=0.0087, -csqnmax=10.0, -kmcsqn=0.8) - -expressions("intracellular concentrations") -dnai_dt=-(INa+INaL+3.0*INaCa_i+3.0*INaK+INab+Isac_P_ns/3)*Acap/(F*vmyo)+JdiffNa*vss/vmyo -dnass_dt=-(ICaNa+3.0*INaCa_ss)*Acap/(F*vss)-JdiffNa -dki_dt=-(Ito+IKr+IKs+IK1+IKb+Isac_P_k+Isac_P_ns/3+Istim-2.0*INaK)*Acap/(F*vmyo)+JdiffK*vss/vmyo -dkss_dt=-(ICaK)*Acap/(F*vss)-JdiffK -Bcass=1.0/(1.0+BSRmax*KmBSR/(KmBSR+cass)**2.0+BSLmax*KmBSL/(KmBSL+cass)**2.0) -dcass_dt=Bcass*(-(ICaL-2.0*INaCa_ss)*Acap/(2.0*F*vss)+Jrel*vjsr/vss-Jdiff) -dcansr_dt=Jup-Jtr*vjsr/vnsr -Bcajsr=1.0/(1.0+csqnmax*kmcsqn/(kmcsqn+cajsr)**2.0) -dcajsr_dt=Bcajsr*(Jtr-Jrel) -Bcai=1.0/(1.0+cmdnmax*kmcmdn/(kmcmdn+cai)**2.0) -dcai_dt=Bcai*(-(IpCa+ICab-2.0*INaCa_i+Isac_P_ns/3)*Acap/(2.0*F*vmyo)-Jup*vnsr/vmyo+Jdiff*vss/vmyo - J_TRPN) - - -parameters("mechanics", -emcoupling=1, -lmbda=1, -dLambda=0, -mode=1, -isacs=0, -calib=1, -ktrpn = 0.1, -ntrpn = 2, -Trpn50 = 0.35, -rw = 0.5, -rs = 0.25, -gammas = 0.0085, -gammaw = 0.615, -phi = 2.23, -Tot_A = 25, -Beta0 = 2.3, -Beta1 = -2.4, -cat50_ref = 0.805, -scale_HF_cat50_ref=1.0, -Tref = 120, -kuw = 0.182, -kws = 0.012, -ku=0.04, -ntm=2.4, -p_a = 2.1, -p_b = 9.1, -p_k = 7, -etal = 200, -etas = 20) - -expressions("mechanics") -XS_max = Conditional(Gt(XS, 0), XS, 0) -XW_max = Conditional(Gt(XW, 0), XW, 0) -CaTrpn_max = Conditional(Gt(CaTrpn, 0), CaTrpn, 0) -kwu = kuw*(1/rw-1)-kws -ksu = kws*rw*(1/rs-1) -Aw = Tot_A*rs/((1-rs)*rw+rs) -As = Aw -cw = phi*kuw*((1-rs)*(1-rw))/((1-rs)*rw) -cs = phi*kws*((1-rs)*rw)/rs -lambda_min12 = Conditional(Lt(lmbda, 1.2), lmbda, 1.2) -lambda_min087 = Conditional(Lt(lambda_min12, 0.87), lambda_min12, 0.87) -h_lambda_prima = 1+Beta0*(lambda_min12+lambda_min087-1.87) -h_lambda = Conditional(Gt(h_lambda_prima, 0), h_lambda_prima, 0) -XU = (1-TmB)-XS-XW -gammawu = gammaw*abs(Zetaw) -gammasu = gammas*Conditional(Gt(Gt(Zetas,0)*Zetas, Lt(Zetas, -1)*(-Zetas-1)), Gt(Zetas,0)*Zetas, Lt(Zetas, -1)*(-Zetas-1)) -dXS_dt = kws*XW - ksu*XS - gammasu*XS -dXW_dt = kuw*XU - kwu*XW - kws*XW - gammawu*XW -cat50 = (cat50_ref+Beta1*(lambda_min12-1))*scale_HF_cat50_ref -dCaTrpn_dt = ktrpn*(((cai*1000/cat50)**ntrpn)*(1-CaTrpn)-CaTrpn) -kb = ku*Trpn50**ntm/(1-rs-(1-rs)*rw) -dTmB_dt = kb*Conditional(Lt(CaTrpn**(-ntm/2), 100), CaTrpn**(-ntm/2), 100)*XU-ku*CaTrpn**(ntm/2)*TmB -dZetas_dt = As*dLambda - cs*Zetas -dZetaw_dt = Aw*dLambda - cw*Zetaw -Ta = h_lambda*(Tref/rs)*(XS*(Zetas+1) + XW*Zetaw) -C = lambda_min12 - 1 -dCd = C - Cd -eta = Conditional(Lt(dCd, 0), etas, etal) -dCd_dt = p_k * (C - Cd) / eta -Fd = eta * dCd -F1 = (exp( p_b * C) - 1) -Tp = p_a * (F1 + Fd) -Ttot = Ta + Tp -J_TRPN = dCaTrpn_dt*trpnmax diff --git a/demos/consistency_checks_across_split_schemes/cai_split/config.toml b/demos/consistency_checks_across_split_schemes/cai_split/config.toml deleted file mode 100644 index 083a8e5..0000000 --- a/demos/consistency_checks_across_split_schemes/cai_split/config.toml +++ /dev/null @@ -1,117 +0,0 @@ -# Configuration file for running a simulation - -# SIMULATION PARAMETERS -sim.mech_mesh = "mesh_mech_3.0" # mechanics mesh filepath without extension -sim.outdir = "100ms_N1_cai_split_ufl_consistent_with_zetasplit_runcheck" # Output directory -sim.sim_dur = 100 # Duration of simulation. Integer -sim.dt = 0.05 # Timestep for ep solve -sim.N = 1 # Solve mechanics step every nth ep solve - -# MODEL PARAMETERS -sim.modelfile = "ORdmm_Land.ode" - -# OUTPUT PARAMETERS -write_all_ep.numbers = 2 -write_all_ep.0.name = "cai" -write_all_ep.1.name = "v" - -write_all_mech.numbers = 2 -write_all_mech.0.name = "Ta" -write_all_mech.1.name = "lambda" - -# Currently output both point traces and average values for these: -write_point_ep.numbers = 2 -write_point_ep.0.name = "cai" -write_point_ep.0.x = 0.0 -write_point_ep.0.y = 0 -write_point_ep.0.z = 0 -write_point_ep.1.name = "v" -write_point_ep.1.x = 0 -write_point_ep.1.y = 0 -write_point_ep.1.z = 0 - -write_point_mech.numbers = 6 -write_point_mech.0.name = "Ta" -write_point_mech.0.x = 0 -write_point_mech.0.y = 0 -write_point_mech.0.z = 0 -write_point_mech.1.name = "Zetas" -write_point_mech.1.x = 0 -write_point_mech.1.y = 0 -write_point_mech.1.z = 0 -write_point_mech.2.name = "XS" -write_point_mech.2.x = 0 -write_point_mech.2.y = 0 -write_point_mech.2.z = 0 -write_point_mech.3.name = "TmB" -write_point_mech.3.x = 0 -write_point_mech.3.y = 0 -write_point_mech.3.z = 0 -write_point_mech.4.name = "CaTrpn" -write_point_mech.4.x = 0 -write_point_mech.4.y = 0 -write_point_mech.4.z = 0 -write_point_mech.5.name = "lambda" -write_point_mech.5.x = 0 -write_point_mech.5.y = 0 -write_point_mech.5.z = 0 - - -# Tissue conductivity values. Currently only a single region, from p.4339 of Niederer benchmark -ep.sigma_il = 0.17 # mS / mm -ep.sigma_it = 0.019 # mS / mm -ep.sigma_el = 0.62 # mS / mm -ep.sigma_et = 0.24 # mS / mm - -# Material parameters -# TODO: make material parameters more generic -mech.a=2.28 -mech.a_f=1.686 -mech.b=9.726 -mech.b_f=15.779 -mech.a_s=0.0 -mech.b_s=0.0 -mech.a_fs=0.0 -mech.b_fs=0.0 - -# STIMULUS PARAMETERS -stim.start = 0.0 -stim.amplitude = 50000.0 # mu A/cm^3 -stim.duration = 2 # ms -stim.xmin = 0.0 -stim.xmax = 1.5 -stim.ymin = 0.0 -stim.ymax = 1.5 -stim.zmin = 0.0 -stim.zmax = 1.5 - -# BOUNDARY CONDITIONS -bcs.numbers = 3 #4 -bcs.markerfile = "mesh_mech_3dx_20Lx_7Ly_3Lz_surface_ffun" - -# Mesh markers used for assigning bcs -bcs.0.marker = 1 -bcs.0.type = "Dirichlet" -bcs.0.V = "u_x" -bcs.0.expression = 0 -bcs.0.param_numbers = 0 - -bcs.1.marker = 3 # if same marker for ux,uy,uz, (e.g. marker = 1), then fixes the entire plane (plane with marker == 1) -bcs.1.type = "Dirichlet" -bcs.1.V = "u_y" -bcs.1.expression = 0 -bcs.1.param_numbers = 0 - -bcs.2.marker = 5 -bcs.2.type = "Dirichlet" -bcs.2.V = "u_z" -bcs.2.expression = 0 -bcs.2.param_numbers = 0 - -#bcs.3.marker = 2 -#bcs.3.type = "Neumann" -#bcs.3.expression = 'a*t' # Value can be a function of t -#bcs.3.param_numbers = 1 -#bcs.3.param.0.name = 'a' -#bcs.3.param.0.value = -0.2 -#bcs.3.degree = 1 diff --git a/demos/consistency_checks_across_split_schemes/cai_split/land_caisplit_consistent_with_zetasplit.py b/demos/consistency_checks_across_split_schemes/cai_split/land_caisplit_consistent_with_zetasplit.py deleted file mode 100644 index 44e4640..0000000 --- a/demos/consistency_checks_across_split_schemes/cai_split/land_caisplit_consistent_with_zetasplit.py +++ /dev/null @@ -1,549 +0,0 @@ -import pulse -import dolfin -import ufl_legacy as ufl -import logging -import numpy as np -from enum import Enum - -from simcardems2 import utils - -logger = logging.getLogger(__name__) - - -class Scheme(str, Enum): - fd = "fd" - bd = "bd" - analytic = "analytic" - - -def _Zeta(Zeta_prev, A, c, dLambda, dt, scheme: Scheme): - # if scheme == Scheme.analytic: - dZetas_dt = A * dLambda - Zeta_prev * c - dZetas_dt_linearized = -c - if abs(c) > 1e-8: - return Zeta_prev + dZetas_dt * (np.exp(-c * dt) - 1.0) / dZetas_dt_linearized - else: - # Forward euler - return Zeta_prev + dZetas_dt * dt - - -# From CaTrpn split -def _XS(XS_prev, XW, gammasu, ksu, kws, dt): - dXS_dt_linearized = -gammasu - ksu - dXS_dt = -XS_prev * gammasu - XS_prev * ksu + XW * kws - return XS_prev + np.where( - (np.abs(dXS_dt_linearized) > 1e-8), - dXS_dt * (np.exp(dXS_dt_linearized * dt) - 1) / dXS_dt_linearized, - dXS_dt * dt, - ) - - -def _XW(XW_prev, XU, gammawu, kws, kuw, kwu, dt): - dXW_dt_linearized = -gammawu - kws - kwu - dXW_dt = -XW_prev * gammawu - XW_prev * kws + XU * kuw - XW_prev * kwu - return XW_prev + np.where( - (np.abs(dXW_dt_linearized) > 1e-8), - dXW_dt * (np.exp(dXW_dt_linearized * dt) - 1) / dXW_dt_linearized, - dXW_dt * dt, - ) - - -def _TmB(TmB_prev, CaTrpn, XU, ntm, kb, ku, dt): - dTmB_dt_linearized = -(CaTrpn ** (ntm / 2)) * ku - dTmB_dt = -TmB_prev * CaTrpn ** (ntm / 2) * ku + XU * ( - kb * np.where((CaTrpn ** (-1 / 2 * ntm) < 100), CaTrpn ** (-1 / 2 * ntm), 100) - ) - - return TmB_prev + np.where( - (np.abs(dTmB_dt_linearized) > 1e-8), - dTmB_dt * (np.exp(dTmB_dt_linearized * dt) - 1) / dTmB_dt_linearized, - dTmB_dt * dt, - ) - - -def _XU(XW, XS, TmB): - return -XW - XS + 1 - TmB - - -def _gammawu(Zetaw, gammaw): - return gammaw * np.abs(Zetaw) - - -def _gammasu(Zetas, gammas): - return gammas * np.where((Zetas > 0), Zetas, np.where((Zetas < -1), -Zetas - 1, 0)) - - -# For cai split -def _CaTrpn(CaTrpn, cai, ktrpn, ntrpn, cat50, dt, scheme: Scheme): - return CaTrpn + np.where( - (np.abs(ktrpn * (-(((1000 * cai) / cat50) ** ntrpn) - 1)) > 1e-08), - (ktrpn * (-CaTrpn + ((1000 * cai) / cat50) ** ntrpn * (1 - CaTrpn))) - * (np.exp((ktrpn * (-(((1000 * cai) / cat50) ** ntrpn) - 1)) * dt) - 1) - / (ktrpn * (-(((1000 * cai) / cat50) ** ntrpn) - 1)), - (ktrpn * (-CaTrpn + ((1000 * cai) / cat50) ** ntrpn * (1 - CaTrpn))) * dt, - ) - - -def _cat50(scale_HF_cat50_ref, Beta1, lmbda, cat50_ref, dt, scheme: Scheme): - return scale_HF_cat50_ref * (Beta1 * ((np.where((lmbda < 1.2), lmbda, 1.2)) - 1) + cat50_ref) - - -def _J_TRPN(CaTrpn, cai, ktrpn, ntrpn, cat50, trpnmax, dt, scheme: Scheme): - return (ktrpn * (-CaTrpn + ((1000 * cai) / cat50) ** ntrpn * (1 - CaTrpn))) * trpnmax - - -_parameters = { - "Beta0": 2.3, - "Beta1": -2.4, # New for cai split - "Tot_A": 25.0, - "Tref": 120, - "kuw": 0.182, - "kws": 0.012, - "phi": 2.23, - "rs": 0.25, - "rw": 0.5, - "gammas": 0.0085, # Parameters from CaTrpn split - "gammaw": 0.615, # Parameters from CaTrpn split - "Trpn50": 0.35, # Parameters from CaTrpn split - "ntm": 2.4, # Parameters from CaTrpn split. - "ku": 0.04, # Parameters from CaTrpn split. - "ntrpn": 2, # New for cai split - "ktrpn": 0.1, # New for cai split - "scale_HF_cat50_ref": 1.0, # New for cai split - "cat50_ref": 0.805, # New for cai split - "trpnmax": 0.07, # New for cai split -} - - -class LandModel(pulse.ActiveModel): - def __init__( - self, - f0, - s0, - n0, - cai, - mesh, - CaTrpn=None, - TmB=None, # Variables from CaTrpn split - XS=None, - XW=None, - parameters=None, - Zetas=None, - Zetaw=None, - lmbda=None, - eta=0, - scheme: Scheme = Scheme.analytic, - dLambda_tol: float = 1e-12, - **kwargs, - ): - logger.debug("Initialize Land Model") - super().__init__(f0=f0, s0=s0, n0=n0) - - self._eta = eta - self.function_space = dolfin.FunctionSpace(mesh, "DG", 1) - - """ From Catrpn split""" - self._XS = dolfin.Function(self.function_space) - self.XS_prev = dolfin.Function(self.function_space) - if XS is not None: - self.XS_prev.assign(XS) - - self._XW = dolfin.Function(self.function_space) - self.XW_prev = dolfin.Function(self.function_space) - if XW is not None: - self.XW_prev.assign(XW) - - self._XU = dolfin.Function(self.function_space) - self._gammasu = dolfin.Function(self.function_space) - self._gammawu = dolfin.Function(self.function_space) - - self._TmB = dolfin.Function(self.function_space) - self.TmB_prev = dolfin.Function(self.function_space) - if TmB is not None: - self.TmB_prev.assign(TmB) - else: # Set initial TmB value - self._TmB.interpolate(dolfin.Constant(1)) - self.TmB_prev.interpolate(dolfin.Constant(1)) - - """ New for Cai split""" - self.cai = cai # Missing variable - self._J_TRPN = dolfin.Function(self.function_space) # Missing in ep - self._cat50 = dolfin.Function(self.function_space) - self._CaTrpn = dolfin.Function(self.function_space) - self.CaTrpn_prev = dolfin.Function(self.function_space) - - if CaTrpn is not None: - self.CaTrpn_prev.assign(CaTrpn) - else: # Set initial Catrpn value - self._CaTrpn.interpolate(dolfin.Constant(0.0001)) - self.CaTrpn_prev.interpolate(dolfin.Constant(0.0001)) - """ """ - - if parameters is None: - parameters = _parameters - self._parameters = parameters - - self._scheme = scheme - - self._dLambda = dolfin.Function(self.function_space) - self.lmbda_prev = dolfin.Function(self.function_space) - self.lmbda_prev.vector()[:] = 1.0 - if lmbda is not None: - self.lmbda_prev.assign(lmbda) - self.lmbda = dolfin.Function(self.function_space) - - self._Zetas = dolfin.Function(self.function_space) - self.Zetas_prev = dolfin.Function(self.function_space) - if Zetas is not None: - self.Zetas_prev.assign(Zetas) - - self._Zetaw = dolfin.Function(self.function_space) - self.Zetaw_prev = dolfin.Function(self.function_space) - if Zetaw is not None: - self.Zetaw_prev.assign(Zetaw) - - self.Ta_current = dolfin.Function(self.function_space, name="Ta") - self._projector = utils.Projector(self.function_space) - self._dLambda_tol = dLambda_tol - self._t_prev = 0.0 - - """ From CaTrpn split""" - - @property - def ksu(self): - kws = self._parameters["kws"] - rw = self._parameters["rw"] - rs = self._parameters["rs"] - return (kws * rw) * (-1 + 1 / rs) - - @property - def kwu(self): - kuw = self._parameters["kuw"] - rw = self._parameters["rw"] - kws = self._parameters["kws"] - return kuw * (-1 + 1 / rw) - kws - - @property - def kb(self): - Trpn50 = self._parameters["Trpn50"] - ntm = self._parameters["ntm"] - ku = self._parameters["ku"] - rs = self._parameters["rs"] - rw = self._parameters["rw"] - return (Trpn50**ntm * ku) / (-rw * (1 - rs) + 1 - rs) - - @property - def XS(self): - return self._XS - - @property - def XW(self): - return self._XW - - @property - def TmB(self): - return self._TmB - - @property - def XU(self): - return self._XU - - @property - def gammawu(self): - return self._gammawu - - @property - def gammasu(self): - return self._gammasu - - def update_TmB(self): - logger.debug("update TmB") - self._TmB.vector()[:] = _TmB( - self.TmB_prev.vector().get_local(), - self.CaTrpn_prev.vector().get_local(), - self.XU.vector().get_local(), - self._parameters["ntm"], - self.kb, - self._parameters["ku"], - self.dt, - ) - - def update_XS(self): - logger.debug("update XS") - self._XS.vector()[:] = _XS( - self.XS_prev.vector().get_local(), - self.XW_prev.vector().get_local(), - self.gammasu.vector().get_local(), - self.ksu, - self._parameters["kws"], - self.dt, - ) - - def update_XW(self): - logger.debug("update XW") - self._XW.vector()[:] = _XW( - self.XW_prev.vector().get_local(), - self.XU.vector().get_local(), - self.gammawu.vector().get_local(), - self._parameters["kws"], - self._parameters["kuw"], - self.kwu, - self.dt, - ) - - # Calculate monitors - def calculate_XU(self): - logger.debug("update XU") - self._XU.vector()[:] = _XU( - self.XW_prev.vector().get_local(), - self.XS_prev.vector().get_local(), - self.TmB_prev.vector().get_local(), - ) - - def calculate_gammasu(self): - logger.debug("update gammasu") - self._gammasu.vector()[:] = _gammasu( - self.Zetas_prev.vector().get_local(), - self._parameters["gammas"], - ) - - def calculate_gammawu(self): - logger.debug("update gammawu") - self._gammawu.vector()[:] = _gammawu( - self.Zetaw_prev.vector().get_local(), - self._parameters["gammaw"], - ) - - """ New for cai split""" - - @property - def CaTrpn(self): - return self._CaTrpn - - def update_CaTrpn(self): - logger.debug("update CaTrpn") - self._CaTrpn.vector()[:] = _CaTrpn( - CaTrpn=self.CaTrpn_prev.vector().get_local(), - cai=self.cai.vector().get_local(), # Missing variable - ktrpn=self._parameters["ktrpn"], - ntrpn=self._parameters["ntrpn"], - cat50=self.cat50.vector().get_local(), - dt=self.dt, - scheme=self._scheme, - ) - - @property - def cat50(self): - return self._cat50 - - def calculate_cat50(self): - logger.debug("update cat50") - self._cat50.vector()[:] = _cat50( - scale_HF_cat50_ref=self._parameters["scale_HF_cat50_ref"], - Beta1=self._parameters["Beta1"], - lmbda=self.lmbda_prev.vector().get_local(), # Explicit update, to be consistent with other split schemes - cat50_ref=self._parameters["cat50_ref"], - dt=self.dt, - scheme=self._scheme, - ) - - @property - def J_TRPN(self): - return self._J_TRPN - - def calculate_J_TRPN(self): - logger.debug("update J_TRPN") - self._J_TRPN.vector()[:] = _J_TRPN( - CaTrpn=self.CaTrpn_prev.vector().get_local(), - cai=self.cai.vector().get_local(), # Missing variable - ktrpn=self._parameters["ktrpn"], - ntrpn=self._parameters["ntrpn"], - cat50=self.cat50.vector().get_local(), - trpnmax=self._parameters["trpnmax"], - dt=self.dt, - scheme=self._scheme, - ) - - """ """ - - def dLambda(self, lmbda): - logger.debug("Evaluate dLambda") - if self.dt == 0: - return self._dLambda - else: - return (lmbda - self.lmbda_prev) / self.dt - - @property - def Aw(self): - Tot_A = self._parameters["Tot_A"] - rs = self._parameters["rs"] - rw = self._parameters["rw"] - scale_popu_rw = 1.0 # self._parameters["scale_popu_rw"] - scale_popu_rs = 1.0 # self._parameters["scale_popu_rs"] - return ( - Tot_A - * rs - * scale_popu_rs - / (rs * scale_popu_rs + rw * scale_popu_rw * (1.0 - (rs * scale_popu_rs))) - ) - - @property - def As(self): - return self.Aw - - @property - def cw(self): - phi = self._parameters["phi"] - kuw = self._parameters["kuw"] - rw = self._parameters["rw"] - - scale_popu_kuw = 1.0 # self._parameters["scale_popu_kuw"] - scale_popu_rw = 1.0 # self._parameters["scale_popu_rw"] - return kuw * scale_popu_kuw * phi * (1.0 - (rw * scale_popu_rw)) / (rw * scale_popu_rw) - - @property - def cs(self): - phi = self._parameters["phi"] - kws = self._parameters["kws"] - rs = self._parameters["rs"] - rw = self._parameters["rw"] - scale_popu_kws = 1.0 # self._parameters["scale_popu_kws"] - scale_popu_rw = 1.0 # self._parameters["scale_popu_rw"] - scale_popu_rs = 1.0 # self._parameters["scale_popu_rs"] - return ( - kws - * scale_popu_kws - * phi - * rw - * scale_popu_rw - * (1.0 - (rs * scale_popu_rs)) - / (rs * scale_popu_rs) - ) - - def update_Zetas(self, lmbda): - logger.debug("update Zetas") - self._projector( - self._Zetas, - _Zeta( - self.Zetas_prev, - self.As, - self.cs, - self.dLambda(lmbda), - self.dt, - self._scheme, - ), - ) - - def Zetas(self, lmbda): - # return self._Zetas - return _Zeta( - self.Zetas_prev, - self.As, - self.cs, - self.dLambda(lmbda), - self.dt, - self._scheme, - ) - - def update_Zetaw(self, lmbda): - logger.debug("update Zetaw") - self._projector( - self._Zetaw, - _Zeta( - self.Zetaw_prev, - self.Aw, - self.cw, - self.dLambda(lmbda), - self.dt, - self._scheme, - ), - ) - - def Zetaw(self, lmbda): - return _Zeta( - self.Zetaw_prev, - self.Aw, - self.cw, - self.dLambda(lmbda), - self.dt, - self._scheme, - ) - - @property - def dt(self) -> float: - return self.t - self._t_prev - - def update_prev(self): - logger.debug("update previous") - self.Zetas_prev.vector()[:] = self._Zetas.vector() - self.Zetaw_prev.vector()[:] = self._Zetaw.vector() - self.lmbda_prev.vector()[:] = self.lmbda.vector() - - """ For CaTrpn split""" - self.XS_prev.vector()[:] = self.XS.vector() - self.XW_prev.vector()[:] = self._XW.vector() - self.TmB_prev.vector()[:] = self._TmB.vector() - """ For cai split""" - self.CaTrpn_prev.vector()[:] = self._CaTrpn.vector() - """ """ - - self._projector.project(self.Ta_current, self.Ta(self.lmbda)) - self._t_prev = self.t - - def Ta(self, lmbda): - logger.debug("Evaluate Ta") - Tref = self._parameters["Tref"] - rs = self._parameters["rs"] - scale_popu_Tref = 1.0 # self._parameters["scale_popu_Tref"] - scale_popu_rs = 1.0 # self._parameters["scale_popu_rs"] - Beta0 = self._parameters["Beta0"] - - _min = ufl.min_value - _max = ufl.max_value - if isinstance(lmbda, (int, float)): - _min = min - _max = max - lmbda = _min(1.2, lmbda) - h_lambda_prima = 1.0 + Beta0 * (lmbda + _min(lmbda, 0.87) - 1.87) - h_lambda = _max(0, h_lambda_prima) - - # Using projection, to be consistent with zetasplit - return ( - h_lambda - * (Tref * scale_popu_Tref / (rs * scale_popu_rs)) - * (self._XS * (self.Zetas(lmbda) + 1.0) + self._XW * self.Zetaw(lmbda)) - ) - - def Wactive(self, F, **kwargs): - """Active stress energy""" - logger.debug("Compute active stress energy") - C = F.T * F - C = F.T * F - f = F * self.f0 - lmbda = dolfin.sqrt(f**2) - self._projector.project(self.lmbda, lmbda) - - # Used to update for next iteration, but not used to calculate Ta, - # since Ta takes lmda directly - self.update_Zetas(lmbda=lmbda) - self.update_Zetaw(lmbda=lmbda) - - """ For Catrpn split""" - self.calculate_XU() - self.calculate_gammasu() - self.calculate_gammawu() - self.update_XS() - self.update_XW() - self.update_TmB() - - """ New for cai split""" - self.calculate_cat50() - self.calculate_J_TRPN() # Missing in ep - self.update_CaTrpn() - - return pulse.material.active_model.Wactive_transversally( - Ta=self.Ta(lmbda), - C=C, - f0=self.f0, - eta=self.eta, - ) diff --git a/demos/consistency_checks_across_split_schemes/cai_split/main_caisplit_consistent_with_zetasplit.py b/demos/consistency_checks_across_split_schemes/cai_split/main_caisplit_consistent_with_zetasplit.py deleted file mode 100644 index 6d54847..0000000 --- a/demos/consistency_checks_across_split_schemes/cai_split/main_caisplit_consistent_with_zetasplit.py +++ /dev/null @@ -1,688 +0,0 @@ -import logging -import gotranx -from pathlib import Path -from typing import Sequence -import numpy as np -import dolfin -import pulse -import beat -import argparse -import toml -import matplotlib.pyplot as plt - - -from simcardems2 import utils -from simcardems2 import mechanicssolver -from simcardems2 import interpolation -from land_caisplit_consistent_with_zetasplit import LandModel -from simcardems2.validate_input_types import validate_input_types - - -try: - raise ImportError - from numba import jit -except ImportError: - - def jit(*args, **kwargs): - def wrapper(func): - return func - - return wrapper - - -logging.getLogger("beat").setLevel(logging.ERROR) - - -def parse_parameters(argv: Sequence[str] | None = None) -> int: - parser = argparse.ArgumentParser(description="Simcardems CLI") - parser.add_argument("config-file", type=Path, help="Config file") - - args = vars(parser.parse_args(argv)) - try: - config = toml.loads(args["config-file"].read_text()) - except toml.TomlDecodeError as e: - print(f"Error when parsing input parameters. Check config file. Error: {e}") - exit(1) - return config - - -config = parse_parameters() - -validate_input_types(config) - -stim_region = ( - [config["stim"]["xmin"], config["stim"]["xmax"]], - [config["stim"]["ymin"], config["stim"]["ymax"]], - [config["stim"]["zmin"], config["stim"]["zmax"]], -) -out_ep_var_names = [ - config["write_all_ep"][f"{i}"]["name"] for i in range(config["write_all_ep"]["numbers"]) -] -out_mech_var_names = [ - config["write_all_mech"][f"{i}"]["name"] for i in range(config["write_all_mech"]["numbers"]) -] -out_ep_coord_names = [ - config["write_point_ep"][f"{i}"]["name"] for i in range(config["write_point_ep"]["numbers"]) -] -ep_coords = [ - [config["write_point_ep"][f"{varnr}"][f"{coord}"] for coord in ["x", "y", "z"]] - for varnr in range(config["write_point_ep"]["numbers"]) -] -out_mech_coord_names = [ - config["write_point_mech"][f"{i}"]["name"] for i in range(config["write_point_mech"]["numbers"]) -] -mech_coords = [ - [config["write_point_mech"][f"{varnr}"][f"{coord}"] for coord in ["x", "y", "z"]] - for varnr in range(config["write_point_mech"]["numbers"]) -] - - -outdir = Path(config["sim"]["outdir"]) -outdir.mkdir(parents=True, exist_ok=True) - -with open(Path(outdir / "config.txt"), "w") as f: - f.write(toml.dumps(config)) - - -# TODO: do a different dirichlet/neumann check than this later. something smoother -t_bcs = dolfin.Constant(0) -bcs_dirichlet = [] -bcs_neumann = [] -bcs_expressions = {} -for bc in range(config["bcs"]["numbers"]): - if config["bcs"][f"{bc}"]["type"] == "Dirichlet": - bcs_dirichlet.append(bc) - elif config["bcs"][f"{bc}"]["type"] == "Neumann": - bcs_neumann.append(bc) - else: - raise KeyError( - f'{config["bcs"][str(bc)]["type"]} is not a valid type of boundary ' - 'condition. Use Dirichlet or Neumann. Check config file' - ) - - if config["bcs"][f"{bc}"]["param_numbers"] > 0: - bcs_parameters = {} - for param_nr in range(config["bcs"][f"{bc}"]["param_numbers"]): - param_name = config["bcs"][f"{bc}"]["param"][f"{param_nr}"]["name"] - param_value = config["bcs"][f"{bc}"]["param"][f"{param_nr}"]["value"] - bcs_parameters[param_name] = param_value - bcs_expressions[f"{bc}"] = dolfin.Expression( - config["bcs"][f"{bc}"]["expression"], - **bcs_parameters, - t=t_bcs, - degree=config["bcs"][f"{bc}"]["degree"], - ) - else: - bcs_expressions[f"{bc}"] = dolfin.Constant(0) - - -mesh = dolfin.Mesh() -with dolfin.XDMFFile(f'{config["sim"]["mech_mesh"]}.xdmf') as infile: - infile.read(mesh) -print(f'Loaded mesh: {config["sim"]["mech_mesh"]}') - - -ffun_bcs = dolfin.MeshFunction("size_t", mesh, mesh.topology().dim() - 1) -with dolfin.XDMFFile(f'{config["bcs"]["markerfile"]}.xdmf') as infile: - infile.read(ffun_bcs) -print(f'Loaded markerfile for bcs: {config["bcs"]["markerfile"]}') - - -tol = 5e-4 -# Surface to volume ratio -chi = 140.0 # mm^{-1} -# Membrane capacitance -C_m = 0.01 # mu F / mm^2 -cm2mm = 10.0 - -t = np.arange(0, config["sim"]["sim_dur"], config["sim"]["dt"]) -sigma = [ - config["ep"]["sigma_il"], - config["ep"]["sigma_it"], - config["ep"]["sigma_el"], - config["ep"]["sigma_et"], -] -material_parameters = dict( - a=config["mech"]["a"], - a_f=config["mech"]["a_f"], - b=config["mech"]["b"], - b_f=config["mech"]["b_f"], - a_s=config["mech"]["a_s"], - b_s=config["mech"]["b_s"], - a_fs=config["mech"]["a_fs"], - b_fs=config["mech"]["b_fs"], -) - - -dolfin.parameters["form_compiler"]["representation"] = "uflacs" -dolfin.parameters["form_compiler"]["cpp_optimize"] = True -dolfin.parameters["form_compiler"]["quadrature_degree"] = 4 - - -def define_conductivity_tensor(sigma, chi, C_m): - # Compute monodomain approximation by taking harmonic mean in each - # direction of intracellular and extracellular part - def harmonic_mean(a, b): - return a * b / (a + b) - - sigma_l = harmonic_mean(sigma[0], sigma[2]) - sigma_t = harmonic_mean(sigma[1], sigma[3]) - - # Scale conducitivites by 1/(C_m * chi) - s_l = sigma_l / (C_m * chi) # mm^2 / ms - s_t = sigma_t / (C_m * chi) # mm^2 / ms - - # Define conductivity tensor - M = dolfin.as_tensor(((s_l, 0, 0), (0, s_t, 0), (0, 0, s_t))) - - return M - - -def define_stimulus( - mesh, - chi, - C_m, - time, - stim_region=stim_region, - stim_start=config["stim"]["start"], - A=config["stim"]["amplitude"], - duration=config["stim"]["duration"], -): - S1_marker = 1 - S1_subdomain = dolfin.CompiledSubDomain( - " ".join( - ( - f"x[0] >= {stim_region[0][0]}", - f"&& x[0] <= {stim_region[0][1]}", - f"&& x[1] >= {stim_region[1][0]}", - f"&& x[1] <= {stim_region[1][1]}", - f"&& x[2] >= {stim_region[2][0]}", - f"&& x[2] <= {stim_region[2][1]}", - ) - ) - ) - - S1_markers = dolfin.MeshFunction("size_t", mesh, mesh.topology().dim()) - S1_subdomain.mark(S1_markers, S1_marker) - with dolfin.XDMFFile((outdir / "stim_region_markers.xdmf").as_posix()) as xdmf: - xdmf.write(S1_markers) - - # Define stimulation (NB: region of interest carried by the mesh - # and assumptions in cbcbeat) - factor = 1.0 / (chi * C_m) # NB: cbcbeat convention - amplitude = factor * A * (1.0 / cm2mm) ** 3 # mV/ms - - I_s = dolfin.Expression( - "time >= start ? (time <= (duration + start) ? amplitude : 0.0) : 0.0", - time=time, - start=config["stim"]["start"], - duration=duration, - amplitude=amplitude, - degree=0, - ) - - dx = dolfin.Measure("dx", domain=mesh, subdomain_data=S1_markers)(S1_marker) - return beat.base_model.Stimulus(dz=dx, expr=I_s) - - -# Load the model -if not Path("ep_model.py").exists(): - ode = gotranx.load_ode(config["sim"]["modelfile"]) - - mechanics_comp = ode.get_component("mechanics") - mechanics_ode = mechanics_comp.to_ode() - - ep_ode = ode - mechanics_comp - - # Generate code for the electrophysiology model - code_ep = gotranx.cli.gotran2py.get_code( - ep_ode, - scheme=[gotranx.schemes.Scheme.forward_generalized_rush_larsen], - missing_values=mechanics_ode.missing_variables, - ) - # Generate code for the mechanics model - code_mechanics = gotranx.cli.gotran2py.get_code( - mechanics_ode, - scheme=[gotranx.schemes.Scheme.forward_generalized_rush_larsen], - missing_values=ep_ode.missing_variables, - ) - - Path("ep_model.py").write_text(code_ep) - # Currently 3D mech needs to be written manually - -import ep_model as _ep_model - -ep_model = _ep_model.__dict__ - - -# Validate ep variables to output -for i in list(set(out_ep_coord_names) | set(out_ep_var_names)): - try: - var = ep_model["state_index"](i) - except KeyError: - print(f"{i} is not an ep state. Check config file") - raise - -# Forwared generalized rush larsen scheme for the electrophysiology model -fgr_ep = jit(nopython=True)(ep_model["forward_generalized_rush_larsen"]) -# Monitor function for the electrophysiology model -mon_ep = ep_model["monitor_values"] -# Missing values function for the electrophysiology model -mv_ep = ep_model["missing_values"] - - -# Get initial values from the EP model -y_ep_ = ep_model["init_state_values"]() -p_ep_ = ep_model["init_parameter_values"](amp=0.0) - -# ep_missing_values_ = np.zeros(len(ep_model["missing"])) # Init value for J_TRPN -ep_missing_values_ = np.array( - [0.00010730972184715098] -) # Init value for J_TRPN = dCaTrpn_dt * trpnmax (to compare with zetasplit) - - -# ep_mesh = dolfin.adapt(dolfin.adapt(dolfin.adapt(mesh))) -ep_mesh = mesh - -time = dolfin.Constant(0.0) -I_s = define_stimulus( - mesh=ep_mesh, - chi=chi, - C_m=C_m, - time=time, - stim_region=stim_region, - stim_start=config["stim"]["start"], - A=config["stim"]["amplitude"], - duration=config["stim"]["duration"], -) -M = define_conductivity_tensor(sigma, chi, C_m) -params = {"preconditioner": "sor", "use_custom_preconditioner": False} -ep_ode_space = dolfin.FunctionSpace(ep_mesh, "DG", 1) -v_ode = dolfin.Function(ep_ode_space) -num_points_ep = v_ode.vector().local_size() -lmbda = dolfin.Function(ep_ode_space) - - -y_ep = np.zeros((len(y_ep_), num_points_ep)) -y_ep.T[:] = y_ep_ # Set to y_ep with initial values defined in ep_model - - -mechanics_missing_values_ = np.array([0.0001]) # Init value for cai - - -# Set the activation -activation_space = dolfin.FunctionSpace(mesh, "DG", 1) -activation = dolfin.Function(activation_space) -num_points_mech = activation.vector().local_size() - -missing_mech = interpolation.MissingValue( - element=activation.ufl_element(), - interpolation_element=ep_ode_space.ufl_element(), - mechanics_mesh=mesh, - ep_mesh=ep_mesh, - num_values=len(mechanics_missing_values_), -) - -missing_ep = interpolation.MissingValue( - element=ep_ode_space.ufl_element(), - interpolation_element=activation.ufl_element(), - mechanics_mesh=mesh, - ep_mesh=ep_mesh, - num_values=len(ep_missing_values_), -) - - -missing_ep.values_mechanics.T[:] = ep_missing_values_ -missing_ep.values_ep.T[:] = ep_missing_values_ - -missing_mech.values_ep.T[:] = mechanics_missing_values_ -missing_mech.values_mechanics.T[:] = mechanics_missing_values_ -missing_mech.mechanics_values_to_function() # Assign initial values to mech functions - - -# Create function spaces for ep variables to output -out_ep_funcs = {} -for out_ep_var in list(set(out_ep_var_names) | set(out_ep_coord_names)): - out_ep_funcs[out_ep_var] = dolfin.Function(ep_ode_space) - -p_ep = np.zeros((len(p_ep_), num_points_ep)) -p_ep.T[:] = p_ep_ # Initialise p_ep with initial values defined in ep_model - -pde = beat.MonodomainModel(time=time, mesh=ep_mesh, M=M, I_s=I_s, params=params) -ode = beat.odesolver.DolfinODESolver( - v_ode=dolfin.Function(ep_ode_space), - v_pde=pde.state, - fun=fgr_ep, - parameters=p_ep, - init_states=y_ep, - num_states=len(y_ep), - v_index=ep_model["state_index"]("v"), - missing_variables=missing_ep.values_ep, - num_missing_variables=len(ep_model["missing"]), -) - -# ep_solver = beat.MonodomainSplittingSolver(pde=pde, ode=ode, theta=0.5) -ep_solver = beat.MonodomainSplittingSolver(pde=pde, ode=ode, theta=1) - -marker_functions = pulse.MarkerFunctions(ffun=ffun_bcs) - - -def create_boundary_conditions( - ffun_bcs, bcs_dirichlet, bcs_neumann, bcs_dict, bcs_expressions -): # TODO: update to not need separate dirichlet and neumann list - def dirichlet_bc(W): - bcs_W = { - "u_x": W.sub(0).sub(0), - "u_y": W.sub(0).sub(1), - "u_z": W.sub(0).sub(2), - # TODO: add the rest (check dolfin doc) - } - - bcs = [] - for bc in bcs_dirichlet: - bcs.append( - dolfin.DirichletBC( - bcs_W[bcs_dict[f"{bc}"]["V"]], - bcs_expressions[f"{bc}"], # TODO: use dolfin expression - ffun_bcs, - bcs_dict[f"{bc}"]["marker"], - ) - ) - return bcs - - neumann_bc = [] - if bcs_neumann is not None: - for bc in bcs_neumann: - neumann_bc.append( - pulse.NeumannBC( - traction=utils.float_to_constant(bcs_expressions[f"{bc}"]), - marker=bcs_dict[f"{bc}"]["marker"], - ) - ) - - # Collect Boundary Conditions - bcs = pulse.BoundaryConditions(dirichlet=(dirichlet_bc,), neumann=neumann_bc) - return bcs - - -f0 = dolfin.as_vector([1.0, 0.0, 0.0]) -s0 = dolfin.as_vector([0.0, 1.0, 0.0]) -n0 = dolfin.as_vector([0.0, 0.0, 1.0]) -microstructure = pulse.Microstructure(f0=f0, s0=s0, n0=n0) -geometry = pulse.Geometry( - mesh=mesh, marker_functions=marker_functions, microstructure=microstructure -) - -active_model = LandModel( - f0=f0, - s0=s0, - n0=n0, - cai=missing_mech.u_mechanics[0], # In this script mech comes before ep, so previous cai is used - mesh=mesh, - eta=0, # Fraction of transverse active tesion for active stress formulation. - # 0 = active only along fiber, 1 = equal forces in all directions - # (default=0.0). - dLambda_tol=1e-12, -) -active_model.t = 0.0 - - -mech_variables = { - "Ta": active_model.Ta_current, - "Zetas": active_model._Zetas, - "Zetaw": active_model._Zetaw, - "lambda": active_model.lmbda, - "XS": active_model._XS, - "XW": active_model._XW, - "TmB": active_model._TmB, - "CaTrpn": active_model._CaTrpn, - "J_TRPN": active_model._J_TRPN, -} - -# Validate mechanics variables to output -for out_mech_var in list(set(out_mech_coord_names) | set(out_mech_var_names)): - assert ( - out_mech_var in mech_variables - ), f"Error: '{out_mech_var}' is not a valid variable name. Check config file" - -material = pulse.HolzapfelOgden( - parameters=material_parameters, - active_model=active_model, - f0=f0, - s0=s0, - n0=n0, -) - - -def compute_function_average_over_mesh(func, mesh): - volume = dolfin.assemble(dolfin.Constant(1.0) * dolfin.dx(domain=mesh)) - return dolfin.assemble(func * dolfin.dx(domain=mesh)) / volume - - -# Collect Boundary Conditions -bcs = create_boundary_conditions( - ffun_bcs, bcs_dirichlet, bcs_neumann, config["bcs"], bcs_expressions -) - -problem = mechanicssolver.MechanicsProblem(geometry, material, bcs) -problem.solve(0.0, 0.0) - -disp_file = Path(outdir / "disp.xdmf") -disp_file.unlink(missing_ok=True) -disp_file.with_suffix(".h5").unlink(missing_ok=True) - -out_ep_files = {} -for out_ep_var in out_ep_var_names: - out_ep_files[out_ep_var] = Path(outdir / f"{out_ep_var}_out_ep.xdmf") - out_ep_files[out_ep_var].unlink(missing_ok=True) - out_ep_files[out_ep_var].with_suffix(".h5").unlink(missing_ok=True) - -out_mech_files = {} -for out_mech_var in out_mech_var_names: - out_mech_files[out_mech_var] = Path(outdir / f"{out_mech_var}_out_mech.xdmf") - out_mech_files[out_mech_var].unlink(missing_ok=True) - out_mech_files[out_mech_var].with_suffix(".h5").unlink(missing_ok=True) - - -# Create arrays for storing values to plot time series for example nodes -out_ep_example_nodes = {} -for out_ep_var in out_ep_coord_names: - out_ep_example_nodes[out_ep_var] = np.zeros(len(t)) - -out_mech_example_nodes = {} -for out_mech_var in out_mech_coord_names: - out_mech_example_nodes[out_mech_var] = np.zeros(len(t)) - -# Create arrays for storing values to plot time series for volume averages -out_ep_volume_average_timeseries = {} -for out_ep_var in out_ep_coord_names: - out_ep_volume_average_timeseries[out_ep_var] = np.zeros(len(t)) - -out_mech_volume_average_timeseries = {} -for out_mech_var in out_mech_coord_names: - out_mech_volume_average_timeseries[out_mech_var] = np.zeros(len(t)) - - -inds = [] # Array with time-steps for which we solve mechanics -j = 0 -timer = dolfin.Timer("solve_loop") -for i, ti in enumerate(t): - print(f"Solving time {ti:.2f} ms") - t_bcs.assign(ti) # Use ti+ dt here instead? - if i % config["sim"]["N"] == 0: - print("Solve mechanics") - active_model.t = ti + config["sim"]["N"] * config["sim"]["dt"] # Addition! - problem.solve(ti, config["sim"]["N"] * config["sim"]["dt"]) - active_model.update_prev() - missing_ep.u_mechanics_int[0].interpolate(active_model._J_TRPN) - missing_ep.interpolate_mechanics_to_ep() - missing_ep.ep_function_to_values() - - for var_nr in range(config["write_point_mech"]["numbers"]): - # Trace variable in coordinate - out_mech_var = config["write_point_mech"][f"{var_nr}"]["name"] - out_mech_example_nodes[out_mech_var][i] = mech_variables[out_mech_var]( - mech_coords[var_nr] - ) - - # Compute volume averages - out_mech_volume_average_timeseries[out_mech_var][i] = ( - compute_function_average_over_mesh(mech_variables[out_mech_var], mesh) - ) - - ep_solver.step((ti, ti + config["sim"]["dt"])) - - # Assign values to ep function - for out_ep_var in list(set(out_ep_var_names) | set(out_ep_coord_names)): - out_ep_funcs[out_ep_var].vector()[:] = ode._values[ep_model["state_index"](out_ep_var)] - - # Store values to plot time series for given coord - for var_nr in range(config["write_point_ep"]["numbers"]): - # Trace variable in coordinate - out_ep_var = config["write_point_ep"][f"{var_nr}"]["name"] - out_ep_example_nodes[out_ep_var][i] = out_ep_funcs[out_ep_var](ep_coords[var_nr]) - # Compute volume averages - out_ep_volume_average_timeseries[out_ep_var][i] = compute_function_average_over_mesh( - out_ep_funcs[out_ep_var], ep_mesh - ) - - if (i + 1) % config["sim"]["N"] == 0: # Extract missing values for next mechanics step - print("update missing") - # Extract missing values for the mechanics step from the ep model (ep function space) - missing_ep_values = mv_ep( - ti + config["sim"]["dt"], - ode._values, - ode.parameters, - missing_ep.values_ep, - ) - # Assign the extracted values as missing_mech for the mech step (ep function space) - for k in range(missing_mech.num_values): - missing_mech.u_ep_int[k].vector()[:] = missing_ep_values[k, :] - - # Interpolate missing variables from ep to mech function space - missing_mech.interpolate_ep_to_mechanics() - missing_mech.mechanics_function_to_values() - - if i % config["sim"]["N"] == 0: - inds.append(i) - print( - active_model.lmbda.vector().get_local().min(), - active_model.lmbda.vector().get_local().max(), - ) - - U, p = problem.state.split(deepcopy=True) - - with dolfin.XDMFFile(disp_file.as_posix()) as file: - file.write_checkpoint(U, "disp", j, dolfin.XDMFFile.Encoding.HDF5, True) - for out_ep_var in out_ep_var_names: - with dolfin.XDMFFile(out_ep_files[out_ep_var].as_posix()) as file: - file.write_checkpoint( - out_ep_funcs[out_ep_var], - out_ep_var, - j, - dolfin.XDMFFile.Encoding.HDF5, - True, - ) - - for out_mech_var in out_mech_var_names: - with dolfin.XDMFFile(out_mech_files[out_mech_var].as_posix()) as file: - file.write_checkpoint( - mech_variables[out_mech_var], - out_mech_var, - j, - dolfin.XDMFFile.Encoding.HDF5, - True, - ) - - j += 1 - -timer.stop() -timings = dolfin.timings( - dolfin.TimingClear.keep, - [dolfin.TimingType.wall, dolfin.TimingType.user, dolfin.TimingType.system], -).str(True) -print(timings) -with open(Path(outdir / "solve_timings.txt"), "w") as f: - f.write(timings) - -# Write averaged results for later analysis -for out_ep_var in out_ep_coord_names: - with open(Path(outdir / f"{out_ep_var}_out_ep_volume_average.txt"), "w") as f: - np.savetxt(f, out_ep_volume_average_timeseries[out_ep_var][inds]) - -for out_mech_var in out_mech_coord_names: - with open(Path(outdir / f"{out_mech_var}_out_mech_volume_average.txt"), "w") as f: - np.savetxt(f, out_mech_volume_average_timeseries[out_mech_var][inds]) - - -# Write point traces for later analysis -for var_nr in range(config["write_point_ep"]["numbers"]): - out_ep_var = config["write_point_ep"][f"{var_nr}"]["name"] - with open( - Path( - outdir - / f"{out_ep_var}_ep_coord{ep_coords[var_nr][0]},{ep_coords[var_nr][1]},{ep_coords[var_nr][2]}.txt".replace( - " ", "" - ) - ), - "w", - ) as f: - np.savetxt(f, out_ep_example_nodes[out_ep_var][inds]) - -for var_nr in range(config["write_point_mech"]["numbers"]): - out_mech_var = config["write_point_mech"][f"{var_nr}"]["name"] - with open( - Path( - outdir - / f"{out_mech_var}_mech_coord{mech_coords[var_nr][0]},{mech_coords[var_nr][1]},{mech_coords[var_nr][2]}.txt" - ), - "w", - ) as f: - np.savetxt(f, out_mech_example_nodes[out_mech_var][inds]) - -print(f"Solved on {100 * len(inds) / len(t)}% of the time steps") -inds = np.array(inds) - -# Plot the results. Currently also output volume averages for selected trace variables -fig, ax = plt.subplots(len(out_ep_coord_names), 1, figsize=(10, 10)) -if len(out_ep_coord_names) == 1: - ax = np.array([ax]) -for i, out_ep_var in enumerate(out_ep_coord_names): - ax[i].plot(t[inds], out_ep_volume_average_timeseries[out_ep_var][inds]) - ax[i].set_title(f"{out_ep_var} volume average") - ax[i].set_xlabel("Time (ms)") -fig.tight_layout() -fig.savefig(Path(outdir / "out_ep_volume_averages.png")) - -fig, ax = plt.subplots(len(out_ep_coord_names), 1, figsize=(10, 10)) -if len(out_ep_coord_names) == 1: - ax = np.array([ax]) -for var_nr in range(config["write_point_ep"]["numbers"]): - out_ep_var = config["write_point_ep"][f"{var_nr}"]["name"] - ax[var_nr].plot(t[inds], out_ep_example_nodes[out_ep_var][inds]) - ax[var_nr].set_title(f"{out_ep_var} in coord {ep_coords[var_nr]}") - ax[var_nr].set_xlabel("Time (ms)") -fig.tight_layout() -fig.savefig(Path(outdir / "out_ep_coord.png")) - -fig, ax = plt.subplots(len(out_mech_coord_names), 1, figsize=(10, 10)) -if len(out_mech_coord_names) == 1: - ax = np.array([ax]) -for i, out_mech_var in enumerate(out_mech_coord_names): - ax[i].plot(t[inds], out_mech_volume_average_timeseries[out_mech_var][inds]) - ax[i].set_title(f"{out_mech_var} volume average") - ax[i].set_xlabel("Time (ms)") -fig.tight_layout() -fig.savefig(Path(outdir / "out_mech_volume_averages.png")) - -fig, ax = plt.subplots(len(out_mech_coord_names), 1, figsize=(10, 10)) -if len(out_mech_coord_names) == 1: - ax = np.array([ax]) - -for var_nr in range(config["write_point_mech"]["numbers"]): - out_mech_var = config["write_point_mech"][f"{var_nr}"]["name"] - ax[var_nr].plot(t[inds], out_mech_example_nodes[out_mech_var][inds]) - ax[var_nr].set_title(f"{out_mech_var} in coord {mech_coords[var_nr]}") - ax[var_nr].set_xlabel("Time (ms)") -fig.tight_layout() -fig.savefig(Path(outdir / "out_mech_coord.png")) diff --git a/demos/create_geometry_with_surface_markers.py b/demos/create_geometry_with_surface_markers.py deleted file mode 100644 index f22dfa3..0000000 --- a/demos/create_geometry_with_surface_markers.py +++ /dev/null @@ -1,93 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -""" -Created on Fri Jun 14 14:47:22 2024 - -@author: lenamyklebust -""" - -import numpy as np -import dolfin -from pathlib import Path -from typing import Dict -from typing import Optional -from typing import Tuple - -dx = 0.5 -Lx = 0.5 # 20 # mm -Ly = 1 # 7 # mm -Lz = 2 # mm - - -def setup_geometry(dx, Lx=Lx, Ly=Ly, Lz=Lz): - mesh = dolfin.BoxMesh( - dolfin.MPI.comm_world, - dolfin.Point(0.0, 0.0, 0.0), - dolfin.Point(Lx, Ly, Lz), - int(np.rint((Lx / dx))), - int(np.rint((Ly / dx))), - int(np.rint((Lz / dx))), - ) - return mesh - - -def default_markers() -> Dict[str, Tuple[int, int]]: - return { - "X0": 1, - "X1": 2, - "Y0": 3, - "Y1": 4, - "Z0": 5, - "Z1": 6, - } - - -def assign_surface_markers( - mesh: dolfin.Mesh, - lx: float, - ly: float, - lz: float, - markers: Optional[Dict[str, Tuple[int, int]]] = None, -) -> dolfin.MeshFunction: - if markers is None: - markers = default_markers() - - # Define domains for each surface - x0 = dolfin.CompiledSubDomain("near(x[0], 0) && on_boundary") - x1 = dolfin.CompiledSubDomain("near(x[0], lx) && on_boundary", lx=lx) - y0 = dolfin.CompiledSubDomain("near(x[1], 0) && on_boundary") - y1 = dolfin.CompiledSubDomain("near(x[1], ly) && on_boundary", ly=ly) - z0 = dolfin.CompiledSubDomain("near(x[2], 0) && on_boundary") - z1 = dolfin.CompiledSubDomain("near(x[2], lz) && on_boundary", lz=lz) - - ffun = dolfin.MeshFunction("size_t", mesh, mesh.topology().dim() - 1) - ffun.set_all(0) - - x0.mark(ffun, markers["X0"]) - x1.mark(ffun, markers["X1"]) - - y0.mark(ffun, markers["Y0"]) - y1.mark(ffun, markers["Y1"]) - - z0.mark(ffun, markers["Z0"]) - z1.mark(ffun, markers["Z1"]) - return ffun, markers - - -mesh = setup_geometry(dx=dx, Lx=Lx, Ly=Ly, Lz=Lz) -mesh_file = Path(f"mesh_mech_{dx}dx_{Lx}Lx_{Ly}Ly_{Lz}Lz.xdmf") -mesh_file.unlink(missing_ok=True) -mesh_file.with_suffix(".h5").unlink(missing_ok=True) - -surface_ffun, surface_markers = assign_surface_markers(mesh, lx=Lx, ly=Ly, lz=Lz) -surface_func_file = Path(f"mesh_mech_{dx}dx_{Lx}Lx_{Ly}Ly_{Lz}Lz_surface_ffun.xdmf") -surface_func_file.unlink(missing_ok=True) -surface_func_file.with_suffix(".h5").unlink(missing_ok=True) - - -print(surface_markers) - -with dolfin.XDMFFile(mesh_file.as_posix()) as file: - file.write(mesh) -with dolfin.XDMFFile(surface_func_file.as_posix()) as xdmf: - xdmf.write(surface_ffun) diff --git a/demos/split-cai/0D/ORdmm_Land.ode b/demos/split-cai/0D/ORdmm_Land.ode deleted file mode 100644 index 2e79499..0000000 --- a/demos/split-cai/0D/ORdmm_Land.ode +++ /dev/null @@ -1,663 +0,0 @@ -# ORd modified by MMora (October-2016) -# Modifications in INa. The original formulation of INa has been -# optimised, according to Passini, in order to look like TT04. -# Modifications: -# 1) mss,hss,jss and hssp -# 2) gNa -# + -# Re-scaled conductances (Dutta et al 2016 CinC) -# + -# -# Land 2017(mechanical model)- Introduced by MMora (Jan2020) -# Tension -# Changes in Cai effect of troponin -# + -# -# Isacs -# -# -# In this version we fix mech.emcoupling=1, -# mode="intact", isacs=0 and celltype = 0 -# -# -# Modifications by Ilse (January 2023) -# Add scaling facotrs for heart failure and drugs - - -parameters("Scales", -scale_IKr = 1.119, -scale_IKs = 1.648, -scale_IK1 = 1.414, -scale_ICaL = 1.018, -scale_INaL = 2.274) - - - -parameters("settings", -celltype=0) - -parameters("extracellular ionic concentrations", -nao=140.0, -cao=1.8, -ko=5.4) - -parameters("physical constants", "mechanics", -R=8314.0, -T=310.0, -F=96485.0) - - -parameters("cell geometry", "mechanics", -L=0.01, -rad=0.0011) - - -expressions("cell geometry", "mechanics") -vcell=1000*3.14*rad*rad*L -Ageo=2*3.14*rad*rad+2*3.14*rad*L -Acap=2*Ageo -vmyo=0.68*vcell -vnsr=0.0552*vcell -vjsr=0.0048*vcell -vss=0.02*vcell - - -# Scaling factors for heart failure -parameters("scaling factors HF", -scale_HF_CaMKa=1.0, -scale_HF_Jrel_inf=1.0, -scale_HF_Jleak=1.0, -scale_HF_Jup=1.0, -scale_HF_GNaL=1.0, -scale_HF_GK1=1.0, -scale_HF_thL=1.0, -scale_HF_Gto=1.0, -scale_HF_Gncx=1.0, -scale_HF_Pnak=1.0) - -# Scaling factors for drug effects -parameters("scaling factors drug", -scale_drug_INa=1.0, -scale_drug_INaL=1.0, -scale_drug_Ito=1.0, -scale_drug_ICaL=1.0, -scale_drug_IKr=1.0, -scale_drug_IKs=1.0, -scale_drug_IK1=1.0, -scale_drug_IKb=1.0, -scale_drug_INab=1.0, -scale_drug_ICab=1.0, -scale_drug_IpCa=1.0, -scale_drug_Isacns=1.0, -scale_drug_Isack=1.0) - -######## EP states -states("CaMKt", -CaMKt=0 -) - -states("I_Na", -m=0, -hf=1, -hs=1, -j=1, -hsp=1, -jp=1) - -states("INaL", -mL=0, -hL=1, -hLp=1) - -states("Ito", -a=0, -iF=1, -iS=1, -ap=0, -iFp=1, -iSp=1) - -states("ICaL ICaNa ICaK", -d=0, -ff=1, -fs=1, -fcaf=1, -fcas=1, -jca=1, -nca=0, -ffp=1, -fcafp=1) - - -states("IKr", -xrf=0, -xrs=0) - - -states("IKs", -xs1=0, -xs2=0, -xk1=1) - -states("membrane potential", -v=-87) - - -states("ryanodione receptor", -Jrelnp=0, -Jrelp=0) - - -states("intracellular concentrations", -cai=0.0001, -nai=7, -nass=7, -ki=145, -kss=145, -cass=0.0001, -cansr=1.2, -cajsr=1.2) - -states("mechanics", -XS=0, -XW=0, -CaTrpn=0.0001, -TmB=1, -Zetas=0, -Zetaw=0, -Cd=0) - - -############################## - -parameters("CaMK constants", -KmCaMK=0.15, -aCaMK=0.05, -bCaMK=0.00068, -CaMKo=0.05, -KmCaM=0.0015) - -expressions("CaMKt") -CaMKb=CaMKo*(1.0-CaMKt)/(1.0+KmCaM/cass) -CaMKa=(CaMKb+CaMKt)*scale_HF_CaMKa -dCaMKt_dt=aCaMK*CaMKb*(CaMKb+CaMKt)-bCaMK*CaMKt - -parameters("reversal potentials", -PKNa=0.01833) - -expressions("reversal potentials") -ENa=(R*T/F)*log(nao/nai) -EK=(R*T/F)*log(ko/ki) -EKs=(R*T/F)*log((ko+PKNa*nao)/(ki+PKNa*nai)) -vffrt=v*F*F/(R*T) -vfrt=v*F/(R*T) - -parameters("I_Na", -Ahf=0.99, -GNa=31) - -expressions("I_Na") -mss=1.0/(1.0+exp((-(v+39.57+9.4))/7.5)) -tm=1.0/(6.765*exp((v+11.64)/34.77)+8.552*exp(-(v+77.42)/5.955)) -dm_dt=(mss-m)/tm -hss=1.0/(1+exp((v+78.5)/6.22)) -thf=1.0/(1.432e-5*exp(-(v+1.196)/6.285)+6.149*exp((v+0.5096)/20.27)) -ths=1.0/(0.009794*exp(-(v+17.95)/28.05)+0.3343*exp((v+5.730)/56.66)) -Ahs=1.0-Ahf -dhf_dt=(hss-hf)/thf -dhs_dt=(hss-hs)/ths -h=Ahf*hf+Ahs*hs -jss=hss -tj=2.038+1.0/(0.02136*exp(-(v+100.6)/8.281)+0.3052*exp((v+0.9941)/38.45)) -dj_dt=(jss-j)/tj -hssp=1.0/(1+exp((v+78.5+6.2)/6.22)) -thsp=3.0*ths -dhsp_dt=(hssp-hsp)/thsp -hp=Ahf*hf+Ahs*hsp -tjp=1.46*tj -djp_dt=(jss-jp)/tjp -fINap=(1.0/(1.0+KmCaMK/CaMKa)) -INa=GNa*scale_drug_INa*(v-ENa)*m**3.0*((1.0-fINap)*h*j+fINap*hp*jp) - -parameters("INaL", -thL=200.0) - -expressions("INaL") -mLss=1.0/(1.0+exp((-(v+42.85))/5.264)) -tmL=tm -dmL_dt=(mLss-mL)/tmL -hLss=1.0/(1.0+exp((v+87.61)/7.488)) -dhL_dt=(hLss-hL)/(thL*scale_HF_thL) -hLssp=1.0/(1.0+exp((v+93.81)/7.488)) -thLp=3.0*thL*scale_HF_thL -dhLp_dt=(hLssp-hLp)/thLp -GNaL=0.0075*scale_INaL*scale_drug_INaL*scale_HF_GNaL -fINaLp=(1.0/(1.0+KmCaMK/CaMKa)) -INaL=GNaL*(v-ENa)*mL*((1.0-fINaLp)*hL+fINaLp*hLp) - -parameters("Ito", -delta_epi=1.0, -Gto=0.02) - -expressions("Ito") -ass=1.0/(1.0+exp((-(v-14.34))/14.82)) -ta=1.0515/(1.0/(1.2089*(1.0+exp(-(v-18.4099)/29.3814)))+3.5/(1.0+exp((v+100.0)/29.3814))) -da_dt=(ass-a)/ta -iss=1.0/(1.0+exp((v+43.94)/5.711)) -tiF=4.562+1/(0.3933*exp((-(v+100.0))/100.0)+0.08004*exp((v+50.0)/16.59)) * delta_epi -tiS=23.62+1/(0.001416*exp((-(v+96.52))/59.05)+1.780e-8*exp((v+114.1)/8.079)) * delta_epi -AiF=1.0/(1.0+exp((v-213.6)/151.2)) -AiS=1.0-AiF -diF_dt=(iss-iF)/tiF -diS_dt=(iss-iS)/tiS -i=AiF*iF+AiS*iS -assp=1.0/(1.0+exp((-(v-24.34))/14.82)) -dap_dt=(assp-ap)/ta -dti_develop=1.354+1.0e-4/(exp((v-167.4)/15.89)+exp(-(v-12.23)/0.2154)) -dti_recover=1.0-0.5/(1.0+exp((v+70.0)/20.0)) -tiFp=dti_develop*dti_recover*tiF -tiSp=dti_develop*dti_recover*tiS -diFp_dt=(iss-iFp)/tiFp -diSp_dt=(iss-iSp)/tiSp -ip=AiF*iFp+AiS*iSp -fItop=(1.0/(1.0+KmCaMK/CaMKa)) -Ito=Gto*scale_drug_Ito*scale_HF_Gto*(v-EK)*((1.0-fItop)*a*i+fItop*ap*ip) - - -parameters("ICaL ICaNa ICaK", -Aff=0.6, -tjca=75.0, -Kmn=0.002, -k2n=1000.0, -zca=2.0) - -expressions("ICaL ICaNa ICaK") -dss=1.0/(1.0+exp((-(v+3.940))/4.230)) -td=0.6+1.0/(exp(-0.05*(v+6.0))+exp(0.09*(v+14.0))) -dd_dt=(dss-d)/td -fss=1.0/(1.0+exp((v+19.58)/3.696)) -tff=7.0+1.0/(0.0045*exp(-(v+20.0)/10.0)+0.0045*exp((v+20.0)/10.0)) -tfs=1000.0+1.0/(0.000035*exp(-(v+5.0)/4.0)+0.000035*exp((v+5.0)/6.0)) -Afs=1.0-Aff -dff_dt=(fss-ff)/tff -dfs_dt=(fss-fs)/tfs -f=Aff*ff+Afs*fs -fcass=fss -tfcaf=7.0+1.0/(0.04*exp(-(v-4.0)/7.0)+0.04*exp((v-4.0)/7.0)) -tfcas=100.0+1.0/(0.00012*exp(-v/3.0)+0.00012*exp(v/7.0)) -Afcaf=0.3+0.6/(1.0+exp((v-10.0)/10.0)) -Afcas=1.0-Afcaf -dfcaf_dt=(fcass-fcaf)/tfcaf -dfcas_dt=(fcass-fcas)/tfcas -fca=Afcaf*fcaf+Afcas*fcas -djca_dt=(fcass-jca)/tjca -tffp=2.5*tff -dffp_dt=(fss-ffp)/tffp -fp=Aff*ffp+Afs*fs -tfcafp=2.5*tfcaf -dfcafp_dt=(fcass-fcafp)/tfcafp -fcap=Afcaf*fcafp+Afcas*fcas -km2n=jca*1.0 -anca=1.0/(k2n/km2n+(1.0+Kmn/cass)**4.0) -dnca_dt=anca*k2n-nca*km2n -PhiCaL=4.0*vffrt*(cass*exp(2.0*vfrt)-0.341*cao)/(exp(2.0*vfrt)-1.0) -PhiCaNa=1.0*vffrt*(0.75*nass*exp(1.0*vfrt)-0.75*nao)/(exp(1.0*vfrt)-1.0) -PhiCaK=1.0*vffrt*(0.75*kss*exp(1.0*vfrt)-0.75*ko)/(exp(1.0*vfrt)-1.0) -PCa=0.0001*scale_ICaL*scale_drug_ICaL -PCap=1.1*PCa -PCaNa=0.00125*PCa -PCaK=3.574e-4*PCa -PCaNap=0.00125*PCap -PCaKp=3.574e-4*PCap -fICaLp=(1.0/(1.0+KmCaMK/CaMKa)) -ICaL=(1.0-fICaLp)*PCa*PhiCaL*d*(f*(1.0-nca)+jca*fca*nca)+fICaLp*PCap*PhiCaL*d*(fp*(1.0-nca)+jca*fcap*nca) -ICaNa=(1.0-fICaLp)*PCaNa*PhiCaNa*d*(f*(1.0-nca)+jca*fca*nca)+fICaLp*PCaNap*PhiCaNa*d*(fp*(1.0-nca)+jca*fcap*nca) -ICaK=(1.0-fICaLp)*PCaK*PhiCaK*d*(f*(1.0-nca)+jca*fca*nca)+fICaLp*PCaKp*PhiCaK*d*(fp*(1.0-nca)+jca*fcap*nca) - -expressions("IKr") -xrss=1.0/(1.0+exp((-(v+8.337))/6.789)) -txrf=12.98+1.0/(0.3652*exp((v-31.66)/3.869)+4.123e-5*exp((-(v-47.78))/20.38)) -txrs=1.865+1.0/(0.06629*exp((v-34.70)/7.355)+1.128e-5*exp((-(v-29.74))/25.94)) -Axrf=1.0/(1.0+exp((v+54.81)/38.21)) -Axrs=1.0-Axrf -dxrf_dt=(xrss-xrf)/txrf -dxrs_dt=(xrss-xrs)/txrs -xr=Axrf*xrf+Axrs*xrs -rkr=1.0/(1.0+exp((v+55.0)/75.0))*1.0/(1.0+exp((v-10.0)/30.0)) -GKr=0.046*scale_IKr*scale_drug_IKr -IKr=GKr*sqrt(ko/5.4)*xr*rkr*(v-EK) - -expressions("IKs") -xs1ss=1.0/(1.0+exp((-(v+11.60))/8.932)) -txs1=817.3+1.0/(2.326e-4*exp((v+48.28)/17.80)+0.001292*exp((-(v+210.0))/230.0)) -dxs1_dt=(xs1ss-xs1)/txs1 -xs2ss=xs1ss -txs2=1.0/(0.01*exp((v-50.0)/20.0)+0.0193*exp((-(v+66.54))/31.0)) -dxs2_dt=(xs2ss-xs2)/txs2 -KsCa=1.0+0.6/(1.0+(3.8e-5/cai)**1.4) -GKs=0.0034*scale_IKs*scale_drug_IKs -IKs=GKs*KsCa*xs1*xs2*(v-EKs) -xk1ss=1.0/(1.0+exp(-(v+2.5538*ko+144.59)/(1.5692*ko+3.8115))) -txk1=122.2/(exp((-(v+127.2))/20.36)+exp((v+236.8)/69.33)) -dxk1_dt=(xk1ss-xk1)/txk1 -rk1=1.0/(1.0+exp((v+105.8-2.6*ko)/9.493)) -GK1=0.1908*scale_IK1*scale_drug_IK1*scale_HF_GK1 -IK1=GK1*sqrt(ko)*rk1*xk1*(v-EK) - - -parameters("INaCa_i", -kna1=15.0, -kna2=5.0, -kna3=88.12, -kasymm=12.5, -wna=6.0e4, -wca=6.0e4, -wnaca=5.0e3, -kcaon=1.5e6, -kcaoff=5.0e3, -qna=0.5224, -qca=0.1670, -KmCaAct=150.0e-6, -Gncx=0.0008) - -expressions("INaCa_i") -hca=exp((qca*v*F)/(R*T)) -hna=exp((qna*v*F)/(R*T)) -h1_i=1+nai/kna3*(1+hna) -h2_i=(nai*hna)/(kna3*h1_i) -h3_i=1.0/h1_i -h4_i=1.0+nai/kna1*(1+nai/kna2) -h5_i=nai*nai/(h4_i*kna1*kna2) -h6_i=1.0/h4_i -h7_i=1.0+nao/kna3*(1.0+1.0/hna) -h8_i=nao/(kna3*hna*h7_i) -h9_i=1.0/h7_i -h10_i=kasymm+1.0+nao/kna1*(1.0+nao/kna2) -h11_i=nao*nao/(h10_i*kna1*kna2) -h12_i=1.0/h10_i -k1_i=h12_i*cao*kcaon -k2_i=kcaoff -k3p_i=h9_i*wca -k3pp_i=h8_i*wnaca -k3_i=k3p_i+k3pp_i -k4p_i=h3_i*wca/hca -k4pp_i=h2_i*wnaca -k4_i=k4p_i+k4pp_i -k5_i=kcaoff -k6_i=h6_i*cai*kcaon -k7_i=h5_i*h2_i*wna -k8_i=h8_i*h11_i*wna -x1_i=k2_i*k4_i*(k7_i+k6_i)+k5_i*k7_i*(k2_i+k3_i) -x2_i=k1_i*k7_i*(k4_i+k5_i)+k4_i*k6_i*(k1_i+k8_i) -x3_i=k1_i*k3_i*(k7_i+k6_i)+k8_i*k6_i*(k2_i+k3_i) -x4_i=k2_i*k8_i*(k4_i+k5_i)+k3_i*k5_i*(k1_i+k8_i) -E1_i=x1_i/(x1_i+x2_i+x3_i+x4_i) -E2_i=x2_i/(x1_i+x2_i+x3_i+x4_i) -E3_i=x3_i/(x1_i+x2_i+x3_i+x4_i) -E4_i=x4_i/(x1_i+x2_i+x3_i+x4_i) -allo_i=1.0/(1.0+(KmCaAct/cai)**2.0) -zna=1.0 -JncxNa_i=3.0*(E4_i*k7_i-E1_i*k8_i)+E3_i*k4pp_i-E2_i*k3pp_i -JncxCa_i=E2_i*k2_i-E1_i*k1_i -INaCa_i=0.8*Gncx*scale_HF_Gncx*allo_i*(zna*JncxNa_i+zca*JncxCa_i) - -expressions("INaCa_ss") -h1=1+nass/kna3*(1+hna) -h2=(nass*hna)/(kna3*h1) -h3=1.0/h1 -h4=1.0+nass/kna1*(1+nass/kna2) -h5=nass*nass/(h4*kna1*kna2) -h6=1.0/h4 -h7=1.0+nao/kna3*(1.0+1.0/hna) -h8=nao/(kna3*hna*h7) -h9=1.0/h7 -h10=kasymm+1.0+nao/kna1*(1+nao/kna2) -h11=nao*nao/(h10*kna1*kna2) -h12=1.0/h10 -k1=h12*cao*kcaon -k2=kcaoff -k3p_ss=h9*wca -k3pp=h8*wnaca -k3=k3p_ss+k3pp -k4p_ss=h3*wca/hca -k4pp=h2*wnaca -k4=k4p_ss+k4pp -k5=kcaoff -k6=h6*cass*kcaon -k7=h5*h2*wna -k8=h8*h11*wna -x1_ss=k2*k4*(k7+k6)+k5*k7*(k2+k3) -x2_ss=k1*k7*(k4+k5)+k4*k6*(k1+k8) -x3_ss=k1*k3*(k7+k6)+k8*k6*(k2+k3) -x4_ss=k2*k8*(k4+k5)+k3*k5*(k1+k8) -E1_ss=x1_ss/(x1_ss+x2_ss+x3_ss+x4_ss) -E2_ss=x2_ss/(x1_ss+x2_ss+x3_ss+x4_ss) -E3_ss=x3_ss/(x1_ss+x2_ss+x3_ss+x4_ss) -E4_ss=x4_ss/(x1_ss+x2_ss+x3_ss+x4_ss) -allo_ss=1.0/(1.0+(KmCaAct/cass)**2.0) -JncxNa_ss=3.0*(E4_ss*k7-E1_ss*k8)+E3_ss*k4pp-E2_ss*k3pp -JncxCa_ss=E2_ss*k2-E1_ss*k1 -INaCa_ss=0.2*Gncx*scale_HF_Gncx*allo_ss*(zna*JncxNa_ss+zca*JncxCa_ss) - - -parameters("INaK", -k1p=949.5, -k1m=182.4, -k2p=687.2, -k2m=39.4, -k3p=1899.0, -k3m=79300.0, -k4p=639.0, -k4m=40.0, -Knai0=9.073, -Knao0=27.78, -delta=-0.1550, -Kki=0.5, -Kko=0.3582, -MgADP=0.05, -MgATP=9.8, -Kmgatp=1.698e-7, -H=1.0e-7, -eP=4.2, -Khp=1.698e-7, -Knap=224.0, -Kxkur=292.0, -zk=1.0, -Pnak=30) - -expressions("INaK") -Knai=Knai0*exp((delta*v*F)/(3.0*R*T)) -Knao=Knao0*exp(((1.0-delta)*v*F)/(3.0*R*T)) -P=eP/(1.0+H/Khp+nai/Knap+ki/Kxkur) -a1=(k1p*(nai/Knai)**3.0)/((1.0+nai/Knai)**3.0+(1.0+ki/Kki)**2.0-1.0) -b1=k1m*MgADP -a2=k2p -b2=(k2m*(nao/Knao)**3.0)/((1.0+nao/Knao)**3.0+(1.0+ko/Kko)**2.0-1.0) -a3=(k3p*(ko/Kko)**2.0)/((1.0+nao/Knao)**3.0+(1.0+ko/Kko)**2.0-1.0) -b3=(k3m*P*H)/(1.0+MgATP/Kmgatp) -a4=(k4p*MgATP/Kmgatp)/(1.0+MgATP/Kmgatp) -b4=(k4m*(ki/Kki)**2.0)/((1.0+nai/Knai)**3.0+(1.0+ki/Kki)**2.0-1.0) -x1=a4*a1*a2+b2*b4*b3+a2*b4*b3+b3*a1*a2 -x2=b2*b1*b4+a1*a2*a3+a3*b1*b4+a2*a3*b4 -x3=a2*a3*a4+b3*b2*b1+b2*b1*a4+a3*a4*b1 -x4=b4*b3*b2+a3*a4*a1+b2*a4*a1+b3*b2*a1 -E1=x1/(x1+x2+x3+x4) -E2=x2/(x1+x2+x3+x4) -E3=x3/(x1+x2+x3+x4) -E4=x4/(x1+x2+x3+x4) -JnakNa=3.0*(E1*a3-E2*b3) -JnakK=2.0*(E4*b1-E3*a1) -INaK=Pnak*scale_HF_Pnak*(zna*JnakNa+zk*JnakK) - - -parameters("IKb", -GKb=0.003) - -expressions("IKb") -xkb=1.0/(1.0+exp(-(v-14.48)/18.34)) -IKb=GKb*scale_drug_IKb*xkb*(v-EK) - -parameters("INab", -PNab=3.75e-10) - -expressions("INab") -INab=PNab*scale_drug_INab*vffrt*(nai*exp(vfrt)-nao)/(exp(vfrt)-1.0) - - -parameters("ICab", -PCab=2.5e-8) - -expressions("ICab") -ICab=PCab*scale_drug_ICab*4.0*vffrt*(cai*exp(2.0*vfrt)-0.341*cao)/(exp(2.0*vfrt)-1.0) - -parameters("IpCa", -GpCa=0.0005) - -expressions("IpCa") -IpCa=GpCa*scale_drug_IpCa*cai/(0.0005+cai) - - -parameters("Isac (Pueyo)--> ns + k", -Gsac_ns=0.006, -Esac_ns=-10, -lambda_max=1.1, -Gsac_k=0.2882*800/210) - -expressions("Isac (Pueyo)--> ns + k") -Isac_P_ns=0 -Isac_P_k=0 - - -parameters("Istim", -amp=-80.0, -duration=0.5) - -expressions("Istim") -Istim = Conditional(Le(t, duration), amp, 0) - -expressions("membrane potential") -dv_dt=-(INa+INaL+Ito+ICaL+ICaNa+ICaK+IKr+IKs+IK1+INaCa_i+INaCa_ss+INaK+INab+IKb+IpCa+ICab+Istim+Isac_P_ns+Isac_P_k) - -expressions("diffusion fluxes") -JdiffNa=(nass-nai)/2.0 -JdiffK=(kss-ki)/2.0 -Jdiff=(cass-cai)/0.2 - -parameters("ryanodione receptor", -bt=4.75) - -expressions("ryanodione receptor") -a_rel=0.5*bt -Jrel_inf=a_rel*(-ICaL)/(1.0+(1.5*scale_HF_Jrel_inf/cajsr)**8.0) -tau_rel_tmp=bt/(1.0+0.0123/cajsr) -tau_rel=Conditional(Lt(tau_rel_tmp, 0.001), 0.001, tau_rel_tmp) -dJrelnp_dt=(Jrel_inf-Jrelnp)/tau_rel -btp=1.25*bt -a_relp=0.5*btp -Jrel_infp=a_relp*(-ICaL)/(1.0+(1.5*scale_HF_Jrel_inf/cajsr)**8.0) -tau_relp_tmp=btp/(1.0+0.0123/cajsr) -tau_relp=Conditional(Lt(tau_relp_tmp, 0.001), 0.001, tau_relp_tmp) -dJrelp_dt=(Jrel_infp-Jrelp)/tau_relp -fJrelp=(1.0/(1.0+KmCaMK/CaMKa)) -Jrel=(1.0-fJrelp)*Jrelnp+fJrelp*Jrelp - -expressions("calcium buffers") -Jupnp=0.004375*cai/(cai+0.00092) -Jupp=2.75*0.004375*cai/(cai+0.00092-0.00017) -fJupp=(1.0/(1.0+KmCaMK/CaMKa)) -Jleak=0.0039375*cansr*scale_HF_Jleak/15.0 -Jup=(1.0-fJupp)*Jupnp+fJupp*Jupp*scale_HF_Jup-Jleak -Jtr=(cansr-cajsr)/100.0 - -parameters("calcium buffers", "mechanics", -cmdnmax=0.05, -kmcmdn=0.00238, -trpnmax=0.07, -kmtrpn=0.0005, -BSRmax=0.047, -KmBSR=0.00087, -BSLmax=1.124, -KmBSL=0.0087, -csqnmax=10.0, -kmcsqn=0.8) - -expressions("intracellular concentrations") -dnai_dt=-(INa+INaL+3.0*INaCa_i+3.0*INaK+INab+Isac_P_ns/3)*Acap/(F*vmyo)+JdiffNa*vss/vmyo -dnass_dt=-(ICaNa+3.0*INaCa_ss)*Acap/(F*vss)-JdiffNa -dki_dt=-(Ito+IKr+IKs+IK1+IKb+Isac_P_k+Isac_P_ns/3+Istim-2.0*INaK)*Acap/(F*vmyo)+JdiffK*vss/vmyo -dkss_dt=-(ICaK)*Acap/(F*vss)-JdiffK -Bcass=1.0/(1.0+BSRmax*KmBSR/(KmBSR+cass)**2.0+BSLmax*KmBSL/(KmBSL+cass)**2.0) -dcass_dt=Bcass*(-(ICaL-2.0*INaCa_ss)*Acap/(2.0*F*vss)+Jrel*vjsr/vss-Jdiff) -dcansr_dt=Jup-Jtr*vjsr/vnsr -Bcajsr=1.0/(1.0+csqnmax*kmcsqn/(kmcsqn+cajsr)**2.0) -dcajsr_dt=Bcajsr*(Jtr-Jrel) -Bcai=1.0/(1.0+cmdnmax*kmcmdn/(kmcmdn+cai)**2.0) -dcai_dt=Bcai*(-(IpCa+ICab-2.0*INaCa_i+Isac_P_ns/3)*Acap/(2.0*F*vmyo)-Jup*vnsr/vmyo+Jdiff*vss/vmyo - J_TRPN) - - -parameters("mechanics", -emcoupling=1, -lmbda=1, -dLambda=0, -mode=1, -isacs=0, -calib=1, -ktrpn = 0.1, -ntrpn = 2, -Trpn50 = 0.35, -rw = 0.5, -rs = 0.25, -gammas = 0.0085, -gammaw = 0.615, -phi = 2.23, -Tot_A = 25, -Beta0 = 2.3, -Beta1 = -2.4, -cat50_ref = 0.805, -scale_HF_cat50_ref=1.0, -Tref = 120, -kuw = 0.182, -kws = 0.012, -ku=0.04, -ntm=2.4, -p_a = 2.1, -p_b = 9.1, -p_k = 7, -etal = 200, -etas = 20) - -expressions("mechanics") -XS_max = Conditional(Gt(XS, 0), XS, 0) -XW_max = Conditional(Gt(XW, 0), XW, 0) -CaTrpn_max = Conditional(Gt(CaTrpn, 0), CaTrpn, 0) -kwu = kuw*(1/rw-1)-kws -ksu = kws*rw*(1/rs-1) -Aw = Tot_A*rs/((1-rs)*rw+rs) -As = Aw -cw = phi*kuw*((1-rs)*(1-rw))/((1-rs)*rw) -cs = phi*kws*((1-rs)*rw)/rs -lambda_min12 = Conditional(Lt(lmbda, 1.2), lmbda, 1.2) -lambda_min087 = Conditional(Lt(lambda_min12, 0.87), lambda_min12, 0.87) -h_lambda_prima = 1+Beta0*(lambda_min12+lambda_min087-1.87) -h_lambda = Conditional(Gt(h_lambda_prima, 0), h_lambda_prima, 0) -XU = (1-TmB)-XS-XW -gammawu = gammaw*abs(Zetaw) -gammasu = gammas*Conditional(Gt(Gt(Zetas,0)*Zetas, Lt(Zetas, -1)*(-Zetas-1)), Gt(Zetas,0)*Zetas, Lt(Zetas, -1)*(-Zetas-1)) -dXS_dt = kws*XW - ksu*XS - gammasu*XS -dXW_dt = kuw*XU - kwu*XW - kws*XW - gammawu*XW -cat50 = (cat50_ref+Beta1*(lambda_min12-1))*scale_HF_cat50_ref -dCaTrpn_dt = ktrpn*(((cai*1000/cat50)**ntrpn)*(1-CaTrpn)-CaTrpn) -kb = ku*Trpn50**ntm/(1-rs-(1-rs)*rw) -dTmB_dt = kb*Conditional(Lt(CaTrpn**(-ntm/2), 100), CaTrpn**(-ntm/2), 100)*XU-ku*CaTrpn**(ntm/2)*TmB -dZetas_dt = As*dLambda - cs*Zetas -dZetaw_dt = Aw*dLambda - cw*Zetaw -Ta = h_lambda*(Tref/rs)*(XS*(Zetas+1) + XW*Zetaw) -C = lambda_min12 - 1 -dCd = C - Cd -eta = Conditional(Lt(dCd, 0), etas, etal) -dCd_dt = p_k * (C - Cd) / eta -Fd = eta * dCd -F1 = (exp( p_b * C) - 1) -Tp = p_a * (F1 + Fd) -Ttot = Ta + Tp -J_TRPN = dCaTrpn_dt*trpnmax diff --git a/demos/split-cai/0D/main.py b/demos/split-cai/0D/main.py deleted file mode 100644 index 76532b7..0000000 --- a/demos/split-cai/0D/main.py +++ /dev/null @@ -1,498 +0,0 @@ -"""Same as 0D but with varying lambda""" - -from pathlib import Path -import gotranx -import numpy as np -import matplotlib.pyplot as plt - - -def twitch(t, tstart=0.05, ca_ampl=-0.2): - tau1 = 0.05 * 1000 - tau2 = 0.110 * 1000 - - ca_diast = 0.0 - - beta = (tau1 / tau2) ** (-1 / (tau1 / tau2 - 1)) - (tau1 / tau2) ** (-1 / (1 - tau2 / tau1)) - ca = np.zeros_like(t) - - ca[t <= tstart] = ca_diast - - ca[t > tstart] = (ca_ampl - ca_diast) / beta * ( - np.exp(-(t[t > tstart] - tstart) / tau1) - np.exp(-(t[t > tstart] - tstart) / tau2) - ) + ca_diast - return ca + 1.0 - - -# Load the model -ode = gotranx.load_ode("ORdmm_Land.ode") - -mechanics_comp = ode.get_component("mechanics") -mechanics_ode = mechanics_comp.to_ode() - -ep_ode = ode - mechanics_comp -ep_file = Path("ORdmm_Land_ep.py") - - -# Generate model code from .ode file -rebuild = False -if not ep_file.is_file() or rebuild: - # Generate code for full model. The full model output is plotted together with the splitting - code = gotranx.cli.gotran2py.get_code( - ode, - scheme=[gotranx.schemes.Scheme.forward_generalized_rush_larsen], - ) - - # Generate code for the electrophysiology model - code_ep = gotranx.cli.gotran2py.get_code( - ep_ode, - scheme=[gotranx.schemes.Scheme.forward_generalized_rush_larsen], - missing_values=mechanics_ode.missing_variables, - ) - - # Generate code for the mechanics model - code_mechanics = gotranx.cli.gotran2py.get_code( - mechanics_ode, - scheme=[gotranx.schemes.Scheme.forward_generalized_rush_larsen], - missing_values=ep_ode.missing_variables, - ) - - # Create ep, mechanics and full model to files: - ep_file.write_text(code_ep) - Path("ORdmm_Land_mechanics.py").write_text(code_mechanics) - Path("ORdmm_Land.py").write_text(code) - - -# Import ep, mechanics and full model -import ORdmm_Land_ep -import ORdmm_Land_mechanics -import ORdmm_Land - -model = ORdmm_Land.__dict__ -ep_model = ORdmm_Land_ep.__dict__ -mechanics_model = ORdmm_Land_mechanics.__dict__ - - -# Set time step to 0.1 ms -dt = 0.1 -# Simulate model for 1000 ms -t = np.arange(0, 700, dt) -fig, ax = plt.subplots() -ax.plot(t, twitch(t)) -ax.set_xlabel("Time (ms)") -ax.set_ylabel("Lambda") -fig.savefig("twitch.png") - -# Get the index of the membrane potential -V_index_ep = ep_model["state_index"]("v") -# Forwared generalized rush larsen scheme for the electrophysiology model -fgr_ep = ep_model["forward_generalized_rush_larsen"] -# Monitor function for the electrophysiology model -mon_ep = ep_model["monitor_values"] -# Missing values function for the electrophysiology model -mv_ep = ep_model["missing_values"] -# Index of the calcium concentration -Ca_index_ep = ep_model["state_index"]("cai") - -# Forwared generalized rush larsen scheme for the mechanics model -fgr_mechanics = mechanics_model["forward_generalized_rush_larsen"] -# Monitor function for the mechanics model -mon_mechanics = mechanics_model["monitor_values"] -# Missing values function for the mechanics model -mv_mechanics = mechanics_model["missing_values"] -# Index of the active tension -Ta_index_mechanics = mechanics_model["monitor_index"]("Ta") - -CaTrpn_index_mechanics = mechanics_model["state_index"]("CaTrpn") -TmB_index_mechanics = mechanics_model["state_index"]("TmB") - -XU_index_mechanics = mechanics_model["monitor_index"]("XU") -J_TRPN_index_mechanics = mechanics_model["monitor_index"]("J_TRPN") -lmbda_index_mechanics = mechanics_model["parameter_index"]("lmbda") -dLambda_index_mechanics = mechanics_model["parameter_index"]("dLambda") -Zetas_index_mechanics = mechanics_model["state_index"]("Zetas") -XS_index_mechanics = mechanics_model["state_index"]("XS") - -CaTrpn_index = model["state_index"]("CaTrpn") -TmB_index = model["state_index"]("TmB") - -# Forwared generalized rush larsen scheme for the full model -fgr = model["forward_generalized_rush_larsen"] -# Monitor function for the full model -mon = model["monitor_values"] -# Index of the active tension for the full model -Ta_index = model["monitor_index"]("Ta") -# Index of the J_TRPN for the full model - -XU_index = model["monitor_index"]("XU") -J_TRPN_index = model["monitor_index"]("J_TRPN") -lmbda_index = model["parameter_index"]("lmbda") -dLambda_index = model["parameter_index"]("dLambda") -XS_index = model["state_index"]("XS") -Zetas_index = model["state_index"]("Zetas") - - -# Tolerances to test for when to perform steps in the mechanics model -tols = [ - 1e-15, - 1e-5, - 5e-5, - 1e-4, - 5e-4, - 1e-3, - 5e-3, - 1e-2, -] -# Colors for the plots -from itertools import cycle - -colors = cycle(["r", "g", "b", "c", "m"]) -linestyles = cycle(["-", "--", "-.", ":"]) - - -# Create arrays to store the results -V_ep = np.zeros(len(t)) -Ca_ep = np.zeros(len(t)) - -CaTrpn_full = np.zeros(len(t)) -TmB_full = np.zeros(len(t)) -XU_full = np.zeros(len(t)) -J_TRPN_full = np.zeros(len(t)) -Ta_full = np.zeros(len(t)) -dLambda_full = np.zeros(len(t)) -XS_full = np.zeros(len(t)) -Zetas_full = np.zeros(len(t)) -lmbda_full = np.zeros(len(t)) - -CaTrpn_mechanics = np.zeros(len(t)) -TmB_mechanics = np.zeros(len(t)) -Ta_mechanics = np.zeros(len(t)) -J_TRPN_mechanics = np.zeros(len(t)) -XU_mechanics = np.zeros(len(t)) -dLambda_mechanics = np.zeros(len(t)) -XS_mechanics = np.zeros(len(t)) -Zetas_mechanics = np.zeros(len(t)) -lmbda_mechanics = np.zeros(len(t)) - - -fig, ax = plt.subplots(9, 2, sharex=True, figsize=(14, 10)) -lines = [] -labels = [] - -for j, (col, ls, tol) in enumerate(zip(colors, linestyles, tols)): - # Get initial values from the EP model - y_ep = ep_model["init_state_values"]() - p_ep = ep_model["init_parameter_values"]() - ep_missing_values = np.zeros(len(ep_ode.missing_variables)) - - # Get initial values from the mechanics model - y_mechanics = mechanics_model["init_state_values"]() - p_mechanics = mechanics_model["init_parameter_values"]() - # mechanics_missing_values = np.zeros(len(mechanics_ode.missing_variables)) - mechanics_missing_values = np.array( - [0.0001] - ) # For cai split, missing variable is cai. Set the initial value instead of setting to zero - - # Get the initial values from the full model - y = model["init_state_values"]() - p = model["init_parameter_values"]() - - # Get the default values of the missing values - # A little bit chicken and egg problem here, but in this specific case we know that - # the mechanics_missing_values is only the calcium concentration, which is a state variable - # and this doesn't require any additional information to be calculated. - mechanics_missing_values[:] = mv_ep(0, y_ep, p_ep, ep_missing_values) - ep_missing_values[:] = mv_mechanics(0, y_mechanics, p_mechanics, mechanics_missing_values) - - # We will store the previous missing values to check for convergence and use for updating - prev_mechanics_missing_values = np.zeros_like(mechanics_missing_values) - prev_mechanics_missing_values[:] = mechanics_missing_values - - inds = [] - count = 1 - max_count = 10 - prev_lmbda = p[lmbda_index] - prev_ti = 0 - for i, ti in enumerate(t): - # Set initial lambda - if ti == 0: - lmbda_ti = twitch(ti) - p[lmbda_index] = lmbda_ti - p_mechanics[lmbda_index_mechanics] = lmbda_ti - dLambda = 0 - p[dLambda_index] = dLambda - p_mechanics[dLambda_index_mechanics] = dLambda - - # Forward step for the full model - y[:] = fgr(y, ti, dt, p) - monitor = mon(ti, y, p) - - J_TRPN_full[i] = monitor[J_TRPN_index] - XU_full[i] = monitor[XU_index] - Ta_full[i] = monitor[Ta_index] - XS_full[i] = y[XS_index] - CaTrpn_full[i] = y[CaTrpn_index] - TmB_full[i] = y[TmB_index] - Zetas_full[i] = y[Zetas_index] - dLambda_full[i] = p[dLambda_index] - lmbda_full[i] = p[lmbda_index] - - # Forward step for the EP model - y_ep[:] = fgr_ep(y_ep, ti, dt, p_ep, ep_missing_values) - V_ep[i] = y_ep[V_index_ep] - Ca_ep[i] = y_ep[Ca_index_ep] - # monitor_ep = mon_ep(ti, y_ep, p_ep, ep_missing_values) #not currently used - - # Update missing values for the mechanics model - mechanics_missing_values[:] = mv_ep( - t, y_ep, p_ep, ep_missing_values - ) # this function just outputs the value of cai straight from y_ep (does not calculate anything) - - # Compute the change in the missing values - change = np.linalg.norm( - mechanics_missing_values - prev_mechanics_missing_values - ) / np.linalg.norm(prev_mechanics_missing_values) - - # Check if the change is small enough to continue to the next time step - if change < tol: - count += 1 - # Very small change to just continue to next time step - if count < max_count: - # Lambda still needs to be updated: - lmbda_ti = twitch(ti + dt) - p[lmbda_index] = lmbda_ti - p_mechanics[lmbda_index_mechanics] = lmbda_ti - dLambda = (lmbda_ti - prev_lmbda) / dt - p[dLambda_index] = dLambda - p_mechanics[dLambda_index_mechanics] = dLambda - prev_ti = ti - prev_lmbda = lmbda_ti - continue - - # Store the index of the time step where we performed a step - inds.append(i) - - # Forward step for the mechanics model - # y_mechanics[:] = fgr_mechanics( - # y_mechanics, ti, count * dt, p_mechanics, mechanics_missing_values - # ) - y_mechanics[:] = fgr_mechanics( - y_mechanics, ti, count * dt, p_mechanics, prev_mechanics_missing_values - ) - - count = 1 - monitor_mechanics = mon_mechanics( - ti, - y_mechanics, - p_mechanics, - mechanics_missing_values, - ) - Ta_mechanics[i] = monitor_mechanics[Ta_index_mechanics] - J_TRPN_mechanics[i] = monitor_mechanics[J_TRPN_index_mechanics] - XU_mechanics[i] = monitor_mechanics[XU_index_mechanics] - dLambda_mechanics[i] = p_mechanics[dLambda_index_mechanics] - Zetas_mechanics[i] = y_mechanics[Zetas_index_mechanics] - XS_mechanics[i] = y_mechanics[XS_index_mechanics] - lmbda_mechanics[i] = p_mechanics[lmbda_index_mechanics] - CaTrpn_mechanics[i] = y_mechanics[CaTrpn_index_mechanics] - TmB_mechanics[i] = y_mechanics[TmB_index_mechanics] - - # Update lambda - # Should be done after all calculations except ep_missing, which is used for next ep step - lmbda_ti = twitch(ti + dt) - p[lmbda_index] = lmbda_ti - p_mechanics[lmbda_index_mechanics] = lmbda_ti - dLambda = (lmbda_ti - prev_lmbda) / dt - p[dLambda_index] = dLambda - p_mechanics[dLambda_index_mechanics] = dLambda - prev_ti = ti - prev_lmbda = lmbda_ti - - # Update missing values for the EP model # J_TRPN for cai split - ep_missing_values[:] = mv_mechanics(t, y_mechanics, p_mechanics, mechanics_missing_values) - - prev_mechanics_missing_values[:] = mechanics_missing_values - - # Plot the results - perc = 100 * len(inds) / len(t) - print(f"Solved on {perc}% of the time steps") - inds = np.array(inds) - - if j == 0: - # Plot the full model with a dashed line only for the first run - (l,) = ax[8, 0].plot(t, Ta_full, color="k", linestyle="--", label="Full") - ax[2, 0].plot(t, J_TRPN_full, color="k", linestyle="--", label="Full") - ax[3, 0].plot(t, CaTrpn_full, color="k", linestyle="--", label="Full") - ax[4, 0].plot(t, TmB_full, color="k", linestyle="--", label="Full") - ax[5, 0].plot(t, XU_full, color="k", linestyle="--", label="Full") - ax[6, 0].plot(t, XS_full, color="k", linestyle="--", label="Full") - ax[7, 0].plot(t, Zetas_full, color="k", linestyle="--", label="Full") - lines.append(l) - labels.append("Full") - - (l,) = ax[0, 0].plot(t, V_ep, color=col, linestyle=ls, label=f"tol={tol}") - lines.append(l) - labels.append(f"tol={tol}, perc={perc:.2f}%") - ax[0, 1].plot( - t, - Ca_ep, - color=col, - linestyle=ls, - # label=f"tol={tol}", - ) - - ax[0, 0].set_ylabel("V (mV)") - ax[0, 1].set_ylabel("Ca (mM)") - - ax[1, 0].plot( - t[inds], - lmbda_mechanics[inds], - color=col, - linestyle=ls, # label=f"tol={tol}" - # marker='.' - ) - - ax[1, 1].plot( - t[inds], - dLambda_mechanics[inds], - color=col, - linestyle=ls, # label=f"tol={tol}" - ) - ax[1, 0].set_ylabel("Lambda \n mech") - ax[1, 1].set_ylabel("dLambda \n mech") - - err_Ta = np.linalg.norm(Ta_full[inds] - Ta_mechanics[inds]) / np.linalg.norm(Ta_mechanics) - - ax[2, 0].plot( - t[inds], - J_TRPN_mechanics[inds], - color=col, - linestyle=ls, # label=f"tol={tol}" - ) - ax[2, 0].set_ylabel("J TRPN \n mech") - - ax[2, 1].plot( - t[inds], - np.around(J_TRPN_full[inds] - J_TRPN_mechanics[inds], 16), # round to float precision - # label=f"err={err_J_TRPN:.2e}, tol={tol}", - color=col, - linestyle=ls, - ) - ax[2, 1].set_ylabel("J TRPN \n mech error") - - ax[3, 0].plot( - t[inds], - CaTrpn_mechanics[inds], - color=col, - linestyle=ls, # label=f"tol={tol}" - # marker='.' - ) - - ax[3, 1].plot( - t[inds], - np.around(CaTrpn_full[inds] - CaTrpn_mechanics[inds], 16), # round to float precision - # label=f"err={err_J_TRPN:.2e}, tol={tol}", - color=col, - linestyle=ls, - # marker='.' - ) - ax[3, 0].set_ylabel("CaTrpn \n mech") - ax[3, 1].set_ylabel("CaTrpn \n mech error") - - ax[4, 0].plot( - t[inds], - TmB_mechanics[inds], - color=col, - linestyle=ls, # label=f"tol={tol}" - ) - ax[4, 0].set_ylabel("TmB mech") - - ax[4, 1].plot( - t[inds], - np.around(TmB_full[inds] - TmB_mechanics[inds], 16), # round to float precision - # label=f"err={err_J_TRPN:.2e}, tol={tol}", - color=col, - linestyle=ls, - ) - ax[4, 1].set_ylabel("TmB \n mech error") - - ax[5, 0].plot( - t[inds], - XU_mechanics[inds], - color=col, - linestyle=ls, # label=f"tol={tol}" - ) - ax[5, 1].plot( - t[inds], - np.around(XU_full[inds] - XU_mechanics[inds], 16), # round to float precision - # label=f"err={err_J_TRPN:.2e}, tol={tol}", - color=col, - linestyle=ls, - ) - ax[5, 0].set_ylabel("XU mech") - ax[5, 1].set_ylabel("XU \n mech error") - - ax[6, 0].plot( - t[inds], - XS_mechanics[inds], - color=col, - linestyle=ls, # label=f"tol={tol}" - ) - ax[6, 1].plot( - t[inds], - np.around(XS_full[inds] - XS_mechanics[inds], 16), # round to float precision - # label=f"err={err_J_TRPN:.2e}, tol={tol}", - color=col, - linestyle=ls, - ) - ax[6, 0].set_ylabel("XS mech") - ax[6, 1].set_ylabel("XS \n mech error") - - ax[7, 0].plot( - t[inds], - Zetas_mechanics[inds], - color=col, - linestyle=ls, # label=f"tol={tol}" - ) - - ax[7, 1].plot( - t[inds], - np.around(Zetas_full[inds] - Zetas_mechanics[inds], 16), # round to float precision - # label=f"err={err_J_TRPN:.2e}, tol={tol}", - color=col, - linestyle=ls, - ) - - ax[7, 0].set_ylabel("Zetas mech") - ax[7, 1].set_ylabel("Zetas\n mech error") - - ax[8, 0].plot( - t[inds], - Ta_mechanics[inds], - color=col, - linestyle=ls, # label=f"tol={tol}" - ) - ax[8, 0].set_ylabel("Ta (kPa)") - - ax[8, 1].plot( - t[inds], - np.around(Ta_full[inds] - Ta_mechanics[inds], 16), # round to float precision - # label=f"tol={tol}, perc={perc}%", - color=col, - linestyle=ls, - ) - ax[8, 1].set_ylabel("Ta error (kPa)") - - ax[8, 0].set_xlabel("Time (ms)") - ax[8, 1].set_xlabel("Time (ms)") - - # for axi in ax.flatten(): - # axi.legend() - - if j == len(tols) - 1: - fig.subplots_adjust(right=0.95) - lgd = fig.legend(lines, labels, loc="center left", bbox_to_anchor=(1.0, 0.5)) - fig.tight_layout() - fig.savefig("V_and_Ta.png", bbox_extra_artists=(lgd,), bbox_inches="tight") - else: - fig.tight_layout() - fig.savefig("V_and_Ta.png") diff --git a/demos/split-cai/0D/main_time_and_Ns.py b/demos/split-cai/0D/main_time_and_Ns.py deleted file mode 100644 index 4e77fd6..0000000 --- a/demos/split-cai/0D/main_time_and_Ns.py +++ /dev/null @@ -1,363 +0,0 @@ -"""Same as 0D but with varying lambda""" - -from pathlib import Path -import gotranx -import numpy as np -import matplotlib.pyplot as plt -import time - -save_traces = False -run_full_model = False - -# Mech step performed every Nth ep step -# Do a set of simulations with various N: -Ns = np.array([1, 2, 4, 6, 8, 10, 20, 50, 100, 200]) - - -def twitch(t, tstart=0.05, ca_ampl=-0.2): - tau1 = 0.05 * 1000 - tau2 = 0.110 * 1000 - - ca_diast = 0.0 - - beta = (tau1 / tau2) ** (-1 / (tau1 / tau2 - 1)) - (tau1 / tau2) ** (-1 / (1 - tau2 / tau1)) - ca = np.zeros_like(t) - - ca[t <= tstart] = ca_diast - - ca[t > tstart] = (ca_ampl - ca_diast) / beta * ( - np.exp(-(t[t > tstart] - tstart) / tau1) - np.exp(-(t[t > tstart] - tstart) / tau2) - ) + ca_diast - return ca + 1.0 - - -# Load the model -ode = gotranx.load_ode("ORdmm_Land.ode") - -mechanics_comp = ode.get_component("mechanics") -mechanics_ode = mechanics_comp.to_ode() - -ep_ode = ode - mechanics_comp -ep_file = Path("ORdmm_Land_ep.py") - - -# Generate model code from .ode file -rebuild = False -if not ep_file.is_file() or rebuild: - # Generate code for full model. - code = gotranx.cli.gotran2py.get_code( - ode, - scheme=[gotranx.schemes.Scheme.forward_generalized_rush_larsen], - ) - - # Generate code for the electrophysiology model - code_ep = gotranx.cli.gotran2py.get_code( - ep_ode, - scheme=[gotranx.schemes.Scheme.forward_generalized_rush_larsen], - missing_values=mechanics_ode.missing_variables, - ) - - # Generate code for the mechanics model - code_mechanics = gotranx.cli.gotran2py.get_code( - mechanics_ode, - scheme=[gotranx.schemes.Scheme.forward_generalized_rush_larsen], - missing_values=ep_ode.missing_variables, - ) - - # Create ep, mechanics and full model to files: - ep_file.write_text(code_ep) - Path("ORdmm_Land_mechanics.py").write_text(code_mechanics) - Path("ORdmm_Land.py").write_text(code) - - -# Import ep, mechanics and full model -import ORdmm_Land_ep -import ORdmm_Land_mechanics -import ORdmm_Land - -model = ORdmm_Land.__dict__ -ep_model = ORdmm_Land_ep.__dict__ -mechanics_model = ORdmm_Land_mechanics.__dict__ - - -# Set time step -dt = 0.05 -simdur = 10 # Simulation duration -t = np.arange(0, simdur, dt) -fig, ax = plt.subplots() -ax.plot(t, twitch(t)) -ax.set_xlabel("Time (ms)") -ax.set_ylabel("Lambda") -fig.savefig("twitch.png") - -# Get the index of the membrane potential -V_index_ep = ep_model["state_index"]("v") -# Forwared generalized rush larsen scheme for the electrophysiology model -fgr_ep = ep_model["forward_generalized_rush_larsen"] -# Monitor function for the electrophysiology model -mon_ep = ep_model["monitor_values"] -# Missing values function for the electrophysiology model -mv_ep = ep_model["missing_values"] -# Index of the calcium concentration -Ca_index_ep = ep_model["state_index"]("cai") - -# Forwared generalized rush larsen scheme for the mechanics model -fgr_mechanics = mechanics_model["forward_generalized_rush_larsen"] -# Monitor function for the mechanics model -mon_mechanics = mechanics_model["monitor_values"] -# Missing values function for the mechanics model -mv_mechanics = mechanics_model["missing_values"] -# Index of the active tension -Ta_index_mechanics = mechanics_model["monitor_index"]("Ta") - -CaTrpn_index_mechanics = mechanics_model["state_index"]("CaTrpn") -TmB_index_mechanics = mechanics_model["state_index"]("TmB") - -XU_index_mechanics = mechanics_model["monitor_index"]("XU") -J_TRPN_index_mechanics = mechanics_model["monitor_index"]("J_TRPN") -lmbda_index_mechanics = mechanics_model["parameter_index"]("lmbda") -dLambda_index_mechanics = mechanics_model["parameter_index"]("dLambda") -Zetas_index_mechanics = mechanics_model["state_index"]("Zetas") -XS_index_mechanics = mechanics_model["state_index"]("XS") - -Ca_index = model["state_index"]("cai") -V_index = model["state_index"]("v") -CaTrpn_index = model["state_index"]("CaTrpn") -TmB_index = model["state_index"]("TmB") - -# Forwared generalized rush larsen scheme for the full model -fgr = model["forward_generalized_rush_larsen"] -# Monitor function for the full model -mon = model["monitor_values"] -# Index of the active tension for the full model -Ta_index = model["monitor_index"]("Ta") -# Index of the J_TRPN for the full model - -XU_index = model["monitor_index"]("XU") -J_TRPN_index = model["monitor_index"]("J_TRPN") -lmbda_index = model["parameter_index"]("lmbda") -dLambda_index = model["parameter_index"]("dLambda") -XS_index = model["state_index"]("XS") -Zetas_index = model["state_index"]("Zetas") - -# Create arrays to store the results -V_ep = np.zeros(len(t)) -Ca_ep = np.zeros(len(t)) - -if run_full_model: - Ca_full = np.zeros(len(t)) - V_full = np.zeros(len(t)) - CaTrpn_full = np.zeros(len(t)) - TmB_full = np.zeros(len(t)) - XU_full = np.zeros(len(t)) - J_TRPN_full = np.zeros(len(t)) - Ta_full = np.zeros(len(t)) - dLambda_full = np.zeros(len(t)) - XS_full = np.zeros(len(t)) - Zetas_full = np.zeros(len(t)) - lmbda_full = np.zeros(len(t)) - -CaTrpn_mechanics = np.zeros(len(t)) -TmB_mechanics = np.zeros(len(t)) -Ta_mechanics = np.zeros(len(t)) -J_TRPN_mechanics = np.zeros(len(t)) -XU_mechanics = np.zeros(len(t)) -dLambda_mechanics = np.zeros(len(t)) -XS_mechanics = np.zeros(len(t)) -Zetas_mechanics = np.zeros(len(t)) -lmbda_mechanics = np.zeros(len(t)) - - -for N in Ns: - timing_init = time.perf_counter() - # Get initial values from the EP model - y_ep = ep_model["init_state_values"]() - p_ep = ep_model["init_parameter_values"]() - ep_missing_values = np.zeros(len(ep_ode.missing_variables)) - - # Get initial values from the mechanics model - y_mechanics = mechanics_model["init_state_values"]() - p_mechanics = mechanics_model["init_parameter_values"]() - # mechanics_missing_values = np.zeros(len(mechanics_ode.missing_variables)) - mechanics_missing_values = np.array( - [0.0001] - ) # For cai split, missing variable is cai. Set the initial value instead of setting to zero - - # Get the initial values from the full model - y = model["init_state_values"]() - p = model["init_parameter_values"]() # Used in lambda update - - # Get the default values of the missing values - # A little bit chicken and egg problem here, but in this specific case we know that - # the mechanics_missing_values is only the calcium concentration, which is a state variable - # and this doesn't require any additional information to be calculated. - mechanics_missing_values[:] = mv_ep(0, y_ep, p_ep, ep_missing_values) - ep_missing_values[:] = mv_mechanics(0, y_mechanics, p_mechanics, mechanics_missing_values) - - # We will store the previous missing values to check for convergence and use for updating - prev_mechanics_missing_values = np.zeros_like(mechanics_missing_values) - prev_mechanics_missing_values[:] = mechanics_missing_values - - inds = [] - count = 1 - max_count = 10 - prev_lmbda = p[lmbda_index] - prev_ti = 0 - - timings_solveloop = [] - timings_ep_steps = [] - timings_mech_steps = [] - for i, ti in enumerate(t): - timing_loopstart = time.perf_counter() - # Set initial lambda - if ti == 0: - lmbda_ti = twitch(ti) - p[lmbda_index] = lmbda_ti - p_mechanics[lmbda_index_mechanics] = lmbda_ti - dLambda = 0 - p[dLambda_index] = dLambda - p_mechanics[dLambda_index_mechanics] = dLambda - - if run_full_model: - # Forward step for the full model - y[:] = fgr(y, ti, dt, p) - monitor = mon(ti, y, p) - V_full[i] = y[V_index] - Ca_full[i] = y[Ca_index] - J_TRPN_full[i] = monitor[J_TRPN_index] - XU_full[i] = monitor[XU_index] - Ta_full[i] = monitor[Ta_index] - XS_full[i] = y[XS_index] - CaTrpn_full[i] = y[CaTrpn_index] - TmB_full[i] = y[TmB_index] - Zetas_full[i] = y[Zetas_index] - dLambda_full[i] = p[dLambda_index] - lmbda_full[i] = p[lmbda_index] - - timing_ep_start = time.perf_counter() - # Forward step for the EP model - y_ep[:] = fgr_ep(y_ep, ti, dt, p_ep, ep_missing_values) - V_ep[i] = y_ep[V_index_ep] - Ca_ep[i] = y_ep[Ca_index_ep] - timing_ep_end = time.perf_counter() - timings_ep_steps.append(timing_ep_end - timing_ep_start) - - # Update missing values for the mechanics model - mechanics_missing_values[:] = mv_ep( - t, y_ep, p_ep, ep_missing_values - ) # this function just outputs the value of cai straight from y_ep (does not calculate anything) - - if i % N != 0: - count += 1 - # Lambda still needs to be updated: - lmbda_ti = twitch(ti + dt) - p[lmbda_index] = lmbda_ti - p_mechanics[lmbda_index_mechanics] = lmbda_ti - dLambda = (lmbda_ti - prev_lmbda) / dt - p[dLambda_index] = dLambda - p_mechanics[dLambda_index_mechanics] = dLambda - prev_ti = ti - prev_lmbda = lmbda_ti - timings_solveloop.append(time.perf_counter() - timing_loopstart) - continue - - # Store the index of the time step where we performed a step - inds.append(i) - - timing_mech_start = time.perf_counter() - # Forward step for the mechanics model - # y_mechanics[:] = fgr_mechanics( - # y_mechanics, ti, count * dt, p_mechanics, mechanics_missing_values - # ) - # For consistency with other models: - y_mechanics[:] = fgr_mechanics( - y_mechanics, ti, count * dt, p_mechanics, prev_mechanics_missing_values - ) - - count = 1 - monitor_mechanics = mon_mechanics( - ti, - y_mechanics, - p_mechanics, - mechanics_missing_values, - ) - Ta_mechanics[i] = monitor_mechanics[Ta_index_mechanics] - J_TRPN_mechanics[i] = monitor_mechanics[J_TRPN_index_mechanics] - XU_mechanics[i] = monitor_mechanics[XU_index_mechanics] - dLambda_mechanics[i] = p_mechanics[dLambda_index_mechanics] - Zetas_mechanics[i] = y_mechanics[Zetas_index_mechanics] - XS_mechanics[i] = y_mechanics[XS_index_mechanics] - lmbda_mechanics[i] = p_mechanics[lmbda_index_mechanics] - CaTrpn_mechanics[i] = y_mechanics[CaTrpn_index_mechanics] - TmB_mechanics[i] = y_mechanics[TmB_index_mechanics] - - timing_mech_end = time.perf_counter() - timings_mech_steps.append(timing_mech_end - timing_mech_start) - - # Update lambda - # Should be done after all calculations except ep_missing, which is used for next ep step - lmbda_ti = twitch(ti + dt) - p[lmbda_index] = lmbda_ti - p_mechanics[lmbda_index_mechanics] = lmbda_ti - dLambda = (lmbda_ti - prev_lmbda) / dt - p[dLambda_index] = dLambda - p_mechanics[dLambda_index_mechanics] = dLambda - prev_ti = ti - prev_lmbda = lmbda_ti - - # Update missing values for the EP model # J_TRPN for cai split - ep_missing_values[:] = mv_mechanics(t, y_mechanics, p_mechanics, mechanics_missing_values) - - prev_mechanics_missing_values[:] = mechanics_missing_values - - timings_solveloop.append(time.perf_counter() - timing_loopstart) - - # Plot the results - perc = 100 * len(inds) / len(t) - print(f"Solved on {perc}% of the time steps") - inds = np.array(inds) - timing_total = time.perf_counter() - timing_init - - with open(f"timings_N{N}", "w") as f: - f.write("Init time\n") - f.write(f"{timing_init}\n") - f.write("Loop total times\n") - np.savetxt(f, timings_solveloop) - f.write("Ep steps times\n") - np.savetxt(f, timings_ep_steps) - f.write("Mech steps times\n") - np.savetxt(f, timings_mech_steps) - f.write("Total time\n") - f.write(f"{timing_total}\n") - - if save_traces: - with open(f"V_ep_N{N}.txt", "w") as f: - np.savetxt(f, V_ep[inds]) - with open(f"Ta_mech_N{N}.txt", "w") as f: - np.savetxt(f, Ta_mechanics[inds]) - with open(f"Ca_ep_N{N}.txt", "w") as f: - np.savetxt(f, Ca_ep[inds]) - with open(f"CaTrpn_mech_N{N}.txt", "w") as f: - np.savetxt(f, CaTrpn_mechanics[inds]) - with open(f"J_TRPN_mech_N{N}.txt", "w") as f: - np.savetxt(f, J_TRPN_mechanics[inds]) - with open(f"XS_mech_N{N}.txt", "w") as f: - np.savetxt(f, XS_mechanics[inds]) - with open(f"Zetas_mech_N{N}.txt", "w") as f: - np.savetxt(f, Zetas_mechanics[inds]) - - if run_full_model: - with open("V_full.txt", "w") as f: - np.savetxt(f, V_full) - with open("Ta_full.txt", "w") as f: - np.savetxt(f, Ta_full) - with open("Ca_full.txt", "w") as f: - np.savetxt(f, Ca_full) - with open("CaTrpn_full.txt", "w") as f: - np.savetxt(f, CaTrpn_full) - with open("J_TRPN_full.txt", "w") as f: - np.savetxt(f, J_TRPN_full) - with open("XS_full.txt", "w") as f: - np.savetxt(f, XS_full) - with open("Zetas_full.txt", "w") as f: - np.savetxt(f, Zetas_full) diff --git a/demos/split-cai/0D_ToRORd/ToRORd_dynCl_endo_caisplit.ode b/demos/split-cai/0D_ToRORd/ToRORd_dynCl_endo_caisplit.ode deleted file mode 100644 index bd24bc1..0000000 --- a/demos/split-cai/0D_ToRORd/ToRORd_dynCl_endo_caisplit.ode +++ /dev/null @@ -1,715 +0,0 @@ -states("IKr", -C1=ScalarParam(0.9982511, unit="1", description=""), -C2=ScalarParam( 7.93602000000000023e-4, unit="1", description=""), -C3=ScalarParam( 6.53214300000000045e-4, unit="1", description=""), -I_=ScalarParam( 9.80408300000000003e-6, unit="1", description=""), -O_=ScalarParam( 2.92244900000000025e-4, unit="1", description="") -) - -states("CaMK", -CaMKt=ScalarParam( 1.09502599999999999e-2, unit="mM", description="") -) - -states("ryr", -Jrel_np=ScalarParam( 1.80824799999999996e-22, unit="mM/ms", description=""), -Jrel_p=ScalarParam( 4.35860800000000030e-21, unit="mM/ms", description="") -) - -states("Ito", -a=ScalarParam( 8.89925900000000051e-4, unit="1", description=""), -ap=ScalarParam( 4.53416500000000005e-4, unit="1", description=""), -iF=ScalarParam(0.9996716, unit="1", description=""), -iFp=ScalarParam(0.9996716, unit="1", description=""), -iS=ScalarParam(0.5988908, unit="1", description=""), -iSp=ScalarParam(0.6620692, unit="1", description="") -) - -states("intracellular_ions", -cajsr=ScalarParam(1.525693, unit="mM", description=""), -cansr=ScalarParam(1.528001, unit="mM", description=""), -cass=ScalarParam( 6.49734100000000044e-5, unit="mM", description=""), -cli=ScalarParam(29.20698, unit="mM", description=""), -clss=ScalarParam(29.20696, unit="mM", description=""), -ki=ScalarParam(147.7115, unit="mM", description=""), -kss=ScalarParam(147.7114, unit="mM", description=""), -nai=ScalarParam(12.39736, unit="mM", description=""), -nass=ScalarParam(12.3977, unit="mM", description="") -) - -states("intracellular_ions", -cai=0.0001 -) - -states("ICaL", -d=ScalarParam( 1.58884100000000000e-31, unit="1", description=""), -fcaf=ScalarParam(1, unit="1", description=""), -fcafp=ScalarParam(1, unit="1", description=""), -fcas=ScalarParam(0.9999014, unit="1", description=""), -ff_=ScalarParam(1, unit="1", description=""), -ffp=ScalarParam(1, unit="1", description=""), -fs=ScalarParam(0.9401791, unit="1", description=""), -jca=ScalarParam(0.9999846, unit="1", description=""), -nca_i=ScalarParam( 8.32600900000000053e-4, unit="1", description=""), -nca_ss=ScalarParam( 4.89937800000000024e-4, unit="1", description="") -) - -states("INa", -h=ScalarParam(0.8473267, unit="1", description=""), -hp=ScalarParam(0.7018454, unit="1", description=""), -j=ScalarParam(0.8471657, unit="1", description=""), -jp=ScalarParam(0.8469014, unit="1", description=""), -m=ScalarParam( 6.51715400000000005e-4, unit="1", description="") -) - -states("INaL", -hL=ScalarParam(0.5566017, unit="1", description=""), -hLp=ScalarParam(0.3115491, unit="1", description=""), -mL=ScalarParam( 1.35120299999999988e-4, unit="1", description="") -) - -states("membrane", -v=ScalarParam(-89.74808, unit="mV", description="") -) - -states("IKs", -xs1=ScalarParam(0.243959, unit="1", description=""), -xs2=ScalarParam( 1.58616700000000009e-4, unit="1", description="") -) - -parameters("I_katp", -A_atp=ScalarParam(2.0, unit="mM", description=""), -K_atp=ScalarParam(0.25, unit="mM", description=""), -K_o_n=ScalarParam(5.0, unit="mM", description=""), -fkatp=ScalarParam(0.0, unit="1", description=""), -gkatp=ScalarParam(4.3195, unit="mS/uF", description="") -) - -parameters("ICaL", -Aff=ScalarParam(0.6, unit="1", description=""), -ICaL_fractionSS=ScalarParam(0.8, unit="1", description=""), -Kmn=ScalarParam(0.002, unit="mM", description=""), -PCa_b=ScalarParam(8.3757e-05, unit="1", description=""), -dielConstant=ScalarParam(74.0, unit="1/K", description=""), -k2n=ScalarParam(500.0, unit="mS/uF", description=""), -offset=ScalarParam(0.0, unit="ms", description=""), -tjca=ScalarParam(72.5, unit="ms", description=""), -vShift=ScalarParam(0.0, unit="mV", description="") -) - -parameters("intracellular_ions","mechanics", -BSLmax=ScalarParam(1.124, unit="mM", description=""), -BSRmax=ScalarParam(0.047, unit="mM", description=""), -KmBSL=ScalarParam(0.0087, unit="mM", description=""), -KmBSR=ScalarParam(0.00087, unit="mM", description=""), -cmdnmax_b=ScalarParam(0.05, unit="mM", description=""), -csqnmax=ScalarParam(10.0, unit="mM", description=""), -kmcmdn=ScalarParam(0.00238, unit="mM", description=""), -kmcsqn=ScalarParam(0.8, unit="mM", description=""), -kmtrpn=ScalarParam(0.0005, unit="mM", description=""), -trpnmax=ScalarParam(0.07, unit="mM", description="") -) - -parameters("CaMK", -CaMKo=ScalarParam(0.05, unit="1", description=""), -KmCaM=ScalarParam(0.0015, unit="mM", description=""), -KmCaMK=ScalarParam(0.15, unit="mM", description=""), -aCaMK=ScalarParam(0.05, unit="1/mM/ms", description=""), -bCaMK=ScalarParam(0.00068, unit="mS/uF", description="") -) - -parameters("Ito", -EKshift=ScalarParam(0.0, unit="mV", description=""), -Gto_b=ScalarParam(0.16, unit="mS/uF", description="") -) - -parameters("physical_constants","mechanics", -F=ScalarParam(96485.0, unit="C/mol", description=""), -R=ScalarParam(8314.0, unit="mJ/mol/K", description=""), -T=ScalarParam(310.0, unit="K", description=""), -zca=ScalarParam(2.0, unit="1", description=""), -zcl=ScalarParam(-1.0, unit="1", description=""), -zk=ScalarParam(1.0, unit="1", description=""), -zna=ScalarParam(1.0, unit="1", description="") -) - -parameters("ICl", -Fjunc=ScalarParam(1.0, unit="1", description=""), -GClCa=ScalarParam(0.2843, unit="mS/uF", description=""), -GClb=ScalarParam(0.00198, unit="mS/uF", description=""), -KdClCa=ScalarParam(0.1, unit="mM", description="") -) - -parameters("IK1", -GK1_b=ScalarParam(0.6992, unit="mS/uF", description="") -) - -parameters("IKb", -GKb_b=ScalarParam(0.0189, unit="mS/uF", description="") -) - -parameters("IKr", -GKr_b=ScalarParam(0.0321, unit="mS/uF", description=""), -alpha_1=ScalarParam(0.154375, unit="mS/uF", description=""), -beta_1=ScalarParam(0.1911, unit="mS/uF", description="") -) - -parameters("IKs", -GKs_b=ScalarParam(0.0011, unit="mS/uF", description="") -) - -parameters("INa", -GNa=ScalarParam(11.7802, unit="mS/uF", description="") -) - -parameters("INaL", -GNaL_b=ScalarParam(0.0279, unit="mS/uF", description=""), -thL=ScalarParam(200.0, unit="ms", description="") -) - -parameters("INaCa", -Gncx_b=ScalarParam(0.0034, unit="mS/uF", description=""), -INaCa_fractionSS=ScalarParam(0.35, unit="1", description=""), -KmCaAct=ScalarParam(0.00015, unit="mM", description=""), -kasymm=ScalarParam(12.5, unit="1", description=""), -kcaoff=ScalarParam(5000.0, unit="mS/uF", description=""), -kcaon=ScalarParam(1500000.0, unit="mS/uF", description=""), -kna1=ScalarParam(15.0, unit="mS/uF", description=""), -kna2=ScalarParam(5.0, unit="mS/uF", description=""), -kna3=ScalarParam(88.12, unit="mS/uF", description=""), -qca=ScalarParam(0.167, unit="1", description=""), -qna=ScalarParam(0.5224, unit="1", description=""), -wca=ScalarParam(60000.0, unit="1", description=""), -wna=ScalarParam(60000.0, unit="1", description=""), -wnaca=ScalarParam(5000.0, unit="1", description="") -) - -parameters("IpCa", -GpCa=ScalarParam(0.0005, unit="mS/uF", description=""), -KmCap=ScalarParam(0.0005, unit="mM", description="") -) - -parameters("INaK", -H=ScalarParam(1e-07, unit="mM", description=""), -Khp=ScalarParam(1.698e-07, unit="mM", description=""), -Kki=ScalarParam(0.5, unit="mS/uF", description=""), -Kko=ScalarParam(0.3582, unit="mS/uF", description=""), -Kmgatp=ScalarParam(1.698e-07, unit="mM", description=""), -Knai0=ScalarParam(9.073, unit="mM", description=""), -Knao0=ScalarParam(27.78, unit="mM", description=""), -Knap=ScalarParam(224.0, unit="mM", description=""), -Kxkur=ScalarParam(292.0, unit="mM", description=""), -MgADP=ScalarParam(0.05, unit="mM", description=""), -MgATP=ScalarParam(9.8, unit="mM", description=""), -Pnak_b=ScalarParam(15.4509, unit="mS/uF", description=""), -delta=ScalarParam(-0.155, unit="mV", description=""), -eP=ScalarParam(4.2, unit="1", description=""), -k1m=ScalarParam(182.4, unit="mS/uF", description=""), -k1p=ScalarParam(949.5, unit="mS/uF", description=""), -k2m=ScalarParam(39.4, unit="mS/uF", description=""), -k2p=ScalarParam(687.2, unit="mS/uF", description=""), -k3m=ScalarParam(79300.0, unit="mS/uF", description=""), -k3p=ScalarParam(1899.0, unit="mS/uF", description=""), -k4m=ScalarParam(40.0, unit="mS/uF", description=""), -k4p=ScalarParam(639.0, unit="mS/uF", description="") -) - -parameters("ryr", -Jrel_b=ScalarParam(1.5378, unit="1", description=""), -bt=ScalarParam(4.75, unit="ms", description=""), -cajsr_half=ScalarParam(1.7, unit="mM", description="") -) - -parameters("SERCA", -Jup_b=ScalarParam(1.0, unit="1", description="") -) - -parameters("cell_geometry","mechanics", -L=ScalarParam(0.01, unit="cm", description=""), -rad_=ScalarParam(0.0011, unit="cm", description="") -) - -parameters("ICab", -PCab=ScalarParam(5.9194e-08, unit="mS/uF", description="") -) - -parameters("reversal_potentials", -PKNa=ScalarParam(0.01833, unit="1", description="") -) - -parameters("INab", -PNab=ScalarParam(1.9239e-09, unit="mS/uF", description="") -) - -parameters("extracellular", -cao=ScalarParam(1.8, unit="mM", description=""), -clo=ScalarParam(150.0, unit="mM", description=""), -ko=ScalarParam(5.0, unit="mM", description=""), -nao=ScalarParam(140.0, unit="mM", description="") -) - -parameters("environment", -celltype=ScalarParam(0.0, unit="1", description="") -) - -parameters("membrane", -i_Stim_Amplitude=ScalarParam(-53.0, unit="A/F", description=""), -i_Stim_End=ScalarParam(1e+17, unit="ms", description=""), -i_Stim_Period=ScalarParam(1000.0, unit="ms", description=""), -i_Stim_PulseDuration=ScalarParam(1.0, unit="ms", description=""), -i_Stim_Start=ScalarParam(0.0, unit="ms", description="") -) - -parameters("diff", -tauCa=ScalarParam(0.2, unit="ms", description=""), -tauCl=ScalarParam(2.0, unit="ms", description=""), -tauK=ScalarParam(2.0, unit="ms", description=""), -tauNa=ScalarParam(2.0, unit="ms", description="") -) - -expressions("cell_geometry", "mechanics") -Acap = 2.0*Ageo # cm**2 -Ageo = L*((2.0*3.14)*rad_) + rad_*((2.0*3.14)*rad_) # cm**2 -vcell = L*(rad_*((1000.0*3.14)*rad_)) # uL -vjsr = 0.0048*vcell # uL -vmyo = 0.68*vcell # uL -vnsr = 0.0552*vcell # uL -vss = 0.02*vcell # uL - -expressions("ICaL") -Afcaf = 0.3 + 0.6/(exp((v - 1*10.0)/10.0) + 1.0) -Afcas = 1.0 - Afcaf -Afs = 1.0 - Aff -ICaK = ICaK_i + ICaK_ss # A/F -ICaK_i = (1.0 - ICaL_fractionSS)*((d*(PhiCaK_i*(PCaK*(1.0 - fICaLp))))*(f*(1.0 - nca_i) + nca_i*(fca*jca)) + (d*(PhiCaK_i*(PCaKp*fICaLp)))*(fp*(1.0 - nca_i) + nca_i*(fcap*jca))) # A/F -ICaK_ss = ICaL_fractionSS*((d*(PhiCaK_ss*(PCaK*(1.0 - fICaLp))))*(f*(1.0 - nca_ss) + nca_ss*(fca*jca)) + (d*(PhiCaK_ss*(PCaKp*fICaLp)))*(fp*(1.0 - nca_ss) + nca_ss*(fcap*jca))) # A/F -ICaL_ICaL = ICaL_i + ICaL_ss # A/F -ICaL_i = (1.0 - ICaL_fractionSS)*((d*(PhiCaL_i*(PCa*(1.0 - fICaLp))))*(f*(1.0 - nca_i) + nca_i*(fca*jca)) + (d*(PhiCaL_i*(PCap*fICaLp)))*(fp*(1.0 - nca_i) + nca_i*(fcap*jca))) # A/F -ICaL_ss = ICaL_fractionSS*((d*(PhiCaL_ss*(PCa*(1.0 - fICaLp))))*(f*(1.0 - nca_ss) + nca_ss*(fca*jca)) + (d*(PhiCaL_ss*(PCap*fICaLp)))*(fp*(1.0 - nca_ss) + nca_ss*(fcap*jca))) # A/F -ICaNa = ICaNa_i + ICaNa_ss # A/F -ICaNa_i = (1.0 - ICaL_fractionSS)*((d*(PhiCaNa_i*(PCaNa*(1.0 - fICaLp))))*(f*(1.0 - nca_i) + nca_i*(fca*jca)) + (d*(PhiCaNa_i*(PCaNap*fICaLp)))*(fp*(1.0 - nca_i) + nca_i*(fcap*jca))) # A/F -ICaNa_ss = ICaL_fractionSS*((d*(PhiCaNa_ss*(PCaNa*(1.0 - fICaLp))))*(f*(1.0 - nca_ss) + nca_ss*(fca*jca)) + (d*(PhiCaNa_ss*(PCaNap*fICaLp)))*(fp*(1.0 - nca_ss) + nca_ss*(fcap*jca))) # A/F -Ii = (0.5*(4.0*cai + (cli + (ki + nai))))/1000.0 -Io = (0.5*(4.0*cao + (clo + (ko + nao))))/1000.0 -Iss = (0.5*(4.0*cass + (clss + (kss + nass))))/1000.0 -PCa = Conditional(Eq(celltype, 1.0), 1.2*PCa_b, Conditional(Eq(celltype, 2.0), 2.0*PCa_b, PCa_b)) -PCaK = 0.0003574*PCa -PCaKp = 0.0003574*PCap -PCaNa = 0.00125*PCa -PCaNap = 0.00125*PCap -PCap = 1.1*PCa -PhiCaK_i = ((1.0*vffrt)*(-gamma_ko*ko + (gamma_ki*ki)*exp(1.0*vfrt)))/(exp(1.0*vfrt) - 1*1.0) -PhiCaK_ss = ((1.0*vffrt)*(-gamma_ko*ko + (gamma_kss*kss)*exp(1.0*vfrt)))/(exp(1.0*vfrt) - 1*1.0) -PhiCaL_i = ((4.0*vffrt)*(-cao*gamma_cao + (cai*gamma_cai)*exp(2.0*vfrt)))/(exp(2.0*vfrt) - 1*1.0) -PhiCaL_ss = ((4.0*vffrt)*(-cao*gamma_cao + (cass*gamma_cass)*exp(2.0*vfrt)))/(exp(2.0*vfrt) - 1*1.0) -PhiCaNa_i = ((1.0*vffrt)*(-gamma_nao*nao + (gamma_nai*nai)*exp(1.0*vfrt)))/(exp(1.0*vfrt) - 1*1.0) -PhiCaNa_ss = ((1.0*vffrt)*(-gamma_nao*nao + (gamma_nass*nass)*exp(1.0*vfrt)))/(exp(1.0*vfrt) - 1*1.0) -anca_i = 1.0/(k2n/km2n + (Kmn/cai + 1.0)**4.0) -anca_ss = 1.0/(k2n/km2n + (Kmn/cass + 1.0)**4.0) -constA = 1820000.0/(T*dielConstant)**1.5 -dss = Conditional(Ge(v, 31.4978), 1.0, 1.0763*exp(-1.007*exp(-0.0829*v))) -f = Aff*ff_ + Afs*fs -fICaLp = 1.0/(1.0 + KmCaMK/CaMKa) -fca = Afcaf*fcaf + Afcas*fcas -fcap = Afcaf*fcafp + Afcas*fcas -fcass = fss -fp = Aff*ffp + Afs*fs -fss = 1.0/(exp((v + 19.58)/3.696) + 1.0) -gamma_cai = exp((-constA*4.0)*(sqrt(Ii)/(sqrt(Ii) + 1.0) - 0.3*Ii)) -gamma_cao = exp((-constA*4.0)*(sqrt(Io)/(sqrt(Io) + 1.0) - 0.3*Io)) -gamma_cass = exp((-constA*4.0)*(sqrt(Iss)/(sqrt(Iss) + 1.0) - 0.3*Iss)) -gamma_ki = exp((-constA*1.0)*(sqrt(Ii)/(sqrt(Ii) + 1.0) - 0.3*Ii)) -gamma_ko = exp((-constA*1.0)*(sqrt(Io)/(sqrt(Io) + 1.0) - 0.3*Io)) -gamma_kss = exp((-constA*1.0)*(sqrt(Iss)/(sqrt(Iss) + 1.0) - 0.3*Iss)) -gamma_nai = exp((-constA*1.0)*(sqrt(Ii)/(sqrt(Ii) + 1.0) - 0.3*Ii)) -gamma_nao = exp((-constA*1.0)*(sqrt(Io)/(sqrt(Io) + 1.0) - 0.3*Io)) -gamma_nass = exp((-constA*1.0)*(sqrt(Iss)/(sqrt(Iss) + 1.0) - 0.3*Iss)) -jcass = 1.0/(exp((v + 18.08)/2.7916) + 1.0) -km2n = jca*1.0 # mS/uF -td = (offset + 0.6) + 1.0/(exp((-1*0.05)*((v + vShift) + 6.0)) + exp(0.09*((v + vShift) + 14.0))) # ms -tfcaf = 7.0 + 1.0/(0.04*exp((-(v - 1*4.0))/7.0) + 0.04*exp((v - 1*4.0)/7.0)) # ms -tfcafp = 2.5*tfcaf # ms -tfcas = 100.0 + 1.0/(0.00012*exp((-v)/3.0) + 0.00012*exp(v/7.0)) # ms -tff = 7.0 + 1.0/(0.0045*exp((-(v + 20.0))/10.0) + 0.0045*exp((v + 20.0)/10.0)) # ms -tffp = 2.5*tff # ms -tfs = 1000.0 + 1.0/(3.5e-5*exp((-(v + 5.0))/4.0) + 3.5e-5*exp((v + 5.0)/6.0)) # ms -dd_dt = (-d + dss)/td -dfcaf_dt = (-fcaf + fcass)/tfcaf -dfcafp_dt = (-fcafp + fcass)/tfcafp -dfcas_dt = (-fcas + fcass)/tfcas -dff__dt = (-ff_ + fss)/tff -dffp_dt = (-ffp + fss)/tffp -dfs_dt = (-fs + fss)/tfs -djca_dt = (-jca + jcass)/tjca -dnca_i_dt = anca_i*k2n - km2n*nca_i -dnca_ss_dt = anca_ss*k2n - km2n*nca_ss - -expressions("Ito") -AiF = 1.0/(exp(((EKshift + v) - 1*213.6)/151.2) + 1.0) -AiS = 1.0 - AiF -Gto = Conditional(Or(Eq(celltype, 1.0), Eq(celltype, 2.0)), 2.0*Gto_b, Gto_b) # mS/uF -Ito_Ito = (Gto*(-EK + v))*(i*(a*(1.0 - fItop)) + ip*(ap*fItop)) # A/F -ass = 1.0/(exp((-((EKshift + v) - 1*14.34))/14.82) + 1.0) -assp = 1.0/(exp((-((EKshift + v) - 1*24.34))/14.82) + 1.0) -delta_epi = Conditional(Eq(celltype, 1.0), 1.0 - 0.95/(exp(((EKshift + v) + 70.0)/5.0) + 1.0), 1.0) -dti_develop = 1.354 + 0.0001/(exp((-((EKshift + v) - 1*12.23))/0.2154) + exp(((EKshift + v) - 1*167.4)/15.89)) -dti_recover = 1.0 - 0.5/(exp(((EKshift + v) + 70.0)/20.0) + 1.0) -fItop = 1.0/(1.0 + KmCaMK/CaMKa) -i = AiF*iF + AiS*iS -ip = AiF*iFp + AiS*iSp -iss = 1.0/(exp(((EKshift + v) + 43.94)/5.711) + 1.0) -ta = 1.0515/(1.0/((1.2089*(exp((-((EKshift + v) - 1*18.4099))/29.3814) + 1.0))) + 3.5/(exp(((EKshift + v) + 100.0)/29.3814) + 1.0)) # ms -tiF = delta_epi*tiF_b # ms -tiF_b = 4.562 + 1.0/(0.3933*exp((-((EKshift + v) + 100.0))/100.0) + 0.08004*exp(((EKshift + v) + 50.0)/16.59)) # ms -tiFp = tiF*(dti_develop*dti_recover) # ms -tiS = delta_epi*tiS_b # ms -tiS_b = 23.62 + 1.0/(0.001416*exp((-((EKshift + v) + 96.52))/59.05) + 1.78e-8*exp(((EKshift + v) + 114.1)/8.079)) # ms -tiSp = tiS*(dti_develop*dti_recover) # ms -da_dt = (-a + ass)/ta -dap_dt = (-ap + assp)/ta -diF_dt = (-iF + iss)/tiF -diFp_dt = (-iFp + iss)/tiFp -diS_dt = (-iS + iss)/tiS -diSp_dt = (-iSp + iss)/tiSp - -expressions("intracellular_ions") -Bcajsr = 1.0/((csqnmax*kmcsqn)/((cajsr + kmcsqn)**2.0) + 1.0) -Bcass = 1.0/((BSLmax*KmBSL)/((KmBSL + cass)**2.0) + ((BSRmax*KmBSR)/((KmBSR + cass)**2.0) + 1.0)) -cmdnmax = Conditional(Eq(celltype, 1.0), 1.3*cmdnmax_b, cmdnmax_b) # mM -dcajsr_dt = Bcajsr*(-Jrel + Jtr) # mM -dcansr_dt = Jup - Jtr*vjsr/vnsr # mM -dcass_dt = Bcass*(-Jdiff + ((Acap*(-(ICaL_ss - 2.0*INaCa_ss)))/(((2.0*F)*vss)) + (Jrel*vjsr)/vss)) # mM -dcli_dt = (Acap*(IClCa_sl + IClb))/((F*vmyo)) + (JdiffCl*vss)/vmyo # mM -dclss_dt = -JdiffCl + (Acap*IClCa_junc)/((F*vss)) # mM -dki_dt = (Acap*(-(ICaK_i + (-2.0*INaK_INaK + (Istim + (I_katp_I_katp + (IKb_IKb + (IK1_IK1 + (IKs_IKs + (IKr_IKr + Ito_Ito))))))))))/((F*vmyo)) + (JdiffK*vss)/vmyo # mM -dkss_dt = -JdiffK + (Acap*(-ICaK_ss))/((F*vss)) # mM -dnai_dt = (Acap*(-(INab_INab + (3.0*INaK_INaK + (ICaNa_i + (3.0*INaCa_i + (INaL_INaL + INa_INa)))))))/((F*vmyo)) + (JdiffNa*vss)/vmyo # mM -dnass_dt = -JdiffNa + (Acap*(-(ICaNa_ss + 3.0*INaCa_ss)))/((F*vss)) # mM -Bcai=1.0/(1.0+cmdnmax*kmcmdn/(kmcmdn+cai)**2.0) -dcai_dt=Bcai*(-(IpCa_IpCa+ICab_ICab-2.0*INaCa_i/3)*Acap/(2.0*F*vmyo)-Jup*vnsr/vmyo+Jdiff*vss/vmyo - J_TRPN) - - -expressions("CaMK") -CaMKa = CaMKb + CaMKt # mM -CaMKb = (CaMKo*(1.0 - CaMKt))/(KmCaM/cass + 1.0) # mM -dCaMKt_dt = -CaMKt*bCaMK + (CaMKb*aCaMK)*(CaMKb + CaMKt) # mM - -expressions("INaK") -E1_ = x1/(x4 + (x3 + (x1 + x2))) -E2 = x2/(x4 + (x3 + (x1 + x2))) -E3 = x3/(x4 + (x3 + (x1 + x2))) -E4 = x4/(x4 + (x3 + (x1 + x2))) -INaK_INaK = Pnak*(JnakK*zk + JnakNa*zna) # A/F -JnakK = 2.0*(-E3*a1 + E4*b1) # mM/ms -JnakNa = 3.0*(E1_*a3 - E2*b3) # mM/ms -Knai = Knai0*exp((delta*vfrt)/3.0) # mM -Knao = Knao0*exp((vfrt*(1.0 - delta))/3.0) # mM -P = eP/(((H/Khp + 1.0) + nai/Knap) + ki/Kxkur) -Pnak = Conditional(Eq(celltype, 1.0), 0.9*Pnak_b, Conditional(Eq(celltype, 2.0), 0.7*Pnak_b, Pnak_b)) # mS/uF -a1 = (k1p*(nai/Knai)**3.0)/(((1.0 + ki/Kki)**2.0 + (1.0 + nai/Knai)**3.0) - 1*1.0) -a2 = k2p -a3 = (k3p*(ko/Kko)**2.0)/(((1.0 + ko/Kko)**2.0 + (1.0 + nao/Knao)**3.0) - 1*1.0) -a4 = ((MgATP*k4p)/Kmgatp)/(1.0 + MgATP/Kmgatp) -b1 = MgADP*k1m -b2 = (k2m*(nao/Knao)**3.0)/(((1.0 + ko/Kko)**2.0 + (1.0 + nao/Knao)**3.0) - 1*1.0) -b3 = (H*(P*k3m))/(1.0 + MgATP/Kmgatp) -b4 = (k4m*(ki/Kki)**2.0)/(((1.0 + ki/Kki)**2.0 + (1.0 + nai/Knai)**3.0) - 1*1.0) -x1 = a2*(a1*b3) + (b3*(a2*b4) + (a2*(a1*a4) + b3*(b2*b4))) -x2 = b4*(a2*a3) + (b4*(a3*b1) + (a3*(a1*a2) + b4*(b1*b2))) -x3 = b1*(a3*a4) + (a4*(b1*b2) + (a4*(a2*a3) + b1*(b2*b3))) -x4 = a1*(b2*b3) + (a1*(a4*b2) + (a1*(a3*a4) + b2*(b3*b4))) - -expressions("INaCa") -E1_i = x1_i/(x4_i + (x3_i + (x1_i + x2_i))) -E1_ss = x1_ss/(x4_ss + (x3_ss + (x1_ss + x2_ss))) -E2_i = x2_i/(x4_i + (x3_i + (x1_i + x2_i))) -E2_ss = x2_ss/(x4_ss + (x3_ss + (x1_ss + x2_ss))) -E3_i = x3_i/(x4_i + (x3_i + (x1_i + x2_i))) -E3_ss = x3_ss/(x4_ss + (x3_ss + (x1_ss + x2_ss))) -E4_i = x4_i/(x4_i + (x3_i + (x1_i + x2_i))) -E4_ss = x4_ss/(x4_ss + (x3_ss + (x1_ss + x2_ss))) -Gncx = Conditional(Eq(celltype, 1.0), 1.1*Gncx_b, Conditional(Eq(celltype, 2.0), 1.4*Gncx_b, Gncx_b)) # mS/uF -INaCa_i = (allo_i*(Gncx*(1.0 - INaCa_fractionSS)))*(JncxCa_i*zca + JncxNa_i*zna) # A/F -INaCa_ss = (allo_ss*(Gncx*INaCa_fractionSS))*(JncxCa_ss*zca + JncxNa_ss*zna) # A/F -JncxCa_i = -E1_i*k1_i + E2_i*k2_i # mM/ms -JncxCa_ss = -E1_ss*k1_ss + E2_ss*k2_ss # mM/ms -JncxNa_i = -E2_i*k3pp_i + (E3_i*k4pp_i + 3.0*(-E1_i*k8_i + E4_i*k7_i)) # mM/ms -JncxNa_ss = -E2_ss*k3pp_ss + (E3_ss*k4pp_ss + 3.0*(-E1_ss*k8_ss + E4_ss*k7_ss)) # mM/ms -allo_i = 1.0/((KmCaAct/cai)**2.0 + 1.0) -allo_ss = 1.0/((KmCaAct/cass)**2.0 + 1.0) -h10_i = (nao/kna1)*(1.0 + nao/kna2) + (kasymm + 1.0) -h10_ss = (nao/kna1)*(1.0 + nao/kna2) + (kasymm + 1.0) -h11_i = (nao*nao)/((kna2*(h10_i*kna1))) -h11_ss = (nao*nao)/((kna2*(h10_ss*kna1))) -h12_i = 1.0/h10_i -h12_ss = 1.0/h10_ss -h1_i = (nai/kna3)*(hna + 1.0) + 1.0 -h1_ss = (nass/kna3)*(hna + 1.0) + 1.0 -h2_i = (hna*nai)/((h1_i*kna3)) -h2_ss = (hna*nass)/((h1_ss*kna3)) -h3_i = 1.0/h1_i -h3_ss = 1.0/h1_ss -h4_i = (nai/kna1)*(1.0 + nai/kna2) + 1.0 -h4_ss = (nass/kna1)*(1.0 + nass/kna2) + 1.0 -h5_i = (nai*nai)/((kna2*(h4_i*kna1))) -h5_ss = (nass*nass)/((kna2*(h4_ss*kna1))) -h6_i = 1.0/h4_i -h6_ss = 1.0/h4_ss -h7_i = (nao/kna3)*(1.0 + 1.0/hna) + 1.0 -h7_ss = (nao/kna3)*(1.0 + 1.0/hna) + 1.0 -h8_i = nao/((h7_i*(hna*kna3))) -h8_ss = nao/((h7_ss*(hna*kna3))) -h9_i = 1.0/h7_i -h9_ss = 1.0/h7_ss -hca = exp(qca*vfrt) -hna = exp(qna*vfrt) -k1_i = kcaon*(cao*h12_i) -k1_ss = kcaon*(cao*h12_ss) -k2_i = kcaoff -k2_ss = kcaoff -k3_i = k3p_i + k3pp_i -k3_ss = k3p_ss + k3pp_ss -k3p_i = h9_i*wca -k3p_ss = h9_ss*wca -k3pp_i = h8_i*wnaca -k3pp_ss = h8_ss*wnaca -k4_i = k4p_i + k4pp_i -k4_ss = k4p_ss + k4pp_ss -k4p_i = (h3_i*wca)/hca -k4p_ss = (h3_ss*wca)/hca -k4pp_i = h2_i*wnaca -k4pp_ss = h2_ss*wnaca -k5_i = kcaoff -k5_ss = kcaoff -k6_i = kcaon*(cai*h6_i) -k6_ss = kcaon*(cass*h6_ss) -k7_i = wna*(h2_i*h5_i) -k7_ss = wna*(h2_ss*h5_ss) -k8_i = wna*(h11_i*h8_i) -k8_ss = wna*(h11_ss*h8_ss) -x1_i = (k2_i*k4_i)*(k6_i + k7_i) + (k5_i*k7_i)*(k2_i + k3_i) -x1_ss = (k2_ss*k4_ss)*(k6_ss + k7_ss) + (k5_ss*k7_ss)*(k2_ss + k3_ss) -x2_i = (k1_i*k7_i)*(k4_i + k5_i) + (k4_i*k6_i)*(k1_i + k8_i) -x2_ss = (k1_ss*k7_ss)*(k4_ss + k5_ss) + (k4_ss*k6_ss)*(k1_ss + k8_ss) -x3_i = (k1_i*k3_i)*(k6_i + k7_i) + (k6_i*k8_i)*(k2_i + k3_i) -x3_ss = (k1_ss*k3_ss)*(k6_ss + k7_ss) + (k6_ss*k8_ss)*(k2_ss + k3_ss) -x4_i = (k2_i*k8_i)*(k4_i + k5_i) + (k3_i*k5_i)*(k1_i + k8_i) -x4_ss = (k2_ss*k8_ss)*(k4_ss + k5_ss) + (k3_ss*k5_ss)*(k1_ss + k8_ss) - -expressions("reversal_potentials") -ECl = ((R*T)/((F*zcl)))*log(clo/cli) # mV -EClss = ((R*T)/((F*zcl)))*log(clo/clss) # mV -EK = ((R*T)/((F*zk)))*log(ko/ki) # mV -EKs = ((R*T)/((F*zk)))*log((PKNa*nao + ko)/(PKNa*nai + ki)) # mV -ENa = ((R*T)/((F*zna)))*log(nao/nai) # mV - -expressions("IK1") -GK1 = Conditional(Eq(celltype, 1.0), 1.2*GK1_b, Conditional(Eq(celltype, 2.0), 1.3*GK1_b, GK1_b)) # mS/uF -IK1_IK1 = (K1ss*(GK1*sqrt(ko/5.0)))*(-EK + v) # A/F -K1ss = aK1/(aK1 + bK1) -aK1 = 4.094/(exp(0.1217*((-EK + v) - 1*49.934)) + 1.0) -bK1 = (15.72*exp(0.0674*((-EK + v) - 1*3.257)) + exp(0.0618*((-EK + v) - 1*594.31)))/(exp((-1*0.1629)*((-EK + v) + 14.207)) + 1.0) - -expressions("IKb") -GKb = Conditional(Eq(celltype, 1.0), 0.6*GKb_b, GKb_b) # mS/uF -IKb_IKb = (GKb*xkb)*(-EK + v) # A/F -xkb = 1.0/(exp((-(v - 1*10.8968))/23.9871) + 1.0) - -expressions("IKr") -GKr = Conditional(Eq(celltype, 1.0), 1.3*GKr_b, Conditional(Eq(celltype, 2.0), 0.8*GKr_b, GKr_b)) # mS/uF -IKr_IKr = (O_*(GKr*sqrt(ko/5.0)))*(-EK + v) # A/F -alpha = 0.1161*exp(0.299*vfrt) # mS/uF -alpha_2 = 0.0578*exp(0.971*vfrt) # mS/uF -alpha_C2ToI = 5.2e-5*exp(1.525*vfrt) # mS/uF -alpha_i = 0.2533*exp(0.5953*vfrt) # mS/uF -beta_ = 0.2442*exp((-1*1.604)*vfrt) # mS/uF -beta_2 = 0.000349*exp((-1*1.062)*vfrt) # mS/uF -beta_ItoC2 = (alpha_C2ToI*(beta_2*beta_i))/((alpha_2*alpha_i)) # mS/uF -beta_i = 0.06525*exp((-1*0.8209)*vfrt) # mS/uF -dC1_dt = -C1*(alpha_C2ToI + (alpha_2 + beta_1)) + (I_*beta_ItoC2 + (C2*alpha_1 + O_*beta_2)) -dC2_dt = -C2*(alpha_1 + beta_) + (C1*beta_1 + C3*alpha) -dC3_dt = C2*beta_ - C3*alpha -dI__dt = -I_*(beta_ItoC2 + beta_i) + (C1*alpha_C2ToI + O_*alpha_i) -dO__dt = -O_*(alpha_i + beta_2) + (C1*alpha_2 + I_*beta_i) - -expressions("IKs") -GKs = Conditional(Eq(celltype, 1.0), 1.4*GKs_b, GKs_b) # mS/uF -IKs_IKs = (xs2*(xs1*(GKs*KsCa)))*(-EKs + v) # A/F -KsCa = 1.0 + 0.6/((3.8e-5/cai)**1.4 + 1.0) -txs1 = 817.3 + 1.0/(0.0002326*exp((v + 48.28)/17.8) + 0.001292*exp((-(v + 210.0))/230.0)) # ms -txs2 = 1.0/(0.01*exp((v - 1*50.0)/20.0) + 0.0193*exp((-(v + 66.54))/31.0)) # ms -xs1ss = 1.0/(exp((-(v + 11.6))/8.932) + 1.0) -xs2ss = xs1ss -dxs1_dt = (-xs1 + xs1ss)/txs1 -dxs2_dt = (-xs2 + xs2ss)/txs2 - -expressions("INaL") -GNaL = Conditional(Eq(celltype, 1.0), 0.6*GNaL_b, GNaL_b) # mS/uF -INaL_INaL = (mL*(GNaL*(-ENa + v)))*(fINaLp*hLp + hL*(1.0 - fINaLp)) # A/F -fINaLp = 1.0/(1.0 + KmCaMK/CaMKa) -hLss = 1.0/(exp((v + 87.61)/7.488) + 1.0) -hLssp = 1.0/(exp((v + 93.81)/7.488) + 1.0) -mLss = 1.0/(exp((-(v + 42.85))/5.264) + 1.0) -thLp = 3.0*thL # ms -tmL = 0.06487*exp(-((v - 1*4.823)/51.12)**2.0) + 0.1292*exp(-((v + 45.79)/15.54)**2.0) # ms -dhL_dt = (-hL + hLss)/thL -dhLp_dt = (-hLp + hLssp)/thLp -dmL_dt = (-mL + mLss)/tmL - -expressions("ICab") -ICab_ICab = ((vffrt*(PCab*4.0))*(-cao*gamma_cao + (cai*gamma_cai)*exp(2.0*vfrt)))/(exp(2.0*vfrt) - 1*1.0) # A/F - -expressions("ICl") -IClCa = IClCa_junc + IClCa_sl # A/F -IClCa_junc = ((Fjunc*GClCa)/(KdClCa/cass + 1.0))*(-EClss + v) # A/F -IClCa_sl = ((GClCa*(1.0 - Fjunc))/(KdClCa/cai + 1.0))*(-ECl + v) # A/F -IClb = GClb*(-ECl + v) # A/F - -expressions("INa") -INa_INa = (m**3.0*(GNa*(-ENa + v)))*(j*(h*(1.0 - fINap)) + jp*(fINap*hp)) # A/F -ah = Conditional(Gt(v, -1*40.0), 0.0, 4.43126792958051e-7*exp(-0.147058823529412*v)) -aj = Conditional(Gt(v, -1*40.0), 0.0, -(v + 37.78)*(25428.0*exp(0.28831*v) + 6.948e-6)*exp(-0.04391*v)/(50262745825.954*exp(0.311*v) + 1.0)) -bh = Conditional(Gt(v, -1*40.0), 0.77*exp(0.0900900900900901*v)/(0.13*exp(0.0900900900900901*v) + 0.0497581410839387), 2.7*exp(0.079*v) + 310000.0*exp(0.3485*v)) -bj = Conditional(Gt(v, -1*40.0), 0.6*exp(0.157*v)/(1.0*exp(0.1*v) + 0.0407622039783662), 0.02424*exp(0.12728*v)/(1.0*exp(0.1378*v) + 0.00396086833990426)) -fINap = 1.0/(1.0 + KmCaMK/CaMKa) -hss = 1.0/((exp((v + 71.55)/7.43) + 1.0)**2.0) -hssp = 1.0/((exp((v + 77.55)/7.43) + 1.0)**2.0) -jss = hss -mss = 1.0/((exp((-(v + 56.86))/9.03) + 1.0)**2.0) -th = 1.0/(ah + bh) # ms -tj = 1.0/(aj + bj) # ms -tjp = 1.46*tj # ms -tm = 0.06487*exp(-((v - 1*4.823)/51.12)**2.0) + 0.1292*exp(-((v + 45.79)/15.54)**2.0) # ms -dh_dt = (-h + hss)/th -dhp_dt = (-hp + hssp)/th -dj_dt = (-j + jss)/tj -djp_dt = (-jp + jss)/tjp -dm_dt = (-m + mss)/tm - -expressions("INab") -INab_INab = ((PNab*vffrt)*(nai*exp(vfrt) - nao))/(exp(vfrt) - 1*1.0) # A/F - -expressions("I_katp") -I_katp_I_katp = (bkik*(akik*(fkatp*gkatp)))*(-EK + v) # A/F -akik = (ko/K_o_n)**0.24 -bkik = 1.0/((A_atp/K_atp)**2.0 + 1.0) - -expressions("IpCa") -IpCa_IpCa = (GpCa*cai)/(KmCap + cai) # A/F - -expressions("membrane") -Istim = Conditional(And(Le(i_Stim_Start, time), Ge(i_Stim_PulseDuration, -i_Stim_Period*floor(-(i_Stim_Start - time)/i_Stim_Period) - i_Stim_Start + time)), i_Stim_Amplitude, 0.0) # A/F -vffrt = (F*(F*v))/((R*T)) # C/mol -vfrt = (F*v)/((R*T)) -dv_dt = -(Istim + (I_katp_I_katp + (IClb + (IClCa + (ICab_ICab + (IpCa_IpCa + (IKb_IKb + (INab_INab + (INaK_INaK + (INaCa_ss + (INaCa_i + (IK1_IK1 + (IKs_IKs + (IKr_IKr + (ICaK + (ICaNa + (ICaL_ICaL + (Ito_Ito + (INaL_INaL + INa_INa))))))))))))))))))) # mV - -expressions("diff") -Jdiff = (-cai + cass)/tauCa # mM/ms -JdiffCl = (-cli + clss)/tauNa # mM/ms -JdiffK = (-ki + kss)/tauK # mM/ms -JdiffNa = (-nai + nass)/tauNa # mM/ms - -expressions("SERCA") -Jleak = (0.0048825*cansr)/15.0 # mM/ms -Jup = Jup_b*(-Jleak + (Jupnp*(1.0 - fJupp) + Jupp*fJupp)) # mM/ms -Jupnp = (cai*(upScale*0.005425))/(cai + 0.00092) # mM/ms -Jupp = (cai*((upScale*2.75)*0.005425))/((cai + 0.00092) - 1*0.00017) # mM/ms -fJupp = 1.0/(1.0 + KmCaMK/CaMKa) -upScale = Conditional(Eq(celltype, 1.0), 1.3, 1.0) - -expressions("ryr") -Jrel = Jrel_b*(Jrel_np*(1.0 - fJrelp) + Jrel_p*fJrelp) # mM/ms -Jrel_inf = Conditional(Eq(celltype, 2.0), 1.7*Jrel_inf_b, Jrel_inf_b) # mM/ms -Jrel_inf_b = ((ICaL_ss*(-a_rel))/1.0)/((cajsr_half/cajsr)**8.0 + 1.0) # mM/ms -Jrel_infp = Conditional(Eq(celltype, 2.0), 1.7*Jrel_infp_b, Jrel_infp_b) # mM/ms -Jrel_infp_b = ((ICaL_ss*(-a_relp))/1.0)/((cajsr_half/cajsr)**8.0 + 1.0) # mM/ms -a_rel = (0.5*bt)/1.0 # mM/ms -a_relp = (0.5*btp)/1.0 # mM/ms -btp = 1.25*bt # ms -fJrelp = 1.0/(1.0 + KmCaMK/CaMKa) -tau_rel = Conditional(Lt(tau_rel_b, 0.001), 0.001, tau_rel_b) # ms -tau_rel_b = bt/(1.0 + 0.0123/cajsr) # ms -tau_relp = Conditional(Lt(tau_relp_b, 0.001), 0.001, tau_relp_b) # ms -tau_relp_b = btp/(1.0 + 0.0123/cajsr) # ms -dJrel_np_dt = (Jrel_inf - Jrel_np)/tau_rel # mM/ms -dJrel_p_dt = (Jrel_infp - Jrel_p)/tau_relp # mM/ms - -expressions("trans_flux") -Jtr = (-cajsr + cansr)/60.0 # mM/ms - - - -states("mechanics", -XS=0, -XW=0, -CaTrpn=1e-8, -TmB=1, -Zetas=0, -Zetaw=0, -Cd=0 -) - -parameters("mechanics", -emcoupling=1, -lmbda=1, -dLambda=0, -mode=1, -isacs=0, -calib=1, -ktrpn = 0.1, -ntrpn = 2, -Trpn50 = 0.35, -rw = 0.5, -rs = 0.25, -gammas = 0.0085, -gammaw = 0.615, -phi = 2.23, -Tot_A = 25, -Beta0 = 2.3, -Beta1 = -2.4, -cat50_ref = 0.805, -Tref = 120, -kuw = 0.182, -kws = 0.012, -ku=0.04, -ntm=2.4, -p_a = 2.1, -p_b = 9.1, -p_k = 7, -etal = 200, -etas = 20) - -expressions("mechanics") -XS_max = Conditional(Gt(XS, 0), XS, 0) -XW_max = Conditional(Gt(XW, 0), XW, 0) -CaTrpn_max = Conditional(Gt(CaTrpn, 0), CaTrpn, 0) -kwu = kuw*(1/rw-1)-kws -ksu = kws*rw*(1/rs-1) -Aw = Tot_A*rs/((1-rs)*rw+rs) -As = Aw -cw = phi*kuw*((1-rs)*(1-rw))/((1-rs)*rw) -cs = phi*kws*((1-rs)*rw)/rs -XU = (1-TmB)-XS-XW -gammawu = gammaw*Abs(Zetaw) -gammasu = gammas*Conditional(Gt(Gt(Zetas,0)*Zetas, Lt(Zetas, -1)*(-Zetas-1)), Gt(Zetas,0)*Zetas, Lt(Zetas, -1)*(-Zetas-1)) -dXS_dt = kws*XW - ksu*XS - gammasu*XS -dXW_dt = kuw*XU - kwu*XW - kws*XW - gammawu*XW -cat50 = (cat50_ref+Beta1*(lambda_min12-1)) -dCaTrpn_dt = ktrpn*(((cai*1000/cat50)**ntrpn)*(1-CaTrpn)-CaTrpn) -kb = ku*Trpn50**ntm/(1-rs-(1-rs)*rw) -dTmB_dt = kb*Conditional(Lt(CaTrpn**(-ntm/2), 100), CaTrpn**(-ntm/2), 100)*XU-ku*CaTrpn**(ntm/2)*TmB -J_TRPN = dCaTrpn_dt*trpnmax -lambda_min12 = Conditional(Lt(lmbda, 1.2), lmbda, 1.2) -dZetas_dt = As*dLambda - cs*Zetas -dZetaw_dt = Aw*dLambda - cw*Zetaw -lambda_min087 = Conditional(Lt(lambda_min12, 0.87), lambda_min12, 0.87) -h_lambda_prima = 1+Beta0*(lambda_min12+lambda_min087-1.87) -h_lambda = Conditional(Gt(h_lambda_prima, 0), h_lambda_prima, 0) -Ta = h_lambda*(Tref/rs)*(XS*(Zetas+1) + XW*Zetaw) -C = lambda_min12 - 1 -dCd = C - Cd -eta = Conditional(Lt(dCd, 0), etas, etal) -dCd_dt = p_k * (C - Cd) / eta -Fd = eta * dCd -F1 = (exp( p_b * C) - 1) -Tp = p_a * (F1 + Fd) -Ttot = Ta + Tp diff --git a/demos/split-cai/3D/ORdmm_Land.ode b/demos/split-cai/3D/ORdmm_Land.ode deleted file mode 100644 index 2e79499..0000000 --- a/demos/split-cai/3D/ORdmm_Land.ode +++ /dev/null @@ -1,663 +0,0 @@ -# ORd modified by MMora (October-2016) -# Modifications in INa. The original formulation of INa has been -# optimised, according to Passini, in order to look like TT04. -# Modifications: -# 1) mss,hss,jss and hssp -# 2) gNa -# + -# Re-scaled conductances (Dutta et al 2016 CinC) -# + -# -# Land 2017(mechanical model)- Introduced by MMora (Jan2020) -# Tension -# Changes in Cai effect of troponin -# + -# -# Isacs -# -# -# In this version we fix mech.emcoupling=1, -# mode="intact", isacs=0 and celltype = 0 -# -# -# Modifications by Ilse (January 2023) -# Add scaling facotrs for heart failure and drugs - - -parameters("Scales", -scale_IKr = 1.119, -scale_IKs = 1.648, -scale_IK1 = 1.414, -scale_ICaL = 1.018, -scale_INaL = 2.274) - - - -parameters("settings", -celltype=0) - -parameters("extracellular ionic concentrations", -nao=140.0, -cao=1.8, -ko=5.4) - -parameters("physical constants", "mechanics", -R=8314.0, -T=310.0, -F=96485.0) - - -parameters("cell geometry", "mechanics", -L=0.01, -rad=0.0011) - - -expressions("cell geometry", "mechanics") -vcell=1000*3.14*rad*rad*L -Ageo=2*3.14*rad*rad+2*3.14*rad*L -Acap=2*Ageo -vmyo=0.68*vcell -vnsr=0.0552*vcell -vjsr=0.0048*vcell -vss=0.02*vcell - - -# Scaling factors for heart failure -parameters("scaling factors HF", -scale_HF_CaMKa=1.0, -scale_HF_Jrel_inf=1.0, -scale_HF_Jleak=1.0, -scale_HF_Jup=1.0, -scale_HF_GNaL=1.0, -scale_HF_GK1=1.0, -scale_HF_thL=1.0, -scale_HF_Gto=1.0, -scale_HF_Gncx=1.0, -scale_HF_Pnak=1.0) - -# Scaling factors for drug effects -parameters("scaling factors drug", -scale_drug_INa=1.0, -scale_drug_INaL=1.0, -scale_drug_Ito=1.0, -scale_drug_ICaL=1.0, -scale_drug_IKr=1.0, -scale_drug_IKs=1.0, -scale_drug_IK1=1.0, -scale_drug_IKb=1.0, -scale_drug_INab=1.0, -scale_drug_ICab=1.0, -scale_drug_IpCa=1.0, -scale_drug_Isacns=1.0, -scale_drug_Isack=1.0) - -######## EP states -states("CaMKt", -CaMKt=0 -) - -states("I_Na", -m=0, -hf=1, -hs=1, -j=1, -hsp=1, -jp=1) - -states("INaL", -mL=0, -hL=1, -hLp=1) - -states("Ito", -a=0, -iF=1, -iS=1, -ap=0, -iFp=1, -iSp=1) - -states("ICaL ICaNa ICaK", -d=0, -ff=1, -fs=1, -fcaf=1, -fcas=1, -jca=1, -nca=0, -ffp=1, -fcafp=1) - - -states("IKr", -xrf=0, -xrs=0) - - -states("IKs", -xs1=0, -xs2=0, -xk1=1) - -states("membrane potential", -v=-87) - - -states("ryanodione receptor", -Jrelnp=0, -Jrelp=0) - - -states("intracellular concentrations", -cai=0.0001, -nai=7, -nass=7, -ki=145, -kss=145, -cass=0.0001, -cansr=1.2, -cajsr=1.2) - -states("mechanics", -XS=0, -XW=0, -CaTrpn=0.0001, -TmB=1, -Zetas=0, -Zetaw=0, -Cd=0) - - -############################## - -parameters("CaMK constants", -KmCaMK=0.15, -aCaMK=0.05, -bCaMK=0.00068, -CaMKo=0.05, -KmCaM=0.0015) - -expressions("CaMKt") -CaMKb=CaMKo*(1.0-CaMKt)/(1.0+KmCaM/cass) -CaMKa=(CaMKb+CaMKt)*scale_HF_CaMKa -dCaMKt_dt=aCaMK*CaMKb*(CaMKb+CaMKt)-bCaMK*CaMKt - -parameters("reversal potentials", -PKNa=0.01833) - -expressions("reversal potentials") -ENa=(R*T/F)*log(nao/nai) -EK=(R*T/F)*log(ko/ki) -EKs=(R*T/F)*log((ko+PKNa*nao)/(ki+PKNa*nai)) -vffrt=v*F*F/(R*T) -vfrt=v*F/(R*T) - -parameters("I_Na", -Ahf=0.99, -GNa=31) - -expressions("I_Na") -mss=1.0/(1.0+exp((-(v+39.57+9.4))/7.5)) -tm=1.0/(6.765*exp((v+11.64)/34.77)+8.552*exp(-(v+77.42)/5.955)) -dm_dt=(mss-m)/tm -hss=1.0/(1+exp((v+78.5)/6.22)) -thf=1.0/(1.432e-5*exp(-(v+1.196)/6.285)+6.149*exp((v+0.5096)/20.27)) -ths=1.0/(0.009794*exp(-(v+17.95)/28.05)+0.3343*exp((v+5.730)/56.66)) -Ahs=1.0-Ahf -dhf_dt=(hss-hf)/thf -dhs_dt=(hss-hs)/ths -h=Ahf*hf+Ahs*hs -jss=hss -tj=2.038+1.0/(0.02136*exp(-(v+100.6)/8.281)+0.3052*exp((v+0.9941)/38.45)) -dj_dt=(jss-j)/tj -hssp=1.0/(1+exp((v+78.5+6.2)/6.22)) -thsp=3.0*ths -dhsp_dt=(hssp-hsp)/thsp -hp=Ahf*hf+Ahs*hsp -tjp=1.46*tj -djp_dt=(jss-jp)/tjp -fINap=(1.0/(1.0+KmCaMK/CaMKa)) -INa=GNa*scale_drug_INa*(v-ENa)*m**3.0*((1.0-fINap)*h*j+fINap*hp*jp) - -parameters("INaL", -thL=200.0) - -expressions("INaL") -mLss=1.0/(1.0+exp((-(v+42.85))/5.264)) -tmL=tm -dmL_dt=(mLss-mL)/tmL -hLss=1.0/(1.0+exp((v+87.61)/7.488)) -dhL_dt=(hLss-hL)/(thL*scale_HF_thL) -hLssp=1.0/(1.0+exp((v+93.81)/7.488)) -thLp=3.0*thL*scale_HF_thL -dhLp_dt=(hLssp-hLp)/thLp -GNaL=0.0075*scale_INaL*scale_drug_INaL*scale_HF_GNaL -fINaLp=(1.0/(1.0+KmCaMK/CaMKa)) -INaL=GNaL*(v-ENa)*mL*((1.0-fINaLp)*hL+fINaLp*hLp) - -parameters("Ito", -delta_epi=1.0, -Gto=0.02) - -expressions("Ito") -ass=1.0/(1.0+exp((-(v-14.34))/14.82)) -ta=1.0515/(1.0/(1.2089*(1.0+exp(-(v-18.4099)/29.3814)))+3.5/(1.0+exp((v+100.0)/29.3814))) -da_dt=(ass-a)/ta -iss=1.0/(1.0+exp((v+43.94)/5.711)) -tiF=4.562+1/(0.3933*exp((-(v+100.0))/100.0)+0.08004*exp((v+50.0)/16.59)) * delta_epi -tiS=23.62+1/(0.001416*exp((-(v+96.52))/59.05)+1.780e-8*exp((v+114.1)/8.079)) * delta_epi -AiF=1.0/(1.0+exp((v-213.6)/151.2)) -AiS=1.0-AiF -diF_dt=(iss-iF)/tiF -diS_dt=(iss-iS)/tiS -i=AiF*iF+AiS*iS -assp=1.0/(1.0+exp((-(v-24.34))/14.82)) -dap_dt=(assp-ap)/ta -dti_develop=1.354+1.0e-4/(exp((v-167.4)/15.89)+exp(-(v-12.23)/0.2154)) -dti_recover=1.0-0.5/(1.0+exp((v+70.0)/20.0)) -tiFp=dti_develop*dti_recover*tiF -tiSp=dti_develop*dti_recover*tiS -diFp_dt=(iss-iFp)/tiFp -diSp_dt=(iss-iSp)/tiSp -ip=AiF*iFp+AiS*iSp -fItop=(1.0/(1.0+KmCaMK/CaMKa)) -Ito=Gto*scale_drug_Ito*scale_HF_Gto*(v-EK)*((1.0-fItop)*a*i+fItop*ap*ip) - - -parameters("ICaL ICaNa ICaK", -Aff=0.6, -tjca=75.0, -Kmn=0.002, -k2n=1000.0, -zca=2.0) - -expressions("ICaL ICaNa ICaK") -dss=1.0/(1.0+exp((-(v+3.940))/4.230)) -td=0.6+1.0/(exp(-0.05*(v+6.0))+exp(0.09*(v+14.0))) -dd_dt=(dss-d)/td -fss=1.0/(1.0+exp((v+19.58)/3.696)) -tff=7.0+1.0/(0.0045*exp(-(v+20.0)/10.0)+0.0045*exp((v+20.0)/10.0)) -tfs=1000.0+1.0/(0.000035*exp(-(v+5.0)/4.0)+0.000035*exp((v+5.0)/6.0)) -Afs=1.0-Aff -dff_dt=(fss-ff)/tff -dfs_dt=(fss-fs)/tfs -f=Aff*ff+Afs*fs -fcass=fss -tfcaf=7.0+1.0/(0.04*exp(-(v-4.0)/7.0)+0.04*exp((v-4.0)/7.0)) -tfcas=100.0+1.0/(0.00012*exp(-v/3.0)+0.00012*exp(v/7.0)) -Afcaf=0.3+0.6/(1.0+exp((v-10.0)/10.0)) -Afcas=1.0-Afcaf -dfcaf_dt=(fcass-fcaf)/tfcaf -dfcas_dt=(fcass-fcas)/tfcas -fca=Afcaf*fcaf+Afcas*fcas -djca_dt=(fcass-jca)/tjca -tffp=2.5*tff -dffp_dt=(fss-ffp)/tffp -fp=Aff*ffp+Afs*fs -tfcafp=2.5*tfcaf -dfcafp_dt=(fcass-fcafp)/tfcafp -fcap=Afcaf*fcafp+Afcas*fcas -km2n=jca*1.0 -anca=1.0/(k2n/km2n+(1.0+Kmn/cass)**4.0) -dnca_dt=anca*k2n-nca*km2n -PhiCaL=4.0*vffrt*(cass*exp(2.0*vfrt)-0.341*cao)/(exp(2.0*vfrt)-1.0) -PhiCaNa=1.0*vffrt*(0.75*nass*exp(1.0*vfrt)-0.75*nao)/(exp(1.0*vfrt)-1.0) -PhiCaK=1.0*vffrt*(0.75*kss*exp(1.0*vfrt)-0.75*ko)/(exp(1.0*vfrt)-1.0) -PCa=0.0001*scale_ICaL*scale_drug_ICaL -PCap=1.1*PCa -PCaNa=0.00125*PCa -PCaK=3.574e-4*PCa -PCaNap=0.00125*PCap -PCaKp=3.574e-4*PCap -fICaLp=(1.0/(1.0+KmCaMK/CaMKa)) -ICaL=(1.0-fICaLp)*PCa*PhiCaL*d*(f*(1.0-nca)+jca*fca*nca)+fICaLp*PCap*PhiCaL*d*(fp*(1.0-nca)+jca*fcap*nca) -ICaNa=(1.0-fICaLp)*PCaNa*PhiCaNa*d*(f*(1.0-nca)+jca*fca*nca)+fICaLp*PCaNap*PhiCaNa*d*(fp*(1.0-nca)+jca*fcap*nca) -ICaK=(1.0-fICaLp)*PCaK*PhiCaK*d*(f*(1.0-nca)+jca*fca*nca)+fICaLp*PCaKp*PhiCaK*d*(fp*(1.0-nca)+jca*fcap*nca) - -expressions("IKr") -xrss=1.0/(1.0+exp((-(v+8.337))/6.789)) -txrf=12.98+1.0/(0.3652*exp((v-31.66)/3.869)+4.123e-5*exp((-(v-47.78))/20.38)) -txrs=1.865+1.0/(0.06629*exp((v-34.70)/7.355)+1.128e-5*exp((-(v-29.74))/25.94)) -Axrf=1.0/(1.0+exp((v+54.81)/38.21)) -Axrs=1.0-Axrf -dxrf_dt=(xrss-xrf)/txrf -dxrs_dt=(xrss-xrs)/txrs -xr=Axrf*xrf+Axrs*xrs -rkr=1.0/(1.0+exp((v+55.0)/75.0))*1.0/(1.0+exp((v-10.0)/30.0)) -GKr=0.046*scale_IKr*scale_drug_IKr -IKr=GKr*sqrt(ko/5.4)*xr*rkr*(v-EK) - -expressions("IKs") -xs1ss=1.0/(1.0+exp((-(v+11.60))/8.932)) -txs1=817.3+1.0/(2.326e-4*exp((v+48.28)/17.80)+0.001292*exp((-(v+210.0))/230.0)) -dxs1_dt=(xs1ss-xs1)/txs1 -xs2ss=xs1ss -txs2=1.0/(0.01*exp((v-50.0)/20.0)+0.0193*exp((-(v+66.54))/31.0)) -dxs2_dt=(xs2ss-xs2)/txs2 -KsCa=1.0+0.6/(1.0+(3.8e-5/cai)**1.4) -GKs=0.0034*scale_IKs*scale_drug_IKs -IKs=GKs*KsCa*xs1*xs2*(v-EKs) -xk1ss=1.0/(1.0+exp(-(v+2.5538*ko+144.59)/(1.5692*ko+3.8115))) -txk1=122.2/(exp((-(v+127.2))/20.36)+exp((v+236.8)/69.33)) -dxk1_dt=(xk1ss-xk1)/txk1 -rk1=1.0/(1.0+exp((v+105.8-2.6*ko)/9.493)) -GK1=0.1908*scale_IK1*scale_drug_IK1*scale_HF_GK1 -IK1=GK1*sqrt(ko)*rk1*xk1*(v-EK) - - -parameters("INaCa_i", -kna1=15.0, -kna2=5.0, -kna3=88.12, -kasymm=12.5, -wna=6.0e4, -wca=6.0e4, -wnaca=5.0e3, -kcaon=1.5e6, -kcaoff=5.0e3, -qna=0.5224, -qca=0.1670, -KmCaAct=150.0e-6, -Gncx=0.0008) - -expressions("INaCa_i") -hca=exp((qca*v*F)/(R*T)) -hna=exp((qna*v*F)/(R*T)) -h1_i=1+nai/kna3*(1+hna) -h2_i=(nai*hna)/(kna3*h1_i) -h3_i=1.0/h1_i -h4_i=1.0+nai/kna1*(1+nai/kna2) -h5_i=nai*nai/(h4_i*kna1*kna2) -h6_i=1.0/h4_i -h7_i=1.0+nao/kna3*(1.0+1.0/hna) -h8_i=nao/(kna3*hna*h7_i) -h9_i=1.0/h7_i -h10_i=kasymm+1.0+nao/kna1*(1.0+nao/kna2) -h11_i=nao*nao/(h10_i*kna1*kna2) -h12_i=1.0/h10_i -k1_i=h12_i*cao*kcaon -k2_i=kcaoff -k3p_i=h9_i*wca -k3pp_i=h8_i*wnaca -k3_i=k3p_i+k3pp_i -k4p_i=h3_i*wca/hca -k4pp_i=h2_i*wnaca -k4_i=k4p_i+k4pp_i -k5_i=kcaoff -k6_i=h6_i*cai*kcaon -k7_i=h5_i*h2_i*wna -k8_i=h8_i*h11_i*wna -x1_i=k2_i*k4_i*(k7_i+k6_i)+k5_i*k7_i*(k2_i+k3_i) -x2_i=k1_i*k7_i*(k4_i+k5_i)+k4_i*k6_i*(k1_i+k8_i) -x3_i=k1_i*k3_i*(k7_i+k6_i)+k8_i*k6_i*(k2_i+k3_i) -x4_i=k2_i*k8_i*(k4_i+k5_i)+k3_i*k5_i*(k1_i+k8_i) -E1_i=x1_i/(x1_i+x2_i+x3_i+x4_i) -E2_i=x2_i/(x1_i+x2_i+x3_i+x4_i) -E3_i=x3_i/(x1_i+x2_i+x3_i+x4_i) -E4_i=x4_i/(x1_i+x2_i+x3_i+x4_i) -allo_i=1.0/(1.0+(KmCaAct/cai)**2.0) -zna=1.0 -JncxNa_i=3.0*(E4_i*k7_i-E1_i*k8_i)+E3_i*k4pp_i-E2_i*k3pp_i -JncxCa_i=E2_i*k2_i-E1_i*k1_i -INaCa_i=0.8*Gncx*scale_HF_Gncx*allo_i*(zna*JncxNa_i+zca*JncxCa_i) - -expressions("INaCa_ss") -h1=1+nass/kna3*(1+hna) -h2=(nass*hna)/(kna3*h1) -h3=1.0/h1 -h4=1.0+nass/kna1*(1+nass/kna2) -h5=nass*nass/(h4*kna1*kna2) -h6=1.0/h4 -h7=1.0+nao/kna3*(1.0+1.0/hna) -h8=nao/(kna3*hna*h7) -h9=1.0/h7 -h10=kasymm+1.0+nao/kna1*(1+nao/kna2) -h11=nao*nao/(h10*kna1*kna2) -h12=1.0/h10 -k1=h12*cao*kcaon -k2=kcaoff -k3p_ss=h9*wca -k3pp=h8*wnaca -k3=k3p_ss+k3pp -k4p_ss=h3*wca/hca -k4pp=h2*wnaca -k4=k4p_ss+k4pp -k5=kcaoff -k6=h6*cass*kcaon -k7=h5*h2*wna -k8=h8*h11*wna -x1_ss=k2*k4*(k7+k6)+k5*k7*(k2+k3) -x2_ss=k1*k7*(k4+k5)+k4*k6*(k1+k8) -x3_ss=k1*k3*(k7+k6)+k8*k6*(k2+k3) -x4_ss=k2*k8*(k4+k5)+k3*k5*(k1+k8) -E1_ss=x1_ss/(x1_ss+x2_ss+x3_ss+x4_ss) -E2_ss=x2_ss/(x1_ss+x2_ss+x3_ss+x4_ss) -E3_ss=x3_ss/(x1_ss+x2_ss+x3_ss+x4_ss) -E4_ss=x4_ss/(x1_ss+x2_ss+x3_ss+x4_ss) -allo_ss=1.0/(1.0+(KmCaAct/cass)**2.0) -JncxNa_ss=3.0*(E4_ss*k7-E1_ss*k8)+E3_ss*k4pp-E2_ss*k3pp -JncxCa_ss=E2_ss*k2-E1_ss*k1 -INaCa_ss=0.2*Gncx*scale_HF_Gncx*allo_ss*(zna*JncxNa_ss+zca*JncxCa_ss) - - -parameters("INaK", -k1p=949.5, -k1m=182.4, -k2p=687.2, -k2m=39.4, -k3p=1899.0, -k3m=79300.0, -k4p=639.0, -k4m=40.0, -Knai0=9.073, -Knao0=27.78, -delta=-0.1550, -Kki=0.5, -Kko=0.3582, -MgADP=0.05, -MgATP=9.8, -Kmgatp=1.698e-7, -H=1.0e-7, -eP=4.2, -Khp=1.698e-7, -Knap=224.0, -Kxkur=292.0, -zk=1.0, -Pnak=30) - -expressions("INaK") -Knai=Knai0*exp((delta*v*F)/(3.0*R*T)) -Knao=Knao0*exp(((1.0-delta)*v*F)/(3.0*R*T)) -P=eP/(1.0+H/Khp+nai/Knap+ki/Kxkur) -a1=(k1p*(nai/Knai)**3.0)/((1.0+nai/Knai)**3.0+(1.0+ki/Kki)**2.0-1.0) -b1=k1m*MgADP -a2=k2p -b2=(k2m*(nao/Knao)**3.0)/((1.0+nao/Knao)**3.0+(1.0+ko/Kko)**2.0-1.0) -a3=(k3p*(ko/Kko)**2.0)/((1.0+nao/Knao)**3.0+(1.0+ko/Kko)**2.0-1.0) -b3=(k3m*P*H)/(1.0+MgATP/Kmgatp) -a4=(k4p*MgATP/Kmgatp)/(1.0+MgATP/Kmgatp) -b4=(k4m*(ki/Kki)**2.0)/((1.0+nai/Knai)**3.0+(1.0+ki/Kki)**2.0-1.0) -x1=a4*a1*a2+b2*b4*b3+a2*b4*b3+b3*a1*a2 -x2=b2*b1*b4+a1*a2*a3+a3*b1*b4+a2*a3*b4 -x3=a2*a3*a4+b3*b2*b1+b2*b1*a4+a3*a4*b1 -x4=b4*b3*b2+a3*a4*a1+b2*a4*a1+b3*b2*a1 -E1=x1/(x1+x2+x3+x4) -E2=x2/(x1+x2+x3+x4) -E3=x3/(x1+x2+x3+x4) -E4=x4/(x1+x2+x3+x4) -JnakNa=3.0*(E1*a3-E2*b3) -JnakK=2.0*(E4*b1-E3*a1) -INaK=Pnak*scale_HF_Pnak*(zna*JnakNa+zk*JnakK) - - -parameters("IKb", -GKb=0.003) - -expressions("IKb") -xkb=1.0/(1.0+exp(-(v-14.48)/18.34)) -IKb=GKb*scale_drug_IKb*xkb*(v-EK) - -parameters("INab", -PNab=3.75e-10) - -expressions("INab") -INab=PNab*scale_drug_INab*vffrt*(nai*exp(vfrt)-nao)/(exp(vfrt)-1.0) - - -parameters("ICab", -PCab=2.5e-8) - -expressions("ICab") -ICab=PCab*scale_drug_ICab*4.0*vffrt*(cai*exp(2.0*vfrt)-0.341*cao)/(exp(2.0*vfrt)-1.0) - -parameters("IpCa", -GpCa=0.0005) - -expressions("IpCa") -IpCa=GpCa*scale_drug_IpCa*cai/(0.0005+cai) - - -parameters("Isac (Pueyo)--> ns + k", -Gsac_ns=0.006, -Esac_ns=-10, -lambda_max=1.1, -Gsac_k=0.2882*800/210) - -expressions("Isac (Pueyo)--> ns + k") -Isac_P_ns=0 -Isac_P_k=0 - - -parameters("Istim", -amp=-80.0, -duration=0.5) - -expressions("Istim") -Istim = Conditional(Le(t, duration), amp, 0) - -expressions("membrane potential") -dv_dt=-(INa+INaL+Ito+ICaL+ICaNa+ICaK+IKr+IKs+IK1+INaCa_i+INaCa_ss+INaK+INab+IKb+IpCa+ICab+Istim+Isac_P_ns+Isac_P_k) - -expressions("diffusion fluxes") -JdiffNa=(nass-nai)/2.0 -JdiffK=(kss-ki)/2.0 -Jdiff=(cass-cai)/0.2 - -parameters("ryanodione receptor", -bt=4.75) - -expressions("ryanodione receptor") -a_rel=0.5*bt -Jrel_inf=a_rel*(-ICaL)/(1.0+(1.5*scale_HF_Jrel_inf/cajsr)**8.0) -tau_rel_tmp=bt/(1.0+0.0123/cajsr) -tau_rel=Conditional(Lt(tau_rel_tmp, 0.001), 0.001, tau_rel_tmp) -dJrelnp_dt=(Jrel_inf-Jrelnp)/tau_rel -btp=1.25*bt -a_relp=0.5*btp -Jrel_infp=a_relp*(-ICaL)/(1.0+(1.5*scale_HF_Jrel_inf/cajsr)**8.0) -tau_relp_tmp=btp/(1.0+0.0123/cajsr) -tau_relp=Conditional(Lt(tau_relp_tmp, 0.001), 0.001, tau_relp_tmp) -dJrelp_dt=(Jrel_infp-Jrelp)/tau_relp -fJrelp=(1.0/(1.0+KmCaMK/CaMKa)) -Jrel=(1.0-fJrelp)*Jrelnp+fJrelp*Jrelp - -expressions("calcium buffers") -Jupnp=0.004375*cai/(cai+0.00092) -Jupp=2.75*0.004375*cai/(cai+0.00092-0.00017) -fJupp=(1.0/(1.0+KmCaMK/CaMKa)) -Jleak=0.0039375*cansr*scale_HF_Jleak/15.0 -Jup=(1.0-fJupp)*Jupnp+fJupp*Jupp*scale_HF_Jup-Jleak -Jtr=(cansr-cajsr)/100.0 - -parameters("calcium buffers", "mechanics", -cmdnmax=0.05, -kmcmdn=0.00238, -trpnmax=0.07, -kmtrpn=0.0005, -BSRmax=0.047, -KmBSR=0.00087, -BSLmax=1.124, -KmBSL=0.0087, -csqnmax=10.0, -kmcsqn=0.8) - -expressions("intracellular concentrations") -dnai_dt=-(INa+INaL+3.0*INaCa_i+3.0*INaK+INab+Isac_P_ns/3)*Acap/(F*vmyo)+JdiffNa*vss/vmyo -dnass_dt=-(ICaNa+3.0*INaCa_ss)*Acap/(F*vss)-JdiffNa -dki_dt=-(Ito+IKr+IKs+IK1+IKb+Isac_P_k+Isac_P_ns/3+Istim-2.0*INaK)*Acap/(F*vmyo)+JdiffK*vss/vmyo -dkss_dt=-(ICaK)*Acap/(F*vss)-JdiffK -Bcass=1.0/(1.0+BSRmax*KmBSR/(KmBSR+cass)**2.0+BSLmax*KmBSL/(KmBSL+cass)**2.0) -dcass_dt=Bcass*(-(ICaL-2.0*INaCa_ss)*Acap/(2.0*F*vss)+Jrel*vjsr/vss-Jdiff) -dcansr_dt=Jup-Jtr*vjsr/vnsr -Bcajsr=1.0/(1.0+csqnmax*kmcsqn/(kmcsqn+cajsr)**2.0) -dcajsr_dt=Bcajsr*(Jtr-Jrel) -Bcai=1.0/(1.0+cmdnmax*kmcmdn/(kmcmdn+cai)**2.0) -dcai_dt=Bcai*(-(IpCa+ICab-2.0*INaCa_i+Isac_P_ns/3)*Acap/(2.0*F*vmyo)-Jup*vnsr/vmyo+Jdiff*vss/vmyo - J_TRPN) - - -parameters("mechanics", -emcoupling=1, -lmbda=1, -dLambda=0, -mode=1, -isacs=0, -calib=1, -ktrpn = 0.1, -ntrpn = 2, -Trpn50 = 0.35, -rw = 0.5, -rs = 0.25, -gammas = 0.0085, -gammaw = 0.615, -phi = 2.23, -Tot_A = 25, -Beta0 = 2.3, -Beta1 = -2.4, -cat50_ref = 0.805, -scale_HF_cat50_ref=1.0, -Tref = 120, -kuw = 0.182, -kws = 0.012, -ku=0.04, -ntm=2.4, -p_a = 2.1, -p_b = 9.1, -p_k = 7, -etal = 200, -etas = 20) - -expressions("mechanics") -XS_max = Conditional(Gt(XS, 0), XS, 0) -XW_max = Conditional(Gt(XW, 0), XW, 0) -CaTrpn_max = Conditional(Gt(CaTrpn, 0), CaTrpn, 0) -kwu = kuw*(1/rw-1)-kws -ksu = kws*rw*(1/rs-1) -Aw = Tot_A*rs/((1-rs)*rw+rs) -As = Aw -cw = phi*kuw*((1-rs)*(1-rw))/((1-rs)*rw) -cs = phi*kws*((1-rs)*rw)/rs -lambda_min12 = Conditional(Lt(lmbda, 1.2), lmbda, 1.2) -lambda_min087 = Conditional(Lt(lambda_min12, 0.87), lambda_min12, 0.87) -h_lambda_prima = 1+Beta0*(lambda_min12+lambda_min087-1.87) -h_lambda = Conditional(Gt(h_lambda_prima, 0), h_lambda_prima, 0) -XU = (1-TmB)-XS-XW -gammawu = gammaw*abs(Zetaw) -gammasu = gammas*Conditional(Gt(Gt(Zetas,0)*Zetas, Lt(Zetas, -1)*(-Zetas-1)), Gt(Zetas,0)*Zetas, Lt(Zetas, -1)*(-Zetas-1)) -dXS_dt = kws*XW - ksu*XS - gammasu*XS -dXW_dt = kuw*XU - kwu*XW - kws*XW - gammawu*XW -cat50 = (cat50_ref+Beta1*(lambda_min12-1))*scale_HF_cat50_ref -dCaTrpn_dt = ktrpn*(((cai*1000/cat50)**ntrpn)*(1-CaTrpn)-CaTrpn) -kb = ku*Trpn50**ntm/(1-rs-(1-rs)*rw) -dTmB_dt = kb*Conditional(Lt(CaTrpn**(-ntm/2), 100), CaTrpn**(-ntm/2), 100)*XU-ku*CaTrpn**(ntm/2)*TmB -dZetas_dt = As*dLambda - cs*Zetas -dZetaw_dt = Aw*dLambda - cw*Zetaw -Ta = h_lambda*(Tref/rs)*(XS*(Zetas+1) + XW*Zetaw) -C = lambda_min12 - 1 -dCd = C - Cd -eta = Conditional(Lt(dCd, 0), etas, etal) -dCd_dt = p_k * (C - Cd) / eta -Fd = eta * dCd -F1 = (exp( p_b * C) - 1) -Tp = p_a * (F1 + Fd) -Ttot = Ta + Tp -J_TRPN = dCaTrpn_dt*trpnmax diff --git a/demos/split-cai/3D/ToRORd_dynCl_endo_caisplit.ode b/demos/split-cai/3D/ToRORd_dynCl_endo_caisplit.ode deleted file mode 100644 index bd24bc1..0000000 --- a/demos/split-cai/3D/ToRORd_dynCl_endo_caisplit.ode +++ /dev/null @@ -1,715 +0,0 @@ -states("IKr", -C1=ScalarParam(0.9982511, unit="1", description=""), -C2=ScalarParam( 7.93602000000000023e-4, unit="1", description=""), -C3=ScalarParam( 6.53214300000000045e-4, unit="1", description=""), -I_=ScalarParam( 9.80408300000000003e-6, unit="1", description=""), -O_=ScalarParam( 2.92244900000000025e-4, unit="1", description="") -) - -states("CaMK", -CaMKt=ScalarParam( 1.09502599999999999e-2, unit="mM", description="") -) - -states("ryr", -Jrel_np=ScalarParam( 1.80824799999999996e-22, unit="mM/ms", description=""), -Jrel_p=ScalarParam( 4.35860800000000030e-21, unit="mM/ms", description="") -) - -states("Ito", -a=ScalarParam( 8.89925900000000051e-4, unit="1", description=""), -ap=ScalarParam( 4.53416500000000005e-4, unit="1", description=""), -iF=ScalarParam(0.9996716, unit="1", description=""), -iFp=ScalarParam(0.9996716, unit="1", description=""), -iS=ScalarParam(0.5988908, unit="1", description=""), -iSp=ScalarParam(0.6620692, unit="1", description="") -) - -states("intracellular_ions", -cajsr=ScalarParam(1.525693, unit="mM", description=""), -cansr=ScalarParam(1.528001, unit="mM", description=""), -cass=ScalarParam( 6.49734100000000044e-5, unit="mM", description=""), -cli=ScalarParam(29.20698, unit="mM", description=""), -clss=ScalarParam(29.20696, unit="mM", description=""), -ki=ScalarParam(147.7115, unit="mM", description=""), -kss=ScalarParam(147.7114, unit="mM", description=""), -nai=ScalarParam(12.39736, unit="mM", description=""), -nass=ScalarParam(12.3977, unit="mM", description="") -) - -states("intracellular_ions", -cai=0.0001 -) - -states("ICaL", -d=ScalarParam( 1.58884100000000000e-31, unit="1", description=""), -fcaf=ScalarParam(1, unit="1", description=""), -fcafp=ScalarParam(1, unit="1", description=""), -fcas=ScalarParam(0.9999014, unit="1", description=""), -ff_=ScalarParam(1, unit="1", description=""), -ffp=ScalarParam(1, unit="1", description=""), -fs=ScalarParam(0.9401791, unit="1", description=""), -jca=ScalarParam(0.9999846, unit="1", description=""), -nca_i=ScalarParam( 8.32600900000000053e-4, unit="1", description=""), -nca_ss=ScalarParam( 4.89937800000000024e-4, unit="1", description="") -) - -states("INa", -h=ScalarParam(0.8473267, unit="1", description=""), -hp=ScalarParam(0.7018454, unit="1", description=""), -j=ScalarParam(0.8471657, unit="1", description=""), -jp=ScalarParam(0.8469014, unit="1", description=""), -m=ScalarParam( 6.51715400000000005e-4, unit="1", description="") -) - -states("INaL", -hL=ScalarParam(0.5566017, unit="1", description=""), -hLp=ScalarParam(0.3115491, unit="1", description=""), -mL=ScalarParam( 1.35120299999999988e-4, unit="1", description="") -) - -states("membrane", -v=ScalarParam(-89.74808, unit="mV", description="") -) - -states("IKs", -xs1=ScalarParam(0.243959, unit="1", description=""), -xs2=ScalarParam( 1.58616700000000009e-4, unit="1", description="") -) - -parameters("I_katp", -A_atp=ScalarParam(2.0, unit="mM", description=""), -K_atp=ScalarParam(0.25, unit="mM", description=""), -K_o_n=ScalarParam(5.0, unit="mM", description=""), -fkatp=ScalarParam(0.0, unit="1", description=""), -gkatp=ScalarParam(4.3195, unit="mS/uF", description="") -) - -parameters("ICaL", -Aff=ScalarParam(0.6, unit="1", description=""), -ICaL_fractionSS=ScalarParam(0.8, unit="1", description=""), -Kmn=ScalarParam(0.002, unit="mM", description=""), -PCa_b=ScalarParam(8.3757e-05, unit="1", description=""), -dielConstant=ScalarParam(74.0, unit="1/K", description=""), -k2n=ScalarParam(500.0, unit="mS/uF", description=""), -offset=ScalarParam(0.0, unit="ms", description=""), -tjca=ScalarParam(72.5, unit="ms", description=""), -vShift=ScalarParam(0.0, unit="mV", description="") -) - -parameters("intracellular_ions","mechanics", -BSLmax=ScalarParam(1.124, unit="mM", description=""), -BSRmax=ScalarParam(0.047, unit="mM", description=""), -KmBSL=ScalarParam(0.0087, unit="mM", description=""), -KmBSR=ScalarParam(0.00087, unit="mM", description=""), -cmdnmax_b=ScalarParam(0.05, unit="mM", description=""), -csqnmax=ScalarParam(10.0, unit="mM", description=""), -kmcmdn=ScalarParam(0.00238, unit="mM", description=""), -kmcsqn=ScalarParam(0.8, unit="mM", description=""), -kmtrpn=ScalarParam(0.0005, unit="mM", description=""), -trpnmax=ScalarParam(0.07, unit="mM", description="") -) - -parameters("CaMK", -CaMKo=ScalarParam(0.05, unit="1", description=""), -KmCaM=ScalarParam(0.0015, unit="mM", description=""), -KmCaMK=ScalarParam(0.15, unit="mM", description=""), -aCaMK=ScalarParam(0.05, unit="1/mM/ms", description=""), -bCaMK=ScalarParam(0.00068, unit="mS/uF", description="") -) - -parameters("Ito", -EKshift=ScalarParam(0.0, unit="mV", description=""), -Gto_b=ScalarParam(0.16, unit="mS/uF", description="") -) - -parameters("physical_constants","mechanics", -F=ScalarParam(96485.0, unit="C/mol", description=""), -R=ScalarParam(8314.0, unit="mJ/mol/K", description=""), -T=ScalarParam(310.0, unit="K", description=""), -zca=ScalarParam(2.0, unit="1", description=""), -zcl=ScalarParam(-1.0, unit="1", description=""), -zk=ScalarParam(1.0, unit="1", description=""), -zna=ScalarParam(1.0, unit="1", description="") -) - -parameters("ICl", -Fjunc=ScalarParam(1.0, unit="1", description=""), -GClCa=ScalarParam(0.2843, unit="mS/uF", description=""), -GClb=ScalarParam(0.00198, unit="mS/uF", description=""), -KdClCa=ScalarParam(0.1, unit="mM", description="") -) - -parameters("IK1", -GK1_b=ScalarParam(0.6992, unit="mS/uF", description="") -) - -parameters("IKb", -GKb_b=ScalarParam(0.0189, unit="mS/uF", description="") -) - -parameters("IKr", -GKr_b=ScalarParam(0.0321, unit="mS/uF", description=""), -alpha_1=ScalarParam(0.154375, unit="mS/uF", description=""), -beta_1=ScalarParam(0.1911, unit="mS/uF", description="") -) - -parameters("IKs", -GKs_b=ScalarParam(0.0011, unit="mS/uF", description="") -) - -parameters("INa", -GNa=ScalarParam(11.7802, unit="mS/uF", description="") -) - -parameters("INaL", -GNaL_b=ScalarParam(0.0279, unit="mS/uF", description=""), -thL=ScalarParam(200.0, unit="ms", description="") -) - -parameters("INaCa", -Gncx_b=ScalarParam(0.0034, unit="mS/uF", description=""), -INaCa_fractionSS=ScalarParam(0.35, unit="1", description=""), -KmCaAct=ScalarParam(0.00015, unit="mM", description=""), -kasymm=ScalarParam(12.5, unit="1", description=""), -kcaoff=ScalarParam(5000.0, unit="mS/uF", description=""), -kcaon=ScalarParam(1500000.0, unit="mS/uF", description=""), -kna1=ScalarParam(15.0, unit="mS/uF", description=""), -kna2=ScalarParam(5.0, unit="mS/uF", description=""), -kna3=ScalarParam(88.12, unit="mS/uF", description=""), -qca=ScalarParam(0.167, unit="1", description=""), -qna=ScalarParam(0.5224, unit="1", description=""), -wca=ScalarParam(60000.0, unit="1", description=""), -wna=ScalarParam(60000.0, unit="1", description=""), -wnaca=ScalarParam(5000.0, unit="1", description="") -) - -parameters("IpCa", -GpCa=ScalarParam(0.0005, unit="mS/uF", description=""), -KmCap=ScalarParam(0.0005, unit="mM", description="") -) - -parameters("INaK", -H=ScalarParam(1e-07, unit="mM", description=""), -Khp=ScalarParam(1.698e-07, unit="mM", description=""), -Kki=ScalarParam(0.5, unit="mS/uF", description=""), -Kko=ScalarParam(0.3582, unit="mS/uF", description=""), -Kmgatp=ScalarParam(1.698e-07, unit="mM", description=""), -Knai0=ScalarParam(9.073, unit="mM", description=""), -Knao0=ScalarParam(27.78, unit="mM", description=""), -Knap=ScalarParam(224.0, unit="mM", description=""), -Kxkur=ScalarParam(292.0, unit="mM", description=""), -MgADP=ScalarParam(0.05, unit="mM", description=""), -MgATP=ScalarParam(9.8, unit="mM", description=""), -Pnak_b=ScalarParam(15.4509, unit="mS/uF", description=""), -delta=ScalarParam(-0.155, unit="mV", description=""), -eP=ScalarParam(4.2, unit="1", description=""), -k1m=ScalarParam(182.4, unit="mS/uF", description=""), -k1p=ScalarParam(949.5, unit="mS/uF", description=""), -k2m=ScalarParam(39.4, unit="mS/uF", description=""), -k2p=ScalarParam(687.2, unit="mS/uF", description=""), -k3m=ScalarParam(79300.0, unit="mS/uF", description=""), -k3p=ScalarParam(1899.0, unit="mS/uF", description=""), -k4m=ScalarParam(40.0, unit="mS/uF", description=""), -k4p=ScalarParam(639.0, unit="mS/uF", description="") -) - -parameters("ryr", -Jrel_b=ScalarParam(1.5378, unit="1", description=""), -bt=ScalarParam(4.75, unit="ms", description=""), -cajsr_half=ScalarParam(1.7, unit="mM", description="") -) - -parameters("SERCA", -Jup_b=ScalarParam(1.0, unit="1", description="") -) - -parameters("cell_geometry","mechanics", -L=ScalarParam(0.01, unit="cm", description=""), -rad_=ScalarParam(0.0011, unit="cm", description="") -) - -parameters("ICab", -PCab=ScalarParam(5.9194e-08, unit="mS/uF", description="") -) - -parameters("reversal_potentials", -PKNa=ScalarParam(0.01833, unit="1", description="") -) - -parameters("INab", -PNab=ScalarParam(1.9239e-09, unit="mS/uF", description="") -) - -parameters("extracellular", -cao=ScalarParam(1.8, unit="mM", description=""), -clo=ScalarParam(150.0, unit="mM", description=""), -ko=ScalarParam(5.0, unit="mM", description=""), -nao=ScalarParam(140.0, unit="mM", description="") -) - -parameters("environment", -celltype=ScalarParam(0.0, unit="1", description="") -) - -parameters("membrane", -i_Stim_Amplitude=ScalarParam(-53.0, unit="A/F", description=""), -i_Stim_End=ScalarParam(1e+17, unit="ms", description=""), -i_Stim_Period=ScalarParam(1000.0, unit="ms", description=""), -i_Stim_PulseDuration=ScalarParam(1.0, unit="ms", description=""), -i_Stim_Start=ScalarParam(0.0, unit="ms", description="") -) - -parameters("diff", -tauCa=ScalarParam(0.2, unit="ms", description=""), -tauCl=ScalarParam(2.0, unit="ms", description=""), -tauK=ScalarParam(2.0, unit="ms", description=""), -tauNa=ScalarParam(2.0, unit="ms", description="") -) - -expressions("cell_geometry", "mechanics") -Acap = 2.0*Ageo # cm**2 -Ageo = L*((2.0*3.14)*rad_) + rad_*((2.0*3.14)*rad_) # cm**2 -vcell = L*(rad_*((1000.0*3.14)*rad_)) # uL -vjsr = 0.0048*vcell # uL -vmyo = 0.68*vcell # uL -vnsr = 0.0552*vcell # uL -vss = 0.02*vcell # uL - -expressions("ICaL") -Afcaf = 0.3 + 0.6/(exp((v - 1*10.0)/10.0) + 1.0) -Afcas = 1.0 - Afcaf -Afs = 1.0 - Aff -ICaK = ICaK_i + ICaK_ss # A/F -ICaK_i = (1.0 - ICaL_fractionSS)*((d*(PhiCaK_i*(PCaK*(1.0 - fICaLp))))*(f*(1.0 - nca_i) + nca_i*(fca*jca)) + (d*(PhiCaK_i*(PCaKp*fICaLp)))*(fp*(1.0 - nca_i) + nca_i*(fcap*jca))) # A/F -ICaK_ss = ICaL_fractionSS*((d*(PhiCaK_ss*(PCaK*(1.0 - fICaLp))))*(f*(1.0 - nca_ss) + nca_ss*(fca*jca)) + (d*(PhiCaK_ss*(PCaKp*fICaLp)))*(fp*(1.0 - nca_ss) + nca_ss*(fcap*jca))) # A/F -ICaL_ICaL = ICaL_i + ICaL_ss # A/F -ICaL_i = (1.0 - ICaL_fractionSS)*((d*(PhiCaL_i*(PCa*(1.0 - fICaLp))))*(f*(1.0 - nca_i) + nca_i*(fca*jca)) + (d*(PhiCaL_i*(PCap*fICaLp)))*(fp*(1.0 - nca_i) + nca_i*(fcap*jca))) # A/F -ICaL_ss = ICaL_fractionSS*((d*(PhiCaL_ss*(PCa*(1.0 - fICaLp))))*(f*(1.0 - nca_ss) + nca_ss*(fca*jca)) + (d*(PhiCaL_ss*(PCap*fICaLp)))*(fp*(1.0 - nca_ss) + nca_ss*(fcap*jca))) # A/F -ICaNa = ICaNa_i + ICaNa_ss # A/F -ICaNa_i = (1.0 - ICaL_fractionSS)*((d*(PhiCaNa_i*(PCaNa*(1.0 - fICaLp))))*(f*(1.0 - nca_i) + nca_i*(fca*jca)) + (d*(PhiCaNa_i*(PCaNap*fICaLp)))*(fp*(1.0 - nca_i) + nca_i*(fcap*jca))) # A/F -ICaNa_ss = ICaL_fractionSS*((d*(PhiCaNa_ss*(PCaNa*(1.0 - fICaLp))))*(f*(1.0 - nca_ss) + nca_ss*(fca*jca)) + (d*(PhiCaNa_ss*(PCaNap*fICaLp)))*(fp*(1.0 - nca_ss) + nca_ss*(fcap*jca))) # A/F -Ii = (0.5*(4.0*cai + (cli + (ki + nai))))/1000.0 -Io = (0.5*(4.0*cao + (clo + (ko + nao))))/1000.0 -Iss = (0.5*(4.0*cass + (clss + (kss + nass))))/1000.0 -PCa = Conditional(Eq(celltype, 1.0), 1.2*PCa_b, Conditional(Eq(celltype, 2.0), 2.0*PCa_b, PCa_b)) -PCaK = 0.0003574*PCa -PCaKp = 0.0003574*PCap -PCaNa = 0.00125*PCa -PCaNap = 0.00125*PCap -PCap = 1.1*PCa -PhiCaK_i = ((1.0*vffrt)*(-gamma_ko*ko + (gamma_ki*ki)*exp(1.0*vfrt)))/(exp(1.0*vfrt) - 1*1.0) -PhiCaK_ss = ((1.0*vffrt)*(-gamma_ko*ko + (gamma_kss*kss)*exp(1.0*vfrt)))/(exp(1.0*vfrt) - 1*1.0) -PhiCaL_i = ((4.0*vffrt)*(-cao*gamma_cao + (cai*gamma_cai)*exp(2.0*vfrt)))/(exp(2.0*vfrt) - 1*1.0) -PhiCaL_ss = ((4.0*vffrt)*(-cao*gamma_cao + (cass*gamma_cass)*exp(2.0*vfrt)))/(exp(2.0*vfrt) - 1*1.0) -PhiCaNa_i = ((1.0*vffrt)*(-gamma_nao*nao + (gamma_nai*nai)*exp(1.0*vfrt)))/(exp(1.0*vfrt) - 1*1.0) -PhiCaNa_ss = ((1.0*vffrt)*(-gamma_nao*nao + (gamma_nass*nass)*exp(1.0*vfrt)))/(exp(1.0*vfrt) - 1*1.0) -anca_i = 1.0/(k2n/km2n + (Kmn/cai + 1.0)**4.0) -anca_ss = 1.0/(k2n/km2n + (Kmn/cass + 1.0)**4.0) -constA = 1820000.0/(T*dielConstant)**1.5 -dss = Conditional(Ge(v, 31.4978), 1.0, 1.0763*exp(-1.007*exp(-0.0829*v))) -f = Aff*ff_ + Afs*fs -fICaLp = 1.0/(1.0 + KmCaMK/CaMKa) -fca = Afcaf*fcaf + Afcas*fcas -fcap = Afcaf*fcafp + Afcas*fcas -fcass = fss -fp = Aff*ffp + Afs*fs -fss = 1.0/(exp((v + 19.58)/3.696) + 1.0) -gamma_cai = exp((-constA*4.0)*(sqrt(Ii)/(sqrt(Ii) + 1.0) - 0.3*Ii)) -gamma_cao = exp((-constA*4.0)*(sqrt(Io)/(sqrt(Io) + 1.0) - 0.3*Io)) -gamma_cass = exp((-constA*4.0)*(sqrt(Iss)/(sqrt(Iss) + 1.0) - 0.3*Iss)) -gamma_ki = exp((-constA*1.0)*(sqrt(Ii)/(sqrt(Ii) + 1.0) - 0.3*Ii)) -gamma_ko = exp((-constA*1.0)*(sqrt(Io)/(sqrt(Io) + 1.0) - 0.3*Io)) -gamma_kss = exp((-constA*1.0)*(sqrt(Iss)/(sqrt(Iss) + 1.0) - 0.3*Iss)) -gamma_nai = exp((-constA*1.0)*(sqrt(Ii)/(sqrt(Ii) + 1.0) - 0.3*Ii)) -gamma_nao = exp((-constA*1.0)*(sqrt(Io)/(sqrt(Io) + 1.0) - 0.3*Io)) -gamma_nass = exp((-constA*1.0)*(sqrt(Iss)/(sqrt(Iss) + 1.0) - 0.3*Iss)) -jcass = 1.0/(exp((v + 18.08)/2.7916) + 1.0) -km2n = jca*1.0 # mS/uF -td = (offset + 0.6) + 1.0/(exp((-1*0.05)*((v + vShift) + 6.0)) + exp(0.09*((v + vShift) + 14.0))) # ms -tfcaf = 7.0 + 1.0/(0.04*exp((-(v - 1*4.0))/7.0) + 0.04*exp((v - 1*4.0)/7.0)) # ms -tfcafp = 2.5*tfcaf # ms -tfcas = 100.0 + 1.0/(0.00012*exp((-v)/3.0) + 0.00012*exp(v/7.0)) # ms -tff = 7.0 + 1.0/(0.0045*exp((-(v + 20.0))/10.0) + 0.0045*exp((v + 20.0)/10.0)) # ms -tffp = 2.5*tff # ms -tfs = 1000.0 + 1.0/(3.5e-5*exp((-(v + 5.0))/4.0) + 3.5e-5*exp((v + 5.0)/6.0)) # ms -dd_dt = (-d + dss)/td -dfcaf_dt = (-fcaf + fcass)/tfcaf -dfcafp_dt = (-fcafp + fcass)/tfcafp -dfcas_dt = (-fcas + fcass)/tfcas -dff__dt = (-ff_ + fss)/tff -dffp_dt = (-ffp + fss)/tffp -dfs_dt = (-fs + fss)/tfs -djca_dt = (-jca + jcass)/tjca -dnca_i_dt = anca_i*k2n - km2n*nca_i -dnca_ss_dt = anca_ss*k2n - km2n*nca_ss - -expressions("Ito") -AiF = 1.0/(exp(((EKshift + v) - 1*213.6)/151.2) + 1.0) -AiS = 1.0 - AiF -Gto = Conditional(Or(Eq(celltype, 1.0), Eq(celltype, 2.0)), 2.0*Gto_b, Gto_b) # mS/uF -Ito_Ito = (Gto*(-EK + v))*(i*(a*(1.0 - fItop)) + ip*(ap*fItop)) # A/F -ass = 1.0/(exp((-((EKshift + v) - 1*14.34))/14.82) + 1.0) -assp = 1.0/(exp((-((EKshift + v) - 1*24.34))/14.82) + 1.0) -delta_epi = Conditional(Eq(celltype, 1.0), 1.0 - 0.95/(exp(((EKshift + v) + 70.0)/5.0) + 1.0), 1.0) -dti_develop = 1.354 + 0.0001/(exp((-((EKshift + v) - 1*12.23))/0.2154) + exp(((EKshift + v) - 1*167.4)/15.89)) -dti_recover = 1.0 - 0.5/(exp(((EKshift + v) + 70.0)/20.0) + 1.0) -fItop = 1.0/(1.0 + KmCaMK/CaMKa) -i = AiF*iF + AiS*iS -ip = AiF*iFp + AiS*iSp -iss = 1.0/(exp(((EKshift + v) + 43.94)/5.711) + 1.0) -ta = 1.0515/(1.0/((1.2089*(exp((-((EKshift + v) - 1*18.4099))/29.3814) + 1.0))) + 3.5/(exp(((EKshift + v) + 100.0)/29.3814) + 1.0)) # ms -tiF = delta_epi*tiF_b # ms -tiF_b = 4.562 + 1.0/(0.3933*exp((-((EKshift + v) + 100.0))/100.0) + 0.08004*exp(((EKshift + v) + 50.0)/16.59)) # ms -tiFp = tiF*(dti_develop*dti_recover) # ms -tiS = delta_epi*tiS_b # ms -tiS_b = 23.62 + 1.0/(0.001416*exp((-((EKshift + v) + 96.52))/59.05) + 1.78e-8*exp(((EKshift + v) + 114.1)/8.079)) # ms -tiSp = tiS*(dti_develop*dti_recover) # ms -da_dt = (-a + ass)/ta -dap_dt = (-ap + assp)/ta -diF_dt = (-iF + iss)/tiF -diFp_dt = (-iFp + iss)/tiFp -diS_dt = (-iS + iss)/tiS -diSp_dt = (-iSp + iss)/tiSp - -expressions("intracellular_ions") -Bcajsr = 1.0/((csqnmax*kmcsqn)/((cajsr + kmcsqn)**2.0) + 1.0) -Bcass = 1.0/((BSLmax*KmBSL)/((KmBSL + cass)**2.0) + ((BSRmax*KmBSR)/((KmBSR + cass)**2.0) + 1.0)) -cmdnmax = Conditional(Eq(celltype, 1.0), 1.3*cmdnmax_b, cmdnmax_b) # mM -dcajsr_dt = Bcajsr*(-Jrel + Jtr) # mM -dcansr_dt = Jup - Jtr*vjsr/vnsr # mM -dcass_dt = Bcass*(-Jdiff + ((Acap*(-(ICaL_ss - 2.0*INaCa_ss)))/(((2.0*F)*vss)) + (Jrel*vjsr)/vss)) # mM -dcli_dt = (Acap*(IClCa_sl + IClb))/((F*vmyo)) + (JdiffCl*vss)/vmyo # mM -dclss_dt = -JdiffCl + (Acap*IClCa_junc)/((F*vss)) # mM -dki_dt = (Acap*(-(ICaK_i + (-2.0*INaK_INaK + (Istim + (I_katp_I_katp + (IKb_IKb + (IK1_IK1 + (IKs_IKs + (IKr_IKr + Ito_Ito))))))))))/((F*vmyo)) + (JdiffK*vss)/vmyo # mM -dkss_dt = -JdiffK + (Acap*(-ICaK_ss))/((F*vss)) # mM -dnai_dt = (Acap*(-(INab_INab + (3.0*INaK_INaK + (ICaNa_i + (3.0*INaCa_i + (INaL_INaL + INa_INa)))))))/((F*vmyo)) + (JdiffNa*vss)/vmyo # mM -dnass_dt = -JdiffNa + (Acap*(-(ICaNa_ss + 3.0*INaCa_ss)))/((F*vss)) # mM -Bcai=1.0/(1.0+cmdnmax*kmcmdn/(kmcmdn+cai)**2.0) -dcai_dt=Bcai*(-(IpCa_IpCa+ICab_ICab-2.0*INaCa_i/3)*Acap/(2.0*F*vmyo)-Jup*vnsr/vmyo+Jdiff*vss/vmyo - J_TRPN) - - -expressions("CaMK") -CaMKa = CaMKb + CaMKt # mM -CaMKb = (CaMKo*(1.0 - CaMKt))/(KmCaM/cass + 1.0) # mM -dCaMKt_dt = -CaMKt*bCaMK + (CaMKb*aCaMK)*(CaMKb + CaMKt) # mM - -expressions("INaK") -E1_ = x1/(x4 + (x3 + (x1 + x2))) -E2 = x2/(x4 + (x3 + (x1 + x2))) -E3 = x3/(x4 + (x3 + (x1 + x2))) -E4 = x4/(x4 + (x3 + (x1 + x2))) -INaK_INaK = Pnak*(JnakK*zk + JnakNa*zna) # A/F -JnakK = 2.0*(-E3*a1 + E4*b1) # mM/ms -JnakNa = 3.0*(E1_*a3 - E2*b3) # mM/ms -Knai = Knai0*exp((delta*vfrt)/3.0) # mM -Knao = Knao0*exp((vfrt*(1.0 - delta))/3.0) # mM -P = eP/(((H/Khp + 1.0) + nai/Knap) + ki/Kxkur) -Pnak = Conditional(Eq(celltype, 1.0), 0.9*Pnak_b, Conditional(Eq(celltype, 2.0), 0.7*Pnak_b, Pnak_b)) # mS/uF -a1 = (k1p*(nai/Knai)**3.0)/(((1.0 + ki/Kki)**2.0 + (1.0 + nai/Knai)**3.0) - 1*1.0) -a2 = k2p -a3 = (k3p*(ko/Kko)**2.0)/(((1.0 + ko/Kko)**2.0 + (1.0 + nao/Knao)**3.0) - 1*1.0) -a4 = ((MgATP*k4p)/Kmgatp)/(1.0 + MgATP/Kmgatp) -b1 = MgADP*k1m -b2 = (k2m*(nao/Knao)**3.0)/(((1.0 + ko/Kko)**2.0 + (1.0 + nao/Knao)**3.0) - 1*1.0) -b3 = (H*(P*k3m))/(1.0 + MgATP/Kmgatp) -b4 = (k4m*(ki/Kki)**2.0)/(((1.0 + ki/Kki)**2.0 + (1.0 + nai/Knai)**3.0) - 1*1.0) -x1 = a2*(a1*b3) + (b3*(a2*b4) + (a2*(a1*a4) + b3*(b2*b4))) -x2 = b4*(a2*a3) + (b4*(a3*b1) + (a3*(a1*a2) + b4*(b1*b2))) -x3 = b1*(a3*a4) + (a4*(b1*b2) + (a4*(a2*a3) + b1*(b2*b3))) -x4 = a1*(b2*b3) + (a1*(a4*b2) + (a1*(a3*a4) + b2*(b3*b4))) - -expressions("INaCa") -E1_i = x1_i/(x4_i + (x3_i + (x1_i + x2_i))) -E1_ss = x1_ss/(x4_ss + (x3_ss + (x1_ss + x2_ss))) -E2_i = x2_i/(x4_i + (x3_i + (x1_i + x2_i))) -E2_ss = x2_ss/(x4_ss + (x3_ss + (x1_ss + x2_ss))) -E3_i = x3_i/(x4_i + (x3_i + (x1_i + x2_i))) -E3_ss = x3_ss/(x4_ss + (x3_ss + (x1_ss + x2_ss))) -E4_i = x4_i/(x4_i + (x3_i + (x1_i + x2_i))) -E4_ss = x4_ss/(x4_ss + (x3_ss + (x1_ss + x2_ss))) -Gncx = Conditional(Eq(celltype, 1.0), 1.1*Gncx_b, Conditional(Eq(celltype, 2.0), 1.4*Gncx_b, Gncx_b)) # mS/uF -INaCa_i = (allo_i*(Gncx*(1.0 - INaCa_fractionSS)))*(JncxCa_i*zca + JncxNa_i*zna) # A/F -INaCa_ss = (allo_ss*(Gncx*INaCa_fractionSS))*(JncxCa_ss*zca + JncxNa_ss*zna) # A/F -JncxCa_i = -E1_i*k1_i + E2_i*k2_i # mM/ms -JncxCa_ss = -E1_ss*k1_ss + E2_ss*k2_ss # mM/ms -JncxNa_i = -E2_i*k3pp_i + (E3_i*k4pp_i + 3.0*(-E1_i*k8_i + E4_i*k7_i)) # mM/ms -JncxNa_ss = -E2_ss*k3pp_ss + (E3_ss*k4pp_ss + 3.0*(-E1_ss*k8_ss + E4_ss*k7_ss)) # mM/ms -allo_i = 1.0/((KmCaAct/cai)**2.0 + 1.0) -allo_ss = 1.0/((KmCaAct/cass)**2.0 + 1.0) -h10_i = (nao/kna1)*(1.0 + nao/kna2) + (kasymm + 1.0) -h10_ss = (nao/kna1)*(1.0 + nao/kna2) + (kasymm + 1.0) -h11_i = (nao*nao)/((kna2*(h10_i*kna1))) -h11_ss = (nao*nao)/((kna2*(h10_ss*kna1))) -h12_i = 1.0/h10_i -h12_ss = 1.0/h10_ss -h1_i = (nai/kna3)*(hna + 1.0) + 1.0 -h1_ss = (nass/kna3)*(hna + 1.0) + 1.0 -h2_i = (hna*nai)/((h1_i*kna3)) -h2_ss = (hna*nass)/((h1_ss*kna3)) -h3_i = 1.0/h1_i -h3_ss = 1.0/h1_ss -h4_i = (nai/kna1)*(1.0 + nai/kna2) + 1.0 -h4_ss = (nass/kna1)*(1.0 + nass/kna2) + 1.0 -h5_i = (nai*nai)/((kna2*(h4_i*kna1))) -h5_ss = (nass*nass)/((kna2*(h4_ss*kna1))) -h6_i = 1.0/h4_i -h6_ss = 1.0/h4_ss -h7_i = (nao/kna3)*(1.0 + 1.0/hna) + 1.0 -h7_ss = (nao/kna3)*(1.0 + 1.0/hna) + 1.0 -h8_i = nao/((h7_i*(hna*kna3))) -h8_ss = nao/((h7_ss*(hna*kna3))) -h9_i = 1.0/h7_i -h9_ss = 1.0/h7_ss -hca = exp(qca*vfrt) -hna = exp(qna*vfrt) -k1_i = kcaon*(cao*h12_i) -k1_ss = kcaon*(cao*h12_ss) -k2_i = kcaoff -k2_ss = kcaoff -k3_i = k3p_i + k3pp_i -k3_ss = k3p_ss + k3pp_ss -k3p_i = h9_i*wca -k3p_ss = h9_ss*wca -k3pp_i = h8_i*wnaca -k3pp_ss = h8_ss*wnaca -k4_i = k4p_i + k4pp_i -k4_ss = k4p_ss + k4pp_ss -k4p_i = (h3_i*wca)/hca -k4p_ss = (h3_ss*wca)/hca -k4pp_i = h2_i*wnaca -k4pp_ss = h2_ss*wnaca -k5_i = kcaoff -k5_ss = kcaoff -k6_i = kcaon*(cai*h6_i) -k6_ss = kcaon*(cass*h6_ss) -k7_i = wna*(h2_i*h5_i) -k7_ss = wna*(h2_ss*h5_ss) -k8_i = wna*(h11_i*h8_i) -k8_ss = wna*(h11_ss*h8_ss) -x1_i = (k2_i*k4_i)*(k6_i + k7_i) + (k5_i*k7_i)*(k2_i + k3_i) -x1_ss = (k2_ss*k4_ss)*(k6_ss + k7_ss) + (k5_ss*k7_ss)*(k2_ss + k3_ss) -x2_i = (k1_i*k7_i)*(k4_i + k5_i) + (k4_i*k6_i)*(k1_i + k8_i) -x2_ss = (k1_ss*k7_ss)*(k4_ss + k5_ss) + (k4_ss*k6_ss)*(k1_ss + k8_ss) -x3_i = (k1_i*k3_i)*(k6_i + k7_i) + (k6_i*k8_i)*(k2_i + k3_i) -x3_ss = (k1_ss*k3_ss)*(k6_ss + k7_ss) + (k6_ss*k8_ss)*(k2_ss + k3_ss) -x4_i = (k2_i*k8_i)*(k4_i + k5_i) + (k3_i*k5_i)*(k1_i + k8_i) -x4_ss = (k2_ss*k8_ss)*(k4_ss + k5_ss) + (k3_ss*k5_ss)*(k1_ss + k8_ss) - -expressions("reversal_potentials") -ECl = ((R*T)/((F*zcl)))*log(clo/cli) # mV -EClss = ((R*T)/((F*zcl)))*log(clo/clss) # mV -EK = ((R*T)/((F*zk)))*log(ko/ki) # mV -EKs = ((R*T)/((F*zk)))*log((PKNa*nao + ko)/(PKNa*nai + ki)) # mV -ENa = ((R*T)/((F*zna)))*log(nao/nai) # mV - -expressions("IK1") -GK1 = Conditional(Eq(celltype, 1.0), 1.2*GK1_b, Conditional(Eq(celltype, 2.0), 1.3*GK1_b, GK1_b)) # mS/uF -IK1_IK1 = (K1ss*(GK1*sqrt(ko/5.0)))*(-EK + v) # A/F -K1ss = aK1/(aK1 + bK1) -aK1 = 4.094/(exp(0.1217*((-EK + v) - 1*49.934)) + 1.0) -bK1 = (15.72*exp(0.0674*((-EK + v) - 1*3.257)) + exp(0.0618*((-EK + v) - 1*594.31)))/(exp((-1*0.1629)*((-EK + v) + 14.207)) + 1.0) - -expressions("IKb") -GKb = Conditional(Eq(celltype, 1.0), 0.6*GKb_b, GKb_b) # mS/uF -IKb_IKb = (GKb*xkb)*(-EK + v) # A/F -xkb = 1.0/(exp((-(v - 1*10.8968))/23.9871) + 1.0) - -expressions("IKr") -GKr = Conditional(Eq(celltype, 1.0), 1.3*GKr_b, Conditional(Eq(celltype, 2.0), 0.8*GKr_b, GKr_b)) # mS/uF -IKr_IKr = (O_*(GKr*sqrt(ko/5.0)))*(-EK + v) # A/F -alpha = 0.1161*exp(0.299*vfrt) # mS/uF -alpha_2 = 0.0578*exp(0.971*vfrt) # mS/uF -alpha_C2ToI = 5.2e-5*exp(1.525*vfrt) # mS/uF -alpha_i = 0.2533*exp(0.5953*vfrt) # mS/uF -beta_ = 0.2442*exp((-1*1.604)*vfrt) # mS/uF -beta_2 = 0.000349*exp((-1*1.062)*vfrt) # mS/uF -beta_ItoC2 = (alpha_C2ToI*(beta_2*beta_i))/((alpha_2*alpha_i)) # mS/uF -beta_i = 0.06525*exp((-1*0.8209)*vfrt) # mS/uF -dC1_dt = -C1*(alpha_C2ToI + (alpha_2 + beta_1)) + (I_*beta_ItoC2 + (C2*alpha_1 + O_*beta_2)) -dC2_dt = -C2*(alpha_1 + beta_) + (C1*beta_1 + C3*alpha) -dC3_dt = C2*beta_ - C3*alpha -dI__dt = -I_*(beta_ItoC2 + beta_i) + (C1*alpha_C2ToI + O_*alpha_i) -dO__dt = -O_*(alpha_i + beta_2) + (C1*alpha_2 + I_*beta_i) - -expressions("IKs") -GKs = Conditional(Eq(celltype, 1.0), 1.4*GKs_b, GKs_b) # mS/uF -IKs_IKs = (xs2*(xs1*(GKs*KsCa)))*(-EKs + v) # A/F -KsCa = 1.0 + 0.6/((3.8e-5/cai)**1.4 + 1.0) -txs1 = 817.3 + 1.0/(0.0002326*exp((v + 48.28)/17.8) + 0.001292*exp((-(v + 210.0))/230.0)) # ms -txs2 = 1.0/(0.01*exp((v - 1*50.0)/20.0) + 0.0193*exp((-(v + 66.54))/31.0)) # ms -xs1ss = 1.0/(exp((-(v + 11.6))/8.932) + 1.0) -xs2ss = xs1ss -dxs1_dt = (-xs1 + xs1ss)/txs1 -dxs2_dt = (-xs2 + xs2ss)/txs2 - -expressions("INaL") -GNaL = Conditional(Eq(celltype, 1.0), 0.6*GNaL_b, GNaL_b) # mS/uF -INaL_INaL = (mL*(GNaL*(-ENa + v)))*(fINaLp*hLp + hL*(1.0 - fINaLp)) # A/F -fINaLp = 1.0/(1.0 + KmCaMK/CaMKa) -hLss = 1.0/(exp((v + 87.61)/7.488) + 1.0) -hLssp = 1.0/(exp((v + 93.81)/7.488) + 1.0) -mLss = 1.0/(exp((-(v + 42.85))/5.264) + 1.0) -thLp = 3.0*thL # ms -tmL = 0.06487*exp(-((v - 1*4.823)/51.12)**2.0) + 0.1292*exp(-((v + 45.79)/15.54)**2.0) # ms -dhL_dt = (-hL + hLss)/thL -dhLp_dt = (-hLp + hLssp)/thLp -dmL_dt = (-mL + mLss)/tmL - -expressions("ICab") -ICab_ICab = ((vffrt*(PCab*4.0))*(-cao*gamma_cao + (cai*gamma_cai)*exp(2.0*vfrt)))/(exp(2.0*vfrt) - 1*1.0) # A/F - -expressions("ICl") -IClCa = IClCa_junc + IClCa_sl # A/F -IClCa_junc = ((Fjunc*GClCa)/(KdClCa/cass + 1.0))*(-EClss + v) # A/F -IClCa_sl = ((GClCa*(1.0 - Fjunc))/(KdClCa/cai + 1.0))*(-ECl + v) # A/F -IClb = GClb*(-ECl + v) # A/F - -expressions("INa") -INa_INa = (m**3.0*(GNa*(-ENa + v)))*(j*(h*(1.0 - fINap)) + jp*(fINap*hp)) # A/F -ah = Conditional(Gt(v, -1*40.0), 0.0, 4.43126792958051e-7*exp(-0.147058823529412*v)) -aj = Conditional(Gt(v, -1*40.0), 0.0, -(v + 37.78)*(25428.0*exp(0.28831*v) + 6.948e-6)*exp(-0.04391*v)/(50262745825.954*exp(0.311*v) + 1.0)) -bh = Conditional(Gt(v, -1*40.0), 0.77*exp(0.0900900900900901*v)/(0.13*exp(0.0900900900900901*v) + 0.0497581410839387), 2.7*exp(0.079*v) + 310000.0*exp(0.3485*v)) -bj = Conditional(Gt(v, -1*40.0), 0.6*exp(0.157*v)/(1.0*exp(0.1*v) + 0.0407622039783662), 0.02424*exp(0.12728*v)/(1.0*exp(0.1378*v) + 0.00396086833990426)) -fINap = 1.0/(1.0 + KmCaMK/CaMKa) -hss = 1.0/((exp((v + 71.55)/7.43) + 1.0)**2.0) -hssp = 1.0/((exp((v + 77.55)/7.43) + 1.0)**2.0) -jss = hss -mss = 1.0/((exp((-(v + 56.86))/9.03) + 1.0)**2.0) -th = 1.0/(ah + bh) # ms -tj = 1.0/(aj + bj) # ms -tjp = 1.46*tj # ms -tm = 0.06487*exp(-((v - 1*4.823)/51.12)**2.0) + 0.1292*exp(-((v + 45.79)/15.54)**2.0) # ms -dh_dt = (-h + hss)/th -dhp_dt = (-hp + hssp)/th -dj_dt = (-j + jss)/tj -djp_dt = (-jp + jss)/tjp -dm_dt = (-m + mss)/tm - -expressions("INab") -INab_INab = ((PNab*vffrt)*(nai*exp(vfrt) - nao))/(exp(vfrt) - 1*1.0) # A/F - -expressions("I_katp") -I_katp_I_katp = (bkik*(akik*(fkatp*gkatp)))*(-EK + v) # A/F -akik = (ko/K_o_n)**0.24 -bkik = 1.0/((A_atp/K_atp)**2.0 + 1.0) - -expressions("IpCa") -IpCa_IpCa = (GpCa*cai)/(KmCap + cai) # A/F - -expressions("membrane") -Istim = Conditional(And(Le(i_Stim_Start, time), Ge(i_Stim_PulseDuration, -i_Stim_Period*floor(-(i_Stim_Start - time)/i_Stim_Period) - i_Stim_Start + time)), i_Stim_Amplitude, 0.0) # A/F -vffrt = (F*(F*v))/((R*T)) # C/mol -vfrt = (F*v)/((R*T)) -dv_dt = -(Istim + (I_katp_I_katp + (IClb + (IClCa + (ICab_ICab + (IpCa_IpCa + (IKb_IKb + (INab_INab + (INaK_INaK + (INaCa_ss + (INaCa_i + (IK1_IK1 + (IKs_IKs + (IKr_IKr + (ICaK + (ICaNa + (ICaL_ICaL + (Ito_Ito + (INaL_INaL + INa_INa))))))))))))))))))) # mV - -expressions("diff") -Jdiff = (-cai + cass)/tauCa # mM/ms -JdiffCl = (-cli + clss)/tauNa # mM/ms -JdiffK = (-ki + kss)/tauK # mM/ms -JdiffNa = (-nai + nass)/tauNa # mM/ms - -expressions("SERCA") -Jleak = (0.0048825*cansr)/15.0 # mM/ms -Jup = Jup_b*(-Jleak + (Jupnp*(1.0 - fJupp) + Jupp*fJupp)) # mM/ms -Jupnp = (cai*(upScale*0.005425))/(cai + 0.00092) # mM/ms -Jupp = (cai*((upScale*2.75)*0.005425))/((cai + 0.00092) - 1*0.00017) # mM/ms -fJupp = 1.0/(1.0 + KmCaMK/CaMKa) -upScale = Conditional(Eq(celltype, 1.0), 1.3, 1.0) - -expressions("ryr") -Jrel = Jrel_b*(Jrel_np*(1.0 - fJrelp) + Jrel_p*fJrelp) # mM/ms -Jrel_inf = Conditional(Eq(celltype, 2.0), 1.7*Jrel_inf_b, Jrel_inf_b) # mM/ms -Jrel_inf_b = ((ICaL_ss*(-a_rel))/1.0)/((cajsr_half/cajsr)**8.0 + 1.0) # mM/ms -Jrel_infp = Conditional(Eq(celltype, 2.0), 1.7*Jrel_infp_b, Jrel_infp_b) # mM/ms -Jrel_infp_b = ((ICaL_ss*(-a_relp))/1.0)/((cajsr_half/cajsr)**8.0 + 1.0) # mM/ms -a_rel = (0.5*bt)/1.0 # mM/ms -a_relp = (0.5*btp)/1.0 # mM/ms -btp = 1.25*bt # ms -fJrelp = 1.0/(1.0 + KmCaMK/CaMKa) -tau_rel = Conditional(Lt(tau_rel_b, 0.001), 0.001, tau_rel_b) # ms -tau_rel_b = bt/(1.0 + 0.0123/cajsr) # ms -tau_relp = Conditional(Lt(tau_relp_b, 0.001), 0.001, tau_relp_b) # ms -tau_relp_b = btp/(1.0 + 0.0123/cajsr) # ms -dJrel_np_dt = (Jrel_inf - Jrel_np)/tau_rel # mM/ms -dJrel_p_dt = (Jrel_infp - Jrel_p)/tau_relp # mM/ms - -expressions("trans_flux") -Jtr = (-cajsr + cansr)/60.0 # mM/ms - - - -states("mechanics", -XS=0, -XW=0, -CaTrpn=1e-8, -TmB=1, -Zetas=0, -Zetaw=0, -Cd=0 -) - -parameters("mechanics", -emcoupling=1, -lmbda=1, -dLambda=0, -mode=1, -isacs=0, -calib=1, -ktrpn = 0.1, -ntrpn = 2, -Trpn50 = 0.35, -rw = 0.5, -rs = 0.25, -gammas = 0.0085, -gammaw = 0.615, -phi = 2.23, -Tot_A = 25, -Beta0 = 2.3, -Beta1 = -2.4, -cat50_ref = 0.805, -Tref = 120, -kuw = 0.182, -kws = 0.012, -ku=0.04, -ntm=2.4, -p_a = 2.1, -p_b = 9.1, -p_k = 7, -etal = 200, -etas = 20) - -expressions("mechanics") -XS_max = Conditional(Gt(XS, 0), XS, 0) -XW_max = Conditional(Gt(XW, 0), XW, 0) -CaTrpn_max = Conditional(Gt(CaTrpn, 0), CaTrpn, 0) -kwu = kuw*(1/rw-1)-kws -ksu = kws*rw*(1/rs-1) -Aw = Tot_A*rs/((1-rs)*rw+rs) -As = Aw -cw = phi*kuw*((1-rs)*(1-rw))/((1-rs)*rw) -cs = phi*kws*((1-rs)*rw)/rs -XU = (1-TmB)-XS-XW -gammawu = gammaw*Abs(Zetaw) -gammasu = gammas*Conditional(Gt(Gt(Zetas,0)*Zetas, Lt(Zetas, -1)*(-Zetas-1)), Gt(Zetas,0)*Zetas, Lt(Zetas, -1)*(-Zetas-1)) -dXS_dt = kws*XW - ksu*XS - gammasu*XS -dXW_dt = kuw*XU - kwu*XW - kws*XW - gammawu*XW -cat50 = (cat50_ref+Beta1*(lambda_min12-1)) -dCaTrpn_dt = ktrpn*(((cai*1000/cat50)**ntrpn)*(1-CaTrpn)-CaTrpn) -kb = ku*Trpn50**ntm/(1-rs-(1-rs)*rw) -dTmB_dt = kb*Conditional(Lt(CaTrpn**(-ntm/2), 100), CaTrpn**(-ntm/2), 100)*XU-ku*CaTrpn**(ntm/2)*TmB -J_TRPN = dCaTrpn_dt*trpnmax -lambda_min12 = Conditional(Lt(lmbda, 1.2), lmbda, 1.2) -dZetas_dt = As*dLambda - cs*Zetas -dZetaw_dt = Aw*dLambda - cw*Zetaw -lambda_min087 = Conditional(Lt(lambda_min12, 0.87), lambda_min12, 0.87) -h_lambda_prima = 1+Beta0*(lambda_min12+lambda_min087-1.87) -h_lambda = Conditional(Gt(h_lambda_prima, 0), h_lambda_prima, 0) -Ta = h_lambda*(Tref/rs)*(XS*(Zetas+1) + XW*Zetaw) -C = lambda_min12 - 1 -dCd = C - Cd -eta = Conditional(Lt(dCd, 0), etas, etal) -dCd_dt = p_k * (C - Cd) / eta -Fd = eta * dCd -F1 = (exp( p_b * C) - 1) -Tp = p_a * (F1 + Fd) -Ttot = Ta + Tp diff --git a/demos/split-cai/3D/config.toml b/demos/split-cai/3D/config.toml deleted file mode 100644 index 739b3d2..0000000 --- a/demos/split-cai/3D/config.toml +++ /dev/null @@ -1,117 +0,0 @@ -# Configuration file for running a simulation - -# SIMULATION PARAMETERS -sim.mech_mesh = "mesh_mech_3.0" # mechanics mesh filepath without extension -sim.outdir = "100ms_N1_cai_split_runcheck" # Output directory -sim.sim_dur = 100 # Duration of simulation. Integer -sim.dt = 0.05 # Timestep for ep solve -sim.N = 1 # Solve mechanics step every nth ep solve - -# MODEL PARAMETERS -sim.modelfile = "ORdmm_Land.ode" - -# OUTPUT PARAMETERS -write_all_ep.numbers = 2 -write_all_ep.0.name = "cai" -write_all_ep.1.name = "v" - -write_all_mech.numbers = 2 -write_all_mech.0.name = "Ta" -write_all_mech.1.name = "lambda" - -# Currently output both point traces and average values for these: -write_point_ep.numbers = 2 -write_point_ep.0.name = "cai" -write_point_ep.0.x = 0.0 -write_point_ep.0.y = 0 -write_point_ep.0.z = 0 -write_point_ep.1.name = "v" -write_point_ep.1.x = 0 -write_point_ep.1.y = 0 -write_point_ep.1.z = 0 - -write_point_mech.numbers = 6 -write_point_mech.0.name = "Ta" -write_point_mech.0.x = 0 -write_point_mech.0.y = 0 -write_point_mech.0.z = 0 -write_point_mech.1.name = "Zetas" -write_point_mech.1.x = 0 -write_point_mech.1.y = 0 -write_point_mech.1.z = 0 -write_point_mech.2.name = "XS" -write_point_mech.2.x = 0 -write_point_mech.2.y = 0 -write_point_mech.2.z = 0 -write_point_mech.3.name = "TmB" -write_point_mech.3.x = 0 -write_point_mech.3.y = 0 -write_point_mech.3.z = 0 -write_point_mech.4.name = "CaTrpn" -write_point_mech.4.x = 0 -write_point_mech.4.y = 0 -write_point_mech.4.z = 0 -write_point_mech.5.name = "lambda" -write_point_mech.5.x = 0 -write_point_mech.5.y = 0 -write_point_mech.5.z = 0 - - -# Tissue conductivity values. Currently only a single region, from p.4339 of Niederer benchmark -ep.sigma_il = 0.17 # mS / mm -ep.sigma_it = 0.019 # mS / mm -ep.sigma_el = 0.62 # mS / mm -ep.sigma_et = 0.24 # mS / mm - -# Material parameters -# TODO: make material parameters more generic -mech.a=2.28 -mech.a_f=1.686 -mech.b=9.726 -mech.b_f=15.779 -mech.a_s=0.0 -mech.b_s=0.0 -mech.a_fs=0.0 -mech.b_fs=0.0 - -# STIMULUS PARAMETERS -stim.start = 0.0 -stim.amplitude = 50000.0 # mu A/cm^3 -stim.duration = 2 # ms -stim.xmin = 0.0 -stim.xmax = 1.5 -stim.ymin = 0.0 -stim.ymax = 1.5 -stim.zmin = 0.0 -stim.zmax = 1.5 - -# BOUNDARY CONDITIONS -bcs.numbers = 3 #4 -bcs.markerfile = "mesh_mech_3dx_20Lx_7Ly_3Lz_surface_ffun" - -# Mesh markers used for assigning bcs -bcs.0.marker = 1 -bcs.0.type = "Dirichlet" -bcs.0.V = "u_x" -bcs.0.expression = 0 -bcs.0.param_numbers = 0 - -bcs.1.marker = 3 # if same marker for ux,uy,uz, (e.g. marker = 1), then fixes the entire plane (plane with marker == 1) -bcs.1.type = "Dirichlet" -bcs.1.V = "u_y" -bcs.1.expression = 0 -bcs.1.param_numbers = 0 - -bcs.2.marker = 5 -bcs.2.type = "Dirichlet" -bcs.2.V = "u_z" -bcs.2.expression = 0 -bcs.2.param_numbers = 0 - -#bcs.3.marker = 2 -#bcs.3.type = "Neumann" -#bcs.3.expression = 'a*t' # Value can be a function of t -#bcs.3.param_numbers = 1 -#bcs.3.param.0.name = 'a' -#bcs.3.param.0.value = -0.2 -#bcs.3.degree = 1 diff --git a/demos/split-cai/3D/main_using_config.py b/demos/split-cai/3D/main_using_config.py deleted file mode 100644 index b853f46..0000000 --- a/demos/split-cai/3D/main_using_config.py +++ /dev/null @@ -1,700 +0,0 @@ -import logging -import gotranx -from pathlib import Path -from typing import Sequence -import numpy as np -import dolfin -import pulse -import beat -import argparse -import toml - -import matplotlib.pyplot as plt - -from simcardems2 import utils -from simcardems2 import mechanicssolver -from simcardems2 import interpolation -from simcardems2.land_caisplit import LandModel -from simcardems2.validate_input_types import validate_input_types - - -try: - raise ImportError - from numba import jit -except ImportError: - - def jit(*args, **kwargs): - def wrapper(func): - return func - - return wrapper - - -logging.getLogger("beat").setLevel(logging.ERROR) - - -def parse_parameters(argv: Sequence[str] | None = None) -> int: - parser = argparse.ArgumentParser(description="Simcardems CLI") - parser.add_argument("config-file", type=Path, help="Config file") - - args = vars(parser.parse_args(argv)) - try: - config = toml.loads(args["config-file"].read_text()) - except toml.TomlDecodeError as e: - print(f"Error when parsing input parameters. Check config file. Error: {e}") - exit(1) - return config - - -config = parse_parameters() - -validate_input_types(config) - -stim_region = ( - [config["stim"]["xmin"], config["stim"]["xmax"]], - [config["stim"]["ymin"], config["stim"]["ymax"]], - [config["stim"]["zmin"], config["stim"]["zmax"]], -) -out_ep_var_names = [ - config["write_all_ep"][f"{i}"]["name"] for i in range(config["write_all_ep"]["numbers"]) -] -out_mech_var_names = [ - config["write_all_mech"][f"{i}"]["name"] for i in range(config["write_all_mech"]["numbers"]) -] -out_ep_coord_names = [ - config["write_point_ep"][f"{i}"]["name"] for i in range(config["write_point_ep"]["numbers"]) -] -ep_coords = [ - [config["write_point_ep"][f"{varnr}"][f"{coord}"] for coord in ["x", "y", "z"]] - for varnr in range(config["write_point_ep"]["numbers"]) -] -out_mech_coord_names = [ - config["write_point_mech"][f"{i}"]["name"] for i in range(config["write_point_mech"]["numbers"]) -] -mech_coords = [ - [config["write_point_mech"][f"{varnr}"][f"{coord}"] for coord in ["x", "y", "z"]] - for varnr in range(config["write_point_mech"]["numbers"]) -] - - -outdir = Path(config["sim"]["outdir"]) -outdir.mkdir(parents=True, exist_ok=True) - -with open(Path(outdir / "config.txt"), "w") as f: - f.write(toml.dumps(config)) - - -# TODO: do a different dirichlet/neumann check than this later. something smoother -t_bcs = dolfin.Constant(0) -bcs_dirichlet = [] -bcs_neumann = [] -bcs_expressions = {} -for bc in range(config["bcs"]["numbers"]): - if config["bcs"][f"{bc}"]["type"] == "Dirichlet": - bcs_dirichlet.append(bc) - elif config["bcs"][f"{bc}"]["type"] == "Neumann": - bcs_neumann.append(bc) - else: - raise KeyError( - f'{config["bcs"][str(bc)]["type"]} is not a valid type of boundary ' - 'condition. Use Dirichlet or Neumann. Check config file' - ) - - if config["bcs"][f"{bc}"]["param_numbers"] > 0: - bcs_parameters = {} - for param_nr in range(config["bcs"][f"{bc}"]["param_numbers"]): - param_name = config["bcs"][f"{bc}"]["param"][f"{param_nr}"]["name"] - param_value = config["bcs"][f"{bc}"]["param"][f"{param_nr}"]["value"] - bcs_parameters[param_name] = param_value - bcs_expressions[f"{bc}"] = dolfin.Expression( - config["bcs"][f"{bc}"]["expression"], - **bcs_parameters, - t=t_bcs, - degree=config["bcs"][f"{bc}"]["degree"], - ) - else: - bcs_expressions[f"{bc}"] = dolfin.Constant(0) - - -mesh = dolfin.Mesh() -with dolfin.XDMFFile(f'{config["sim"]["mech_mesh"]}.xdmf') as infile: - infile.read(mesh) -print(f'Loaded mesh: {config["sim"]["mech_mesh"]}') - - -ffun_bcs = dolfin.MeshFunction("size_t", mesh, mesh.topology().dim() - 1) -with dolfin.XDMFFile(f'{config["bcs"]["markerfile"]}.xdmf') as infile: - infile.read(ffun_bcs) -print(f'Loaded markerfile for bcs: {config["bcs"]["markerfile"]}') - - -tol = 5e-4 -# Surface to volume ratio -chi = 140.0 # mm^{-1} -# Membrane capacitance -C_m = 0.01 # mu F / mm^2 -cm2mm = 10.0 - -t = np.arange(0, config["sim"]["sim_dur"], config["sim"]["dt"]) -sigma = [ - config["ep"]["sigma_il"], - config["ep"]["sigma_it"], - config["ep"]["sigma_el"], - config["ep"]["sigma_et"], -] -material_parameters = dict( - a=config["mech"]["a"], - a_f=config["mech"]["a_f"], - b=config["mech"]["b"], - b_f=config["mech"]["b_f"], - a_s=config["mech"]["a_s"], - b_s=config["mech"]["b_s"], - a_fs=config["mech"]["a_fs"], - b_fs=config["mech"]["b_fs"], -) - - -dolfin.parameters["form_compiler"]["representation"] = "uflacs" -dolfin.parameters["form_compiler"]["cpp_optimize"] = True -dolfin.parameters["form_compiler"]["quadrature_degree"] = 4 - - -def define_conductivity_tensor(sigma, chi, C_m): - # Compute monodomain approximation by taking harmonic mean in each - # direction of intracellular and extracellular part - def harmonic_mean(a, b): - return a * b / (a + b) - - sigma_l = harmonic_mean(sigma[0], sigma[2]) - sigma_t = harmonic_mean(sigma[1], sigma[3]) - - # Scale conducitivites by 1/(C_m * chi) - s_l = sigma_l / (C_m * chi) # mm^2 / ms - s_t = sigma_t / (C_m * chi) # mm^2 / ms - - # Define conductivity tensor - M = dolfin.as_tensor(((s_l, 0, 0), (0, s_t, 0), (0, 0, s_t))) - - return M - - -def define_stimulus( - mesh, - chi, - C_m, - time, - stim_region=stim_region, - stim_start=config["stim"]["start"], - A=config["stim"]["amplitude"], - duration=config["stim"]["duration"], -): - S1_marker = 1 - S1_subdomain = dolfin.CompiledSubDomain( - " ".join( - ( - f"x[0] >= {stim_region[0][0]}", - f"&& x[0] <= {stim_region[0][1]}", - f"&& x[1] >= {stim_region[1][0]}", - f"&& x[1] <= {stim_region[1][1]}", - f"&& x[2] >= {stim_region[2][0]}", - f"&& x[2] <= {stim_region[2][1]}", - ) - ) - ) - - S1_markers = dolfin.MeshFunction("size_t", mesh, mesh.topology().dim()) - S1_subdomain.mark(S1_markers, S1_marker) - with dolfin.XDMFFile((outdir / "stim_region_markers.xdmf").as_posix()) as xdmf: - xdmf.write(S1_markers) - - # Define stimulation (NB: region of interest carried by the mesh - # and assumptions in cbcbeat) - factor = 1.0 / (chi * C_m) # NB: cbcbeat convention - amplitude = factor * A * (1.0 / cm2mm) ** 3 # mV/ms - - I_s = dolfin.Expression( - "time >= start ? (time <= (duration + start) ? amplitude : 0.0) : 0.0", - time=time, - start=config["stim"]["start"], - duration=duration, - amplitude=amplitude, - degree=0, - ) - - dx = dolfin.Measure("dx", domain=mesh, subdomain_data=S1_markers)(S1_marker) - return beat.base_model.Stimulus(dz=dx, expr=I_s) - - -# Load the model -if not Path("ep_model.py").exists(): - ode = gotranx.load_ode(config["sim"]["modelfile"]) - - mechanics_comp = ode.get_component("mechanics") - mechanics_ode = mechanics_comp.to_ode() - - ep_ode = ode - mechanics_comp - - # Generate code for the electrophysiology model - code_ep = gotranx.cli.gotran2py.get_code( - ep_ode, - scheme=[gotranx.schemes.Scheme.forward_generalized_rush_larsen], - missing_values=mechanics_ode.missing_variables, - ) - # Generate code for the mechanics model - code_mechanics = gotranx.cli.gotran2py.get_code( - mechanics_ode, - scheme=[gotranx.schemes.Scheme.forward_generalized_rush_larsen], - missing_values=ep_ode.missing_variables, - ) - - Path("ep_model.py").write_text(code_ep) - # Currently 3D mech needs to be written manually - -import ep_model as _ep_model - -ep_model = _ep_model.__dict__ - - -# Validate ep variables to output -for i in list(set(out_ep_coord_names) | set(out_ep_var_names)): - try: - var = ep_model["state_index"](i) - except KeyError: - print(f"{i} is not an ep state. Check config file") - raise - -# Forwared generalized rush larsen scheme for the electrophysiology model -fgr_ep = jit(nopython=True)(ep_model["forward_generalized_rush_larsen"]) -# Monitor function for the electrophysiology model -mon_ep = ep_model["monitor_values"] -# Missing values function for the electrophysiology model -mv_ep = ep_model["missing_values"] - - -# Get initial values from the EP model -y_ep_ = ep_model["init_state_values"]() -p_ep_ = ep_model["init_parameter_values"](amp=0.0) - -# ep_missing_values_ = np.zeros(len(ep_model["missing"])) # Init value for J_TRPN -ep_missing_values_ = np.array( - [0.00010730972184715098] -) # Init value for J_TRPN = dCaTrpn_dt * trpnmax (to compare with zetasplit) - -# ep_mesh = dolfin.adapt(dolfin.adapt(dolfin.adapt(mesh))) -ep_mesh = mesh - -time = dolfin.Constant(0.0) -I_s = define_stimulus( - mesh=ep_mesh, - chi=chi, - C_m=C_m, - time=time, - stim_region=stim_region, - stim_start=config["stim"]["start"], - A=config["stim"]["amplitude"], - duration=config["stim"]["duration"], -) -M = define_conductivity_tensor(sigma, chi, C_m) -params = {"preconditioner": "sor", "use_custom_preconditioner": False} -ep_ode_space = dolfin.FunctionSpace(ep_mesh, "DG", 1) -v_ode = dolfin.Function(ep_ode_space) -num_points_ep = v_ode.vector().local_size() -lmbda = dolfin.Function(ep_ode_space) - - -y_ep = np.zeros((len(y_ep_), num_points_ep)) -y_ep.T[:] = y_ep_ # Set to y_ep with initial values defined in ep_model - - -mechanics_missing_values_ = np.array([0.0001]) # Init value for cai - - -# Set the activation -activation_space = dolfin.FunctionSpace(mesh, "DG", 1) -activation = dolfin.Function(activation_space) -num_points_mech = activation.vector().local_size() - -missing_mech = interpolation.MissingValue( - element=activation.ufl_element(), - interpolation_element=ep_ode_space.ufl_element(), - mechanics_mesh=mesh, - ep_mesh=ep_mesh, - num_values=len(mechanics_missing_values_), -) - -missing_ep = interpolation.MissingValue( - element=ep_ode_space.ufl_element(), - interpolation_element=activation.ufl_element(), - mechanics_mesh=mesh, - ep_mesh=ep_mesh, - num_values=len(ep_missing_values_), -) - - -missing_ep.values_mechanics.T[:] = ep_missing_values_ -missing_ep.values_ep.T[:] = ep_missing_values_ - -missing_mech.values_ep.T[:] = mechanics_missing_values_ -missing_mech.values_mechanics.T[:] = mechanics_missing_values_ -missing_mech.mechanics_values_to_function() # Assign initial values to mech functions - - -# Use previous cai in mech to be consistent across splitting schemes -prev_missing_mech = interpolation.MissingValue( - element=activation.ufl_element(), - interpolation_element=ep_ode_space.ufl_element(), - mechanics_mesh=mesh, - ep_mesh=ep_mesh, - num_values=len(mechanics_missing_values_), -) -for i in range(len(mechanics_missing_values_)): - prev_missing_mech.u_mechanics[i].vector().set_local(missing_mech.values_mechanics[i]) - - -# Create function spaces for ep variables to output -out_ep_funcs = {} -for out_ep_var in list(set(out_ep_var_names) | set(out_ep_coord_names)): - out_ep_funcs[out_ep_var] = dolfin.Function(ep_ode_space) - -p_ep = np.zeros((len(p_ep_), num_points_ep)) -p_ep.T[:] = p_ep_ # Initialise p_ep with initial values defined in ep_model - -pde = beat.MonodomainModel(time=time, mesh=ep_mesh, M=M, I_s=I_s, params=params) -ode = beat.odesolver.DolfinODESolver( - v_ode=dolfin.Function(ep_ode_space), - v_pde=pde.state, - fun=fgr_ep, - parameters=p_ep, - init_states=y_ep, - num_states=len(y_ep), - v_index=ep_model["state_index"]("v"), - missing_variables=missing_ep.values_ep, - num_missing_variables=len(ep_model["missing"]), -) - -# ep_solver = beat.MonodomainSplittingSolver(pde=pde, ode=ode, theta=0.5) -ep_solver = beat.MonodomainSplittingSolver(pde=pde, ode=ode, theta=1) - -marker_functions = pulse.MarkerFunctions(ffun=ffun_bcs) - - -def create_boundary_conditions( - ffun_bcs, bcs_dirichlet, bcs_neumann, bcs_dict, bcs_expressions -): # TODO: update to not need separate dirichlet and neumann list - def dirichlet_bc(W): - bcs_W = { - "u_x": W.sub(0).sub(0), - "u_y": W.sub(0).sub(1), - "u_z": W.sub(0).sub(2), - # TODO: add the rest (check dolfin doc) - } - - bcs = [] - for bc in bcs_dirichlet: - bcs.append( - dolfin.DirichletBC( - bcs_W[bcs_dict[f"{bc}"]["V"]], - bcs_expressions[f"{bc}"], # TODO: use dolfin expression - ffun_bcs, - bcs_dict[f"{bc}"]["marker"], - ) - ) - return bcs - - neumann_bc = [] - if bcs_neumann is not None: - for bc in bcs_neumann: - neumann_bc.append( - pulse.NeumannBC( - traction=utils.float_to_constant(bcs_expressions[f"{bc}"]), - marker=bcs_dict[f"{bc}"]["marker"], - ) - ) - - # Collect Boundary Conditions - bcs = pulse.BoundaryConditions(dirichlet=(dirichlet_bc,), neumann=neumann_bc) - return bcs - - -f0 = dolfin.as_vector([1.0, 0.0, 0.0]) -s0 = dolfin.as_vector([0.0, 1.0, 0.0]) -n0 = dolfin.as_vector([0.0, 0.0, 1.0]) -microstructure = pulse.Microstructure(f0=f0, s0=s0, n0=n0) -geometry = pulse.Geometry( - mesh=mesh, marker_functions=marker_functions, microstructure=microstructure -) - -active_model = LandModel( - f0=f0, - s0=s0, - n0=n0, - cai=prev_missing_mech.u_mechanics[0], # Use prev cai in mech to be consistent with zeta split - mesh=mesh, - eta=0, # Fraction of transverse active tesion for active stress formulation. - # 0 = active only along fiber, 1 = equal forces in all directions - # (default=0.0). - dLambda_tol=1e-12, -) -active_model.t = 0.0 - - -mech_variables = { - "Ta": active_model.Ta_current, - "Zetas": active_model._Zetas, - "Zetaw": active_model._Zetaw, - "lambda": active_model.lmbda, - "XS": active_model._XS, - "XW": active_model._XW, - "TmB": active_model._TmB, - "CaTrpn": active_model._CaTrpn, - "J_TRPN": active_model._J_TRPN, -} - -# Validate mechanics variables to output -for out_mech_var in list(set(out_mech_coord_names) | set(out_mech_var_names)): - assert ( - out_mech_var in mech_variables - ), f"Error: '{out_mech_var}' is not a valid variable name. Check config file" - -material = pulse.HolzapfelOgden( - parameters=material_parameters, - active_model=active_model, - f0=f0, - s0=s0, - n0=n0, -) - - -def compute_function_average_over_mesh(func, mesh): - volume = dolfin.assemble(dolfin.Constant(1.0) * dolfin.dx(domain=mesh)) - return dolfin.assemble(func * dolfin.dx(domain=mesh)) / volume - - -# Collect Boundary Conditions -bcs = create_boundary_conditions( - ffun_bcs, bcs_dirichlet, bcs_neumann, config["bcs"], bcs_expressions -) - -problem = mechanicssolver.MechanicsProblem(geometry, material, bcs) -problem.solve(0.0, 0.0) - -disp_file = Path(outdir / "disp.xdmf") -disp_file.unlink(missing_ok=True) -disp_file.with_suffix(".h5").unlink(missing_ok=True) - -out_ep_files = {} -for out_ep_var in out_ep_var_names: - out_ep_files[out_ep_var] = Path(outdir / f"{out_ep_var}_out_ep.xdmf") - out_ep_files[out_ep_var].unlink(missing_ok=True) - out_ep_files[out_ep_var].with_suffix(".h5").unlink(missing_ok=True) - -out_mech_files = {} -for out_mech_var in out_mech_var_names: - out_mech_files[out_mech_var] = Path(outdir / f"{out_mech_var}_out_mech.xdmf") - out_mech_files[out_mech_var].unlink(missing_ok=True) - out_mech_files[out_mech_var].with_suffix(".h5").unlink(missing_ok=True) - - -# Create arrays for storing values to plot time series for example nodes -out_ep_example_nodes = {} -for out_ep_var in out_ep_coord_names: - out_ep_example_nodes[out_ep_var] = np.zeros(len(t)) - -out_mech_example_nodes = {} -for out_mech_var in out_mech_coord_names: - out_mech_example_nodes[out_mech_var] = np.zeros(len(t)) - -# Create arrays for storing values to plot time series for volume averages -out_ep_volume_average_timeseries = {} -for out_ep_var in out_ep_coord_names: - out_ep_volume_average_timeseries[out_ep_var] = np.zeros(len(t)) - -out_mech_volume_average_timeseries = {} -for out_mech_var in out_mech_coord_names: - out_mech_volume_average_timeseries[out_mech_var] = np.zeros(len(t)) - - -inds = [] # Array with time-steps for which we solve mechanics -j = 0 -timer = dolfin.Timer("solve_loop") -for i, ti in enumerate(t): - print(f"Solving time {ti:.2f} ms") - t_bcs.assign(ti) # Use ti+ dt here instead? - ep_solver.step((ti, ti + config["sim"]["dt"])) - - # Assign values to ep function - for out_ep_var in list(set(out_ep_var_names) | set(out_ep_coord_names)): - out_ep_funcs[out_ep_var].vector()[:] = ode._values[ep_model["state_index"](out_ep_var)] - - # Store values to plot time series for given coord - for var_nr in range(config["write_point_ep"]["numbers"]): - # Trace variable in coordinate - out_ep_var = config["write_point_ep"][f"{var_nr}"]["name"] - out_ep_example_nodes[out_ep_var][i] = out_ep_funcs[out_ep_var](ep_coords[var_nr]) - # Compute volume averages - out_ep_volume_average_timeseries[out_ep_var][i] = compute_function_average_over_mesh( - out_ep_funcs[out_ep_var], ep_mesh - ) - - if i % config["sim"]["N"] != 0: - continue - - # Extract missing values for the mechanics step from the ep model (ep function space) - missing_ep_values = mv_ep( - ti + config["sim"]["dt"], - ode._values, - ode.parameters, - missing_ep.values_ep, - ) - # Assign the extracted values as missing_mech for the mech step (ep function space) - for k in range(missing_mech.num_values): - missing_mech.u_ep_int[k].vector()[:] = missing_ep_values[k, :] - - # Interpolate missing variables from ep to mech function space - missing_mech.interpolate_ep_to_mechanics() - missing_mech.mechanics_function_to_values() - inds.append(i) - - print("Solve mechanics") - active_model.t = ti + config["sim"]["N"] * config["sim"]["dt"] # Addition! - problem.solve(ti, config["sim"]["N"] * config["sim"]["dt"]) - active_model.update_prev() - - missing_ep.u_mechanics_int[0].interpolate(active_model._J_TRPN) - - missing_ep.interpolate_mechanics_to_ep() - missing_ep.ep_function_to_values() - - print( - active_model.lmbda.vector().get_local().min(), - active_model.lmbda.vector().get_local().max(), - ) - - U, p = problem.state.split(deepcopy=True) - - for var_nr in range(config["write_point_mech"]["numbers"]): - # Trace variable in coordinate - out_mech_var = config["write_point_mech"][f"{var_nr}"]["name"] - out_mech_example_nodes[out_mech_var][i] = mech_variables[out_mech_var](mech_coords[var_nr]) - - # Compute volume averages - out_mech_volume_average_timeseries[out_mech_var][i] = compute_function_average_over_mesh( - mech_variables[out_mech_var], mesh - ) - - # Use previous cai in mech to be consistent with zeta split - for i in range(len(mechanics_missing_values_)): - prev_missing_mech.u_mechanics[i].vector().set_local(missing_mech.values_mechanics[i]) - - with dolfin.XDMFFile(disp_file.as_posix()) as file: - file.write_checkpoint(U, "disp", j, dolfin.XDMFFile.Encoding.HDF5, True) - for out_ep_var in out_ep_var_names: - with dolfin.XDMFFile(out_ep_files[out_ep_var].as_posix()) as file: - file.write_checkpoint( - out_ep_funcs[out_ep_var], - out_ep_var, - j, - dolfin.XDMFFile.Encoding.HDF5, - True, - ) - for out_mech_var in out_mech_var_names: - with dolfin.XDMFFile(out_mech_files[out_mech_var].as_posix()) as file: - file.write_checkpoint( - mech_variables[out_mech_var], - out_mech_var, - j, - dolfin.XDMFFile.Encoding.HDF5, - True, - ) - - j += 1 -timer.stop() -timings = dolfin.timings( - dolfin.TimingClear.keep, - [dolfin.TimingType.wall, dolfin.TimingType.user, dolfin.TimingType.system], -).str(True) -print(timings) -with open(Path(outdir / "solve_timings.txt"), "w") as f: - f.write(timings) - -# Write averaged results for later analysis -for out_ep_var in out_ep_coord_names: - with open(Path(outdir / f"{out_ep_var}_out_ep_volume_average.txt"), "w") as f: - np.savetxt(f, out_ep_volume_average_timeseries[out_ep_var][inds]) - -for out_mech_var in out_mech_coord_names: - with open(Path(outdir / f"{out_mech_var}_out_mech_volume_average.txt"), "w") as f: - np.savetxt(f, out_mech_volume_average_timeseries[out_mech_var][inds]) - - -# Write point traces for later analysis -for var_nr in range(config["write_point_ep"]["numbers"]): - out_ep_var = config["write_point_ep"][f"{var_nr}"]["name"] - with open( - Path( - outdir - / f"{out_ep_var}_ep_coord{ep_coords[var_nr][0]},{ep_coords[var_nr][1]},{ep_coords[var_nr][2]}.txt".replace( - " ", "" - ) - ), - "w", - ) as f: - np.savetxt(f, out_ep_example_nodes[out_ep_var][inds]) - -for var_nr in range(config["write_point_mech"]["numbers"]): - out_mech_var = config["write_point_mech"][f"{var_nr}"]["name"] - with open( - Path( - outdir - / f"{out_mech_var}_mech_coord{mech_coords[var_nr][0]},{mech_coords[var_nr][1]},{mech_coords[var_nr][2]}.txt" - ), - "w", - ) as f: - np.savetxt(f, out_mech_example_nodes[out_mech_var][inds]) - -print(f"Solved on {100 * len(inds) / len(t)}% of the time steps") -inds = np.array(inds) - -# Plot the results. Currently also output volume averages for selected trace variables -fig, ax = plt.subplots(len(out_ep_coord_names), 1, figsize=(10, 10)) -if len(out_ep_coord_names) == 1: - ax = np.array([ax]) -for i, out_ep_var in enumerate(out_ep_coord_names): - ax[i].plot(t[inds], out_ep_volume_average_timeseries[out_ep_var][inds]) - ax[i].set_title(f"{out_ep_var} volume average") - ax[i].set_xlabel("Time (ms)") -fig.tight_layout() -fig.savefig(Path(outdir / "out_ep_volume_averages.png")) - -fig, ax = plt.subplots(len(out_ep_coord_names), 1, figsize=(10, 10)) -if len(out_ep_coord_names) == 1: - ax = np.array([ax]) -for var_nr in range(config["write_point_ep"]["numbers"]): - out_ep_var = config["write_point_ep"][f"{var_nr}"]["name"] - ax[var_nr].plot(t[inds], out_ep_example_nodes[out_ep_var][inds]) - ax[var_nr].set_title(f"{out_ep_var} in coord {ep_coords[var_nr]}") - ax[var_nr].set_xlabel("Time (ms)") -fig.tight_layout() -fig.savefig(Path(outdir / "out_ep_coord.png")) - -fig, ax = plt.subplots(len(out_mech_coord_names), 1, figsize=(10, 10)) -if len(out_mech_coord_names) == 1: - ax = np.array([ax]) -for i, out_mech_var in enumerate(out_mech_coord_names): - ax[i].plot(t[inds], out_mech_volume_average_timeseries[out_mech_var][inds]) - ax[i].set_title(f"{out_mech_var} volume average") - ax[i].set_xlabel("Time (ms)") -fig.tight_layout() -fig.savefig(Path(outdir / "out_mech_volume_averages.png")) - -fig, ax = plt.subplots(len(out_mech_coord_names), 1, figsize=(10, 10)) -if len(out_mech_coord_names) == 1: - ax = np.array([ax]) - -for var_nr in range(config["write_point_mech"]["numbers"]): - out_mech_var = config["write_point_mech"][f"{var_nr}"]["name"] - ax[var_nr].plot(t[inds], out_mech_example_nodes[out_mech_var][inds]) - ax[var_nr].set_title(f"{out_mech_var} in coord {mech_coords[var_nr]}") - ax[var_nr].set_xlabel("Time (ms)") -fig.tight_layout() -fig.savefig(Path(outdir / "out_mech_coord.png")) diff --git a/demos/split-cai/3D/main_using_config_time.py b/demos/split-cai/3D/main_using_config_time.py deleted file mode 100644 index a8ae4f8..0000000 --- a/demos/split-cai/3D/main_using_config_time.py +++ /dev/null @@ -1,737 +0,0 @@ -import logging -import gotranx -from pathlib import Path -from typing import Sequence -import numpy as np -import dolfin -import pulse -import beat -import argparse -import toml -import matplotlib.pyplot as plt - - -from simcardems2 import utils -from simcardems2 import mechanicssolver -from simcardems2 import interpolation -from simcardems2.land_caisplit import LandModel -from simcardems2.validate_input_types import validate_input_types - -plot_results = True -write_disp = True - -try: - raise ImportError - from numba import jit -except ImportError: - - def jit(*args, **kwargs): - def wrapper(func): - return func - - return wrapper - - -logging.getLogger("beat").setLevel(logging.ERROR) - - -def parse_parameters(argv: Sequence[str] | None = None) -> int: - parser = argparse.ArgumentParser(description="Simcardems CLI") - parser.add_argument("config-file", type=Path, help="Config file") - - args = vars(parser.parse_args(argv)) - try: - config = toml.loads(args["config-file"].read_text()) - except toml.TomlDecodeError as e: - print(f"Error when parsing input parameters. Check config file. Error: {e}") - exit(1) - return config - - -config = parse_parameters() - -validate_input_types(config) - -stim_region = ( - [config["stim"]["xmin"], config["stim"]["xmax"]], - [config["stim"]["ymin"], config["stim"]["ymax"]], - [config["stim"]["zmin"], config["stim"]["zmax"]], -) -out_ep_var_names = [ - config["write_all_ep"][f"{i}"]["name"] for i in range(config["write_all_ep"]["numbers"]) -] -out_mech_var_names = [ - config["write_all_mech"][f"{i}"]["name"] for i in range(config["write_all_mech"]["numbers"]) -] -out_ep_coord_names = [ - config["write_point_ep"][f"{i}"]["name"] for i in range(config["write_point_ep"]["numbers"]) -] -ep_coords = [ - [config["write_point_ep"][f"{varnr}"][f"{coord}"] for coord in ["x", "y", "z"]] - for varnr in range(config["write_point_ep"]["numbers"]) -] -out_mech_coord_names = [ - config["write_point_mech"][f"{i}"]["name"] for i in range(config["write_point_mech"]["numbers"]) -] -mech_coords = [ - [config["write_point_mech"][f"{varnr}"][f"{coord}"] for coord in ["x", "y", "z"]] - for varnr in range(config["write_point_mech"]["numbers"]) -] - - -outdir = Path(config["sim"]["outdir"]) -outdir.mkdir(parents=True, exist_ok=True) - -with open(Path(outdir / "config.txt"), "w") as f: - f.write(toml.dumps(config)) - - -# TODO: do a different dirichlet/neumann check than this later. something smoother -t_bcs = dolfin.Constant(0) -bcs_dirichlet = [] -bcs_neumann = [] -bcs_expressions = {} -for bc in range(config["bcs"]["numbers"]): - if config["bcs"][f"{bc}"]["type"] == "Dirichlet": - bcs_dirichlet.append(bc) - elif config["bcs"][f"{bc}"]["type"] == "Neumann": - bcs_neumann.append(bc) - else: - raise KeyError( - f'{config["bcs"][str(bc)]["type"]} is not a valid type of boundary ' - 'condition. Use Dirichlet or Neumann. Check config file' - ) - - if config["bcs"][f"{bc}"]["param_numbers"] > 0: - bcs_parameters = {} - for param_nr in range(config["bcs"][f"{bc}"]["param_numbers"]): - param_name = config["bcs"][f"{bc}"]["param"][f"{param_nr}"]["name"] - param_value = config["bcs"][f"{bc}"]["param"][f"{param_nr}"]["value"] - bcs_parameters[param_name] = param_value - bcs_expressions[f"{bc}"] = dolfin.Expression( - config["bcs"][f"{bc}"]["expression"], - **bcs_parameters, - t=t_bcs, - degree=config["bcs"][f"{bc}"]["degree"], - ) - else: - bcs_expressions[f"{bc}"] = dolfin.Constant(0) - - -mesh = dolfin.Mesh() -with dolfin.XDMFFile(f'{config["sim"]["mech_mesh"]}.xdmf') as infile: - infile.read(mesh) -print(f'Loaded mesh: {config["sim"]["mech_mesh"]}') - - -ffun_bcs = dolfin.MeshFunction("size_t", mesh, mesh.topology().dim() - 1) -with dolfin.XDMFFile(f'{config["bcs"]["markerfile"]}.xdmf') as infile: - infile.read(ffun_bcs) -print(f'Loaded markerfile for bcs: {config["bcs"]["markerfile"]}') - - -tol = 5e-4 -# Surface to volume ratio -chi = 140.0 # mm^{-1} -# Membrane capacitance -C_m = 0.01 # mu F / mm^2 -cm2mm = 10.0 - -t = np.arange(0, config["sim"]["sim_dur"], config["sim"]["dt"]) -sigma = [ - config["ep"]["sigma_il"], - config["ep"]["sigma_it"], - config["ep"]["sigma_el"], - config["ep"]["sigma_et"], -] -material_parameters = dict( - a=config["mech"]["a"], - a_f=config["mech"]["a_f"], - b=config["mech"]["b"], - b_f=config["mech"]["b_f"], - a_s=config["mech"]["a_s"], - b_s=config["mech"]["b_s"], - a_fs=config["mech"]["a_fs"], - b_fs=config["mech"]["b_fs"], -) - - -dolfin.parameters["form_compiler"]["representation"] = "uflacs" -dolfin.parameters["form_compiler"]["cpp_optimize"] = True -dolfin.parameters["form_compiler"]["quadrature_degree"] = 4 - - -def define_conductivity_tensor(sigma, chi, C_m): - # Compute monodomain approximation by taking harmonic mean in each - # direction of intracellular and extracellular part - def harmonic_mean(a, b): - return a * b / (a + b) - - sigma_l = harmonic_mean(sigma[0], sigma[2]) - sigma_t = harmonic_mean(sigma[1], sigma[3]) - - # Scale conducitivites by 1/(C_m * chi) - s_l = sigma_l / (C_m * chi) # mm^2 / ms - s_t = sigma_t / (C_m * chi) # mm^2 / ms - - # Define conductivity tensor - M = dolfin.as_tensor(((s_l, 0, 0), (0, s_t, 0), (0, 0, s_t))) - - return M - - -def define_stimulus( - mesh, - chi, - C_m, - time, - stim_region=stim_region, - stim_start=config["stim"]["start"], - A=config["stim"]["amplitude"], - duration=config["stim"]["duration"], -): - S1_marker = 1 - S1_subdomain = dolfin.CompiledSubDomain( - " ".join( - ( - f"x[0] >= {stim_region[0][0]}", - f"&& x[0] <= {stim_region[0][1]}", - f"&& x[1] >= {stim_region[1][0]}", - f"&& x[1] <= {stim_region[1][1]}", - f"&& x[2] >= {stim_region[2][0]}", - f"&& x[2] <= {stim_region[2][1]}", - ) - ) - ) - - S1_markers = dolfin.MeshFunction("size_t", mesh, mesh.topology().dim()) - S1_subdomain.mark(S1_markers, S1_marker) - with dolfin.XDMFFile((outdir / "stim_region_markers.xdmf").as_posix()) as xdmf: - xdmf.write(S1_markers) - - # Define stimulation (NB: region of interest carried by the mesh - # and assumptions in cbcbeat) - factor = 1.0 / (chi * C_m) # NB: cbcbeat convention - amplitude = factor * A * (1.0 / cm2mm) ** 3 # mV/ms - - I_s = dolfin.Expression( - "time >= start ? (time <= (duration + start) ? amplitude : 0.0) : 0.0", - time=time, - start=config["stim"]["start"], - duration=duration, - amplitude=amplitude, - degree=0, - ) - - dx = dolfin.Measure("dx", domain=mesh, subdomain_data=S1_markers)(S1_marker) - return beat.base_model.Stimulus(dz=dx, expr=I_s) - - -# Load the model -if not Path("ep_model.py").exists(): - ode = gotranx.load_ode(config["sim"]["modelfile"]) - - mechanics_comp = ode.get_component("mechanics") - mechanics_ode = mechanics_comp.to_ode() - - ep_ode = ode - mechanics_comp - - # Generate code for the electrophysiology model - code_ep = gotranx.cli.gotran2py.get_code( - ep_ode, - scheme=[gotranx.schemes.Scheme.forward_generalized_rush_larsen], - missing_values=mechanics_ode.missing_variables, - ) - # Generate code for the mechanics model - code_mechanics = gotranx.cli.gotran2py.get_code( - mechanics_ode, - scheme=[gotranx.schemes.Scheme.forward_generalized_rush_larsen], - missing_values=ep_ode.missing_variables, - ) - - Path("ep_model.py").write_text(code_ep) - # Currently 3D mech needs to be written manually - -import ep_model as _ep_model - -ep_model = _ep_model.__dict__ - - -# Validate ep variables to output -for i in list(set(out_ep_coord_names) | set(out_ep_var_names)): - try: - var = ep_model["state_index"](i) - except KeyError: - print(f"{i} is not an ep state. Check config file") - raise - -# Forwared generalized rush larsen scheme for the electrophysiology model -fgr_ep = jit(nopython=True)(ep_model["forward_generalized_rush_larsen"]) -# Monitor function for the electrophysiology model -mon_ep = ep_model["monitor_values"] -# Missing values function for the electrophysiology model -mv_ep = ep_model["missing_values"] - - -# Get initial values from the EP model -y_ep_ = ep_model["init_state_values"]() -p_ep_ = ep_model["init_parameter_values"](i_Stim_Amplitude=0.0) - -# ep_missing_values_ = np.zeros(len(ep_model["missing"])) # Init value for J_TRPN -ep_missing_values_ = np.array( - [0.00010730972184715098] -) # Init value for J_TRPN = dCaTrpn_dt * trpnmax (to compare with zetasplit) - -# ep_mesh = dolfin.adapt(dolfin.adapt(dolfin.adapt(mesh))) -ep_mesh = mesh - -time = dolfin.Constant(0.0) -I_s = define_stimulus( - mesh=ep_mesh, - chi=chi, - C_m=C_m, - time=time, - stim_region=stim_region, - stim_start=config["stim"]["start"], - A=config["stim"]["amplitude"], - duration=config["stim"]["duration"], -) -M = define_conductivity_tensor(sigma, chi, C_m) -params = {"preconditioner": "sor", "use_custom_preconditioner": False} -ep_ode_space = dolfin.FunctionSpace(ep_mesh, "DG", 1) -v_ode = dolfin.Function(ep_ode_space) -num_points_ep = v_ode.vector().local_size() -lmbda = dolfin.Function(ep_ode_space) - - -y_ep = np.zeros((len(y_ep_), num_points_ep)) -y_ep.T[:] = y_ep_ # Set to y_ep with initial values defined in ep_model - - -mechanics_missing_values_ = np.array([0.0001]) # Init value for cai - - -# Set the activation -activation_space = dolfin.FunctionSpace(mesh, "DG", 1) -activation = dolfin.Function(activation_space) -num_points_mech = activation.vector().local_size() - -missing_mech = interpolation.MissingValue( - element=activation.ufl_element(), - interpolation_element=ep_ode_space.ufl_element(), - mechanics_mesh=mesh, - ep_mesh=ep_mesh, - num_values=len(mechanics_missing_values_), -) - -missing_ep = interpolation.MissingValue( - element=ep_ode_space.ufl_element(), - interpolation_element=activation.ufl_element(), - mechanics_mesh=mesh, - ep_mesh=ep_mesh, - num_values=len(ep_missing_values_), -) - - -missing_ep.values_mechanics.T[:] = ep_missing_values_ -missing_ep.values_ep.T[:] = ep_missing_values_ - -missing_mech.values_ep.T[:] = mechanics_missing_values_ -missing_mech.values_mechanics.T[:] = mechanics_missing_values_ -missing_mech.mechanics_values_to_function() # Assign initial values to mech functions - - -# Use previous cai in mech to be consistent across splitting schemes -prev_missing_mech = interpolation.MissingValue( - element=activation.ufl_element(), - interpolation_element=ep_ode_space.ufl_element(), - mechanics_mesh=mesh, - ep_mesh=ep_mesh, - num_values=len(mechanics_missing_values_), -) -for i in range(len(mechanics_missing_values_)): - prev_missing_mech.u_mechanics[i].vector().set_local(missing_mech.values_mechanics[i]) - - -# Create function spaces for ep variables to output -out_ep_funcs = {} -for out_ep_var in list(set(out_ep_var_names) | set(out_ep_coord_names)): - out_ep_funcs[out_ep_var] = dolfin.Function(ep_ode_space) - -p_ep = np.zeros((len(p_ep_), num_points_ep)) -p_ep.T[:] = p_ep_ # Initialise p_ep with initial values defined in ep_model - -pde = beat.MonodomainModel(time=time, mesh=ep_mesh, M=M, I_s=I_s, params=params) -ode = beat.odesolver.DolfinODESolver( - v_ode=dolfin.Function(ep_ode_space), - v_pde=pde.state, - fun=fgr_ep, - parameters=p_ep, - init_states=y_ep, - num_states=len(y_ep), - v_index=ep_model["state_index"]("v"), - missing_variables=missing_ep.values_ep, - num_missing_variables=len(ep_model["missing"]), -) - -# ep_solver = beat.MonodomainSplittingSolver(pde=pde, ode=ode, theta=0.5) -ep_solver = beat.MonodomainSplittingSolver(pde=pde, ode=ode, theta=1) - -marker_functions = pulse.MarkerFunctions(ffun=ffun_bcs) - - -def create_boundary_conditions( - ffun_bcs, bcs_dirichlet, bcs_neumann, bcs_dict, bcs_expressions -): # TODO: update to not need separate dirichlet and neumann list - def dirichlet_bc(W): - bcs_W = { - "u_x": W.sub(0).sub(0), - "u_y": W.sub(0).sub(1), - "u_z": W.sub(0).sub(2), - # TODO: add the rest (check dolfin doc) - } - - bcs = [] - for bc in bcs_dirichlet: - bcs.append( - dolfin.DirichletBC( - bcs_W[bcs_dict[f"{bc}"]["V"]], - bcs_expressions[f"{bc}"], # TODO: use dolfin expression - ffun_bcs, - bcs_dict[f"{bc}"]["marker"], - ) - ) - return bcs - - neumann_bc = [] - if bcs_neumann is not None: - for bc in bcs_neumann: - neumann_bc.append( - pulse.NeumannBC( - traction=utils.float_to_constant(bcs_expressions[f"{bc}"]), - marker=bcs_dict[f"{bc}"]["marker"], - ) - ) - - # Collect Boundary Conditions - bcs = pulse.BoundaryConditions(dirichlet=(dirichlet_bc,), neumann=neumann_bc) - return bcs - - -f0 = dolfin.as_vector([1.0, 0.0, 0.0]) -s0 = dolfin.as_vector([0.0, 1.0, 0.0]) -n0 = dolfin.as_vector([0.0, 0.0, 1.0]) -microstructure = pulse.Microstructure(f0=f0, s0=s0, n0=n0) -geometry = pulse.Geometry( - mesh=mesh, marker_functions=marker_functions, microstructure=microstructure -) - -active_model = LandModel( - f0=f0, - s0=s0, - n0=n0, - cai=prev_missing_mech.u_mechanics[0], # Use prev cai in mech to be consistent with zeta split - mesh=mesh, - eta=0, # Fraction of transverse active tesion for active stress formulation. - # 0 = active only along fiber, 1 = equal forces in all directions - # (default=0.0). - dLambda_tol=1e-12, -) -active_model.t = 0.0 - - -mech_variables = { - "Ta": active_model.Ta_current, - "Zetas": active_model._Zetas, - "Zetaw": active_model._Zetaw, - "lambda": active_model.lmbda, - "XS": active_model._XS, - "XW": active_model._XW, - "TmB": active_model._TmB, - "CaTrpn": active_model._CaTrpn, - "J_TRPN": active_model._J_TRPN, -} - -# Validate mechanics variables to output -for out_mech_var in list(set(out_mech_coord_names) | set(out_mech_var_names)): - assert ( - out_mech_var in mech_variables - ), f"Error: '{out_mech_var}' is not a valid variable name. Check config file" - -material = pulse.HolzapfelOgden( - parameters=material_parameters, - active_model=active_model, - f0=f0, - s0=s0, - n0=n0, -) - - -def compute_function_average_over_mesh(func, mesh): - volume = dolfin.assemble(dolfin.Constant(1.0) * dolfin.dx(domain=mesh)) - return dolfin.assemble(func * dolfin.dx(domain=mesh)) / volume - - -# Collect Boundary Conditions -bcs = create_boundary_conditions( - ffun_bcs, bcs_dirichlet, bcs_neumann, config["bcs"], bcs_expressions -) - -problem = mechanicssolver.MechanicsProblem(geometry, material, bcs) -problem.solve(0.0, 0.0) - -disp_file = Path(outdir / "disp.xdmf") -disp_file.unlink(missing_ok=True) -disp_file.with_suffix(".h5").unlink(missing_ok=True) - -out_ep_files = {} -for out_ep_var in out_ep_var_names: - out_ep_files[out_ep_var] = Path(outdir / f"{out_ep_var}_out_ep.xdmf") - out_ep_files[out_ep_var].unlink(missing_ok=True) - out_ep_files[out_ep_var].with_suffix(".h5").unlink(missing_ok=True) - -out_mech_files = {} -for out_mech_var in out_mech_var_names: - out_mech_files[out_mech_var] = Path(outdir / f"{out_mech_var}_out_mech.xdmf") - out_mech_files[out_mech_var].unlink(missing_ok=True) - out_mech_files[out_mech_var].with_suffix(".h5").unlink(missing_ok=True) - - -# Create arrays for storing values to plot time series for example nodes -out_ep_example_nodes = {} -for out_ep_var in out_ep_coord_names: - out_ep_example_nodes[out_ep_var] = np.zeros(len(t)) - -out_mech_example_nodes = {} -for out_mech_var in out_mech_coord_names: - out_mech_example_nodes[out_mech_var] = np.zeros(len(t)) - -# Create arrays for storing values to plot time series for volume averages -out_ep_volume_average_timeseries = {} -for out_ep_var in out_ep_coord_names: - out_ep_volume_average_timeseries[out_ep_var] = np.zeros(len(t)) - -out_mech_volume_average_timeseries = {} -for out_mech_var in out_mech_coord_names: - out_mech_volume_average_timeseries[out_mech_var] = np.zeros(len(t)) - - -inds = [] # Array with time-steps for which we solve mechanics -j = 0 -total_timer = dolfin.Timer("total") -timings_solveloop = [] -timings_ep_steps = [] -timings_mech_steps = [] -no_of_newton_iterations = [] -timings_var_transfer = [] -for i, ti in enumerate(t): - timing_single_loop = dolfin.Timer("single_loop") - print(f"Solving time {ti:.2f} ms") - t_bcs.assign(ti) # Use ti+ dt here instead? - - timing_ep = dolfin.Timer("ep time") - ep_solver.step((ti, ti + config["sim"]["dt"])) - timing_ep.stop() - timings_ep_steps.append(timing_ep.elapsed()[0]) - - # Assign values to ep function - for out_ep_var in list(set(out_ep_var_names) | set(out_ep_coord_names)): - out_ep_funcs[out_ep_var].vector()[:] = ode._values[ep_model["state_index"](out_ep_var)] - - # Store values to plot time series for given coord - for var_nr in range(config["write_point_ep"]["numbers"]): - # Trace variable in coordinate - out_ep_var = config["write_point_ep"][f"{var_nr}"]["name"] - out_ep_example_nodes[out_ep_var][i] = out_ep_funcs[out_ep_var](ep_coords[var_nr]) - # Compute volume averages - out_ep_volume_average_timeseries[out_ep_var][i] = compute_function_average_over_mesh( - out_ep_funcs[out_ep_var], ep_mesh - ) - - if i % config["sim"]["N"] != 0: - timing_single_loop.stop() - timings_solveloop.append(timing_single_loop.elapsed()[0]) - continue - - timing_var_transfer = dolfin.Timer("mv and lambda transfer time") - # Extract missing values for the mechanics step from the ep model (ep function space) - missing_ep_values = mv_ep( - ti + config["sim"]["dt"], - ode._values, - ode.parameters, - missing_ep.values_ep, - ) - # Assign the extracted values as missing_mech for the mech step (ep function space) - for k in range(missing_mech.num_values): - missing_mech.u_ep_int[k].vector()[:] = missing_ep_values[k, :] - - # Interpolate missing variables from ep to mech function space - missing_mech.interpolate_ep_to_mechanics() - missing_mech.mechanics_function_to_values() - inds.append(i) - timing_var_transfer.stop() - - print("Solve mechanics") - timing_mech = dolfin.Timer("mech time") - active_model.t = ti + config["sim"]["N"] * config["sim"]["dt"] # Addition! - nit, conv = problem.solve(ti, config["sim"]["N"] * config["sim"]["dt"]) - no_of_newton_iterations.append(nit) - print(f"No of iterations: {nit}") - active_model.update_prev() - timing_mech.stop() - timings_mech_steps.append(timing_mech.elapsed()[0]) - - timing_var_transfer.start() - missing_ep.u_mechanics_int[0].interpolate(active_model._J_TRPN) - missing_ep.interpolate_mechanics_to_ep() - missing_ep.ep_function_to_values() - timing_var_transfer.stop() - - if write_disp: - U, p = problem.state.split(deepcopy=True) - - for var_nr in range(config["write_point_mech"]["numbers"]): - # Trace variable in coordinate - out_mech_var = config["write_point_mech"][f"{var_nr}"]["name"] - out_mech_example_nodes[out_mech_var][i] = mech_variables[out_mech_var](mech_coords[var_nr]) - - # Compute volume averages - out_mech_volume_average_timeseries[out_mech_var][i] = compute_function_average_over_mesh( - mech_variables[out_mech_var], mesh - ) - - timing_var_transfer.start() - # Use previous cai in mech to be consistent with zeta split - for i in range(len(mechanics_missing_values_)): - prev_missing_mech.u_mechanics[i].vector().set_local(missing_mech.values_mechanics[i]) - timing_var_transfer.stop() - timings_var_transfer.append(timing_var_transfer.elapsed()[0]) - - if write_disp: - with dolfin.XDMFFile(disp_file.as_posix()) as file: - file.write_checkpoint(U, "disp", j, dolfin.XDMFFile.Encoding.HDF5, True) - for out_ep_var in out_ep_var_names: - with dolfin.XDMFFile(out_ep_files[out_ep_var].as_posix()) as file: - file.write_checkpoint( - out_ep_funcs[out_ep_var], - out_ep_var, - j, - dolfin.XDMFFile.Encoding.HDF5, - True, - ) - for out_mech_var in out_mech_var_names: - with dolfin.XDMFFile(out_mech_files[out_mech_var].as_posix()) as file: - file.write_checkpoint( - mech_variables[out_mech_var], - out_mech_var, - j, - dolfin.XDMFFile.Encoding.HDF5, - True, - ) - - j += 1 - timing_single_loop.stop() - timings_solveloop.append(timing_single_loop.elapsed()[0]) - -total_timer.stop() -timings = dolfin.timings( - dolfin.TimingClear.keep, - [dolfin.TimingType.wall, dolfin.TimingType.user, dolfin.TimingType.system], -).str(True) -print(timings) -with open(Path(outdir / "solve_timings.txt"), "w") as f: - f.write("Loop total times\n") - np.savetxt(f, timings_solveloop) - f.write("Ep steps times\n") - np.savetxt(f, timings_ep_steps) - f.write("Mech steps times\n") - np.savetxt(f, timings_mech_steps) - f.write("No of mech iterations\n") - np.savetxt(f, no_of_newton_iterations, fmt="%s") - f.write("mv and lambda transfer time\n") - np.savetxt(f, timings_var_transfer) - f.write("Total time\n") - f.write(f"{total_timer.elapsed()[0]}\n") - f.write(timings) - -# Write averaged results for later analysis -for out_ep_var in out_ep_coord_names: - with open(Path(outdir / f"{out_ep_var}_out_ep_volume_average.txt"), "w") as f: - np.savetxt(f, out_ep_volume_average_timeseries[out_ep_var][inds]) - -for out_mech_var in out_mech_coord_names: - with open(Path(outdir / f"{out_mech_var}_out_mech_volume_average.txt"), "w") as f: - np.savetxt(f, out_mech_volume_average_timeseries[out_mech_var][inds]) - - -# Write point traces for later analysis -for var_nr in range(config["write_point_ep"]["numbers"]): - out_ep_var = config["write_point_ep"][f"{var_nr}"]["name"] - with open( - Path( - outdir - / f"{out_ep_var}_ep_coord{ep_coords[var_nr][0]},{ep_coords[var_nr][1]},{ep_coords[var_nr][2]}.txt".replace( - " ", "" - ) - ), - "w", - ) as f: - np.savetxt(f, out_ep_example_nodes[out_ep_var][inds]) - -for var_nr in range(config["write_point_mech"]["numbers"]): - out_mech_var = config["write_point_mech"][f"{var_nr}"]["name"] - with open( - Path( - outdir - / f"{out_mech_var}_mech_coord{mech_coords[var_nr][0]},{mech_coords[var_nr][1]},{mech_coords[var_nr][2]}.txt" - ), - "w", - ) as f: - np.savetxt(f, out_mech_example_nodes[out_mech_var][inds]) - -print(f"Solved on {100 * len(inds) / len(t)}% of the time steps") -inds = np.array(inds) - -if plot_results: - fig, ax = plt.subplots(len(out_ep_coord_names), 1, figsize=(10, 10)) - if len(out_ep_coord_names) == 1: - ax = np.array([ax]) - for i, out_ep_var in enumerate(out_ep_coord_names): - ax[i].plot(t[inds], out_ep_volume_average_timeseries[out_ep_var][inds]) - ax[i].set_title(f"{out_ep_var} volume average") - ax[i].set_xlabel("Time (ms)") - fig.tight_layout() - fig.savefig(Path(outdir / "out_ep_volume_averages.png")) - - fig, ax = plt.subplots(len(out_ep_coord_names), 1, figsize=(10, 10)) - if len(out_ep_coord_names) == 1: - ax = np.array([ax]) - for var_nr in range(config["write_point_ep"]["numbers"]): - out_ep_var = config["write_point_ep"][f"{var_nr}"]["name"] - ax[var_nr].plot(t[inds], out_ep_example_nodes[out_ep_var][inds]) - ax[var_nr].set_title(f"{out_ep_var} in coord {ep_coords[var_nr]}") - ax[var_nr].set_xlabel("Time (ms)") - fig.tight_layout() - fig.savefig(Path(outdir / "out_ep_coord.png")) - - fig, ax = plt.subplots(len(out_mech_coord_names), 1, figsize=(10, 10)) - if len(out_mech_coord_names) == 1: - ax = np.array([ax]) - for i, out_mech_var in enumerate(out_mech_coord_names): - ax[i].plot(t[inds], out_mech_volume_average_timeseries[out_mech_var][inds]) - ax[i].set_title(f"{out_mech_var} volume average") - ax[i].set_xlabel("Time (ms)") - fig.tight_layout() - fig.savefig(Path(outdir / "out_mech_volume_averages.png")) - - fig, ax = plt.subplots(len(out_mech_coord_names), 1, figsize=(10, 10)) - if len(out_mech_coord_names) == 1: - ax = np.array([ax]) - - for var_nr in range(config["write_point_mech"]["numbers"]): - out_mech_var = config["write_point_mech"][f"{var_nr}"]["name"] - ax[var_nr].plot(t[inds], out_mech_example_nodes[out_mech_var][inds]) - ax[var_nr].set_title(f"{out_mech_var} in coord {mech_coords[var_nr]}") - ax[var_nr].set_xlabel("Time (ms)") - fig.tight_layout() - fig.savefig(Path(outdir / "out_mech_coord.png")) diff --git a/demos/split-cai_catrpn/0D/ORdmm_Land.ode b/demos/split-cai_catrpn/0D/ORdmm_Land.ode deleted file mode 100644 index c753ce8..0000000 --- a/demos/split-cai_catrpn/0D/ORdmm_Land.ode +++ /dev/null @@ -1,663 +0,0 @@ -# ORd modified by MMora (October-2016) -# Modifications in INa. The original formulation of INa has been -# optimised, according to Passini, in order to look like TT04. -# Modifications: -# 1) mss,hss,jss and hssp -# 2) gNa -# + -# Re-scaled conductances (Dutta et al 2016 CinC) -# + -# -# Land 2017(mechanical model)- Introduced by MMora (Jan2020) -# Tension -# Changes in Cai effect of troponin -# + -# -# Isacs -# -# -# In this version we fix mech.emcoupling=1, -# mode="intact", isacs=0 and celltype = 0 -# -# -# Modifications by Ilse (January 2023) -# Add scaling facotrs for heart failure and drugs - - -parameters("Scales", -scale_IKr = 1.119, -scale_IKs = 1.648, -scale_IK1 = 1.414, -scale_ICaL = 1.018, -scale_INaL = 2.274) - - - -parameters("settings", -celltype=0) - -parameters("extracellular ionic concentrations", -nao=140.0, -cao=1.8, -ko=5.4) - -parameters("physical constants", "mechanics", -R=8314.0, -T=310.0, -F=96485.0) - - -parameters("cell geometry", "mechanics", -L=0.01, -rad=0.0011) - - -expressions("cell geometry", "mechanics") -vcell=1000*3.14*rad*rad*L -Ageo=2*3.14*rad*rad+2*3.14*rad*L -Acap=2*Ageo -vmyo=0.68*vcell -vnsr=0.0552*vcell -vjsr=0.0048*vcell -vss=0.02*vcell - - -# Scaling factors for heart failure -parameters("scaling factors HF", -scale_HF_CaMKa=1.0, -scale_HF_Jrel_inf=1.0, -scale_HF_Jleak=1.0, -scale_HF_Jup=1.0, -scale_HF_GNaL=1.0, -scale_HF_GK1=1.0, -scale_HF_thL=1.0, -scale_HF_Gto=1.0, -scale_HF_Gncx=1.0, -scale_HF_Pnak=1.0) - -# Scaling factors for drug effects -parameters("scaling factors drug", -scale_drug_INa=1.0, -scale_drug_INaL=1.0, -scale_drug_Ito=1.0, -scale_drug_ICaL=1.0, -scale_drug_IKr=1.0, -scale_drug_IKs=1.0, -scale_drug_IK1=1.0, -scale_drug_IKb=1.0, -scale_drug_INab=1.0, -scale_drug_ICab=1.0, -scale_drug_IpCa=1.0, -scale_drug_Isacns=1.0, -scale_drug_Isack=1.0) - -######## EP states -states("CaMKt", -CaMKt=0 -) - -states("I_Na", -m=0, -hf=1, -hs=1, -j=1, -hsp=1, -jp=1) - -states("INaL", -mL=0, -hL=1, -hLp=1) - -states("Ito", -a=0, -iF=1, -iS=1, -ap=0, -iFp=1, -iSp=1) - -states("ICaL ICaNa ICaK", -d=0, -ff=1, -fs=1, -fcaf=1, -fcas=1, -jca=1, -nca=0, -ffp=1, -fcafp=1) - - -states("IKr", -xrf=0, -xrs=0) - - -states("IKs", -xs1=0, -xs2=0, -xk1=1) - -states("membrane potential", -v=-87) - - -states("ryanodione receptor", -Jrelnp=0, -Jrelp=0) - - -states("intracellular concentrations", -cai=0.0001, -nai=7, -nass=7, -ki=145, -kss=145, -cass=0.0001, -cansr=1.2, -CaTrpn=0.0001, -cajsr=1.2) - -states("mechanics", -XS=0, -XW=0, -TmB=1, -Zetas=0, -Zetaw=0, -Cd=0) - - -############################## - -parameters("CaMK constants", -KmCaMK=0.15, -aCaMK=0.05, -bCaMK=0.00068, -CaMKo=0.05, -KmCaM=0.0015) - -expressions("CaMKt") -CaMKb=CaMKo*(1.0-CaMKt)/(1.0+KmCaM/cass) -CaMKa=(CaMKb+CaMKt)*scale_HF_CaMKa -dCaMKt_dt=aCaMK*CaMKb*(CaMKb+CaMKt)-bCaMK*CaMKt - -parameters("reversal potentials", -PKNa=0.01833) - -expressions("reversal potentials") -ENa=(R*T/F)*log(nao/nai) -EK=(R*T/F)*log(ko/ki) -EKs=(R*T/F)*log((ko+PKNa*nao)/(ki+PKNa*nai)) -vffrt=v*F*F/(R*T) -vfrt=v*F/(R*T) - -parameters("I_Na", -Ahf=0.99, -GNa=31) - -expressions("I_Na") -mss=1.0/(1.0+exp((-(v+39.57+9.4))/7.5)) -tm=1.0/(6.765*exp((v+11.64)/34.77)+8.552*exp(-(v+77.42)/5.955)) -dm_dt=(mss-m)/tm -hss=1.0/(1+exp((v+78.5)/6.22)) -thf=1.0/(1.432e-5*exp(-(v+1.196)/6.285)+6.149*exp((v+0.5096)/20.27)) -ths=1.0/(0.009794*exp(-(v+17.95)/28.05)+0.3343*exp((v+5.730)/56.66)) -Ahs=1.0-Ahf -dhf_dt=(hss-hf)/thf -dhs_dt=(hss-hs)/ths -h=Ahf*hf+Ahs*hs -jss=hss -tj=2.038+1.0/(0.02136*exp(-(v+100.6)/8.281)+0.3052*exp((v+0.9941)/38.45)) -dj_dt=(jss-j)/tj -hssp=1.0/(1+exp((v+78.5+6.2)/6.22)) -thsp=3.0*ths -dhsp_dt=(hssp-hsp)/thsp -hp=Ahf*hf+Ahs*hsp -tjp=1.46*tj -djp_dt=(jss-jp)/tjp -fINap=(1.0/(1.0+KmCaMK/CaMKa)) -INa=GNa*scale_drug_INa*(v-ENa)*m**3.0*((1.0-fINap)*h*j+fINap*hp*jp) - -parameters("INaL", -thL=200.0) - -expressions("INaL") -mLss=1.0/(1.0+exp((-(v+42.85))/5.264)) -tmL=tm -dmL_dt=(mLss-mL)/tmL -hLss=1.0/(1.0+exp((v+87.61)/7.488)) -dhL_dt=(hLss-hL)/(thL*scale_HF_thL) -hLssp=1.0/(1.0+exp((v+93.81)/7.488)) -thLp=3.0*thL*scale_HF_thL -dhLp_dt=(hLssp-hLp)/thLp -GNaL=0.0075*scale_INaL*scale_drug_INaL*scale_HF_GNaL -fINaLp=(1.0/(1.0+KmCaMK/CaMKa)) -INaL=GNaL*(v-ENa)*mL*((1.0-fINaLp)*hL+fINaLp*hLp) - -parameters("Ito", -delta_epi=1.0, -Gto=0.02) - -expressions("Ito") -ass=1.0/(1.0+exp((-(v-14.34))/14.82)) -ta=1.0515/(1.0/(1.2089*(1.0+exp(-(v-18.4099)/29.3814)))+3.5/(1.0+exp((v+100.0)/29.3814))) -da_dt=(ass-a)/ta -iss=1.0/(1.0+exp((v+43.94)/5.711)) -tiF=4.562+1/(0.3933*exp((-(v+100.0))/100.0)+0.08004*exp((v+50.0)/16.59)) * delta_epi -tiS=23.62+1/(0.001416*exp((-(v+96.52))/59.05)+1.780e-8*exp((v+114.1)/8.079)) * delta_epi -AiF=1.0/(1.0+exp((v-213.6)/151.2)) -AiS=1.0-AiF -diF_dt=(iss-iF)/tiF -diS_dt=(iss-iS)/tiS -i=AiF*iF+AiS*iS -assp=1.0/(1.0+exp((-(v-24.34))/14.82)) -dap_dt=(assp-ap)/ta -dti_develop=1.354+1.0e-4/(exp((v-167.4)/15.89)+exp(-(v-12.23)/0.2154)) -dti_recover=1.0-0.5/(1.0+exp((v+70.0)/20.0)) -tiFp=dti_develop*dti_recover*tiF -tiSp=dti_develop*dti_recover*tiS -diFp_dt=(iss-iFp)/tiFp -diSp_dt=(iss-iSp)/tiSp -ip=AiF*iFp+AiS*iSp -fItop=(1.0/(1.0+KmCaMK/CaMKa)) -Ito=Gto*scale_drug_Ito*scale_HF_Gto*(v-EK)*((1.0-fItop)*a*i+fItop*ap*ip) - - -parameters("ICaL ICaNa ICaK", -Aff=0.6, -tjca=75.0, -Kmn=0.002, -k2n=1000.0, -zca=2.0) - -expressions("ICaL ICaNa ICaK") -dss=1.0/(1.0+exp((-(v+3.940))/4.230)) -td=0.6+1.0/(exp(-0.05*(v+6.0))+exp(0.09*(v+14.0))) -dd_dt=(dss-d)/td -fss=1.0/(1.0+exp((v+19.58)/3.696)) -tff=7.0+1.0/(0.0045*exp(-(v+20.0)/10.0)+0.0045*exp((v+20.0)/10.0)) -tfs=1000.0+1.0/(0.000035*exp(-(v+5.0)/4.0)+0.000035*exp((v+5.0)/6.0)) -Afs=1.0-Aff -dff_dt=(fss-ff)/tff -dfs_dt=(fss-fs)/tfs -f=Aff*ff+Afs*fs -fcass=fss -tfcaf=7.0+1.0/(0.04*exp(-(v-4.0)/7.0)+0.04*exp((v-4.0)/7.0)) -tfcas=100.0+1.0/(0.00012*exp(-v/3.0)+0.00012*exp(v/7.0)) -Afcaf=0.3+0.6/(1.0+exp((v-10.0)/10.0)) -Afcas=1.0-Afcaf -dfcaf_dt=(fcass-fcaf)/tfcaf -dfcas_dt=(fcass-fcas)/tfcas -fca=Afcaf*fcaf+Afcas*fcas -djca_dt=(fcass-jca)/tjca -tffp=2.5*tff -dffp_dt=(fss-ffp)/tffp -fp=Aff*ffp+Afs*fs -tfcafp=2.5*tfcaf -dfcafp_dt=(fcass-fcafp)/tfcafp -fcap=Afcaf*fcafp+Afcas*fcas -km2n=jca*1.0 -anca=1.0/(k2n/km2n+(1.0+Kmn/cass)**4.0) -dnca_dt=anca*k2n-nca*km2n -PhiCaL=4.0*vffrt*(cass*exp(2.0*vfrt)-0.341*cao)/(exp(2.0*vfrt)-1.0) -PhiCaNa=1.0*vffrt*(0.75*nass*exp(1.0*vfrt)-0.75*nao)/(exp(1.0*vfrt)-1.0) -PhiCaK=1.0*vffrt*(0.75*kss*exp(1.0*vfrt)-0.75*ko)/(exp(1.0*vfrt)-1.0) -PCa=0.0001*scale_ICaL*scale_drug_ICaL -PCap=1.1*PCa -PCaNa=0.00125*PCa -PCaK=3.574e-4*PCa -PCaNap=0.00125*PCap -PCaKp=3.574e-4*PCap -fICaLp=(1.0/(1.0+KmCaMK/CaMKa)) -ICaL=(1.0-fICaLp)*PCa*PhiCaL*d*(f*(1.0-nca)+jca*fca*nca)+fICaLp*PCap*PhiCaL*d*(fp*(1.0-nca)+jca*fcap*nca) -ICaNa=(1.0-fICaLp)*PCaNa*PhiCaNa*d*(f*(1.0-nca)+jca*fca*nca)+fICaLp*PCaNap*PhiCaNa*d*(fp*(1.0-nca)+jca*fcap*nca) -ICaK=(1.0-fICaLp)*PCaK*PhiCaK*d*(f*(1.0-nca)+jca*fca*nca)+fICaLp*PCaKp*PhiCaK*d*(fp*(1.0-nca)+jca*fcap*nca) - -expressions("IKr") -xrss=1.0/(1.0+exp((-(v+8.337))/6.789)) -txrf=12.98+1.0/(0.3652*exp((v-31.66)/3.869)+4.123e-5*exp((-(v-47.78))/20.38)) -txrs=1.865+1.0/(0.06629*exp((v-34.70)/7.355)+1.128e-5*exp((-(v-29.74))/25.94)) -Axrf=1.0/(1.0+exp((v+54.81)/38.21)) -Axrs=1.0-Axrf -dxrf_dt=(xrss-xrf)/txrf -dxrs_dt=(xrss-xrs)/txrs -xr=Axrf*xrf+Axrs*xrs -rkr=1.0/(1.0+exp((v+55.0)/75.0))*1.0/(1.0+exp((v-10.0)/30.0)) -GKr=0.046*scale_IKr*scale_drug_IKr -IKr=GKr*sqrt(ko/5.4)*xr*rkr*(v-EK) - -expressions("IKs") -xs1ss=1.0/(1.0+exp((-(v+11.60))/8.932)) -txs1=817.3+1.0/(2.326e-4*exp((v+48.28)/17.80)+0.001292*exp((-(v+210.0))/230.0)) -dxs1_dt=(xs1ss-xs1)/txs1 -xs2ss=xs1ss -txs2=1.0/(0.01*exp((v-50.0)/20.0)+0.0193*exp((-(v+66.54))/31.0)) -dxs2_dt=(xs2ss-xs2)/txs2 -KsCa=1.0+0.6/(1.0+(3.8e-5/cai)**1.4) -GKs=0.0034*scale_IKs*scale_drug_IKs -IKs=GKs*KsCa*xs1*xs2*(v-EKs) -xk1ss=1.0/(1.0+exp(-(v+2.5538*ko+144.59)/(1.5692*ko+3.8115))) -txk1=122.2/(exp((-(v+127.2))/20.36)+exp((v+236.8)/69.33)) -dxk1_dt=(xk1ss-xk1)/txk1 -rk1=1.0/(1.0+exp((v+105.8-2.6*ko)/9.493)) -GK1=0.1908*scale_IK1*scale_drug_IK1*scale_HF_GK1 -IK1=GK1*sqrt(ko)*rk1*xk1*(v-EK) - - -parameters("INaCa_i", -kna1=15.0, -kna2=5.0, -kna3=88.12, -kasymm=12.5, -wna=6.0e4, -wca=6.0e4, -wnaca=5.0e3, -kcaon=1.5e6, -kcaoff=5.0e3, -qna=0.5224, -qca=0.1670, -KmCaAct=150.0e-6, -Gncx=0.0008) - -expressions("INaCa_i") -hca=exp((qca*v*F)/(R*T)) -hna=exp((qna*v*F)/(R*T)) -h1_i=1+nai/kna3*(1+hna) -h2_i=(nai*hna)/(kna3*h1_i) -h3_i=1.0/h1_i -h4_i=1.0+nai/kna1*(1+nai/kna2) -h5_i=nai*nai/(h4_i*kna1*kna2) -h6_i=1.0/h4_i -h7_i=1.0+nao/kna3*(1.0+1.0/hna) -h8_i=nao/(kna3*hna*h7_i) -h9_i=1.0/h7_i -h10_i=kasymm+1.0+nao/kna1*(1.0+nao/kna2) -h11_i=nao*nao/(h10_i*kna1*kna2) -h12_i=1.0/h10_i -k1_i=h12_i*cao*kcaon -k2_i=kcaoff -k3p_i=h9_i*wca -k3pp_i=h8_i*wnaca -k3_i=k3p_i+k3pp_i -k4p_i=h3_i*wca/hca -k4pp_i=h2_i*wnaca -k4_i=k4p_i+k4pp_i -k5_i=kcaoff -k6_i=h6_i*cai*kcaon -k7_i=h5_i*h2_i*wna -k8_i=h8_i*h11_i*wna -x1_i=k2_i*k4_i*(k7_i+k6_i)+k5_i*k7_i*(k2_i+k3_i) -x2_i=k1_i*k7_i*(k4_i+k5_i)+k4_i*k6_i*(k1_i+k8_i) -x3_i=k1_i*k3_i*(k7_i+k6_i)+k8_i*k6_i*(k2_i+k3_i) -x4_i=k2_i*k8_i*(k4_i+k5_i)+k3_i*k5_i*(k1_i+k8_i) -E1_i=x1_i/(x1_i+x2_i+x3_i+x4_i) -E2_i=x2_i/(x1_i+x2_i+x3_i+x4_i) -E3_i=x3_i/(x1_i+x2_i+x3_i+x4_i) -E4_i=x4_i/(x1_i+x2_i+x3_i+x4_i) -allo_i=1.0/(1.0+(KmCaAct/cai)**2.0) -zna=1.0 -JncxNa_i=3.0*(E4_i*k7_i-E1_i*k8_i)+E3_i*k4pp_i-E2_i*k3pp_i -JncxCa_i=E2_i*k2_i-E1_i*k1_i -INaCa_i=0.8*Gncx*scale_HF_Gncx*allo_i*(zna*JncxNa_i+zca*JncxCa_i) - -expressions("INaCa_ss") -h1=1+nass/kna3*(1+hna) -h2=(nass*hna)/(kna3*h1) -h3=1.0/h1 -h4=1.0+nass/kna1*(1+nass/kna2) -h5=nass*nass/(h4*kna1*kna2) -h6=1.0/h4 -h7=1.0+nao/kna3*(1.0+1.0/hna) -h8=nao/(kna3*hna*h7) -h9=1.0/h7 -h10=kasymm+1.0+nao/kna1*(1+nao/kna2) -h11=nao*nao/(h10*kna1*kna2) -h12=1.0/h10 -k1=h12*cao*kcaon -k2=kcaoff -k3p_ss=h9*wca -k3pp=h8*wnaca -k3=k3p_ss+k3pp -k4p_ss=h3*wca/hca -k4pp=h2*wnaca -k4=k4p_ss+k4pp -k5=kcaoff -k6=h6*cass*kcaon -k7=h5*h2*wna -k8=h8*h11*wna -x1_ss=k2*k4*(k7+k6)+k5*k7*(k2+k3) -x2_ss=k1*k7*(k4+k5)+k4*k6*(k1+k8) -x3_ss=k1*k3*(k7+k6)+k8*k6*(k2+k3) -x4_ss=k2*k8*(k4+k5)+k3*k5*(k1+k8) -E1_ss=x1_ss/(x1_ss+x2_ss+x3_ss+x4_ss) -E2_ss=x2_ss/(x1_ss+x2_ss+x3_ss+x4_ss) -E3_ss=x3_ss/(x1_ss+x2_ss+x3_ss+x4_ss) -E4_ss=x4_ss/(x1_ss+x2_ss+x3_ss+x4_ss) -allo_ss=1.0/(1.0+(KmCaAct/cass)**2.0) -JncxNa_ss=3.0*(E4_ss*k7-E1_ss*k8)+E3_ss*k4pp-E2_ss*k3pp -JncxCa_ss=E2_ss*k2-E1_ss*k1 -INaCa_ss=0.2*Gncx*scale_HF_Gncx*allo_ss*(zna*JncxNa_ss+zca*JncxCa_ss) - - -parameters("INaK", -k1p=949.5, -k1m=182.4, -k2p=687.2, -k2m=39.4, -k3p=1899.0, -k3m=79300.0, -k4p=639.0, -k4m=40.0, -Knai0=9.073, -Knao0=27.78, -delta=-0.1550, -Kki=0.5, -Kko=0.3582, -MgADP=0.05, -MgATP=9.8, -Kmgatp=1.698e-7, -H=1.0e-7, -eP=4.2, -Khp=1.698e-7, -Knap=224.0, -Kxkur=292.0, -zk=1.0, -Pnak=30) - -expressions("INaK") -Knai=Knai0*exp((delta*v*F)/(3.0*R*T)) -Knao=Knao0*exp(((1.0-delta)*v*F)/(3.0*R*T)) -P=eP/(1.0+H/Khp+nai/Knap+ki/Kxkur) -a1=(k1p*(nai/Knai)**3.0)/((1.0+nai/Knai)**3.0+(1.0+ki/Kki)**2.0-1.0) -b1=k1m*MgADP -a2=k2p -b2=(k2m*(nao/Knao)**3.0)/((1.0+nao/Knao)**3.0+(1.0+ko/Kko)**2.0-1.0) -a3=(k3p*(ko/Kko)**2.0)/((1.0+nao/Knao)**3.0+(1.0+ko/Kko)**2.0-1.0) -b3=(k3m*P*H)/(1.0+MgATP/Kmgatp) -a4=(k4p*MgATP/Kmgatp)/(1.0+MgATP/Kmgatp) -b4=(k4m*(ki/Kki)**2.0)/((1.0+nai/Knai)**3.0+(1.0+ki/Kki)**2.0-1.0) -x1=a4*a1*a2+b2*b4*b3+a2*b4*b3+b3*a1*a2 -x2=b2*b1*b4+a1*a2*a3+a3*b1*b4+a2*a3*b4 -x3=a2*a3*a4+b3*b2*b1+b2*b1*a4+a3*a4*b1 -x4=b4*b3*b2+a3*a4*a1+b2*a4*a1+b3*b2*a1 -E1=x1/(x1+x2+x3+x4) -E2=x2/(x1+x2+x3+x4) -E3=x3/(x1+x2+x3+x4) -E4=x4/(x1+x2+x3+x4) -JnakNa=3.0*(E1*a3-E2*b3) -JnakK=2.0*(E4*b1-E3*a1) -INaK=Pnak*scale_HF_Pnak*(zna*JnakNa+zk*JnakK) - - -parameters("IKb", -GKb=0.003) - -expressions("IKb") -xkb=1.0/(1.0+exp(-(v-14.48)/18.34)) -IKb=GKb*scale_drug_IKb*xkb*(v-EK) - -parameters("INab", -PNab=3.75e-10) - -expressions("INab") -INab=PNab*scale_drug_INab*vffrt*(nai*exp(vfrt)-nao)/(exp(vfrt)-1.0) - - -parameters("ICab", -PCab=2.5e-8) - -expressions("ICab") -ICab=PCab*scale_drug_ICab*4.0*vffrt*(cai*exp(2.0*vfrt)-0.341*cao)/(exp(2.0*vfrt)-1.0) - -parameters("IpCa", -GpCa=0.0005) - -expressions("IpCa") -IpCa=GpCa*scale_drug_IpCa*cai/(0.0005+cai) - - -parameters("Isac (Pueyo)--> ns + k", -Gsac_ns=0.006, -Esac_ns=-10, -lambda_max=1.1, -Gsac_k=0.2882*800/210) - -expressions("Isac (Pueyo)--> ns + k") -Isac_P_ns=0 -Isac_P_k=0 - - -parameters("Istim", -amp=-80.0, -duration=0.5) - -expressions("Istim") -Istim = Conditional(Le(t, duration), amp, 0) - -expressions("membrane potential") -dv_dt=-(INa+INaL+Ito+ICaL+ICaNa+ICaK+IKr+IKs+IK1+INaCa_i+INaCa_ss+INaK+INab+IKb+IpCa+ICab+Istim+Isac_P_ns+Isac_P_k) - -expressions("diffusion fluxes") -JdiffNa=(nass-nai)/2.0 -JdiffK=(kss-ki)/2.0 -Jdiff=(cass-cai)/0.2 - -parameters("ryanodione receptor", -bt=4.75) - -expressions("ryanodione receptor") -a_rel=0.5*bt -Jrel_inf=a_rel*(-ICaL)/(1.0+(1.5*scale_HF_Jrel_inf/cajsr)**8.0) -tau_rel_tmp=bt/(1.0+0.0123/cajsr) -tau_rel=Conditional(Lt(tau_rel_tmp, 0.001), 0.001, tau_rel_tmp) -dJrelnp_dt=(Jrel_inf-Jrelnp)/tau_rel -btp=1.25*bt -a_relp=0.5*btp -Jrel_infp=a_relp*(-ICaL)/(1.0+(1.5*scale_HF_Jrel_inf/cajsr)**8.0) -tau_relp_tmp=btp/(1.0+0.0123/cajsr) -tau_relp=Conditional(Lt(tau_relp_tmp, 0.001), 0.001, tau_relp_tmp) -dJrelp_dt=(Jrel_infp-Jrelp)/tau_relp -fJrelp=(1.0/(1.0+KmCaMK/CaMKa)) -Jrel=(1.0-fJrelp)*Jrelnp+fJrelp*Jrelp - -expressions("calcium buffers") -Jupnp=0.004375*cai/(cai+0.00092) -Jupp=2.75*0.004375*cai/(cai+0.00092-0.00017) -fJupp=(1.0/(1.0+KmCaMK/CaMKa)) -Jleak=0.0039375*cansr*scale_HF_Jleak/15.0 -Jup=(1.0-fJupp)*Jupnp+fJupp*Jupp*scale_HF_Jup-Jleak -Jtr=(cansr-cajsr)/100.0 - -parameters("calcium buffers", "mechanics", -cmdnmax=0.05, -kmcmdn=0.00238, -trpnmax=0.07, -kmtrpn=0.0005, -BSRmax=0.047, -KmBSR=0.00087, -BSLmax=1.124, -KmBSL=0.0087, -csqnmax=10.0, -Beta1 = -2.4, -ktrpn = 0.1, -cat50_ref = 0.805, -ntrpn = 2, -lmbda=1, -scale_HF_cat50_ref=1.0, -kmcsqn=0.8) - -expressions("intracellular concentrations") -dnai_dt=-(INa+INaL+3.0*INaCa_i+3.0*INaK+INab+Isac_P_ns/3)*Acap/(F*vmyo)+JdiffNa*vss/vmyo -dnass_dt=-(ICaNa+3.0*INaCa_ss)*Acap/(F*vss)-JdiffNa -dki_dt=-(Ito+IKr+IKs+IK1+IKb+Isac_P_k+Isac_P_ns/3+Istim-2.0*INaK)*Acap/(F*vmyo)+JdiffK*vss/vmyo -dkss_dt=-(ICaK)*Acap/(F*vss)-JdiffK -Bcass=1.0/(1.0+BSRmax*KmBSR/(KmBSR+cass)**2.0+BSLmax*KmBSL/(KmBSL+cass)**2.0) -dcass_dt=Bcass*(-(ICaL-2.0*INaCa_ss)*Acap/(2.0*F*vss)+Jrel*vjsr/vss-Jdiff) -dcansr_dt=Jup-Jtr*vjsr/vnsr -Bcajsr=1.0/(1.0+csqnmax*kmcsqn/(kmcsqn+cajsr)**2.0) -dcajsr_dt=Bcajsr*(Jtr-Jrel) -Bcai=1.0/(1.0+cmdnmax*kmcmdn/(kmcmdn+cai)**2.0) -lambda_min12 = Conditional(Lt(lmbda, 1.2), lmbda, 1.2) -dcai_dt=Bcai*(-(IpCa+ICab-2.0*INaCa_i+Isac_P_ns/3)*Acap/(2.0*F*vmyo)-Jup*vnsr/vmyo+Jdiff*vss/vmyo - J_TRPN) -cat50 = (cat50_ref+Beta1*(lambda_min12-1))*scale_HF_cat50_ref -dCaTrpn_dt = ktrpn*(((cai*1000/cat50)**ntrpn)*(1-CaTrpn)-CaTrpn) -J_TRPN = dCaTrpn_dt*trpnmax - -parameters("mechanics", -emcoupling=1, -dLambda=0, -mode=1, -isacs=0, -calib=1, -Trpn50 = 0.35, -rw = 0.5, -rs = 0.25, -gammas = 0.0085, -gammaw = 0.615, -phi = 2.23, -Tot_A = 25, -Beta0 = 2.3, -Tref = 120, -kuw = 0.182, -kws = 0.012, -ku=0.04, -ntm=2.4, -p_a = 2.1, -p_b = 9.1, -p_k = 7, -etal = 200, -etas = 20) - -expressions("mechanics") -XS_max = Conditional(Gt(XS, 0), XS, 0) -XW_max = Conditional(Gt(XW, 0), XW, 0) -CaTrpn_max = Conditional(Gt(CaTrpn, 0), CaTrpn, 0) -kwu = kuw*(1/rw-1)-kws -ksu = kws*rw*(1/rs-1) -Aw = Tot_A*rs/((1-rs)*rw+rs) -As = Aw -cw = phi*kuw*((1-rs)*(1-rw))/((1-rs)*rw) -cs = phi*kws*((1-rs)*rw)/rs -lambda_min12 = Conditional(Lt(lmbda, 1.2), lmbda, 1.2) -lambda_min087 = Conditional(Lt(lambda_min12, 0.87), lambda_min12, 0.87) -h_lambda_prima = 1+Beta0*(lambda_min12+lambda_min087-1.87) -h_lambda = Conditional(Gt(h_lambda_prima, 0), h_lambda_prima, 0) -XU = (1-TmB)-XS-XW -gammawu = gammaw*abs(Zetaw) -gammasu = gammas*Conditional(Gt(Gt(Zetas,0)*Zetas, Lt(Zetas, -1)*(-Zetas-1)), Gt(Zetas,0)*Zetas, Lt(Zetas, -1)*(-Zetas-1)) -dXS_dt = kws*XW - ksu*XS - gammasu*XS -dXW_dt = kuw*XU - kwu*XW - kws*XW - gammawu*XW -kb = ku*Trpn50**ntm/(1-rs-(1-rs)*rw) -dTmB_dt = kb*Conditional(Lt(CaTrpn**(-ntm/2), 100), CaTrpn**(-ntm/2), 100)*XU-ku*CaTrpn**(ntm/2)*TmB -dZetas_dt = As*dLambda - cs*Zetas -dZetaw_dt = Aw*dLambda - cw*Zetaw -Ta = h_lambda*(Tref/rs)*(XS*(Zetas+1) + XW*Zetaw) -C = lambda_min12 - 1 -dCd = C - Cd -eta = Conditional(Lt(dCd, 0), etas, etal) -dCd_dt = p_k * (C - Cd) / eta -Fd = eta * dCd -F1 = (exp( p_b * C) - 1) -Tp = p_a * (F1 + Fd) -Ttot = Ta + Tp diff --git a/demos/split-cai_catrpn/0D/main.py b/demos/split-cai_catrpn/0D/main.py deleted file mode 100644 index e33574d..0000000 --- a/demos/split-cai_catrpn/0D/main.py +++ /dev/null @@ -1,490 +0,0 @@ -"""Same as 0D but with varying lambda""" - -import gotranx -import numpy as np -import matplotlib.pyplot as plt -from pathlib import Path - - -def twitch(t, tstart=0.05, ca_ampl=-0.2): - tau1 = 0.05 * 1000 - tau2 = 0.110 * 1000 - - ca_diast = 0.0 - - beta = (tau1 / tau2) ** (-1 / (tau1 / tau2 - 1)) - (tau1 / tau2) ** (-1 / (1 - tau2 / tau1)) - ca = np.zeros_like(t) - - ca[t <= tstart] = ca_diast - - ca[t > tstart] = (ca_ampl - ca_diast) / beta * ( - np.exp(-(t[t > tstart] - tstart) / tau1) - np.exp(-(t[t > tstart] - tstart) / tau2) - ) + ca_diast - return ca + 1.0 - - -def update_lambda_and_dlambda(t, prev_lmbda, dt): - lmbda_ti = twitch(t) - p[lmbda_index] = lmbda_ti - p_mechanics[lmbda_index_mechanics] = lmbda_ti - p_ep[lmbda_index_ep] = lmbda_ti - - dLambda = (lmbda_ti - prev_lmbda) / dt - p[dLambda_index] = dLambda - p_mechanics[dLambda_index_mechanics] = dLambda - prev_lmbda = lmbda_ti - return p, p_mechanics, p_ep, prev_lmbda - - -# Load the model -ode = gotranx.load_ode("ORdmm_Land.ode") - -mechanics_comp = ode.get_component("mechanics") -mechanics_ode = mechanics_comp.to_ode() - -ep_ode = ode - mechanics_comp -ep_file = Path("ORdmm_Land_ep.py") - - -# Generate model code from .ode file -rebuild = False -if not ep_file.is_file() or rebuild: - # Generate code for full model. The full model output is plotted together with the splitting - code = gotranx.cli.gotran2py.get_code( - ode, - scheme=[gotranx.schemes.Scheme.forward_generalized_rush_larsen], - ) - - # Generate code for the electrophysiology model - code_ep = gotranx.cli.gotran2py.get_code( - ep_ode, - scheme=[gotranx.schemes.Scheme.forward_generalized_rush_larsen], - missing_values=mechanics_ode.missing_variables, - ) - - # Generate code for the mechanics model - code_mechanics = gotranx.cli.gotran2py.get_code( - mechanics_ode, - scheme=[gotranx.schemes.Scheme.forward_generalized_rush_larsen], - missing_values=ep_ode.missing_variables, - ) - - # Create ep, mechanics and full model to files: - ep_file.write_text(code_ep) - Path("ORdmm_Land_mechanics.py").write_text(code_mechanics) - Path("ORdmm_Land.py").write_text(code) - - -# Import ep, mechanics and full model -import ORdmm_Land_ep -import ORdmm_Land_mechanics -import ORdmm_Land - -model = ORdmm_Land.__dict__ -ep_model = ORdmm_Land_ep.__dict__ -mechanics_model = ORdmm_Land_mechanics.__dict__ - - -# Set time step to 0.1 ms -dt = 0.1 -# Simulate model for 1000 ms -t = np.arange(0, 700, dt) -fig, ax = plt.subplots() -ax.plot(t, twitch(t)) -ax.set_xlabel("Time (ms)") -ax.set_ylabel("Lambda") -fig.savefig("twitch.png") - -# Get the index of the membrane potential -V_index_ep = ep_model["state_index"]("v") -# Forwared generalized rush larsen scheme for the electrophysiology model -fgr_ep = ep_model["forward_generalized_rush_larsen"] -# Monitor function for the electrophysiology model -mon_ep = ep_model["monitor_values"] -# Missing values function for the electrophysiology model -mv_ep = ep_model["missing_values"] -# Index of the calcium concentration -Ca_index_ep = ep_model["state_index"]("cai") - -CaTrpn_index_ep = ep_model["state_index"]("CaTrpn") - - -J_TRPN_index_ep = ep_model["monitor_index"]("J_TRPN") -lmbda_index_ep = ep_model["parameter_index"]("lmbda") - -# Forwared generalized rush larsen scheme for the mechanics model -fgr_mechanics = mechanics_model["forward_generalized_rush_larsen"] -# Monitor function for the mechanics model -mon_mechanics = mechanics_model["monitor_values"] -# Missing values function for the mechanics model -mv_mechanics = mechanics_model["missing_values"] -# Index of the active tension -Ta_index_mechanics = mechanics_model["monitor_index"]("Ta") - - -lmbda_index_mechanics = mechanics_model["parameter_index"]("lmbda") -dLambda_index_mechanics = mechanics_model["parameter_index"]("dLambda") -Zetas_index_mechanics = mechanics_model["state_index"]("Zetas") -XS_index_mechanics = mechanics_model["state_index"]("XS") -TmB_index_mechanics = mechanics_model["state_index"]("TmB") -XU_index_mechanics = mechanics_model["monitor_index"]("XU") - - -# Forwared generalized rush larsen scheme for the full model -fgr = model["forward_generalized_rush_larsen"] -# Monitor function for the full model -mon = model["monitor_values"] - -CaTrpn_index = model["state_index"]("CaTrpn") -TmB_index = model["state_index"]("TmB") -XU_index = model["monitor_index"]("XU") - - -Ta_index = model["monitor_index"]("Ta") -J_TRPN_index = model["monitor_index"]("J_TRPN") -lmbda_index = model["parameter_index"]("lmbda") -dLambda_index = model["parameter_index"]("dLambda") -XS_index = model["state_index"]("XS") -Zetas_index = model["state_index"]("Zetas") - - -# Tolerances to test for when to perform steps in the mechanics model -tols = [ - 1e-15, - 2e-5, - 4e-5, - 6e-5, - 8e-5, - 2e-4, - 4e-4, - 6e-4, - 8e-4, - 2e-3, - 4e-3, - 6e-3, - 8e-3, - 1e-2, -] -# Colors for the plots -from itertools import cycle - -colors = cycle(["r", "g", "b", "c", "m"]) -linestyles = cycle(["-", "--", "-.", ":"]) - - -# Create arrays to store the results -V_ep = np.zeros(len(t)) -Ca_ep = np.zeros(len(t)) -J_TRPN_ep = np.zeros(len(t)) -CaTrpn_ep = np.zeros(len(t)) - -CaTrpn_full = np.zeros(len(t)) -J_TRPN_full = np.zeros(len(t)) -Ta_full = np.zeros(len(t)) -dLambda_full = np.zeros(len(t)) -XS_full = np.zeros(len(t)) -Zetas_full = np.zeros(len(t)) -lmbda_full = np.zeros(len(t)) -TmB_full = np.zeros(len(t)) -XU_full = np.zeros(len(t)) - -Ta_mechanics = np.zeros(len(t)) -dLambda_mechanics = np.zeros(len(t)) -XS_mechanics = np.zeros(len(t)) -Zetas_mechanics = np.zeros(len(t)) -lmbda_mechanics = np.zeros(len(t)) -TmB_mechanics = np.zeros(len(t)) -XU_mechanics = np.zeros(len(t)) - - -fig, ax = plt.subplots(9, 2, sharex=True, figsize=(14, 10)) -lines = [] -labels = [] - -for j, (col, ls, tol) in enumerate(zip(colors, linestyles, tols)): - # Get initial values from the EP model - y_ep = ep_model["init_state_values"]() - p_ep = ep_model["init_parameter_values"]() - - # Get initial values from the mechanics model - y_mechanics = mechanics_model["init_state_values"]() - p_mechanics = mechanics_model["init_parameter_values"]() - mechanics_missing_values = np.repeat(0.0001, len(mechanics_ode.missing_variables)) - - # Get the initial values from the full model - y = model["init_state_values"]() - p = model["init_parameter_values"]() - - # The missing variables in mechanics is catrpn. No missing variables in ep - mechanics_missing_values[:] = mv_ep(0, y_ep, p_ep) - - # We will store the previous missing values to check for convergence - prev_mechanics_missing_values = np.zeros_like(mechanics_missing_values) - prev_mechanics_missing_values[:] = mechanics_missing_values - - inds = [] - count = 1 - max_count = 10 - prev_lmbda = p[lmbda_index] - p, p_mechanics, p_ep, prev_lmbda = update_lambda_and_dlambda(np.float64(0), prev_lmbda, dt) - for i, ti in enumerate(t): - # Forward step for the full model - y[:] = fgr(y, ti, dt, p) - monitor = mon(ti, y, p) - J_TRPN_full[i] = monitor[J_TRPN_index] - Ta_full[i] = monitor[Ta_index] - CaTrpn_full[i] = y[CaTrpn_index] - XS_full[i] = y[XS_index] - Zetas_full[i] = y[Zetas_index] - dLambda_full[i] = p[dLambda_index] - lmbda_full[i] = p[lmbda_index] - TmB_full[i] = y[TmB_index] - XU_full[i] = monitor[XU_index] - - # Forward step for the EP model - y_ep[:] = fgr_ep(y_ep, ti, dt, p_ep) # no missing ep values for cai-catrpn split - V_ep[i] = y_ep[V_index_ep] - Ca_ep[i] = y_ep[Ca_index_ep] - CaTrpn_ep[i] = y_ep[CaTrpn_index_ep] - - monitor_ep = mon_ep(ti, y_ep, p_ep) # no missing ep values for cai-catrpn split - J_TRPN_ep[i] = monitor_ep[J_TRPN_index_ep] - - # Update missing values for the mechanics model - mechanics_missing_values[:] = mv_ep( - t, y_ep, p_ep - ) # no missing ep values for cai-catrpn split - - # Compute the change in the missing values - change = np.linalg.norm( - mechanics_missing_values - prev_mechanics_missing_values - ) / np.linalg.norm(prev_mechanics_missing_values) - - # Check if the change is small enough to continue to the next time step - if change < tol: - count += 1 - # Very small change to just continue to next time step - if count < max_count: - p, p_mechanics, p_ep, prev_lmbda = update_lambda_and_dlambda( - ti + dt, prev_lmbda, dt - ) - continue - - # Store the index of the time step where we performed a step - inds.append(i) - - # Forward step for the mechanics model - # y_mechanics[:] = fgr_mechanics( - # y_mechanics, ti, count * dt, p_mechanics, mechanics_missing_values - # ) - y_mechanics[:] = fgr_mechanics( - y_mechanics, ti, count * dt, p_mechanics, prev_mechanics_missing_values - ) - count = 1 - monitor_mechanics = mon_mechanics( - ti, - y_mechanics, - p_mechanics, - mechanics_missing_values, - ) - Ta_mechanics[i] = monitor_mechanics[Ta_index_mechanics] - dLambda_mechanics[i] = p_mechanics[dLambda_index_mechanics] - Zetas_mechanics[i] = y_mechanics[Zetas_index_mechanics] - XS_mechanics[i] = y_mechanics[XS_index_mechanics] - lmbda_mechanics[i] = p_mechanics[lmbda_index_mechanics] - TmB_mechanics[i] = y_mechanics[TmB_index_mechanics] - XU_mechanics[i] = monitor_mechanics[XU_index_mechanics] - - # no missing ep values for cai-catrpn split - - p, p_mechanics, p_ep, prev_lmbda = update_lambda_and_dlambda(ti + dt, prev_lmbda, dt) - # Update missing values for the mechanics model - prev_mechanics_missing_values[:] = mechanics_missing_values - - # Plot the results - perc = 100 * len(inds) / len(t) - print(f"Solved on {perc}% of the time steps") - inds = np.array(inds) - - if j == 0: - # Plot the full model with a dashed line only for the first run - (l,) = ax[8, 0].plot(t, Ta_full, color="k", linestyle="--", label="Full") - ax[2, 0].plot(t, J_TRPN_full, color="k", linestyle="--", label="Full") - ax[3, 0].plot(t, CaTrpn_full, color="k", linestyle="--", label="Full") - ax[4, 0].plot(t, TmB_full, color="k", linestyle="--", label="Full") - ax[5, 0].plot(t, XU_full, color="k", linestyle="--", label="Full") - ax[6, 0].plot(t, XS_full, color="k", linestyle="--", label="Full") - ax[7, 0].plot(t, Zetas_full, color="k", linestyle="--", label="Full") - - lines.append(l) - labels.append("Full") - - (l,) = ax[0, 0].plot(t, V_ep, color=col, linestyle=ls, label=f"tol={tol}") - lines.append(l) - labels.append(f"tol={tol}, perc={perc:.2f}%") - - ax[0, 1].plot( - t, - Ca_ep, - color=col, - linestyle=ls, - # label=f"tol={tol}", - ) - - ax[0, 0].set_ylabel("V (mV)") - ax[0, 1].set_ylabel("Ca (mM)") - - ax[1, 0].plot( - t[inds], - lmbda_mechanics[inds], - color=col, - linestyle=ls, # label=f"tol={tol}" - # marker='.' - ) - - ax[1, 1].plot( - t[inds], - dLambda_mechanics[inds], - color=col, - linestyle=ls, # label=f"tol={tol}" - ) - ax[1, 0].set_ylabel("Lambda \n mech") - ax[1, 1].set_ylabel("dLambda \n mech") - - err_Ta = np.linalg.norm(Ta_full[inds] - Ta_mechanics[inds]) / np.linalg.norm(Ta_mechanics) - err_J_TRPN = np.linalg.norm(J_TRPN_full[inds] - J_TRPN_ep[inds]) / np.linalg.norm(J_TRPN_ep) - ax[2, 0].plot( - t[inds], - J_TRPN_ep[inds], - color=col, - linestyle=ls, # label=f"tol={tol}" - ) - ax[2, 0].set_ylabel("J TRPN ") - - ax[2, 1].plot( - t[inds], - J_TRPN_full[inds] - J_TRPN_ep[inds], - # label=f"err={err_J_TRPN:.2e}, tol={tol}", - color=col, - linestyle=ls, - ) - ax[2, 1].set_ylabel("J TRPN \n error") - - ax[3, 0].plot( - t[inds], - CaTrpn_ep[inds], - color=col, - linestyle=ls, # label=f"tol={tol}" - # marker='.' - ) - - ax[3, 1].plot( - t[inds], - CaTrpn_full[inds] - CaTrpn_ep[inds], - # label=f"err={err_J_TRPN:.2e}, tol={tol}", - color=col, - linestyle=ls, - # marker='.' - ) - ax[3, 0].set_ylabel("CaTrpn ep") - ax[3, 1].set_ylabel("CaTrpn \n error") - - ax[4, 0].plot( - t[inds], - TmB_mechanics[inds], - color=col, - linestyle=ls, # label=f"tol={tol}" - ) - ax[4, 0].set_ylabel("TmB mech") - - ax[4, 1].plot( - t[inds], - np.around(TmB_full[inds] - TmB_mechanics[inds], 16), # round to float precision - # label=f"err={err_J_TRPN:.2e}, tol={tol}", - color=col, - linestyle=ls, - ) - ax[4, 1].set_ylabel("TmB \n mech error") - - ax[5, 0].plot( - t[inds], - XU_mechanics[inds], - color=col, - linestyle=ls, # label=f"tol={tol}" - ) - ax[5, 1].plot( - t[inds], - np.around(XU_full[inds] - XU_mechanics[inds], 16), # round to float precision - # label=f"err={err_J_TRPN:.2e}, tol={tol}", - color=col, - linestyle=ls, - ) - ax[5, 0].set_ylabel("XU mech") - ax[5, 1].set_ylabel("XU \n mech error") - - ax[6, 0].plot( - t[inds], - XS_mechanics[inds], - color=col, - linestyle=ls, # label=f"tol={tol}" - ) - ax[6, 1].plot( - t[inds], - XS_full[inds] - XS_mechanics[inds], - # label=f"err={err_J_TRPN:.2e}, tol={tol}", - color=col, - linestyle=ls, - ) - - ax[6, 0].set_ylabel("XS mech") - ax[6, 1].set_ylabel("XS \n mech error") - - ax[7, 0].plot( - t[inds], - Zetas_mechanics[inds], - color=col, - linestyle=ls, # label=f"tol={tol}" - ) - - ax[7, 1].plot( - t[inds], - Zetas_full[inds] - Zetas_mechanics[inds], - # label=f"err={err_J_TRPN:.2e}, tol={tol}", - color=col, - linestyle=ls, - ) - ax[7, 0].set_ylabel("Zetas mech") - ax[7, 1].set_ylabel("Zetas \n mech error") - - ax[8, 0].plot( - t[inds], - Ta_mechanics[inds], - color=col, - linestyle=ls, # label=f"tol={tol}" - ) - ax[8, 0].set_ylabel("Ta (kPa)") - - ax[8, 1].plot( - t[inds], - Ta_full[inds] - Ta_mechanics[inds], - # label=f"tol={tol}, perc={perc}%", - color=col, - linestyle=ls, - ) - ax[8, 1].set_ylabel("Ta \n error (kPa)") - - ax[8, 0].set_xlabel("Time (ms)") - ax[8, 1].set_xlabel("Time (ms)") - - # for axi in ax.flatten(): - # axi.legend() - - # fig.tight_layout() - if j == len(tols) - 1: - fig.subplots_adjust(right=0.95) - lgd = fig.legend(lines, labels, loc="center left", bbox_to_anchor=(1.0, 0.5)) - fig.tight_layout() - fig.savefig("V_and_Ta.png", bbox_extra_artists=(lgd,), bbox_inches="tight") - else: - fig.tight_layout() - fig.savefig("V_and_Ta.png") diff --git a/demos/split-cai_catrpn/0D/main_time_and_Ns.py b/demos/split-cai_catrpn/0D/main_time_and_Ns.py deleted file mode 100644 index cf3b400..0000000 --- a/demos/split-cai_catrpn/0D/main_time_and_Ns.py +++ /dev/null @@ -1,342 +0,0 @@ -import gotranx -import numpy as np -import matplotlib.pyplot as plt -from pathlib import Path -import time - -save_traces = False -run_full_model = True - - -def twitch(t, tstart=0.05, ca_ampl=-0.2): - tau1 = 0.05 * 1000 - tau2 = 0.110 * 1000 - - ca_diast = 0.0 - - beta = (tau1 / tau2) ** (-1 / (tau1 / tau2 - 1)) - (tau1 / tau2) ** (-1 / (1 - tau2 / tau1)) - ca = np.zeros_like(t) - - ca[t <= tstart] = ca_diast - - ca[t > tstart] = (ca_ampl - ca_diast) / beta * ( - np.exp(-(t[t > tstart] - tstart) / tau1) - np.exp(-(t[t > tstart] - tstart) / tau2) - ) + ca_diast - return ca + 1.0 - - -def update_lambda_and_dlambda(t, prev_lmbda, dt): - lmbda_ti = twitch(t) - p[lmbda_index] = lmbda_ti - p_mechanics[lmbda_index_mechanics] = lmbda_ti - p_ep[lmbda_index_ep] = lmbda_ti - - dLambda = (lmbda_ti - prev_lmbda) / dt - p[dLambda_index] = dLambda - p_mechanics[dLambda_index_mechanics] = dLambda - prev_lmbda = lmbda_ti - return p, p_mechanics, p_ep, prev_lmbda - - -# Load the model -ode = gotranx.load_ode("ORdmm_Land.ode") - -mechanics_comp = ode.get_component("mechanics") -mechanics_ode = mechanics_comp.to_ode() - -ep_ode = ode - mechanics_comp -ep_file = Path("ORdmm_Land_ep.py") - - -# Generate model code from .ode file -rebuild = False -if not ep_file.is_file() or rebuild: - # Generate code for full model - code = gotranx.cli.gotran2py.get_code( - ode, - scheme=[gotranx.schemes.Scheme.forward_generalized_rush_larsen], - ) - - # Generate code for the electrophysiology model - code_ep = gotranx.cli.gotran2py.get_code( - ep_ode, - scheme=[gotranx.schemes.Scheme.forward_generalized_rush_larsen], - missing_values=mechanics_ode.missing_variables, - ) - - # Generate code for the mechanics model - code_mechanics = gotranx.cli.gotran2py.get_code( - mechanics_ode, - scheme=[gotranx.schemes.Scheme.forward_generalized_rush_larsen], - missing_values=ep_ode.missing_variables, - ) - - # Create ep, mechanics and full model to files: - ep_file.write_text(code_ep) - Path("ORdmm_Land_mechanics.py").write_text(code_mechanics) - Path("ORdmm_Land.py").write_text(code) - - -# Import ep, mechanics and full model -import ORdmm_Land_ep -import ORdmm_Land_mechanics -import ORdmm_Land - -model = ORdmm_Land.__dict__ -ep_model = ORdmm_Land_ep.__dict__ -mechanics_model = ORdmm_Land_mechanics.__dict__ - - -# Set time step to 0.1 ms -dt = 0.05 -simdur = 10 -t = np.arange(0, simdur, dt) -fig, ax = plt.subplots() -ax.plot(t, twitch(t)) -ax.set_xlabel("Time (ms)") -ax.set_ylabel("Lambda") -fig.savefig("twitch.png") - -# Get the index of the membrane potential -V_index_ep = ep_model["state_index"]("v") -# Forwared generalized rush larsen scheme for the electrophysiology model -fgr_ep = ep_model["forward_generalized_rush_larsen"] -# Monitor function for the electrophysiology model -mon_ep = ep_model["monitor_values"] -# Missing values function for the electrophysiology model -mv_ep = ep_model["missing_values"] -# Index of the calcium concentration -Ca_index_ep = ep_model["state_index"]("cai") - -CaTrpn_index_ep = ep_model["state_index"]("CaTrpn") - - -J_TRPN_index_ep = ep_model["monitor_index"]("J_TRPN") -lmbda_index_ep = ep_model["parameter_index"]("lmbda") - -# Forwared generalized rush larsen scheme for the mechanics model -fgr_mechanics = mechanics_model["forward_generalized_rush_larsen"] -# Monitor function for the mechanics model -mon_mechanics = mechanics_model["monitor_values"] -# Missing values function for the mechanics model -mv_mechanics = mechanics_model["missing_values"] -# Index of the active tension -Ta_index_mechanics = mechanics_model["monitor_index"]("Ta") - - -lmbda_index_mechanics = mechanics_model["parameter_index"]("lmbda") -dLambda_index_mechanics = mechanics_model["parameter_index"]("dLambda") -Zetas_index_mechanics = mechanics_model["state_index"]("Zetas") -XS_index_mechanics = mechanics_model["state_index"]("XS") -TmB_index_mechanics = mechanics_model["state_index"]("TmB") -XU_index_mechanics = mechanics_model["monitor_index"]("XU") - - -# Forwared generalized rush larsen scheme for the full model -fgr = model["forward_generalized_rush_larsen"] -# Monitor function for the full model -mon = model["monitor_values"] - -Ca_index = model["state_index"]("cai") -V_index = model["state_index"]("v") -CaTrpn_index = model["state_index"]("CaTrpn") -TmB_index = model["state_index"]("TmB") -XU_index = model["monitor_index"]("XU") - - -Ta_index = model["monitor_index"]("Ta") -J_TRPN_index = model["monitor_index"]("J_TRPN") -lmbda_index = model["parameter_index"]("lmbda") -dLambda_index = model["parameter_index"]("dLambda") -XS_index = model["state_index"]("XS") -Zetas_index = model["state_index"]("Zetas") - - -Ns = np.array([1, 2, 4, 6, 8, 10, 20, 50, 100, 200]) - - -# Create arrays to store the results -V_ep = np.zeros(len(t)) -Ca_ep = np.zeros(len(t)) -J_TRPN_ep = np.zeros(len(t)) -CaTrpn_ep = np.zeros(len(t)) - -if run_full_model: - Ca_full = np.zeros(len(t)) - V_full = np.zeros(len(t)) - CaTrpn_full = np.zeros(len(t)) - J_TRPN_full = np.zeros(len(t)) - Ta_full = np.zeros(len(t)) - dLambda_full = np.zeros(len(t)) - XS_full = np.zeros(len(t)) - Zetas_full = np.zeros(len(t)) - lmbda_full = np.zeros(len(t)) - TmB_full = np.zeros(len(t)) - XU_full = np.zeros(len(t)) - -Ta_mechanics = np.zeros(len(t)) -dLambda_mechanics = np.zeros(len(t)) -XS_mechanics = np.zeros(len(t)) -Zetas_mechanics = np.zeros(len(t)) -lmbda_mechanics = np.zeros(len(t)) -TmB_mechanics = np.zeros(len(t)) -XU_mechanics = np.zeros(len(t)) - - -for N in Ns: - timing_init = time.perf_counter() - # Get initial values from the EP model - y_ep = ep_model["init_state_values"]() - p_ep = ep_model["init_parameter_values"]() - - # Get initial values from the mechanics model - y_mechanics = mechanics_model["init_state_values"]() - p_mechanics = mechanics_model["init_parameter_values"]() - mechanics_missing_values = np.repeat(0.0001, len(mechanics_ode.missing_variables)) - - # Get the initial values from the full model - y = model["init_state_values"]() - p = model["init_parameter_values"]() - - # The missing variables in mechanics is catrpn. No missing variables in ep - mechanics_missing_values[:] = mv_ep(0, y_ep, p_ep) - - # We will store the previous missing values to check for convergence - prev_mechanics_missing_values = np.zeros_like(mechanics_missing_values) - prev_mechanics_missing_values[:] = mechanics_missing_values - - inds = [] - count = 1 - max_count = 10 - prev_lmbda = p[lmbda_index] - p, p_mechanics, p_ep, prev_lmbda = update_lambda_and_dlambda(np.float64(0), prev_lmbda, dt) - - timings_solveloop = [] - timings_ep_steps = [] - timings_mech_steps = [] - for i, ti in enumerate(t): - timing_loopstart = time.perf_counter() - - if run_full_model: - # Forward step for the full model - y[:] = fgr(y, ti, dt, p) - monitor = mon(ti, y, p) - V_full[i] = y[V_index] - Ca_full[i] = y[Ca_index] - J_TRPN_full[i] = monitor[J_TRPN_index] - Ta_full[i] = monitor[Ta_index] - CaTrpn_full[i] = y[CaTrpn_index] - XS_full[i] = y[XS_index] - Zetas_full[i] = y[Zetas_index] - dLambda_full[i] = p[dLambda_index] - lmbda_full[i] = p[lmbda_index] - TmB_full[i] = y[TmB_index] - XU_full[i] = monitor[XU_index] - - timing_ep_start = time.perf_counter() - # Forward step for the EP model - y_ep[:] = fgr_ep(y_ep, ti, dt, p_ep) # no missing ep values for cai-catrpn split - V_ep[i] = y_ep[V_index_ep] - Ca_ep[i] = y_ep[Ca_index_ep] - CaTrpn_ep[i] = y_ep[CaTrpn_index_ep] - monitor_ep = mon_ep(ti, y_ep, p_ep) # no missing ep values for cai-catrpn split - J_TRPN_ep[i] = monitor_ep[J_TRPN_index_ep] - - timing_ep_end = time.perf_counter() - timings_ep_steps.append(timing_ep_end - timing_ep_start) - - # Update missing values for the mechanics model - mechanics_missing_values[:] = mv_ep( - t, y_ep, p_ep - ) # no missing ep values for cai-catrpn split - - if i % N != 0: - count += 1 - p, p_mechanics, p_ep, prev_lmbda = update_lambda_and_dlambda(ti + dt, prev_lmbda, dt) - timings_solveloop.append(time.perf_counter() - timing_loopstart) - continue - - # Store the index of the time step where we performed a step - inds.append(i) - - # Forward step for the mechanics model - timing_mech_start = time.perf_counter() - # y_mechanics[:] = fgr_mechanics( - # y_mechanics, ti, count * dt, p_mechanics, mechanics_missing_values - # ) - y_mechanics[:] = fgr_mechanics( - y_mechanics, ti, count * dt, p_mechanics, prev_mechanics_missing_values - ) - count = 1 - monitor_mechanics = mon_mechanics( - ti, - y_mechanics, - p_mechanics, - mechanics_missing_values, - ) - Ta_mechanics[i] = monitor_mechanics[Ta_index_mechanics] - dLambda_mechanics[i] = p_mechanics[dLambda_index_mechanics] - Zetas_mechanics[i] = y_mechanics[Zetas_index_mechanics] - XS_mechanics[i] = y_mechanics[XS_index_mechanics] - lmbda_mechanics[i] = p_mechanics[lmbda_index_mechanics] - TmB_mechanics[i] = y_mechanics[TmB_index_mechanics] - XU_mechanics[i] = monitor_mechanics[XU_index_mechanics] - - timing_mech_end = time.perf_counter() - timings_mech_steps.append(timing_mech_end - timing_mech_start) - # no missing ep values for cai-catrpn split - - p, p_mechanics, p_ep, prev_lmbda = update_lambda_and_dlambda(ti + dt, prev_lmbda, dt) - # Update missing values for the mechanics model - prev_mechanics_missing_values[:] = mechanics_missing_values - - timings_solveloop.append(time.perf_counter() - timing_loopstart) - - # Plot the results - perc = 100 * len(inds) / len(t) - print(f"Solved on {perc}% of the time steps") - inds = np.array(inds) - timing_total = time.perf_counter() - timing_init - - with open(f"timings_N{N}", "w") as f: - f.write("Init time\n") - f.write(f"{timing_init}\n") - f.write("Loop total times\n") - np.savetxt(f, timings_solveloop) - f.write("Ep steps times\n") - np.savetxt(f, timings_ep_steps) - f.write("Mech steps times\n") - np.savetxt(f, timings_mech_steps) - f.write("Total time\n") - f.write(f"{timing_total}\n") - - with open(f"V_ep_N{N}.txt", "w") as f: - np.savetxt(f, V_ep[inds]) - with open(f"Ta_mech_N{N}.txt", "w") as f: - np.savetxt(f, Ta_mechanics[inds]) - with open(f"Ca_ep_N{N}.txt", "w") as f: - np.savetxt(f, Ca_ep[inds]) - with open(f"CaTrpn_ep_N{N}.txt", "w") as f: - np.savetxt(f, CaTrpn_ep[inds]) - with open(f"J_TRPN_ep_N{N}.txt", "w") as f: - np.savetxt(f, J_TRPN_ep[inds]) - with open(f"XS_mech_N{N}.txt", "w") as f: - np.savetxt(f, XS_mechanics[inds]) - with open(f"Zetas_mech_N{N}.txt", "w") as f: - np.savetxt(f, Zetas_mechanics[inds]) - - if run_full_model: - with open("V_full.txt", "w") as f: - np.savetxt(f, V_full) - with open("Ta_full.txt", "w") as f: - np.savetxt(f, Ta_full) - with open("Ca_full.txt", "w") as f: - np.savetxt(f, Ca_full) - with open("CaTrpn_full.txt", "w") as f: - np.savetxt(f, CaTrpn_full) - with open("J_TRPN_full.txt", "w") as f: - np.savetxt(f, J_TRPN_full) - with open("XS_full.txt", "w") as f: - np.savetxt(f, XS_full) - with open("Zetas_full.txt", "w") as f: - np.savetxt(f, Zetas_full) diff --git a/demos/split-cai_catrpn/0D_ToRORd/ToRORd_dynCl_endo_catrpnsplit.ode b/demos/split-cai_catrpn/0D_ToRORd/ToRORd_dynCl_endo_catrpnsplit.ode deleted file mode 100644 index 7f3afdc..0000000 --- a/demos/split-cai_catrpn/0D_ToRORd/ToRORd_dynCl_endo_catrpnsplit.ode +++ /dev/null @@ -1,719 +0,0 @@ -states("IKr", -C1=ScalarParam(0.9982511, unit="1", description=""), -C2=ScalarParam( 7.93602000000000023e-4, unit="1", description=""), -C3=ScalarParam( 6.53214300000000045e-4, unit="1", description=""), -I_=ScalarParam( 9.80408300000000003e-6, unit="1", description=""), -O_=ScalarParam( 2.92244900000000025e-4, unit="1", description="") -) - -states("CaMK", -CaMKt=ScalarParam( 1.09502599999999999e-2, unit="mM", description="") -) - -states("ryr", -Jrel_np=ScalarParam( 1.80824799999999996e-22, unit="mM/ms", description=""), -Jrel_p=ScalarParam( 4.35860800000000030e-21, unit="mM/ms", description="") -) - -states("Ito", -a=ScalarParam( 8.89925900000000051e-4, unit="1", description=""), -ap=ScalarParam( 4.53416500000000005e-4, unit="1", description=""), -iF=ScalarParam(0.9996716, unit="1", description=""), -iFp=ScalarParam(0.9996716, unit="1", description=""), -iS=ScalarParam(0.5988908, unit="1", description=""), -iSp=ScalarParam(0.6620692, unit="1", description="") -) - -states("intracellular_ions", -cajsr=ScalarParam(1.525693, unit="mM", description=""), -cansr=ScalarParam(1.528001, unit="mM", description=""), -cass=ScalarParam( 6.49734100000000044e-5, unit="mM", description=""), -cli=ScalarParam(29.20698, unit="mM", description=""), -clss=ScalarParam(29.20696, unit="mM", description=""), -ki=ScalarParam(147.7115, unit="mM", description=""), -kss=ScalarParam(147.7114, unit="mM", description=""), -nai=ScalarParam(12.39736, unit="mM", description=""), -nass=ScalarParam(12.3977, unit="mM", description="") -) - -states("ICaL", -d=ScalarParam( 1.58884100000000000e-31, unit="1", description=""), -fcaf=ScalarParam(1, unit="1", description=""), -fcafp=ScalarParam(1, unit="1", description=""), -fcas=ScalarParam(0.9999014, unit="1", description=""), -ff_=ScalarParam(1, unit="1", description=""), -ffp=ScalarParam(1, unit="1", description=""), -fs=ScalarParam(0.9401791, unit="1", description=""), -jca=ScalarParam(0.9999846, unit="1", description=""), -nca_i=ScalarParam( 8.32600900000000053e-4, unit="1", description=""), -nca_ss=ScalarParam( 4.89937800000000024e-4, unit="1", description="") -) - -states("INa", -h=ScalarParam(0.8473267, unit="1", description=""), -hp=ScalarParam(0.7018454, unit="1", description=""), -j=ScalarParam(0.8471657, unit="1", description=""), -jp=ScalarParam(0.8469014, unit="1", description=""), -m=ScalarParam( 6.51715400000000005e-4, unit="1", description="") -) - -states("INaL", -hL=ScalarParam(0.5566017, unit="1", description=""), -hLp=ScalarParam(0.3115491, unit="1", description=""), -mL=ScalarParam( 1.35120299999999988e-4, unit="1", description="") -) - -states("membrane", -v=ScalarParam(-89.74808, unit="mV", description="") -) - -states("IKs", -xs1=ScalarParam(0.243959, unit="1", description=""), -xs2=ScalarParam( 1.58616700000000009e-4, unit="1", description="") -) - -parameters("I_katp", -A_atp=ScalarParam(2.0, unit="mM", description=""), -K_atp=ScalarParam(0.25, unit="mM", description=""), -K_o_n=ScalarParam(5.0, unit="mM", description=""), -fkatp=ScalarParam(0.0, unit="1", description=""), -gkatp=ScalarParam(4.3195, unit="mS/uF", description="") -) - -parameters("ICaL", -Aff=ScalarParam(0.6, unit="1", description=""), -ICaL_fractionSS=ScalarParam(0.8, unit="1", description=""), -Kmn=ScalarParam(0.002, unit="mM", description=""), -PCa_b=ScalarParam(8.3757e-05, unit="1", description=""), -dielConstant=ScalarParam(74.0, unit="1/K", description=""), -k2n=ScalarParam(500.0, unit="mS/uF", description=""), -offset=ScalarParam(0.0, unit="ms", description=""), -tjca=ScalarParam(72.5, unit="ms", description=""), -vShift=ScalarParam(0.0, unit="mV", description="") -) - -parameters("intracellular_ions","mechanics", -BSLmax=ScalarParam(1.124, unit="mM", description=""), -BSRmax=ScalarParam(0.047, unit="mM", description=""), -KmBSL=ScalarParam(0.0087, unit="mM", description=""), -KmBSR=ScalarParam(0.00087, unit="mM", description=""), -cmdnmax_b=ScalarParam(0.05, unit="mM", description=""), -csqnmax=ScalarParam(10.0, unit="mM", description=""), -kmcmdn=ScalarParam(0.00238, unit="mM", description=""), -kmcsqn=ScalarParam(0.8, unit="mM", description=""), -kmtrpn=ScalarParam(0.0005, unit="mM", description=""), -trpnmax=ScalarParam(0.07, unit="mM", description=""), -lmbda=1, -ktrpn = 0.1, -ntrpn = 2, -Beta1 = -2.4, -cat50_ref = 0.805 -) - -parameters("CaMK", -CaMKo=ScalarParam(0.05, unit="1", description=""), -KmCaM=ScalarParam(0.0015, unit="mM", description=""), -KmCaMK=ScalarParam(0.15, unit="mM", description=""), -aCaMK=ScalarParam(0.05, unit="1/mM/ms", description=""), -bCaMK=ScalarParam(0.00068, unit="mS/uF", description="") -) - -parameters("Ito", -EKshift=ScalarParam(0.0, unit="mV", description=""), -Gto_b=ScalarParam(0.16, unit="mS/uF", description="") -) - -parameters("physical_constants", "mechanics", -F=ScalarParam(96485.0, unit="C/mol", description=""), -R=ScalarParam(8314.0, unit="mJ/mol/K", description=""), -T=ScalarParam(310.0, unit="K", description=""), -zca=ScalarParam(2.0, unit="1", description=""), -zcl=ScalarParam(-1.0, unit="1", description=""), -zk=ScalarParam(1.0, unit="1", description=""), -zna=ScalarParam(1.0, unit="1", description="") -) - -parameters("ICl", -Fjunc=ScalarParam(1.0, unit="1", description=""), -GClCa=ScalarParam(0.2843, unit="mS/uF", description=""), -GClb=ScalarParam(0.00198, unit="mS/uF", description=""), -KdClCa=ScalarParam(0.1, unit="mM", description="") -) - -parameters("IK1", -GK1_b=ScalarParam(0.6992, unit="mS/uF", description="") -) - -parameters("IKb", -GKb_b=ScalarParam(0.0189, unit="mS/uF", description="") -) - -parameters("IKr", -GKr_b=ScalarParam(0.0321, unit="mS/uF", description=""), -alpha_1=ScalarParam(0.154375, unit="mS/uF", description=""), -beta_1=ScalarParam(0.1911, unit="mS/uF", description="") -) - -parameters("IKs", -GKs_b=ScalarParam(0.0011, unit="mS/uF", description="") -) - -parameters("INa", -GNa=ScalarParam(11.7802, unit="mS/uF", description="") -) - -parameters("INaL", -GNaL_b=ScalarParam(0.0279, unit="mS/uF", description=""), -thL=ScalarParam(200.0, unit="ms", description="") -) - -parameters("INaCa", -Gncx_b=ScalarParam(0.0034, unit="mS/uF", description=""), -INaCa_fractionSS=ScalarParam(0.35, unit="1", description=""), -KmCaAct=ScalarParam(0.00015, unit="mM", description=""), -kasymm=ScalarParam(12.5, unit="1", description=""), -kcaoff=ScalarParam(5000.0, unit="mS/uF", description=""), -kcaon=ScalarParam(1500000.0, unit="mS/uF", description=""), -kna1=ScalarParam(15.0, unit="mS/uF", description=""), -kna2=ScalarParam(5.0, unit="mS/uF", description=""), -kna3=ScalarParam(88.12, unit="mS/uF", description=""), -qca=ScalarParam(0.167, unit="1", description=""), -qna=ScalarParam(0.5224, unit="1", description=""), -wca=ScalarParam(60000.0, unit="1", description=""), -wna=ScalarParam(60000.0, unit="1", description=""), -wnaca=ScalarParam(5000.0, unit="1", description="") -) - -parameters("IpCa", -GpCa=ScalarParam(0.0005, unit="mS/uF", description=""), -KmCap=ScalarParam(0.0005, unit="mM", description="") -) - -parameters("INaK", -H=ScalarParam(1e-07, unit="mM", description=""), -Khp=ScalarParam(1.698e-07, unit="mM", description=""), -Kki=ScalarParam(0.5, unit="mS/uF", description=""), -Kko=ScalarParam(0.3582, unit="mS/uF", description=""), -Kmgatp=ScalarParam(1.698e-07, unit="mM", description=""), -Knai0=ScalarParam(9.073, unit="mM", description=""), -Knao0=ScalarParam(27.78, unit="mM", description=""), -Knap=ScalarParam(224.0, unit="mM", description=""), -Kxkur=ScalarParam(292.0, unit="mM", description=""), -MgADP=ScalarParam(0.05, unit="mM", description=""), -MgATP=ScalarParam(9.8, unit="mM", description=""), -Pnak_b=ScalarParam(15.4509, unit="mS/uF", description=""), -delta=ScalarParam(-0.155, unit="mV", description=""), -eP=ScalarParam(4.2, unit="1", description=""), -k1m=ScalarParam(182.4, unit="mS/uF", description=""), -k1p=ScalarParam(949.5, unit="mS/uF", description=""), -k2m=ScalarParam(39.4, unit="mS/uF", description=""), -k2p=ScalarParam(687.2, unit="mS/uF", description=""), -k3m=ScalarParam(79300.0, unit="mS/uF", description=""), -k3p=ScalarParam(1899.0, unit="mS/uF", description=""), -k4m=ScalarParam(40.0, unit="mS/uF", description=""), -k4p=ScalarParam(639.0, unit="mS/uF", description="") -) - -parameters("ryr", -Jrel_b=ScalarParam(1.5378, unit="1", description=""), -bt=ScalarParam(4.75, unit="ms", description=""), -cajsr_half=ScalarParam(1.7, unit="mM", description="") -) - -parameters("SERCA", -Jup_b=ScalarParam(1.0, unit="1", description="") -) - -parameters("cell_geometry","mechanics", -L=ScalarParam(0.01, unit="cm", description=""), -rad_=ScalarParam(0.0011, unit="cm", description="") -) - -parameters("ICab", -PCab=ScalarParam(5.9194e-08, unit="mS/uF", description="") -) - -parameters("reversal_potentials", -PKNa=ScalarParam(0.01833, unit="1", description="") -) - -parameters("INab", -PNab=ScalarParam(1.9239e-09, unit="mS/uF", description="") -) - -parameters("extracellular", -cao=ScalarParam(1.8, unit="mM", description=""), -clo=ScalarParam(150.0, unit="mM", description=""), -ko=ScalarParam(5.0, unit="mM", description=""), -nao=ScalarParam(140.0, unit="mM", description="") -) - -parameters("environment", -celltype=ScalarParam(0.0, unit="1", description="") -) - -parameters("membrane", -i_Stim_Amplitude=ScalarParam(-53.0, unit="A/F", description=""), -i_Stim_End=ScalarParam(1e+17, unit="ms", description=""), -i_Stim_Period=ScalarParam(1000.0, unit="ms", description=""), -i_Stim_PulseDuration=ScalarParam(1.0, unit="ms", description=""), -i_Stim_Start=ScalarParam(0.0, unit="ms", description="") -) - -parameters("diff", -tauCa=ScalarParam(0.2, unit="ms", description=""), -tauCl=ScalarParam(2.0, unit="ms", description=""), -tauK=ScalarParam(2.0, unit="ms", description=""), -tauNa=ScalarParam(2.0, unit="ms", description="") -) - -expressions("cell_geometry","mechanics") -Acap = 2.0*Ageo # cm**2 -Ageo = L*((2.0*3.14)*rad_) + rad_*((2.0*3.14)*rad_) # cm**2 -vcell = L*(rad_*((1000.0*3.14)*rad_)) # uL -vjsr = 0.0048*vcell # uL -vmyo = 0.68*vcell # uL -vnsr = 0.0552*vcell # uL -vss = 0.02*vcell # uL - -expressions("ICaL") -Afcaf = 0.3 + 0.6/(exp((v - 1*10.0)/10.0) + 1.0) -Afcas = 1.0 - Afcaf -Afs = 1.0 - Aff -ICaK = ICaK_i + ICaK_ss # A/F -ICaK_i = (1.0 - ICaL_fractionSS)*((d*(PhiCaK_i*(PCaK*(1.0 - fICaLp))))*(f*(1.0 - nca_i) + nca_i*(fca*jca)) + (d*(PhiCaK_i*(PCaKp*fICaLp)))*(fp*(1.0 - nca_i) + nca_i*(fcap*jca))) # A/F -ICaK_ss = ICaL_fractionSS*((d*(PhiCaK_ss*(PCaK*(1.0 - fICaLp))))*(f*(1.0 - nca_ss) + nca_ss*(fca*jca)) + (d*(PhiCaK_ss*(PCaKp*fICaLp)))*(fp*(1.0 - nca_ss) + nca_ss*(fcap*jca))) # A/F -ICaL_ICaL = ICaL_i + ICaL_ss # A/F -ICaL_i = (1.0 - ICaL_fractionSS)*((d*(PhiCaL_i*(PCa*(1.0 - fICaLp))))*(f*(1.0 - nca_i) + nca_i*(fca*jca)) + (d*(PhiCaL_i*(PCap*fICaLp)))*(fp*(1.0 - nca_i) + nca_i*(fcap*jca))) # A/F -ICaL_ss = ICaL_fractionSS*((d*(PhiCaL_ss*(PCa*(1.0 - fICaLp))))*(f*(1.0 - nca_ss) + nca_ss*(fca*jca)) + (d*(PhiCaL_ss*(PCap*fICaLp)))*(fp*(1.0 - nca_ss) + nca_ss*(fcap*jca))) # A/F -ICaNa = ICaNa_i + ICaNa_ss # A/F -ICaNa_i = (1.0 - ICaL_fractionSS)*((d*(PhiCaNa_i*(PCaNa*(1.0 - fICaLp))))*(f*(1.0 - nca_i) + nca_i*(fca*jca)) + (d*(PhiCaNa_i*(PCaNap*fICaLp)))*(fp*(1.0 - nca_i) + nca_i*(fcap*jca))) # A/F -ICaNa_ss = ICaL_fractionSS*((d*(PhiCaNa_ss*(PCaNa*(1.0 - fICaLp))))*(f*(1.0 - nca_ss) + nca_ss*(fca*jca)) + (d*(PhiCaNa_ss*(PCaNap*fICaLp)))*(fp*(1.0 - nca_ss) + nca_ss*(fcap*jca))) # A/F -Ii = (0.5*(4.0*cai + (cli + (ki + nai))))/1000.0 -Io = (0.5*(4.0*cao + (clo + (ko + nao))))/1000.0 -Iss = (0.5*(4.0*cass + (clss + (kss + nass))))/1000.0 -PCa = Conditional(Eq(celltype, 1.0), 1.2*PCa_b, Conditional(Eq(celltype, 2.0), 2.0*PCa_b, PCa_b)) -PCaK = 0.0003574*PCa -PCaKp = 0.0003574*PCap -PCaNa = 0.00125*PCa -PCaNap = 0.00125*PCap -PCap = 1.1*PCa -PhiCaK_i = ((1.0*vffrt)*(-gamma_ko*ko + (gamma_ki*ki)*exp(1.0*vfrt)))/(exp(1.0*vfrt) - 1*1.0) -PhiCaK_ss = ((1.0*vffrt)*(-gamma_ko*ko + (gamma_kss*kss)*exp(1.0*vfrt)))/(exp(1.0*vfrt) - 1*1.0) -PhiCaL_i = ((4.0*vffrt)*(-cao*gamma_cao + (cai*gamma_cai)*exp(2.0*vfrt)))/(exp(2.0*vfrt) - 1*1.0) -PhiCaL_ss = ((4.0*vffrt)*(-cao*gamma_cao + (cass*gamma_cass)*exp(2.0*vfrt)))/(exp(2.0*vfrt) - 1*1.0) -PhiCaNa_i = ((1.0*vffrt)*(-gamma_nao*nao + (gamma_nai*nai)*exp(1.0*vfrt)))/(exp(1.0*vfrt) - 1*1.0) -PhiCaNa_ss = ((1.0*vffrt)*(-gamma_nao*nao + (gamma_nass*nass)*exp(1.0*vfrt)))/(exp(1.0*vfrt) - 1*1.0) -anca_i = 1.0/(k2n/km2n + (Kmn/cai + 1.0)**4.0) -anca_ss = 1.0/(k2n/km2n + (Kmn/cass + 1.0)**4.0) -constA = 1820000.0/(T*dielConstant)**1.5 -dss = Conditional(Ge(v, 31.4978), 1.0, 1.0763*exp(-1.007*exp(-0.0829*v))) -f = Aff*ff_ + Afs*fs -fICaLp = 1.0/(1.0 + KmCaMK/CaMKa) -fca = Afcaf*fcaf + Afcas*fcas -fcap = Afcaf*fcafp + Afcas*fcas -fcass = fss -fp = Aff*ffp + Afs*fs -fss = 1.0/(exp((v + 19.58)/3.696) + 1.0) -gamma_cai = exp((-constA*4.0)*(sqrt(Ii)/(sqrt(Ii) + 1.0) - 0.3*Ii)) -gamma_cao = exp((-constA*4.0)*(sqrt(Io)/(sqrt(Io) + 1.0) - 0.3*Io)) -gamma_cass = exp((-constA*4.0)*(sqrt(Iss)/(sqrt(Iss) + 1.0) - 0.3*Iss)) -gamma_ki = exp((-constA*1.0)*(sqrt(Ii)/(sqrt(Ii) + 1.0) - 0.3*Ii)) -gamma_ko = exp((-constA*1.0)*(sqrt(Io)/(sqrt(Io) + 1.0) - 0.3*Io)) -gamma_kss = exp((-constA*1.0)*(sqrt(Iss)/(sqrt(Iss) + 1.0) - 0.3*Iss)) -gamma_nai = exp((-constA*1.0)*(sqrt(Ii)/(sqrt(Ii) + 1.0) - 0.3*Ii)) -gamma_nao = exp((-constA*1.0)*(sqrt(Io)/(sqrt(Io) + 1.0) - 0.3*Io)) -gamma_nass = exp((-constA*1.0)*(sqrt(Iss)/(sqrt(Iss) + 1.0) - 0.3*Iss)) -jcass = 1.0/(exp((v + 18.08)/2.7916) + 1.0) -km2n = jca*1.0 # mS/uF -td = (offset + 0.6) + 1.0/(exp((-1*0.05)*((v + vShift) + 6.0)) + exp(0.09*((v + vShift) + 14.0))) # ms -tfcaf = 7.0 + 1.0/(0.04*exp((-(v - 1*4.0))/7.0) + 0.04*exp((v - 1*4.0)/7.0)) # ms -tfcafp = 2.5*tfcaf # ms -tfcas = 100.0 + 1.0/(0.00012*exp((-v)/3.0) + 0.00012*exp(v/7.0)) # ms -tff = 7.0 + 1.0/(0.0045*exp((-(v + 20.0))/10.0) + 0.0045*exp((v + 20.0)/10.0)) # ms -tffp = 2.5*tff # ms -tfs = 1000.0 + 1.0/(3.5e-5*exp((-(v + 5.0))/4.0) + 3.5e-5*exp((v + 5.0)/6.0)) # ms -dd_dt = (-d + dss)/td -dfcaf_dt = (-fcaf + fcass)/tfcaf -dfcafp_dt = (-fcafp + fcass)/tfcafp -dfcas_dt = (-fcas + fcass)/tfcas -dff__dt = (-ff_ + fss)/tff -dffp_dt = (-ffp + fss)/tffp -dfs_dt = (-fs + fss)/tfs -djca_dt = (-jca + jcass)/tjca -dnca_i_dt = anca_i*k2n - km2n*nca_i -dnca_ss_dt = anca_ss*k2n - km2n*nca_ss - -expressions("Ito") -AiF = 1.0/(exp(((EKshift + v) - 1*213.6)/151.2) + 1.0) -AiS = 1.0 - AiF -Gto = Conditional(Or(Eq(celltype, 1.0), Eq(celltype, 2.0)), 2.0*Gto_b, Gto_b) # mS/uF -Ito_Ito = (Gto*(-EK + v))*(i*(a*(1.0 - fItop)) + ip*(ap*fItop)) # A/F -ass = 1.0/(exp((-((EKshift + v) - 1*14.34))/14.82) + 1.0) -assp = 1.0/(exp((-((EKshift + v) - 1*24.34))/14.82) + 1.0) -delta_epi = Conditional(Eq(celltype, 1.0), 1.0 - 0.95/(exp(((EKshift + v) + 70.0)/5.0) + 1.0), 1.0) -dti_develop = 1.354 + 0.0001/(exp((-((EKshift + v) - 1*12.23))/0.2154) + exp(((EKshift + v) - 1*167.4)/15.89)) -dti_recover = 1.0 - 0.5/(exp(((EKshift + v) + 70.0)/20.0) + 1.0) -fItop = 1.0/(1.0 + KmCaMK/CaMKa) -i = AiF*iF + AiS*iS -ip = AiF*iFp + AiS*iSp -iss = 1.0/(exp(((EKshift + v) + 43.94)/5.711) + 1.0) -ta = 1.0515/(1.0/((1.2089*(exp((-((EKshift + v) - 1*18.4099))/29.3814) + 1.0))) + 3.5/(exp(((EKshift + v) + 100.0)/29.3814) + 1.0)) # ms -tiF = delta_epi*tiF_b # ms -tiF_b = 4.562 + 1.0/(0.3933*exp((-((EKshift + v) + 100.0))/100.0) + 0.08004*exp(((EKshift + v) + 50.0)/16.59)) # ms -tiFp = tiF*(dti_develop*dti_recover) # ms -tiS = delta_epi*tiS_b # ms -tiS_b = 23.62 + 1.0/(0.001416*exp((-((EKshift + v) + 96.52))/59.05) + 1.78e-8*exp(((EKshift + v) + 114.1)/8.079)) # ms -tiSp = tiS*(dti_develop*dti_recover) # ms -da_dt = (-a + ass)/ta -dap_dt = (-ap + assp)/ta -diF_dt = (-iF + iss)/tiF -diFp_dt = (-iFp + iss)/tiFp -diS_dt = (-iS + iss)/tiS -diSp_dt = (-iSp + iss)/tiSp - -expressions("intracellular_ions") -Bcajsr = 1.0/((csqnmax*kmcsqn)/((cajsr + kmcsqn)**2.0) + 1.0) -Bcass = 1.0/((BSLmax*KmBSL)/((KmBSL + cass)**2.0) + ((BSRmax*KmBSR)/((KmBSR + cass)**2.0) + 1.0)) -cmdnmax = Conditional(Eq(celltype, 1.0), 1.3*cmdnmax_b, cmdnmax_b) # mM -dcajsr_dt = Bcajsr*(-Jrel + Jtr) # mM -dcansr_dt = Jup - Jtr*vjsr/vnsr # mM -dcass_dt = Bcass*(-Jdiff + ((Acap*(-(ICaL_ss - 2.0*INaCa_ss)))/(((2.0*F)*vss)) + (Jrel*vjsr)/vss)) # mM -dcli_dt = (Acap*(IClCa_sl + IClb))/((F*vmyo)) + (JdiffCl*vss)/vmyo # mM -dclss_dt = -JdiffCl + (Acap*IClCa_junc)/((F*vss)) # mM -dki_dt = (Acap*(-(ICaK_i + (-2.0*INaK_INaK + (Istim + (I_katp_I_katp + (IKb_IKb + (IK1_IK1 + (IKs_IKs + (IKr_IKr + Ito_Ito))))))))))/((F*vmyo)) + (JdiffK*vss)/vmyo # mM -dkss_dt = -JdiffK + (Acap*(-ICaK_ss))/((F*vss)) # mM -dnai_dt = (Acap*(-(INab_INab + (3.0*INaK_INaK + (ICaNa_i + (3.0*INaCa_i + (INaL_INaL + INa_INa)))))))/((F*vmyo)) + (JdiffNa*vss)/vmyo # mM -dnass_dt = -JdiffNa + (Acap*(-(ICaNa_ss + 3.0*INaCa_ss)))/((F*vss)) # mM -lambda_min12 = Conditional(Lt(lmbda, 1.2), lmbda, 1.2) -dcai_dt=Bcai*(-(IpCa_IpCa+ICab_ICab-2.0*INaCa_i/3)*Acap/(2.0*F*vmyo)-Jup*vnsr/vmyo+Jdiff*vss/vmyo - J_TRPN) -cat50 = (cat50_ref+Beta1*(lambda_min12-1)) -dCaTrpn_dt = ktrpn*(((cai*1000/cat50)**ntrpn)*(1-CaTrpn)-CaTrpn) -Bcai=1.0/(1.0+cmdnmax*kmcmdn/(kmcmdn+cai)**2.0) -J_TRPN = dCaTrpn_dt*trpnmax - - -expressions("CaMK") -CaMKa = CaMKb + CaMKt # mM -CaMKb = (CaMKo*(1.0 - CaMKt))/(KmCaM/cass + 1.0) # mM -dCaMKt_dt = -CaMKt*bCaMK + (CaMKb*aCaMK)*(CaMKb + CaMKt) # mM - -expressions("INaK") -E1_ = x1/(x4 + (x3 + (x1 + x2))) -E2 = x2/(x4 + (x3 + (x1 + x2))) -E3 = x3/(x4 + (x3 + (x1 + x2))) -E4 = x4/(x4 + (x3 + (x1 + x2))) -INaK_INaK = Pnak*(JnakK*zk + JnakNa*zna) # A/F -JnakK = 2.0*(-E3*a1 + E4*b1) # mM/ms -JnakNa = 3.0*(E1_*a3 - E2*b3) # mM/ms -Knai = Knai0*exp((delta*vfrt)/3.0) # mM -Knao = Knao0*exp((vfrt*(1.0 - delta))/3.0) # mM -P = eP/(((H/Khp + 1.0) + nai/Knap) + ki/Kxkur) -Pnak = Conditional(Eq(celltype, 1.0), 0.9*Pnak_b, Conditional(Eq(celltype, 2.0), 0.7*Pnak_b, Pnak_b)) # mS/uF -a1 = (k1p*(nai/Knai)**3.0)/(((1.0 + ki/Kki)**2.0 + (1.0 + nai/Knai)**3.0) - 1*1.0) -a2 = k2p -a3 = (k3p*(ko/Kko)**2.0)/(((1.0 + ko/Kko)**2.0 + (1.0 + nao/Knao)**3.0) - 1*1.0) -a4 = ((MgATP*k4p)/Kmgatp)/(1.0 + MgATP/Kmgatp) -b1 = MgADP*k1m -b2 = (k2m*(nao/Knao)**3.0)/(((1.0 + ko/Kko)**2.0 + (1.0 + nao/Knao)**3.0) - 1*1.0) -b3 = (H*(P*k3m))/(1.0 + MgATP/Kmgatp) -b4 = (k4m*(ki/Kki)**2.0)/(((1.0 + ki/Kki)**2.0 + (1.0 + nai/Knai)**3.0) - 1*1.0) -x1 = a2*(a1*b3) + (b3*(a2*b4) + (a2*(a1*a4) + b3*(b2*b4))) -x2 = b4*(a2*a3) + (b4*(a3*b1) + (a3*(a1*a2) + b4*(b1*b2))) -x3 = b1*(a3*a4) + (a4*(b1*b2) + (a4*(a2*a3) + b1*(b2*b3))) -x4 = a1*(b2*b3) + (a1*(a4*b2) + (a1*(a3*a4) + b2*(b3*b4))) - -expressions("INaCa") -E1_i = x1_i/(x4_i + (x3_i + (x1_i + x2_i))) -E1_ss = x1_ss/(x4_ss + (x3_ss + (x1_ss + x2_ss))) -E2_i = x2_i/(x4_i + (x3_i + (x1_i + x2_i))) -E2_ss = x2_ss/(x4_ss + (x3_ss + (x1_ss + x2_ss))) -E3_i = x3_i/(x4_i + (x3_i + (x1_i + x2_i))) -E3_ss = x3_ss/(x4_ss + (x3_ss + (x1_ss + x2_ss))) -E4_i = x4_i/(x4_i + (x3_i + (x1_i + x2_i))) -E4_ss = x4_ss/(x4_ss + (x3_ss + (x1_ss + x2_ss))) -Gncx = Conditional(Eq(celltype, 1.0), 1.1*Gncx_b, Conditional(Eq(celltype, 2.0), 1.4*Gncx_b, Gncx_b)) # mS/uF -INaCa_i = (allo_i*(Gncx*(1.0 - INaCa_fractionSS)))*(JncxCa_i*zca + JncxNa_i*zna) # A/F -INaCa_ss = (allo_ss*(Gncx*INaCa_fractionSS))*(JncxCa_ss*zca + JncxNa_ss*zna) # A/F -JncxCa_i = -E1_i*k1_i + E2_i*k2_i # mM/ms -JncxCa_ss = -E1_ss*k1_ss + E2_ss*k2_ss # mM/ms -JncxNa_i = -E2_i*k3pp_i + (E3_i*k4pp_i + 3.0*(-E1_i*k8_i + E4_i*k7_i)) # mM/ms -JncxNa_ss = -E2_ss*k3pp_ss + (E3_ss*k4pp_ss + 3.0*(-E1_ss*k8_ss + E4_ss*k7_ss)) # mM/ms -allo_i = 1.0/((KmCaAct/cai)**2.0 + 1.0) -allo_ss = 1.0/((KmCaAct/cass)**2.0 + 1.0) -h10_i = (nao/kna1)*(1.0 + nao/kna2) + (kasymm + 1.0) -h10_ss = (nao/kna1)*(1.0 + nao/kna2) + (kasymm + 1.0) -h11_i = (nao*nao)/((kna2*(h10_i*kna1))) -h11_ss = (nao*nao)/((kna2*(h10_ss*kna1))) -h12_i = 1.0/h10_i -h12_ss = 1.0/h10_ss -h1_i = (nai/kna3)*(hna + 1.0) + 1.0 -h1_ss = (nass/kna3)*(hna + 1.0) + 1.0 -h2_i = (hna*nai)/((h1_i*kna3)) -h2_ss = (hna*nass)/((h1_ss*kna3)) -h3_i = 1.0/h1_i -h3_ss = 1.0/h1_ss -h4_i = (nai/kna1)*(1.0 + nai/kna2) + 1.0 -h4_ss = (nass/kna1)*(1.0 + nass/kna2) + 1.0 -h5_i = (nai*nai)/((kna2*(h4_i*kna1))) -h5_ss = (nass*nass)/((kna2*(h4_ss*kna1))) -h6_i = 1.0/h4_i -h6_ss = 1.0/h4_ss -h7_i = (nao/kna3)*(1.0 + 1.0/hna) + 1.0 -h7_ss = (nao/kna3)*(1.0 + 1.0/hna) + 1.0 -h8_i = nao/((h7_i*(hna*kna3))) -h8_ss = nao/((h7_ss*(hna*kna3))) -h9_i = 1.0/h7_i -h9_ss = 1.0/h7_ss -hca = exp(qca*vfrt) -hna = exp(qna*vfrt) -k1_i = kcaon*(cao*h12_i) -k1_ss = kcaon*(cao*h12_ss) -k2_i = kcaoff -k2_ss = kcaoff -k3_i = k3p_i + k3pp_i -k3_ss = k3p_ss + k3pp_ss -k3p_i = h9_i*wca -k3p_ss = h9_ss*wca -k3pp_i = h8_i*wnaca -k3pp_ss = h8_ss*wnaca -k4_i = k4p_i + k4pp_i -k4_ss = k4p_ss + k4pp_ss -k4p_i = (h3_i*wca)/hca -k4p_ss = (h3_ss*wca)/hca -k4pp_i = h2_i*wnaca -k4pp_ss = h2_ss*wnaca -k5_i = kcaoff -k5_ss = kcaoff -k6_i = kcaon*(cai*h6_i) -k6_ss = kcaon*(cass*h6_ss) -k7_i = wna*(h2_i*h5_i) -k7_ss = wna*(h2_ss*h5_ss) -k8_i = wna*(h11_i*h8_i) -k8_ss = wna*(h11_ss*h8_ss) -x1_i = (k2_i*k4_i)*(k6_i + k7_i) + (k5_i*k7_i)*(k2_i + k3_i) -x1_ss = (k2_ss*k4_ss)*(k6_ss + k7_ss) + (k5_ss*k7_ss)*(k2_ss + k3_ss) -x2_i = (k1_i*k7_i)*(k4_i + k5_i) + (k4_i*k6_i)*(k1_i + k8_i) -x2_ss = (k1_ss*k7_ss)*(k4_ss + k5_ss) + (k4_ss*k6_ss)*(k1_ss + k8_ss) -x3_i = (k1_i*k3_i)*(k6_i + k7_i) + (k6_i*k8_i)*(k2_i + k3_i) -x3_ss = (k1_ss*k3_ss)*(k6_ss + k7_ss) + (k6_ss*k8_ss)*(k2_ss + k3_ss) -x4_i = (k2_i*k8_i)*(k4_i + k5_i) + (k3_i*k5_i)*(k1_i + k8_i) -x4_ss = (k2_ss*k8_ss)*(k4_ss + k5_ss) + (k3_ss*k5_ss)*(k1_ss + k8_ss) - -expressions("reversal_potentials") -ECl = ((R*T)/((F*zcl)))*log(clo/cli) # mV -EClss = ((R*T)/((F*zcl)))*log(clo/clss) # mV -EK = ((R*T)/((F*zk)))*log(ko/ki) # mV -EKs = ((R*T)/((F*zk)))*log((PKNa*nao + ko)/(PKNa*nai + ki)) # mV -ENa = ((R*T)/((F*zna)))*log(nao/nai) # mV - -expressions("IK1") -GK1 = Conditional(Eq(celltype, 1.0), 1.2*GK1_b, Conditional(Eq(celltype, 2.0), 1.3*GK1_b, GK1_b)) # mS/uF -IK1_IK1 = (K1ss*(GK1*sqrt(ko/5.0)))*(-EK + v) # A/F -K1ss = aK1/(aK1 + bK1) -aK1 = 4.094/(exp(0.1217*((-EK + v) - 1*49.934)) + 1.0) -bK1 = (15.72*exp(0.0674*((-EK + v) - 1*3.257)) + exp(0.0618*((-EK + v) - 1*594.31)))/(exp((-1*0.1629)*((-EK + v) + 14.207)) + 1.0) - -expressions("IKb") -GKb = Conditional(Eq(celltype, 1.0), 0.6*GKb_b, GKb_b) # mS/uF -IKb_IKb = (GKb*xkb)*(-EK + v) # A/F -xkb = 1.0/(exp((-(v - 1*10.8968))/23.9871) + 1.0) - -expressions("IKr") -GKr = Conditional(Eq(celltype, 1.0), 1.3*GKr_b, Conditional(Eq(celltype, 2.0), 0.8*GKr_b, GKr_b)) # mS/uF -IKr_IKr = (O_*(GKr*sqrt(ko/5.0)))*(-EK + v) # A/F -alpha = 0.1161*exp(0.299*vfrt) # mS/uF -alpha_2 = 0.0578*exp(0.971*vfrt) # mS/uF -alpha_C2ToI = 5.2e-5*exp(1.525*vfrt) # mS/uF -alpha_i = 0.2533*exp(0.5953*vfrt) # mS/uF -beta_ = 0.2442*exp((-1*1.604)*vfrt) # mS/uF -beta_2 = 0.000349*exp((-1*1.062)*vfrt) # mS/uF -beta_ItoC2 = (alpha_C2ToI*(beta_2*beta_i))/((alpha_2*alpha_i)) # mS/uF -beta_i = 0.06525*exp((-1*0.8209)*vfrt) # mS/uF -dC1_dt = -C1*(alpha_C2ToI + (alpha_2 + beta_1)) + (I_*beta_ItoC2 + (C2*alpha_1 + O_*beta_2)) -dC2_dt = -C2*(alpha_1 + beta_) + (C1*beta_1 + C3*alpha) -dC3_dt = C2*beta_ - C3*alpha -dI__dt = -I_*(beta_ItoC2 + beta_i) + (C1*alpha_C2ToI + O_*alpha_i) -dO__dt = -O_*(alpha_i + beta_2) + (C1*alpha_2 + I_*beta_i) - -expressions("IKs") -GKs = Conditional(Eq(celltype, 1.0), 1.4*GKs_b, GKs_b) # mS/uF -IKs_IKs = (xs2*(xs1*(GKs*KsCa)))*(-EKs + v) # A/F -KsCa = 1.0 + 0.6/((3.8e-5/cai)**1.4 + 1.0) -txs1 = 817.3 + 1.0/(0.0002326*exp((v + 48.28)/17.8) + 0.001292*exp((-(v + 210.0))/230.0)) # ms -txs2 = 1.0/(0.01*exp((v - 1*50.0)/20.0) + 0.0193*exp((-(v + 66.54))/31.0)) # ms -xs1ss = 1.0/(exp((-(v + 11.6))/8.932) + 1.0) -xs2ss = xs1ss -dxs1_dt = (-xs1 + xs1ss)/txs1 -dxs2_dt = (-xs2 + xs2ss)/txs2 - -expressions("INaL") -GNaL = Conditional(Eq(celltype, 1.0), 0.6*GNaL_b, GNaL_b) # mS/uF -INaL_INaL = (mL*(GNaL*(-ENa + v)))*(fINaLp*hLp + hL*(1.0 - fINaLp)) # A/F -fINaLp = 1.0/(1.0 + KmCaMK/CaMKa) -hLss = 1.0/(exp((v + 87.61)/7.488) + 1.0) -hLssp = 1.0/(exp((v + 93.81)/7.488) + 1.0) -mLss = 1.0/(exp((-(v + 42.85))/5.264) + 1.0) -thLp = 3.0*thL # ms -tmL = 0.06487*exp(-((v - 1*4.823)/51.12)**2.0) + 0.1292*exp(-((v + 45.79)/15.54)**2.0) # ms -dhL_dt = (-hL + hLss)/thL -dhLp_dt = (-hLp + hLssp)/thLp -dmL_dt = (-mL + mLss)/tmL - -expressions("ICab") -ICab_ICab = ((vffrt*(PCab*4.0))*(-cao*gamma_cao + (cai*gamma_cai)*exp(2.0*vfrt)))/(exp(2.0*vfrt) - 1*1.0) # A/F - -expressions("ICl") -IClCa = IClCa_junc + IClCa_sl # A/F -IClCa_junc = ((Fjunc*GClCa)/(KdClCa/cass + 1.0))*(-EClss + v) # A/F -IClCa_sl = ((GClCa*(1.0 - Fjunc))/(KdClCa/cai + 1.0))*(-ECl + v) # A/F -IClb = GClb*(-ECl + v) # A/F - -expressions("INa") -INa_INa = (m**3.0*(GNa*(-ENa + v)))*(j*(h*(1.0 - fINap)) + jp*(fINap*hp)) # A/F -ah = Conditional(Gt(v, -1*40.0), 0.0, 4.43126792958051e-7*exp(-0.147058823529412*v)) -aj = Conditional(Gt(v, -1*40.0), 0.0, -(v + 37.78)*(25428.0*exp(0.28831*v) + 6.948e-6)*exp(-0.04391*v)/(50262745825.954*exp(0.311*v) + 1.0)) -bh = Conditional(Gt(v, -1*40.0), 0.77*exp(0.0900900900900901*v)/(0.13*exp(0.0900900900900901*v) + 0.0497581410839387), 2.7*exp(0.079*v) + 310000.0*exp(0.3485*v)) -bj = Conditional(Gt(v, -1*40.0), 0.6*exp(0.157*v)/(1.0*exp(0.1*v) + 0.0407622039783662), 0.02424*exp(0.12728*v)/(1.0*exp(0.1378*v) + 0.00396086833990426)) -fINap = 1.0/(1.0 + KmCaMK/CaMKa) -hss = 1.0/((exp((v + 71.55)/7.43) + 1.0)**2.0) -hssp = 1.0/((exp((v + 77.55)/7.43) + 1.0)**2.0) -jss = hss -mss = 1.0/((exp((-(v + 56.86))/9.03) + 1.0)**2.0) -th = 1.0/(ah + bh) # ms -tj = 1.0/(aj + bj) # ms -tjp = 1.46*tj # ms -tm = 0.06487*exp(-((v - 1*4.823)/51.12)**2.0) + 0.1292*exp(-((v + 45.79)/15.54)**2.0) # ms -dh_dt = (-h + hss)/th -dhp_dt = (-hp + hssp)/th -dj_dt = (-j + jss)/tj -djp_dt = (-jp + jss)/tjp -dm_dt = (-m + mss)/tm - -expressions("INab") -INab_INab = ((PNab*vffrt)*(nai*exp(vfrt) - nao))/(exp(vfrt) - 1*1.0) # A/F - -expressions("I_katp") -I_katp_I_katp = (bkik*(akik*(fkatp*gkatp)))*(-EK + v) # A/F -akik = (ko/K_o_n)**0.24 -bkik = 1.0/((A_atp/K_atp)**2.0 + 1.0) - -expressions("IpCa") -IpCa_IpCa = (GpCa*cai)/(KmCap + cai) # A/F - -expressions("membrane") -Istim = Conditional(And(Le(i_Stim_Start, time), Ge(i_Stim_PulseDuration, -i_Stim_Period*floor(-(i_Stim_Start - time)/i_Stim_Period) - i_Stim_Start + time)), i_Stim_Amplitude, 0.0) # A/F -vffrt = (F*(F*v))/((R*T)) # C/mol -vfrt = (F*v)/((R*T)) -dv_dt = -(Istim + (I_katp_I_katp + (IClb + (IClCa + (ICab_ICab + (IpCa_IpCa + (IKb_IKb + (INab_INab + (INaK_INaK + (INaCa_ss + (INaCa_i + (IK1_IK1 + (IKs_IKs + (IKr_IKr + (ICaK + (ICaNa + (ICaL_ICaL + (Ito_Ito + (INaL_INaL + INa_INa))))))))))))))))))) # mV - -expressions("diff") -Jdiff = (-cai + cass)/tauCa # mM/ms -JdiffCl = (-cli + clss)/tauNa # mM/ms -JdiffK = (-ki + kss)/tauK # mM/ms -JdiffNa = (-nai + nass)/tauNa # mM/ms - -expressions("SERCA") -Jleak = (0.0048825*cansr)/15.0 # mM/ms -Jup = Jup_b*(-Jleak + (Jupnp*(1.0 - fJupp) + Jupp*fJupp)) # mM/ms -Jupnp = (cai*(upScale*0.005425))/(cai + 0.00092) # mM/ms -Jupp = (cai*((upScale*2.75)*0.005425))/((cai + 0.00092) - 1*0.00017) # mM/ms -fJupp = 1.0/(1.0 + KmCaMK/CaMKa) -upScale = Conditional(Eq(celltype, 1.0), 1.3, 1.0) - -expressions("ryr") -Jrel = Jrel_b*(Jrel_np*(1.0 - fJrelp) + Jrel_p*fJrelp) # mM/ms -Jrel_inf = Conditional(Eq(celltype, 2.0), 1.7*Jrel_inf_b, Jrel_inf_b) # mM/ms -Jrel_inf_b = ((ICaL_ss*(-a_rel))/1.0)/((cajsr_half/cajsr)**8.0 + 1.0) # mM/ms -Jrel_infp = Conditional(Eq(celltype, 2.0), 1.7*Jrel_infp_b, Jrel_infp_b) # mM/ms -Jrel_infp_b = ((ICaL_ss*(-a_relp))/1.0)/((cajsr_half/cajsr)**8.0 + 1.0) # mM/ms -a_rel = (0.5*bt)/1.0 # mM/ms -a_relp = (0.5*btp)/1.0 # mM/ms -btp = 1.25*bt # ms -fJrelp = 1.0/(1.0 + KmCaMK/CaMKa) -tau_rel = Conditional(Lt(tau_rel_b, 0.001), 0.001, tau_rel_b) # ms -tau_rel_b = bt/(1.0 + 0.0123/cajsr) # ms -tau_relp = Conditional(Lt(tau_relp_b, 0.001), 0.001, tau_relp_b) # ms -tau_relp_b = btp/(1.0 + 0.0123/cajsr) # ms -dJrel_np_dt = (Jrel_inf - Jrel_np)/tau_rel # mM/ms -dJrel_p_dt = (Jrel_infp - Jrel_p)/tau_relp # mM/ms - -expressions("trans_flux") -Jtr = (-cajsr + cansr)/60.0 # mM/ms - - -states("intracellular_ions", -cai=0.0001, -CaTrpn=1e-8 -) - -states("mechanics", -XS=0, -XW=0, -TmB=1, -Zetas=0, -Zetaw=0, -Cd=0) - -parameters("mechanics", -emcoupling=1, -lmbda=1, -dLambda=0, -mode=1, -isacs=0, -calib=1, -ktrpn = 0.1, -ntrpn = 2, -Trpn50 = 0.35, -rw = 0.5, -rs = 0.25, -gammas = 0.0085, -gammaw = 0.615, -phi = 2.23, -Tot_A = 25, -Beta0 = 2.3, -Beta1 = -2.4, -cat50_ref = 0.805, -Tref = 120, -kuw = 0.182, -kws = 0.012, -ku=0.04, -ntm=2.4, -p_a = 2.1, -p_b = 9.1, -p_k = 7, -etal = 200, -etas = 20) - -expressions("mechanics") -XS_max = Conditional(Gt(XS, 0), XS, 0) -XW_max = Conditional(Gt(XW, 0), XW, 0) -CaTrpn_max = Conditional(Gt(CaTrpn, 0), CaTrpn, 0) -kwu = kuw*(1/rw-1)-kws -ksu = kws*rw*(1/rs-1) -Aw = Tot_A*rs/((1-rs)*rw+rs) -As = Aw -cw = phi*kuw*((1-rs)*(1-rw))/((1-rs)*rw) -cs = phi*kws*((1-rs)*rw)/rs -lambda_min12 = Conditional(Lt(lmbda, 1.2), lmbda, 1.2) -lambda_min087 = Conditional(Lt(lambda_min12, 0.87), lambda_min12, 0.87) -h_lambda_prima = 1+Beta0*(lambda_min12+lambda_min087-1.87) -h_lambda = Conditional(Gt(h_lambda_prima, 0), h_lambda_prima, 0) -XU = (1-TmB)-XS-XW -gammawu = gammaw*Abs(Zetaw) -gammasu = gammas*Conditional(Gt(Gt(Zetas,0)*Zetas, Lt(Zetas, -1)*(-Zetas-1)), Gt(Zetas,0)*Zetas, Lt(Zetas, -1)*(-Zetas-1)) -dXS_dt = kws*XW - ksu*XS - gammasu*XS -dXW_dt = kuw*XU - kwu*XW - kws*XW - gammawu*XW -kb = ku*Trpn50**ntm/(1-rs-(1-rs)*rw) -dTmB_dt = kb*Conditional(Lt(CaTrpn**(-ntm/2), 100), CaTrpn**(-ntm/2), 100)*XU-ku*CaTrpn**(ntm/2)*TmB -dZetas_dt = As*dLambda - cs*Zetas -dZetaw_dt = Aw*dLambda - cw*Zetaw -Ta = h_lambda*(Tref/rs)*(XS*(Zetas+1) + XW*Zetaw) -C = lambda_min12 - 1 -dCd = C - Cd -eta = Conditional(Lt(dCd, 0), etas, etal) -dCd_dt = p_k * (C - Cd) / eta -Fd = eta * dCd -F1 = (exp( p_b * C) - 1) -Tp = p_a * (F1 + Fd) -Ttot = Ta + Tp diff --git a/demos/split-cai_catrpn/3D/ORdmm_Land.ode b/demos/split-cai_catrpn/3D/ORdmm_Land.ode deleted file mode 100644 index c753ce8..0000000 --- a/demos/split-cai_catrpn/3D/ORdmm_Land.ode +++ /dev/null @@ -1,663 +0,0 @@ -# ORd modified by MMora (October-2016) -# Modifications in INa. The original formulation of INa has been -# optimised, according to Passini, in order to look like TT04. -# Modifications: -# 1) mss,hss,jss and hssp -# 2) gNa -# + -# Re-scaled conductances (Dutta et al 2016 CinC) -# + -# -# Land 2017(mechanical model)- Introduced by MMora (Jan2020) -# Tension -# Changes in Cai effect of troponin -# + -# -# Isacs -# -# -# In this version we fix mech.emcoupling=1, -# mode="intact", isacs=0 and celltype = 0 -# -# -# Modifications by Ilse (January 2023) -# Add scaling facotrs for heart failure and drugs - - -parameters("Scales", -scale_IKr = 1.119, -scale_IKs = 1.648, -scale_IK1 = 1.414, -scale_ICaL = 1.018, -scale_INaL = 2.274) - - - -parameters("settings", -celltype=0) - -parameters("extracellular ionic concentrations", -nao=140.0, -cao=1.8, -ko=5.4) - -parameters("physical constants", "mechanics", -R=8314.0, -T=310.0, -F=96485.0) - - -parameters("cell geometry", "mechanics", -L=0.01, -rad=0.0011) - - -expressions("cell geometry", "mechanics") -vcell=1000*3.14*rad*rad*L -Ageo=2*3.14*rad*rad+2*3.14*rad*L -Acap=2*Ageo -vmyo=0.68*vcell -vnsr=0.0552*vcell -vjsr=0.0048*vcell -vss=0.02*vcell - - -# Scaling factors for heart failure -parameters("scaling factors HF", -scale_HF_CaMKa=1.0, -scale_HF_Jrel_inf=1.0, -scale_HF_Jleak=1.0, -scale_HF_Jup=1.0, -scale_HF_GNaL=1.0, -scale_HF_GK1=1.0, -scale_HF_thL=1.0, -scale_HF_Gto=1.0, -scale_HF_Gncx=1.0, -scale_HF_Pnak=1.0) - -# Scaling factors for drug effects -parameters("scaling factors drug", -scale_drug_INa=1.0, -scale_drug_INaL=1.0, -scale_drug_Ito=1.0, -scale_drug_ICaL=1.0, -scale_drug_IKr=1.0, -scale_drug_IKs=1.0, -scale_drug_IK1=1.0, -scale_drug_IKb=1.0, -scale_drug_INab=1.0, -scale_drug_ICab=1.0, -scale_drug_IpCa=1.0, -scale_drug_Isacns=1.0, -scale_drug_Isack=1.0) - -######## EP states -states("CaMKt", -CaMKt=0 -) - -states("I_Na", -m=0, -hf=1, -hs=1, -j=1, -hsp=1, -jp=1) - -states("INaL", -mL=0, -hL=1, -hLp=1) - -states("Ito", -a=0, -iF=1, -iS=1, -ap=0, -iFp=1, -iSp=1) - -states("ICaL ICaNa ICaK", -d=0, -ff=1, -fs=1, -fcaf=1, -fcas=1, -jca=1, -nca=0, -ffp=1, -fcafp=1) - - -states("IKr", -xrf=0, -xrs=0) - - -states("IKs", -xs1=0, -xs2=0, -xk1=1) - -states("membrane potential", -v=-87) - - -states("ryanodione receptor", -Jrelnp=0, -Jrelp=0) - - -states("intracellular concentrations", -cai=0.0001, -nai=7, -nass=7, -ki=145, -kss=145, -cass=0.0001, -cansr=1.2, -CaTrpn=0.0001, -cajsr=1.2) - -states("mechanics", -XS=0, -XW=0, -TmB=1, -Zetas=0, -Zetaw=0, -Cd=0) - - -############################## - -parameters("CaMK constants", -KmCaMK=0.15, -aCaMK=0.05, -bCaMK=0.00068, -CaMKo=0.05, -KmCaM=0.0015) - -expressions("CaMKt") -CaMKb=CaMKo*(1.0-CaMKt)/(1.0+KmCaM/cass) -CaMKa=(CaMKb+CaMKt)*scale_HF_CaMKa -dCaMKt_dt=aCaMK*CaMKb*(CaMKb+CaMKt)-bCaMK*CaMKt - -parameters("reversal potentials", -PKNa=0.01833) - -expressions("reversal potentials") -ENa=(R*T/F)*log(nao/nai) -EK=(R*T/F)*log(ko/ki) -EKs=(R*T/F)*log((ko+PKNa*nao)/(ki+PKNa*nai)) -vffrt=v*F*F/(R*T) -vfrt=v*F/(R*T) - -parameters("I_Na", -Ahf=0.99, -GNa=31) - -expressions("I_Na") -mss=1.0/(1.0+exp((-(v+39.57+9.4))/7.5)) -tm=1.0/(6.765*exp((v+11.64)/34.77)+8.552*exp(-(v+77.42)/5.955)) -dm_dt=(mss-m)/tm -hss=1.0/(1+exp((v+78.5)/6.22)) -thf=1.0/(1.432e-5*exp(-(v+1.196)/6.285)+6.149*exp((v+0.5096)/20.27)) -ths=1.0/(0.009794*exp(-(v+17.95)/28.05)+0.3343*exp((v+5.730)/56.66)) -Ahs=1.0-Ahf -dhf_dt=(hss-hf)/thf -dhs_dt=(hss-hs)/ths -h=Ahf*hf+Ahs*hs -jss=hss -tj=2.038+1.0/(0.02136*exp(-(v+100.6)/8.281)+0.3052*exp((v+0.9941)/38.45)) -dj_dt=(jss-j)/tj -hssp=1.0/(1+exp((v+78.5+6.2)/6.22)) -thsp=3.0*ths -dhsp_dt=(hssp-hsp)/thsp -hp=Ahf*hf+Ahs*hsp -tjp=1.46*tj -djp_dt=(jss-jp)/tjp -fINap=(1.0/(1.0+KmCaMK/CaMKa)) -INa=GNa*scale_drug_INa*(v-ENa)*m**3.0*((1.0-fINap)*h*j+fINap*hp*jp) - -parameters("INaL", -thL=200.0) - -expressions("INaL") -mLss=1.0/(1.0+exp((-(v+42.85))/5.264)) -tmL=tm -dmL_dt=(mLss-mL)/tmL -hLss=1.0/(1.0+exp((v+87.61)/7.488)) -dhL_dt=(hLss-hL)/(thL*scale_HF_thL) -hLssp=1.0/(1.0+exp((v+93.81)/7.488)) -thLp=3.0*thL*scale_HF_thL -dhLp_dt=(hLssp-hLp)/thLp -GNaL=0.0075*scale_INaL*scale_drug_INaL*scale_HF_GNaL -fINaLp=(1.0/(1.0+KmCaMK/CaMKa)) -INaL=GNaL*(v-ENa)*mL*((1.0-fINaLp)*hL+fINaLp*hLp) - -parameters("Ito", -delta_epi=1.0, -Gto=0.02) - -expressions("Ito") -ass=1.0/(1.0+exp((-(v-14.34))/14.82)) -ta=1.0515/(1.0/(1.2089*(1.0+exp(-(v-18.4099)/29.3814)))+3.5/(1.0+exp((v+100.0)/29.3814))) -da_dt=(ass-a)/ta -iss=1.0/(1.0+exp((v+43.94)/5.711)) -tiF=4.562+1/(0.3933*exp((-(v+100.0))/100.0)+0.08004*exp((v+50.0)/16.59)) * delta_epi -tiS=23.62+1/(0.001416*exp((-(v+96.52))/59.05)+1.780e-8*exp((v+114.1)/8.079)) * delta_epi -AiF=1.0/(1.0+exp((v-213.6)/151.2)) -AiS=1.0-AiF -diF_dt=(iss-iF)/tiF -diS_dt=(iss-iS)/tiS -i=AiF*iF+AiS*iS -assp=1.0/(1.0+exp((-(v-24.34))/14.82)) -dap_dt=(assp-ap)/ta -dti_develop=1.354+1.0e-4/(exp((v-167.4)/15.89)+exp(-(v-12.23)/0.2154)) -dti_recover=1.0-0.5/(1.0+exp((v+70.0)/20.0)) -tiFp=dti_develop*dti_recover*tiF -tiSp=dti_develop*dti_recover*tiS -diFp_dt=(iss-iFp)/tiFp -diSp_dt=(iss-iSp)/tiSp -ip=AiF*iFp+AiS*iSp -fItop=(1.0/(1.0+KmCaMK/CaMKa)) -Ito=Gto*scale_drug_Ito*scale_HF_Gto*(v-EK)*((1.0-fItop)*a*i+fItop*ap*ip) - - -parameters("ICaL ICaNa ICaK", -Aff=0.6, -tjca=75.0, -Kmn=0.002, -k2n=1000.0, -zca=2.0) - -expressions("ICaL ICaNa ICaK") -dss=1.0/(1.0+exp((-(v+3.940))/4.230)) -td=0.6+1.0/(exp(-0.05*(v+6.0))+exp(0.09*(v+14.0))) -dd_dt=(dss-d)/td -fss=1.0/(1.0+exp((v+19.58)/3.696)) -tff=7.0+1.0/(0.0045*exp(-(v+20.0)/10.0)+0.0045*exp((v+20.0)/10.0)) -tfs=1000.0+1.0/(0.000035*exp(-(v+5.0)/4.0)+0.000035*exp((v+5.0)/6.0)) -Afs=1.0-Aff -dff_dt=(fss-ff)/tff -dfs_dt=(fss-fs)/tfs -f=Aff*ff+Afs*fs -fcass=fss -tfcaf=7.0+1.0/(0.04*exp(-(v-4.0)/7.0)+0.04*exp((v-4.0)/7.0)) -tfcas=100.0+1.0/(0.00012*exp(-v/3.0)+0.00012*exp(v/7.0)) -Afcaf=0.3+0.6/(1.0+exp((v-10.0)/10.0)) -Afcas=1.0-Afcaf -dfcaf_dt=(fcass-fcaf)/tfcaf -dfcas_dt=(fcass-fcas)/tfcas -fca=Afcaf*fcaf+Afcas*fcas -djca_dt=(fcass-jca)/tjca -tffp=2.5*tff -dffp_dt=(fss-ffp)/tffp -fp=Aff*ffp+Afs*fs -tfcafp=2.5*tfcaf -dfcafp_dt=(fcass-fcafp)/tfcafp -fcap=Afcaf*fcafp+Afcas*fcas -km2n=jca*1.0 -anca=1.0/(k2n/km2n+(1.0+Kmn/cass)**4.0) -dnca_dt=anca*k2n-nca*km2n -PhiCaL=4.0*vffrt*(cass*exp(2.0*vfrt)-0.341*cao)/(exp(2.0*vfrt)-1.0) -PhiCaNa=1.0*vffrt*(0.75*nass*exp(1.0*vfrt)-0.75*nao)/(exp(1.0*vfrt)-1.0) -PhiCaK=1.0*vffrt*(0.75*kss*exp(1.0*vfrt)-0.75*ko)/(exp(1.0*vfrt)-1.0) -PCa=0.0001*scale_ICaL*scale_drug_ICaL -PCap=1.1*PCa -PCaNa=0.00125*PCa -PCaK=3.574e-4*PCa -PCaNap=0.00125*PCap -PCaKp=3.574e-4*PCap -fICaLp=(1.0/(1.0+KmCaMK/CaMKa)) -ICaL=(1.0-fICaLp)*PCa*PhiCaL*d*(f*(1.0-nca)+jca*fca*nca)+fICaLp*PCap*PhiCaL*d*(fp*(1.0-nca)+jca*fcap*nca) -ICaNa=(1.0-fICaLp)*PCaNa*PhiCaNa*d*(f*(1.0-nca)+jca*fca*nca)+fICaLp*PCaNap*PhiCaNa*d*(fp*(1.0-nca)+jca*fcap*nca) -ICaK=(1.0-fICaLp)*PCaK*PhiCaK*d*(f*(1.0-nca)+jca*fca*nca)+fICaLp*PCaKp*PhiCaK*d*(fp*(1.0-nca)+jca*fcap*nca) - -expressions("IKr") -xrss=1.0/(1.0+exp((-(v+8.337))/6.789)) -txrf=12.98+1.0/(0.3652*exp((v-31.66)/3.869)+4.123e-5*exp((-(v-47.78))/20.38)) -txrs=1.865+1.0/(0.06629*exp((v-34.70)/7.355)+1.128e-5*exp((-(v-29.74))/25.94)) -Axrf=1.0/(1.0+exp((v+54.81)/38.21)) -Axrs=1.0-Axrf -dxrf_dt=(xrss-xrf)/txrf -dxrs_dt=(xrss-xrs)/txrs -xr=Axrf*xrf+Axrs*xrs -rkr=1.0/(1.0+exp((v+55.0)/75.0))*1.0/(1.0+exp((v-10.0)/30.0)) -GKr=0.046*scale_IKr*scale_drug_IKr -IKr=GKr*sqrt(ko/5.4)*xr*rkr*(v-EK) - -expressions("IKs") -xs1ss=1.0/(1.0+exp((-(v+11.60))/8.932)) -txs1=817.3+1.0/(2.326e-4*exp((v+48.28)/17.80)+0.001292*exp((-(v+210.0))/230.0)) -dxs1_dt=(xs1ss-xs1)/txs1 -xs2ss=xs1ss -txs2=1.0/(0.01*exp((v-50.0)/20.0)+0.0193*exp((-(v+66.54))/31.0)) -dxs2_dt=(xs2ss-xs2)/txs2 -KsCa=1.0+0.6/(1.0+(3.8e-5/cai)**1.4) -GKs=0.0034*scale_IKs*scale_drug_IKs -IKs=GKs*KsCa*xs1*xs2*(v-EKs) -xk1ss=1.0/(1.0+exp(-(v+2.5538*ko+144.59)/(1.5692*ko+3.8115))) -txk1=122.2/(exp((-(v+127.2))/20.36)+exp((v+236.8)/69.33)) -dxk1_dt=(xk1ss-xk1)/txk1 -rk1=1.0/(1.0+exp((v+105.8-2.6*ko)/9.493)) -GK1=0.1908*scale_IK1*scale_drug_IK1*scale_HF_GK1 -IK1=GK1*sqrt(ko)*rk1*xk1*(v-EK) - - -parameters("INaCa_i", -kna1=15.0, -kna2=5.0, -kna3=88.12, -kasymm=12.5, -wna=6.0e4, -wca=6.0e4, -wnaca=5.0e3, -kcaon=1.5e6, -kcaoff=5.0e3, -qna=0.5224, -qca=0.1670, -KmCaAct=150.0e-6, -Gncx=0.0008) - -expressions("INaCa_i") -hca=exp((qca*v*F)/(R*T)) -hna=exp((qna*v*F)/(R*T)) -h1_i=1+nai/kna3*(1+hna) -h2_i=(nai*hna)/(kna3*h1_i) -h3_i=1.0/h1_i -h4_i=1.0+nai/kna1*(1+nai/kna2) -h5_i=nai*nai/(h4_i*kna1*kna2) -h6_i=1.0/h4_i -h7_i=1.0+nao/kna3*(1.0+1.0/hna) -h8_i=nao/(kna3*hna*h7_i) -h9_i=1.0/h7_i -h10_i=kasymm+1.0+nao/kna1*(1.0+nao/kna2) -h11_i=nao*nao/(h10_i*kna1*kna2) -h12_i=1.0/h10_i -k1_i=h12_i*cao*kcaon -k2_i=kcaoff -k3p_i=h9_i*wca -k3pp_i=h8_i*wnaca -k3_i=k3p_i+k3pp_i -k4p_i=h3_i*wca/hca -k4pp_i=h2_i*wnaca -k4_i=k4p_i+k4pp_i -k5_i=kcaoff -k6_i=h6_i*cai*kcaon -k7_i=h5_i*h2_i*wna -k8_i=h8_i*h11_i*wna -x1_i=k2_i*k4_i*(k7_i+k6_i)+k5_i*k7_i*(k2_i+k3_i) -x2_i=k1_i*k7_i*(k4_i+k5_i)+k4_i*k6_i*(k1_i+k8_i) -x3_i=k1_i*k3_i*(k7_i+k6_i)+k8_i*k6_i*(k2_i+k3_i) -x4_i=k2_i*k8_i*(k4_i+k5_i)+k3_i*k5_i*(k1_i+k8_i) -E1_i=x1_i/(x1_i+x2_i+x3_i+x4_i) -E2_i=x2_i/(x1_i+x2_i+x3_i+x4_i) -E3_i=x3_i/(x1_i+x2_i+x3_i+x4_i) -E4_i=x4_i/(x1_i+x2_i+x3_i+x4_i) -allo_i=1.0/(1.0+(KmCaAct/cai)**2.0) -zna=1.0 -JncxNa_i=3.0*(E4_i*k7_i-E1_i*k8_i)+E3_i*k4pp_i-E2_i*k3pp_i -JncxCa_i=E2_i*k2_i-E1_i*k1_i -INaCa_i=0.8*Gncx*scale_HF_Gncx*allo_i*(zna*JncxNa_i+zca*JncxCa_i) - -expressions("INaCa_ss") -h1=1+nass/kna3*(1+hna) -h2=(nass*hna)/(kna3*h1) -h3=1.0/h1 -h4=1.0+nass/kna1*(1+nass/kna2) -h5=nass*nass/(h4*kna1*kna2) -h6=1.0/h4 -h7=1.0+nao/kna3*(1.0+1.0/hna) -h8=nao/(kna3*hna*h7) -h9=1.0/h7 -h10=kasymm+1.0+nao/kna1*(1+nao/kna2) -h11=nao*nao/(h10*kna1*kna2) -h12=1.0/h10 -k1=h12*cao*kcaon -k2=kcaoff -k3p_ss=h9*wca -k3pp=h8*wnaca -k3=k3p_ss+k3pp -k4p_ss=h3*wca/hca -k4pp=h2*wnaca -k4=k4p_ss+k4pp -k5=kcaoff -k6=h6*cass*kcaon -k7=h5*h2*wna -k8=h8*h11*wna -x1_ss=k2*k4*(k7+k6)+k5*k7*(k2+k3) -x2_ss=k1*k7*(k4+k5)+k4*k6*(k1+k8) -x3_ss=k1*k3*(k7+k6)+k8*k6*(k2+k3) -x4_ss=k2*k8*(k4+k5)+k3*k5*(k1+k8) -E1_ss=x1_ss/(x1_ss+x2_ss+x3_ss+x4_ss) -E2_ss=x2_ss/(x1_ss+x2_ss+x3_ss+x4_ss) -E3_ss=x3_ss/(x1_ss+x2_ss+x3_ss+x4_ss) -E4_ss=x4_ss/(x1_ss+x2_ss+x3_ss+x4_ss) -allo_ss=1.0/(1.0+(KmCaAct/cass)**2.0) -JncxNa_ss=3.0*(E4_ss*k7-E1_ss*k8)+E3_ss*k4pp-E2_ss*k3pp -JncxCa_ss=E2_ss*k2-E1_ss*k1 -INaCa_ss=0.2*Gncx*scale_HF_Gncx*allo_ss*(zna*JncxNa_ss+zca*JncxCa_ss) - - -parameters("INaK", -k1p=949.5, -k1m=182.4, -k2p=687.2, -k2m=39.4, -k3p=1899.0, -k3m=79300.0, -k4p=639.0, -k4m=40.0, -Knai0=9.073, -Knao0=27.78, -delta=-0.1550, -Kki=0.5, -Kko=0.3582, -MgADP=0.05, -MgATP=9.8, -Kmgatp=1.698e-7, -H=1.0e-7, -eP=4.2, -Khp=1.698e-7, -Knap=224.0, -Kxkur=292.0, -zk=1.0, -Pnak=30) - -expressions("INaK") -Knai=Knai0*exp((delta*v*F)/(3.0*R*T)) -Knao=Knao0*exp(((1.0-delta)*v*F)/(3.0*R*T)) -P=eP/(1.0+H/Khp+nai/Knap+ki/Kxkur) -a1=(k1p*(nai/Knai)**3.0)/((1.0+nai/Knai)**3.0+(1.0+ki/Kki)**2.0-1.0) -b1=k1m*MgADP -a2=k2p -b2=(k2m*(nao/Knao)**3.0)/((1.0+nao/Knao)**3.0+(1.0+ko/Kko)**2.0-1.0) -a3=(k3p*(ko/Kko)**2.0)/((1.0+nao/Knao)**3.0+(1.0+ko/Kko)**2.0-1.0) -b3=(k3m*P*H)/(1.0+MgATP/Kmgatp) -a4=(k4p*MgATP/Kmgatp)/(1.0+MgATP/Kmgatp) -b4=(k4m*(ki/Kki)**2.0)/((1.0+nai/Knai)**3.0+(1.0+ki/Kki)**2.0-1.0) -x1=a4*a1*a2+b2*b4*b3+a2*b4*b3+b3*a1*a2 -x2=b2*b1*b4+a1*a2*a3+a3*b1*b4+a2*a3*b4 -x3=a2*a3*a4+b3*b2*b1+b2*b1*a4+a3*a4*b1 -x4=b4*b3*b2+a3*a4*a1+b2*a4*a1+b3*b2*a1 -E1=x1/(x1+x2+x3+x4) -E2=x2/(x1+x2+x3+x4) -E3=x3/(x1+x2+x3+x4) -E4=x4/(x1+x2+x3+x4) -JnakNa=3.0*(E1*a3-E2*b3) -JnakK=2.0*(E4*b1-E3*a1) -INaK=Pnak*scale_HF_Pnak*(zna*JnakNa+zk*JnakK) - - -parameters("IKb", -GKb=0.003) - -expressions("IKb") -xkb=1.0/(1.0+exp(-(v-14.48)/18.34)) -IKb=GKb*scale_drug_IKb*xkb*(v-EK) - -parameters("INab", -PNab=3.75e-10) - -expressions("INab") -INab=PNab*scale_drug_INab*vffrt*(nai*exp(vfrt)-nao)/(exp(vfrt)-1.0) - - -parameters("ICab", -PCab=2.5e-8) - -expressions("ICab") -ICab=PCab*scale_drug_ICab*4.0*vffrt*(cai*exp(2.0*vfrt)-0.341*cao)/(exp(2.0*vfrt)-1.0) - -parameters("IpCa", -GpCa=0.0005) - -expressions("IpCa") -IpCa=GpCa*scale_drug_IpCa*cai/(0.0005+cai) - - -parameters("Isac (Pueyo)--> ns + k", -Gsac_ns=0.006, -Esac_ns=-10, -lambda_max=1.1, -Gsac_k=0.2882*800/210) - -expressions("Isac (Pueyo)--> ns + k") -Isac_P_ns=0 -Isac_P_k=0 - - -parameters("Istim", -amp=-80.0, -duration=0.5) - -expressions("Istim") -Istim = Conditional(Le(t, duration), amp, 0) - -expressions("membrane potential") -dv_dt=-(INa+INaL+Ito+ICaL+ICaNa+ICaK+IKr+IKs+IK1+INaCa_i+INaCa_ss+INaK+INab+IKb+IpCa+ICab+Istim+Isac_P_ns+Isac_P_k) - -expressions("diffusion fluxes") -JdiffNa=(nass-nai)/2.0 -JdiffK=(kss-ki)/2.0 -Jdiff=(cass-cai)/0.2 - -parameters("ryanodione receptor", -bt=4.75) - -expressions("ryanodione receptor") -a_rel=0.5*bt -Jrel_inf=a_rel*(-ICaL)/(1.0+(1.5*scale_HF_Jrel_inf/cajsr)**8.0) -tau_rel_tmp=bt/(1.0+0.0123/cajsr) -tau_rel=Conditional(Lt(tau_rel_tmp, 0.001), 0.001, tau_rel_tmp) -dJrelnp_dt=(Jrel_inf-Jrelnp)/tau_rel -btp=1.25*bt -a_relp=0.5*btp -Jrel_infp=a_relp*(-ICaL)/(1.0+(1.5*scale_HF_Jrel_inf/cajsr)**8.0) -tau_relp_tmp=btp/(1.0+0.0123/cajsr) -tau_relp=Conditional(Lt(tau_relp_tmp, 0.001), 0.001, tau_relp_tmp) -dJrelp_dt=(Jrel_infp-Jrelp)/tau_relp -fJrelp=(1.0/(1.0+KmCaMK/CaMKa)) -Jrel=(1.0-fJrelp)*Jrelnp+fJrelp*Jrelp - -expressions("calcium buffers") -Jupnp=0.004375*cai/(cai+0.00092) -Jupp=2.75*0.004375*cai/(cai+0.00092-0.00017) -fJupp=(1.0/(1.0+KmCaMK/CaMKa)) -Jleak=0.0039375*cansr*scale_HF_Jleak/15.0 -Jup=(1.0-fJupp)*Jupnp+fJupp*Jupp*scale_HF_Jup-Jleak -Jtr=(cansr-cajsr)/100.0 - -parameters("calcium buffers", "mechanics", -cmdnmax=0.05, -kmcmdn=0.00238, -trpnmax=0.07, -kmtrpn=0.0005, -BSRmax=0.047, -KmBSR=0.00087, -BSLmax=1.124, -KmBSL=0.0087, -csqnmax=10.0, -Beta1 = -2.4, -ktrpn = 0.1, -cat50_ref = 0.805, -ntrpn = 2, -lmbda=1, -scale_HF_cat50_ref=1.0, -kmcsqn=0.8) - -expressions("intracellular concentrations") -dnai_dt=-(INa+INaL+3.0*INaCa_i+3.0*INaK+INab+Isac_P_ns/3)*Acap/(F*vmyo)+JdiffNa*vss/vmyo -dnass_dt=-(ICaNa+3.0*INaCa_ss)*Acap/(F*vss)-JdiffNa -dki_dt=-(Ito+IKr+IKs+IK1+IKb+Isac_P_k+Isac_P_ns/3+Istim-2.0*INaK)*Acap/(F*vmyo)+JdiffK*vss/vmyo -dkss_dt=-(ICaK)*Acap/(F*vss)-JdiffK -Bcass=1.0/(1.0+BSRmax*KmBSR/(KmBSR+cass)**2.0+BSLmax*KmBSL/(KmBSL+cass)**2.0) -dcass_dt=Bcass*(-(ICaL-2.0*INaCa_ss)*Acap/(2.0*F*vss)+Jrel*vjsr/vss-Jdiff) -dcansr_dt=Jup-Jtr*vjsr/vnsr -Bcajsr=1.0/(1.0+csqnmax*kmcsqn/(kmcsqn+cajsr)**2.0) -dcajsr_dt=Bcajsr*(Jtr-Jrel) -Bcai=1.0/(1.0+cmdnmax*kmcmdn/(kmcmdn+cai)**2.0) -lambda_min12 = Conditional(Lt(lmbda, 1.2), lmbda, 1.2) -dcai_dt=Bcai*(-(IpCa+ICab-2.0*INaCa_i+Isac_P_ns/3)*Acap/(2.0*F*vmyo)-Jup*vnsr/vmyo+Jdiff*vss/vmyo - J_TRPN) -cat50 = (cat50_ref+Beta1*(lambda_min12-1))*scale_HF_cat50_ref -dCaTrpn_dt = ktrpn*(((cai*1000/cat50)**ntrpn)*(1-CaTrpn)-CaTrpn) -J_TRPN = dCaTrpn_dt*trpnmax - -parameters("mechanics", -emcoupling=1, -dLambda=0, -mode=1, -isacs=0, -calib=1, -Trpn50 = 0.35, -rw = 0.5, -rs = 0.25, -gammas = 0.0085, -gammaw = 0.615, -phi = 2.23, -Tot_A = 25, -Beta0 = 2.3, -Tref = 120, -kuw = 0.182, -kws = 0.012, -ku=0.04, -ntm=2.4, -p_a = 2.1, -p_b = 9.1, -p_k = 7, -etal = 200, -etas = 20) - -expressions("mechanics") -XS_max = Conditional(Gt(XS, 0), XS, 0) -XW_max = Conditional(Gt(XW, 0), XW, 0) -CaTrpn_max = Conditional(Gt(CaTrpn, 0), CaTrpn, 0) -kwu = kuw*(1/rw-1)-kws -ksu = kws*rw*(1/rs-1) -Aw = Tot_A*rs/((1-rs)*rw+rs) -As = Aw -cw = phi*kuw*((1-rs)*(1-rw))/((1-rs)*rw) -cs = phi*kws*((1-rs)*rw)/rs -lambda_min12 = Conditional(Lt(lmbda, 1.2), lmbda, 1.2) -lambda_min087 = Conditional(Lt(lambda_min12, 0.87), lambda_min12, 0.87) -h_lambda_prima = 1+Beta0*(lambda_min12+lambda_min087-1.87) -h_lambda = Conditional(Gt(h_lambda_prima, 0), h_lambda_prima, 0) -XU = (1-TmB)-XS-XW -gammawu = gammaw*abs(Zetaw) -gammasu = gammas*Conditional(Gt(Gt(Zetas,0)*Zetas, Lt(Zetas, -1)*(-Zetas-1)), Gt(Zetas,0)*Zetas, Lt(Zetas, -1)*(-Zetas-1)) -dXS_dt = kws*XW - ksu*XS - gammasu*XS -dXW_dt = kuw*XU - kwu*XW - kws*XW - gammawu*XW -kb = ku*Trpn50**ntm/(1-rs-(1-rs)*rw) -dTmB_dt = kb*Conditional(Lt(CaTrpn**(-ntm/2), 100), CaTrpn**(-ntm/2), 100)*XU-ku*CaTrpn**(ntm/2)*TmB -dZetas_dt = As*dLambda - cs*Zetas -dZetaw_dt = Aw*dLambda - cw*Zetaw -Ta = h_lambda*(Tref/rs)*(XS*(Zetas+1) + XW*Zetaw) -C = lambda_min12 - 1 -dCd = C - Cd -eta = Conditional(Lt(dCd, 0), etas, etal) -dCd_dt = p_k * (C - Cd) / eta -Fd = eta * dCd -F1 = (exp( p_b * C) - 1) -Tp = p_a * (F1 + Fd) -Ttot = Ta + Tp diff --git a/demos/split-cai_catrpn/3D/ToRORd_dynCl_endo_catrpnsplit.ode b/demos/split-cai_catrpn/3D/ToRORd_dynCl_endo_catrpnsplit.ode deleted file mode 100644 index 7f3afdc..0000000 --- a/demos/split-cai_catrpn/3D/ToRORd_dynCl_endo_catrpnsplit.ode +++ /dev/null @@ -1,719 +0,0 @@ -states("IKr", -C1=ScalarParam(0.9982511, unit="1", description=""), -C2=ScalarParam( 7.93602000000000023e-4, unit="1", description=""), -C3=ScalarParam( 6.53214300000000045e-4, unit="1", description=""), -I_=ScalarParam( 9.80408300000000003e-6, unit="1", description=""), -O_=ScalarParam( 2.92244900000000025e-4, unit="1", description="") -) - -states("CaMK", -CaMKt=ScalarParam( 1.09502599999999999e-2, unit="mM", description="") -) - -states("ryr", -Jrel_np=ScalarParam( 1.80824799999999996e-22, unit="mM/ms", description=""), -Jrel_p=ScalarParam( 4.35860800000000030e-21, unit="mM/ms", description="") -) - -states("Ito", -a=ScalarParam( 8.89925900000000051e-4, unit="1", description=""), -ap=ScalarParam( 4.53416500000000005e-4, unit="1", description=""), -iF=ScalarParam(0.9996716, unit="1", description=""), -iFp=ScalarParam(0.9996716, unit="1", description=""), -iS=ScalarParam(0.5988908, unit="1", description=""), -iSp=ScalarParam(0.6620692, unit="1", description="") -) - -states("intracellular_ions", -cajsr=ScalarParam(1.525693, unit="mM", description=""), -cansr=ScalarParam(1.528001, unit="mM", description=""), -cass=ScalarParam( 6.49734100000000044e-5, unit="mM", description=""), -cli=ScalarParam(29.20698, unit="mM", description=""), -clss=ScalarParam(29.20696, unit="mM", description=""), -ki=ScalarParam(147.7115, unit="mM", description=""), -kss=ScalarParam(147.7114, unit="mM", description=""), -nai=ScalarParam(12.39736, unit="mM", description=""), -nass=ScalarParam(12.3977, unit="mM", description="") -) - -states("ICaL", -d=ScalarParam( 1.58884100000000000e-31, unit="1", description=""), -fcaf=ScalarParam(1, unit="1", description=""), -fcafp=ScalarParam(1, unit="1", description=""), -fcas=ScalarParam(0.9999014, unit="1", description=""), -ff_=ScalarParam(1, unit="1", description=""), -ffp=ScalarParam(1, unit="1", description=""), -fs=ScalarParam(0.9401791, unit="1", description=""), -jca=ScalarParam(0.9999846, unit="1", description=""), -nca_i=ScalarParam( 8.32600900000000053e-4, unit="1", description=""), -nca_ss=ScalarParam( 4.89937800000000024e-4, unit="1", description="") -) - -states("INa", -h=ScalarParam(0.8473267, unit="1", description=""), -hp=ScalarParam(0.7018454, unit="1", description=""), -j=ScalarParam(0.8471657, unit="1", description=""), -jp=ScalarParam(0.8469014, unit="1", description=""), -m=ScalarParam( 6.51715400000000005e-4, unit="1", description="") -) - -states("INaL", -hL=ScalarParam(0.5566017, unit="1", description=""), -hLp=ScalarParam(0.3115491, unit="1", description=""), -mL=ScalarParam( 1.35120299999999988e-4, unit="1", description="") -) - -states("membrane", -v=ScalarParam(-89.74808, unit="mV", description="") -) - -states("IKs", -xs1=ScalarParam(0.243959, unit="1", description=""), -xs2=ScalarParam( 1.58616700000000009e-4, unit="1", description="") -) - -parameters("I_katp", -A_atp=ScalarParam(2.0, unit="mM", description=""), -K_atp=ScalarParam(0.25, unit="mM", description=""), -K_o_n=ScalarParam(5.0, unit="mM", description=""), -fkatp=ScalarParam(0.0, unit="1", description=""), -gkatp=ScalarParam(4.3195, unit="mS/uF", description="") -) - -parameters("ICaL", -Aff=ScalarParam(0.6, unit="1", description=""), -ICaL_fractionSS=ScalarParam(0.8, unit="1", description=""), -Kmn=ScalarParam(0.002, unit="mM", description=""), -PCa_b=ScalarParam(8.3757e-05, unit="1", description=""), -dielConstant=ScalarParam(74.0, unit="1/K", description=""), -k2n=ScalarParam(500.0, unit="mS/uF", description=""), -offset=ScalarParam(0.0, unit="ms", description=""), -tjca=ScalarParam(72.5, unit="ms", description=""), -vShift=ScalarParam(0.0, unit="mV", description="") -) - -parameters("intracellular_ions","mechanics", -BSLmax=ScalarParam(1.124, unit="mM", description=""), -BSRmax=ScalarParam(0.047, unit="mM", description=""), -KmBSL=ScalarParam(0.0087, unit="mM", description=""), -KmBSR=ScalarParam(0.00087, unit="mM", description=""), -cmdnmax_b=ScalarParam(0.05, unit="mM", description=""), -csqnmax=ScalarParam(10.0, unit="mM", description=""), -kmcmdn=ScalarParam(0.00238, unit="mM", description=""), -kmcsqn=ScalarParam(0.8, unit="mM", description=""), -kmtrpn=ScalarParam(0.0005, unit="mM", description=""), -trpnmax=ScalarParam(0.07, unit="mM", description=""), -lmbda=1, -ktrpn = 0.1, -ntrpn = 2, -Beta1 = -2.4, -cat50_ref = 0.805 -) - -parameters("CaMK", -CaMKo=ScalarParam(0.05, unit="1", description=""), -KmCaM=ScalarParam(0.0015, unit="mM", description=""), -KmCaMK=ScalarParam(0.15, unit="mM", description=""), -aCaMK=ScalarParam(0.05, unit="1/mM/ms", description=""), -bCaMK=ScalarParam(0.00068, unit="mS/uF", description="") -) - -parameters("Ito", -EKshift=ScalarParam(0.0, unit="mV", description=""), -Gto_b=ScalarParam(0.16, unit="mS/uF", description="") -) - -parameters("physical_constants", "mechanics", -F=ScalarParam(96485.0, unit="C/mol", description=""), -R=ScalarParam(8314.0, unit="mJ/mol/K", description=""), -T=ScalarParam(310.0, unit="K", description=""), -zca=ScalarParam(2.0, unit="1", description=""), -zcl=ScalarParam(-1.0, unit="1", description=""), -zk=ScalarParam(1.0, unit="1", description=""), -zna=ScalarParam(1.0, unit="1", description="") -) - -parameters("ICl", -Fjunc=ScalarParam(1.0, unit="1", description=""), -GClCa=ScalarParam(0.2843, unit="mS/uF", description=""), -GClb=ScalarParam(0.00198, unit="mS/uF", description=""), -KdClCa=ScalarParam(0.1, unit="mM", description="") -) - -parameters("IK1", -GK1_b=ScalarParam(0.6992, unit="mS/uF", description="") -) - -parameters("IKb", -GKb_b=ScalarParam(0.0189, unit="mS/uF", description="") -) - -parameters("IKr", -GKr_b=ScalarParam(0.0321, unit="mS/uF", description=""), -alpha_1=ScalarParam(0.154375, unit="mS/uF", description=""), -beta_1=ScalarParam(0.1911, unit="mS/uF", description="") -) - -parameters("IKs", -GKs_b=ScalarParam(0.0011, unit="mS/uF", description="") -) - -parameters("INa", -GNa=ScalarParam(11.7802, unit="mS/uF", description="") -) - -parameters("INaL", -GNaL_b=ScalarParam(0.0279, unit="mS/uF", description=""), -thL=ScalarParam(200.0, unit="ms", description="") -) - -parameters("INaCa", -Gncx_b=ScalarParam(0.0034, unit="mS/uF", description=""), -INaCa_fractionSS=ScalarParam(0.35, unit="1", description=""), -KmCaAct=ScalarParam(0.00015, unit="mM", description=""), -kasymm=ScalarParam(12.5, unit="1", description=""), -kcaoff=ScalarParam(5000.0, unit="mS/uF", description=""), -kcaon=ScalarParam(1500000.0, unit="mS/uF", description=""), -kna1=ScalarParam(15.0, unit="mS/uF", description=""), -kna2=ScalarParam(5.0, unit="mS/uF", description=""), -kna3=ScalarParam(88.12, unit="mS/uF", description=""), -qca=ScalarParam(0.167, unit="1", description=""), -qna=ScalarParam(0.5224, unit="1", description=""), -wca=ScalarParam(60000.0, unit="1", description=""), -wna=ScalarParam(60000.0, unit="1", description=""), -wnaca=ScalarParam(5000.0, unit="1", description="") -) - -parameters("IpCa", -GpCa=ScalarParam(0.0005, unit="mS/uF", description=""), -KmCap=ScalarParam(0.0005, unit="mM", description="") -) - -parameters("INaK", -H=ScalarParam(1e-07, unit="mM", description=""), -Khp=ScalarParam(1.698e-07, unit="mM", description=""), -Kki=ScalarParam(0.5, unit="mS/uF", description=""), -Kko=ScalarParam(0.3582, unit="mS/uF", description=""), -Kmgatp=ScalarParam(1.698e-07, unit="mM", description=""), -Knai0=ScalarParam(9.073, unit="mM", description=""), -Knao0=ScalarParam(27.78, unit="mM", description=""), -Knap=ScalarParam(224.0, unit="mM", description=""), -Kxkur=ScalarParam(292.0, unit="mM", description=""), -MgADP=ScalarParam(0.05, unit="mM", description=""), -MgATP=ScalarParam(9.8, unit="mM", description=""), -Pnak_b=ScalarParam(15.4509, unit="mS/uF", description=""), -delta=ScalarParam(-0.155, unit="mV", description=""), -eP=ScalarParam(4.2, unit="1", description=""), -k1m=ScalarParam(182.4, unit="mS/uF", description=""), -k1p=ScalarParam(949.5, unit="mS/uF", description=""), -k2m=ScalarParam(39.4, unit="mS/uF", description=""), -k2p=ScalarParam(687.2, unit="mS/uF", description=""), -k3m=ScalarParam(79300.0, unit="mS/uF", description=""), -k3p=ScalarParam(1899.0, unit="mS/uF", description=""), -k4m=ScalarParam(40.0, unit="mS/uF", description=""), -k4p=ScalarParam(639.0, unit="mS/uF", description="") -) - -parameters("ryr", -Jrel_b=ScalarParam(1.5378, unit="1", description=""), -bt=ScalarParam(4.75, unit="ms", description=""), -cajsr_half=ScalarParam(1.7, unit="mM", description="") -) - -parameters("SERCA", -Jup_b=ScalarParam(1.0, unit="1", description="") -) - -parameters("cell_geometry","mechanics", -L=ScalarParam(0.01, unit="cm", description=""), -rad_=ScalarParam(0.0011, unit="cm", description="") -) - -parameters("ICab", -PCab=ScalarParam(5.9194e-08, unit="mS/uF", description="") -) - -parameters("reversal_potentials", -PKNa=ScalarParam(0.01833, unit="1", description="") -) - -parameters("INab", -PNab=ScalarParam(1.9239e-09, unit="mS/uF", description="") -) - -parameters("extracellular", -cao=ScalarParam(1.8, unit="mM", description=""), -clo=ScalarParam(150.0, unit="mM", description=""), -ko=ScalarParam(5.0, unit="mM", description=""), -nao=ScalarParam(140.0, unit="mM", description="") -) - -parameters("environment", -celltype=ScalarParam(0.0, unit="1", description="") -) - -parameters("membrane", -i_Stim_Amplitude=ScalarParam(-53.0, unit="A/F", description=""), -i_Stim_End=ScalarParam(1e+17, unit="ms", description=""), -i_Stim_Period=ScalarParam(1000.0, unit="ms", description=""), -i_Stim_PulseDuration=ScalarParam(1.0, unit="ms", description=""), -i_Stim_Start=ScalarParam(0.0, unit="ms", description="") -) - -parameters("diff", -tauCa=ScalarParam(0.2, unit="ms", description=""), -tauCl=ScalarParam(2.0, unit="ms", description=""), -tauK=ScalarParam(2.0, unit="ms", description=""), -tauNa=ScalarParam(2.0, unit="ms", description="") -) - -expressions("cell_geometry","mechanics") -Acap = 2.0*Ageo # cm**2 -Ageo = L*((2.0*3.14)*rad_) + rad_*((2.0*3.14)*rad_) # cm**2 -vcell = L*(rad_*((1000.0*3.14)*rad_)) # uL -vjsr = 0.0048*vcell # uL -vmyo = 0.68*vcell # uL -vnsr = 0.0552*vcell # uL -vss = 0.02*vcell # uL - -expressions("ICaL") -Afcaf = 0.3 + 0.6/(exp((v - 1*10.0)/10.0) + 1.0) -Afcas = 1.0 - Afcaf -Afs = 1.0 - Aff -ICaK = ICaK_i + ICaK_ss # A/F -ICaK_i = (1.0 - ICaL_fractionSS)*((d*(PhiCaK_i*(PCaK*(1.0 - fICaLp))))*(f*(1.0 - nca_i) + nca_i*(fca*jca)) + (d*(PhiCaK_i*(PCaKp*fICaLp)))*(fp*(1.0 - nca_i) + nca_i*(fcap*jca))) # A/F -ICaK_ss = ICaL_fractionSS*((d*(PhiCaK_ss*(PCaK*(1.0 - fICaLp))))*(f*(1.0 - nca_ss) + nca_ss*(fca*jca)) + (d*(PhiCaK_ss*(PCaKp*fICaLp)))*(fp*(1.0 - nca_ss) + nca_ss*(fcap*jca))) # A/F -ICaL_ICaL = ICaL_i + ICaL_ss # A/F -ICaL_i = (1.0 - ICaL_fractionSS)*((d*(PhiCaL_i*(PCa*(1.0 - fICaLp))))*(f*(1.0 - nca_i) + nca_i*(fca*jca)) + (d*(PhiCaL_i*(PCap*fICaLp)))*(fp*(1.0 - nca_i) + nca_i*(fcap*jca))) # A/F -ICaL_ss = ICaL_fractionSS*((d*(PhiCaL_ss*(PCa*(1.0 - fICaLp))))*(f*(1.0 - nca_ss) + nca_ss*(fca*jca)) + (d*(PhiCaL_ss*(PCap*fICaLp)))*(fp*(1.0 - nca_ss) + nca_ss*(fcap*jca))) # A/F -ICaNa = ICaNa_i + ICaNa_ss # A/F -ICaNa_i = (1.0 - ICaL_fractionSS)*((d*(PhiCaNa_i*(PCaNa*(1.0 - fICaLp))))*(f*(1.0 - nca_i) + nca_i*(fca*jca)) + (d*(PhiCaNa_i*(PCaNap*fICaLp)))*(fp*(1.0 - nca_i) + nca_i*(fcap*jca))) # A/F -ICaNa_ss = ICaL_fractionSS*((d*(PhiCaNa_ss*(PCaNa*(1.0 - fICaLp))))*(f*(1.0 - nca_ss) + nca_ss*(fca*jca)) + (d*(PhiCaNa_ss*(PCaNap*fICaLp)))*(fp*(1.0 - nca_ss) + nca_ss*(fcap*jca))) # A/F -Ii = (0.5*(4.0*cai + (cli + (ki + nai))))/1000.0 -Io = (0.5*(4.0*cao + (clo + (ko + nao))))/1000.0 -Iss = (0.5*(4.0*cass + (clss + (kss + nass))))/1000.0 -PCa = Conditional(Eq(celltype, 1.0), 1.2*PCa_b, Conditional(Eq(celltype, 2.0), 2.0*PCa_b, PCa_b)) -PCaK = 0.0003574*PCa -PCaKp = 0.0003574*PCap -PCaNa = 0.00125*PCa -PCaNap = 0.00125*PCap -PCap = 1.1*PCa -PhiCaK_i = ((1.0*vffrt)*(-gamma_ko*ko + (gamma_ki*ki)*exp(1.0*vfrt)))/(exp(1.0*vfrt) - 1*1.0) -PhiCaK_ss = ((1.0*vffrt)*(-gamma_ko*ko + (gamma_kss*kss)*exp(1.0*vfrt)))/(exp(1.0*vfrt) - 1*1.0) -PhiCaL_i = ((4.0*vffrt)*(-cao*gamma_cao + (cai*gamma_cai)*exp(2.0*vfrt)))/(exp(2.0*vfrt) - 1*1.0) -PhiCaL_ss = ((4.0*vffrt)*(-cao*gamma_cao + (cass*gamma_cass)*exp(2.0*vfrt)))/(exp(2.0*vfrt) - 1*1.0) -PhiCaNa_i = ((1.0*vffrt)*(-gamma_nao*nao + (gamma_nai*nai)*exp(1.0*vfrt)))/(exp(1.0*vfrt) - 1*1.0) -PhiCaNa_ss = ((1.0*vffrt)*(-gamma_nao*nao + (gamma_nass*nass)*exp(1.0*vfrt)))/(exp(1.0*vfrt) - 1*1.0) -anca_i = 1.0/(k2n/km2n + (Kmn/cai + 1.0)**4.0) -anca_ss = 1.0/(k2n/km2n + (Kmn/cass + 1.0)**4.0) -constA = 1820000.0/(T*dielConstant)**1.5 -dss = Conditional(Ge(v, 31.4978), 1.0, 1.0763*exp(-1.007*exp(-0.0829*v))) -f = Aff*ff_ + Afs*fs -fICaLp = 1.0/(1.0 + KmCaMK/CaMKa) -fca = Afcaf*fcaf + Afcas*fcas -fcap = Afcaf*fcafp + Afcas*fcas -fcass = fss -fp = Aff*ffp + Afs*fs -fss = 1.0/(exp((v + 19.58)/3.696) + 1.0) -gamma_cai = exp((-constA*4.0)*(sqrt(Ii)/(sqrt(Ii) + 1.0) - 0.3*Ii)) -gamma_cao = exp((-constA*4.0)*(sqrt(Io)/(sqrt(Io) + 1.0) - 0.3*Io)) -gamma_cass = exp((-constA*4.0)*(sqrt(Iss)/(sqrt(Iss) + 1.0) - 0.3*Iss)) -gamma_ki = exp((-constA*1.0)*(sqrt(Ii)/(sqrt(Ii) + 1.0) - 0.3*Ii)) -gamma_ko = exp((-constA*1.0)*(sqrt(Io)/(sqrt(Io) + 1.0) - 0.3*Io)) -gamma_kss = exp((-constA*1.0)*(sqrt(Iss)/(sqrt(Iss) + 1.0) - 0.3*Iss)) -gamma_nai = exp((-constA*1.0)*(sqrt(Ii)/(sqrt(Ii) + 1.0) - 0.3*Ii)) -gamma_nao = exp((-constA*1.0)*(sqrt(Io)/(sqrt(Io) + 1.0) - 0.3*Io)) -gamma_nass = exp((-constA*1.0)*(sqrt(Iss)/(sqrt(Iss) + 1.0) - 0.3*Iss)) -jcass = 1.0/(exp((v + 18.08)/2.7916) + 1.0) -km2n = jca*1.0 # mS/uF -td = (offset + 0.6) + 1.0/(exp((-1*0.05)*((v + vShift) + 6.0)) + exp(0.09*((v + vShift) + 14.0))) # ms -tfcaf = 7.0 + 1.0/(0.04*exp((-(v - 1*4.0))/7.0) + 0.04*exp((v - 1*4.0)/7.0)) # ms -tfcafp = 2.5*tfcaf # ms -tfcas = 100.0 + 1.0/(0.00012*exp((-v)/3.0) + 0.00012*exp(v/7.0)) # ms -tff = 7.0 + 1.0/(0.0045*exp((-(v + 20.0))/10.0) + 0.0045*exp((v + 20.0)/10.0)) # ms -tffp = 2.5*tff # ms -tfs = 1000.0 + 1.0/(3.5e-5*exp((-(v + 5.0))/4.0) + 3.5e-5*exp((v + 5.0)/6.0)) # ms -dd_dt = (-d + dss)/td -dfcaf_dt = (-fcaf + fcass)/tfcaf -dfcafp_dt = (-fcafp + fcass)/tfcafp -dfcas_dt = (-fcas + fcass)/tfcas -dff__dt = (-ff_ + fss)/tff -dffp_dt = (-ffp + fss)/tffp -dfs_dt = (-fs + fss)/tfs -djca_dt = (-jca + jcass)/tjca -dnca_i_dt = anca_i*k2n - km2n*nca_i -dnca_ss_dt = anca_ss*k2n - km2n*nca_ss - -expressions("Ito") -AiF = 1.0/(exp(((EKshift + v) - 1*213.6)/151.2) + 1.0) -AiS = 1.0 - AiF -Gto = Conditional(Or(Eq(celltype, 1.0), Eq(celltype, 2.0)), 2.0*Gto_b, Gto_b) # mS/uF -Ito_Ito = (Gto*(-EK + v))*(i*(a*(1.0 - fItop)) + ip*(ap*fItop)) # A/F -ass = 1.0/(exp((-((EKshift + v) - 1*14.34))/14.82) + 1.0) -assp = 1.0/(exp((-((EKshift + v) - 1*24.34))/14.82) + 1.0) -delta_epi = Conditional(Eq(celltype, 1.0), 1.0 - 0.95/(exp(((EKshift + v) + 70.0)/5.0) + 1.0), 1.0) -dti_develop = 1.354 + 0.0001/(exp((-((EKshift + v) - 1*12.23))/0.2154) + exp(((EKshift + v) - 1*167.4)/15.89)) -dti_recover = 1.0 - 0.5/(exp(((EKshift + v) + 70.0)/20.0) + 1.0) -fItop = 1.0/(1.0 + KmCaMK/CaMKa) -i = AiF*iF + AiS*iS -ip = AiF*iFp + AiS*iSp -iss = 1.0/(exp(((EKshift + v) + 43.94)/5.711) + 1.0) -ta = 1.0515/(1.0/((1.2089*(exp((-((EKshift + v) - 1*18.4099))/29.3814) + 1.0))) + 3.5/(exp(((EKshift + v) + 100.0)/29.3814) + 1.0)) # ms -tiF = delta_epi*tiF_b # ms -tiF_b = 4.562 + 1.0/(0.3933*exp((-((EKshift + v) + 100.0))/100.0) + 0.08004*exp(((EKshift + v) + 50.0)/16.59)) # ms -tiFp = tiF*(dti_develop*dti_recover) # ms -tiS = delta_epi*tiS_b # ms -tiS_b = 23.62 + 1.0/(0.001416*exp((-((EKshift + v) + 96.52))/59.05) + 1.78e-8*exp(((EKshift + v) + 114.1)/8.079)) # ms -tiSp = tiS*(dti_develop*dti_recover) # ms -da_dt = (-a + ass)/ta -dap_dt = (-ap + assp)/ta -diF_dt = (-iF + iss)/tiF -diFp_dt = (-iFp + iss)/tiFp -diS_dt = (-iS + iss)/tiS -diSp_dt = (-iSp + iss)/tiSp - -expressions("intracellular_ions") -Bcajsr = 1.0/((csqnmax*kmcsqn)/((cajsr + kmcsqn)**2.0) + 1.0) -Bcass = 1.0/((BSLmax*KmBSL)/((KmBSL + cass)**2.0) + ((BSRmax*KmBSR)/((KmBSR + cass)**2.0) + 1.0)) -cmdnmax = Conditional(Eq(celltype, 1.0), 1.3*cmdnmax_b, cmdnmax_b) # mM -dcajsr_dt = Bcajsr*(-Jrel + Jtr) # mM -dcansr_dt = Jup - Jtr*vjsr/vnsr # mM -dcass_dt = Bcass*(-Jdiff + ((Acap*(-(ICaL_ss - 2.0*INaCa_ss)))/(((2.0*F)*vss)) + (Jrel*vjsr)/vss)) # mM -dcli_dt = (Acap*(IClCa_sl + IClb))/((F*vmyo)) + (JdiffCl*vss)/vmyo # mM -dclss_dt = -JdiffCl + (Acap*IClCa_junc)/((F*vss)) # mM -dki_dt = (Acap*(-(ICaK_i + (-2.0*INaK_INaK + (Istim + (I_katp_I_katp + (IKb_IKb + (IK1_IK1 + (IKs_IKs + (IKr_IKr + Ito_Ito))))))))))/((F*vmyo)) + (JdiffK*vss)/vmyo # mM -dkss_dt = -JdiffK + (Acap*(-ICaK_ss))/((F*vss)) # mM -dnai_dt = (Acap*(-(INab_INab + (3.0*INaK_INaK + (ICaNa_i + (3.0*INaCa_i + (INaL_INaL + INa_INa)))))))/((F*vmyo)) + (JdiffNa*vss)/vmyo # mM -dnass_dt = -JdiffNa + (Acap*(-(ICaNa_ss + 3.0*INaCa_ss)))/((F*vss)) # mM -lambda_min12 = Conditional(Lt(lmbda, 1.2), lmbda, 1.2) -dcai_dt=Bcai*(-(IpCa_IpCa+ICab_ICab-2.0*INaCa_i/3)*Acap/(2.0*F*vmyo)-Jup*vnsr/vmyo+Jdiff*vss/vmyo - J_TRPN) -cat50 = (cat50_ref+Beta1*(lambda_min12-1)) -dCaTrpn_dt = ktrpn*(((cai*1000/cat50)**ntrpn)*(1-CaTrpn)-CaTrpn) -Bcai=1.0/(1.0+cmdnmax*kmcmdn/(kmcmdn+cai)**2.0) -J_TRPN = dCaTrpn_dt*trpnmax - - -expressions("CaMK") -CaMKa = CaMKb + CaMKt # mM -CaMKb = (CaMKo*(1.0 - CaMKt))/(KmCaM/cass + 1.0) # mM -dCaMKt_dt = -CaMKt*bCaMK + (CaMKb*aCaMK)*(CaMKb + CaMKt) # mM - -expressions("INaK") -E1_ = x1/(x4 + (x3 + (x1 + x2))) -E2 = x2/(x4 + (x3 + (x1 + x2))) -E3 = x3/(x4 + (x3 + (x1 + x2))) -E4 = x4/(x4 + (x3 + (x1 + x2))) -INaK_INaK = Pnak*(JnakK*zk + JnakNa*zna) # A/F -JnakK = 2.0*(-E3*a1 + E4*b1) # mM/ms -JnakNa = 3.0*(E1_*a3 - E2*b3) # mM/ms -Knai = Knai0*exp((delta*vfrt)/3.0) # mM -Knao = Knao0*exp((vfrt*(1.0 - delta))/3.0) # mM -P = eP/(((H/Khp + 1.0) + nai/Knap) + ki/Kxkur) -Pnak = Conditional(Eq(celltype, 1.0), 0.9*Pnak_b, Conditional(Eq(celltype, 2.0), 0.7*Pnak_b, Pnak_b)) # mS/uF -a1 = (k1p*(nai/Knai)**3.0)/(((1.0 + ki/Kki)**2.0 + (1.0 + nai/Knai)**3.0) - 1*1.0) -a2 = k2p -a3 = (k3p*(ko/Kko)**2.0)/(((1.0 + ko/Kko)**2.0 + (1.0 + nao/Knao)**3.0) - 1*1.0) -a4 = ((MgATP*k4p)/Kmgatp)/(1.0 + MgATP/Kmgatp) -b1 = MgADP*k1m -b2 = (k2m*(nao/Knao)**3.0)/(((1.0 + ko/Kko)**2.0 + (1.0 + nao/Knao)**3.0) - 1*1.0) -b3 = (H*(P*k3m))/(1.0 + MgATP/Kmgatp) -b4 = (k4m*(ki/Kki)**2.0)/(((1.0 + ki/Kki)**2.0 + (1.0 + nai/Knai)**3.0) - 1*1.0) -x1 = a2*(a1*b3) + (b3*(a2*b4) + (a2*(a1*a4) + b3*(b2*b4))) -x2 = b4*(a2*a3) + (b4*(a3*b1) + (a3*(a1*a2) + b4*(b1*b2))) -x3 = b1*(a3*a4) + (a4*(b1*b2) + (a4*(a2*a3) + b1*(b2*b3))) -x4 = a1*(b2*b3) + (a1*(a4*b2) + (a1*(a3*a4) + b2*(b3*b4))) - -expressions("INaCa") -E1_i = x1_i/(x4_i + (x3_i + (x1_i + x2_i))) -E1_ss = x1_ss/(x4_ss + (x3_ss + (x1_ss + x2_ss))) -E2_i = x2_i/(x4_i + (x3_i + (x1_i + x2_i))) -E2_ss = x2_ss/(x4_ss + (x3_ss + (x1_ss + x2_ss))) -E3_i = x3_i/(x4_i + (x3_i + (x1_i + x2_i))) -E3_ss = x3_ss/(x4_ss + (x3_ss + (x1_ss + x2_ss))) -E4_i = x4_i/(x4_i + (x3_i + (x1_i + x2_i))) -E4_ss = x4_ss/(x4_ss + (x3_ss + (x1_ss + x2_ss))) -Gncx = Conditional(Eq(celltype, 1.0), 1.1*Gncx_b, Conditional(Eq(celltype, 2.0), 1.4*Gncx_b, Gncx_b)) # mS/uF -INaCa_i = (allo_i*(Gncx*(1.0 - INaCa_fractionSS)))*(JncxCa_i*zca + JncxNa_i*zna) # A/F -INaCa_ss = (allo_ss*(Gncx*INaCa_fractionSS))*(JncxCa_ss*zca + JncxNa_ss*zna) # A/F -JncxCa_i = -E1_i*k1_i + E2_i*k2_i # mM/ms -JncxCa_ss = -E1_ss*k1_ss + E2_ss*k2_ss # mM/ms -JncxNa_i = -E2_i*k3pp_i + (E3_i*k4pp_i + 3.0*(-E1_i*k8_i + E4_i*k7_i)) # mM/ms -JncxNa_ss = -E2_ss*k3pp_ss + (E3_ss*k4pp_ss + 3.0*(-E1_ss*k8_ss + E4_ss*k7_ss)) # mM/ms -allo_i = 1.0/((KmCaAct/cai)**2.0 + 1.0) -allo_ss = 1.0/((KmCaAct/cass)**2.0 + 1.0) -h10_i = (nao/kna1)*(1.0 + nao/kna2) + (kasymm + 1.0) -h10_ss = (nao/kna1)*(1.0 + nao/kna2) + (kasymm + 1.0) -h11_i = (nao*nao)/((kna2*(h10_i*kna1))) -h11_ss = (nao*nao)/((kna2*(h10_ss*kna1))) -h12_i = 1.0/h10_i -h12_ss = 1.0/h10_ss -h1_i = (nai/kna3)*(hna + 1.0) + 1.0 -h1_ss = (nass/kna3)*(hna + 1.0) + 1.0 -h2_i = (hna*nai)/((h1_i*kna3)) -h2_ss = (hna*nass)/((h1_ss*kna3)) -h3_i = 1.0/h1_i -h3_ss = 1.0/h1_ss -h4_i = (nai/kna1)*(1.0 + nai/kna2) + 1.0 -h4_ss = (nass/kna1)*(1.0 + nass/kna2) + 1.0 -h5_i = (nai*nai)/((kna2*(h4_i*kna1))) -h5_ss = (nass*nass)/((kna2*(h4_ss*kna1))) -h6_i = 1.0/h4_i -h6_ss = 1.0/h4_ss -h7_i = (nao/kna3)*(1.0 + 1.0/hna) + 1.0 -h7_ss = (nao/kna3)*(1.0 + 1.0/hna) + 1.0 -h8_i = nao/((h7_i*(hna*kna3))) -h8_ss = nao/((h7_ss*(hna*kna3))) -h9_i = 1.0/h7_i -h9_ss = 1.0/h7_ss -hca = exp(qca*vfrt) -hna = exp(qna*vfrt) -k1_i = kcaon*(cao*h12_i) -k1_ss = kcaon*(cao*h12_ss) -k2_i = kcaoff -k2_ss = kcaoff -k3_i = k3p_i + k3pp_i -k3_ss = k3p_ss + k3pp_ss -k3p_i = h9_i*wca -k3p_ss = h9_ss*wca -k3pp_i = h8_i*wnaca -k3pp_ss = h8_ss*wnaca -k4_i = k4p_i + k4pp_i -k4_ss = k4p_ss + k4pp_ss -k4p_i = (h3_i*wca)/hca -k4p_ss = (h3_ss*wca)/hca -k4pp_i = h2_i*wnaca -k4pp_ss = h2_ss*wnaca -k5_i = kcaoff -k5_ss = kcaoff -k6_i = kcaon*(cai*h6_i) -k6_ss = kcaon*(cass*h6_ss) -k7_i = wna*(h2_i*h5_i) -k7_ss = wna*(h2_ss*h5_ss) -k8_i = wna*(h11_i*h8_i) -k8_ss = wna*(h11_ss*h8_ss) -x1_i = (k2_i*k4_i)*(k6_i + k7_i) + (k5_i*k7_i)*(k2_i + k3_i) -x1_ss = (k2_ss*k4_ss)*(k6_ss + k7_ss) + (k5_ss*k7_ss)*(k2_ss + k3_ss) -x2_i = (k1_i*k7_i)*(k4_i + k5_i) + (k4_i*k6_i)*(k1_i + k8_i) -x2_ss = (k1_ss*k7_ss)*(k4_ss + k5_ss) + (k4_ss*k6_ss)*(k1_ss + k8_ss) -x3_i = (k1_i*k3_i)*(k6_i + k7_i) + (k6_i*k8_i)*(k2_i + k3_i) -x3_ss = (k1_ss*k3_ss)*(k6_ss + k7_ss) + (k6_ss*k8_ss)*(k2_ss + k3_ss) -x4_i = (k2_i*k8_i)*(k4_i + k5_i) + (k3_i*k5_i)*(k1_i + k8_i) -x4_ss = (k2_ss*k8_ss)*(k4_ss + k5_ss) + (k3_ss*k5_ss)*(k1_ss + k8_ss) - -expressions("reversal_potentials") -ECl = ((R*T)/((F*zcl)))*log(clo/cli) # mV -EClss = ((R*T)/((F*zcl)))*log(clo/clss) # mV -EK = ((R*T)/((F*zk)))*log(ko/ki) # mV -EKs = ((R*T)/((F*zk)))*log((PKNa*nao + ko)/(PKNa*nai + ki)) # mV -ENa = ((R*T)/((F*zna)))*log(nao/nai) # mV - -expressions("IK1") -GK1 = Conditional(Eq(celltype, 1.0), 1.2*GK1_b, Conditional(Eq(celltype, 2.0), 1.3*GK1_b, GK1_b)) # mS/uF -IK1_IK1 = (K1ss*(GK1*sqrt(ko/5.0)))*(-EK + v) # A/F -K1ss = aK1/(aK1 + bK1) -aK1 = 4.094/(exp(0.1217*((-EK + v) - 1*49.934)) + 1.0) -bK1 = (15.72*exp(0.0674*((-EK + v) - 1*3.257)) + exp(0.0618*((-EK + v) - 1*594.31)))/(exp((-1*0.1629)*((-EK + v) + 14.207)) + 1.0) - -expressions("IKb") -GKb = Conditional(Eq(celltype, 1.0), 0.6*GKb_b, GKb_b) # mS/uF -IKb_IKb = (GKb*xkb)*(-EK + v) # A/F -xkb = 1.0/(exp((-(v - 1*10.8968))/23.9871) + 1.0) - -expressions("IKr") -GKr = Conditional(Eq(celltype, 1.0), 1.3*GKr_b, Conditional(Eq(celltype, 2.0), 0.8*GKr_b, GKr_b)) # mS/uF -IKr_IKr = (O_*(GKr*sqrt(ko/5.0)))*(-EK + v) # A/F -alpha = 0.1161*exp(0.299*vfrt) # mS/uF -alpha_2 = 0.0578*exp(0.971*vfrt) # mS/uF -alpha_C2ToI = 5.2e-5*exp(1.525*vfrt) # mS/uF -alpha_i = 0.2533*exp(0.5953*vfrt) # mS/uF -beta_ = 0.2442*exp((-1*1.604)*vfrt) # mS/uF -beta_2 = 0.000349*exp((-1*1.062)*vfrt) # mS/uF -beta_ItoC2 = (alpha_C2ToI*(beta_2*beta_i))/((alpha_2*alpha_i)) # mS/uF -beta_i = 0.06525*exp((-1*0.8209)*vfrt) # mS/uF -dC1_dt = -C1*(alpha_C2ToI + (alpha_2 + beta_1)) + (I_*beta_ItoC2 + (C2*alpha_1 + O_*beta_2)) -dC2_dt = -C2*(alpha_1 + beta_) + (C1*beta_1 + C3*alpha) -dC3_dt = C2*beta_ - C3*alpha -dI__dt = -I_*(beta_ItoC2 + beta_i) + (C1*alpha_C2ToI + O_*alpha_i) -dO__dt = -O_*(alpha_i + beta_2) + (C1*alpha_2 + I_*beta_i) - -expressions("IKs") -GKs = Conditional(Eq(celltype, 1.0), 1.4*GKs_b, GKs_b) # mS/uF -IKs_IKs = (xs2*(xs1*(GKs*KsCa)))*(-EKs + v) # A/F -KsCa = 1.0 + 0.6/((3.8e-5/cai)**1.4 + 1.0) -txs1 = 817.3 + 1.0/(0.0002326*exp((v + 48.28)/17.8) + 0.001292*exp((-(v + 210.0))/230.0)) # ms -txs2 = 1.0/(0.01*exp((v - 1*50.0)/20.0) + 0.0193*exp((-(v + 66.54))/31.0)) # ms -xs1ss = 1.0/(exp((-(v + 11.6))/8.932) + 1.0) -xs2ss = xs1ss -dxs1_dt = (-xs1 + xs1ss)/txs1 -dxs2_dt = (-xs2 + xs2ss)/txs2 - -expressions("INaL") -GNaL = Conditional(Eq(celltype, 1.0), 0.6*GNaL_b, GNaL_b) # mS/uF -INaL_INaL = (mL*(GNaL*(-ENa + v)))*(fINaLp*hLp + hL*(1.0 - fINaLp)) # A/F -fINaLp = 1.0/(1.0 + KmCaMK/CaMKa) -hLss = 1.0/(exp((v + 87.61)/7.488) + 1.0) -hLssp = 1.0/(exp((v + 93.81)/7.488) + 1.0) -mLss = 1.0/(exp((-(v + 42.85))/5.264) + 1.0) -thLp = 3.0*thL # ms -tmL = 0.06487*exp(-((v - 1*4.823)/51.12)**2.0) + 0.1292*exp(-((v + 45.79)/15.54)**2.0) # ms -dhL_dt = (-hL + hLss)/thL -dhLp_dt = (-hLp + hLssp)/thLp -dmL_dt = (-mL + mLss)/tmL - -expressions("ICab") -ICab_ICab = ((vffrt*(PCab*4.0))*(-cao*gamma_cao + (cai*gamma_cai)*exp(2.0*vfrt)))/(exp(2.0*vfrt) - 1*1.0) # A/F - -expressions("ICl") -IClCa = IClCa_junc + IClCa_sl # A/F -IClCa_junc = ((Fjunc*GClCa)/(KdClCa/cass + 1.0))*(-EClss + v) # A/F -IClCa_sl = ((GClCa*(1.0 - Fjunc))/(KdClCa/cai + 1.0))*(-ECl + v) # A/F -IClb = GClb*(-ECl + v) # A/F - -expressions("INa") -INa_INa = (m**3.0*(GNa*(-ENa + v)))*(j*(h*(1.0 - fINap)) + jp*(fINap*hp)) # A/F -ah = Conditional(Gt(v, -1*40.0), 0.0, 4.43126792958051e-7*exp(-0.147058823529412*v)) -aj = Conditional(Gt(v, -1*40.0), 0.0, -(v + 37.78)*(25428.0*exp(0.28831*v) + 6.948e-6)*exp(-0.04391*v)/(50262745825.954*exp(0.311*v) + 1.0)) -bh = Conditional(Gt(v, -1*40.0), 0.77*exp(0.0900900900900901*v)/(0.13*exp(0.0900900900900901*v) + 0.0497581410839387), 2.7*exp(0.079*v) + 310000.0*exp(0.3485*v)) -bj = Conditional(Gt(v, -1*40.0), 0.6*exp(0.157*v)/(1.0*exp(0.1*v) + 0.0407622039783662), 0.02424*exp(0.12728*v)/(1.0*exp(0.1378*v) + 0.00396086833990426)) -fINap = 1.0/(1.0 + KmCaMK/CaMKa) -hss = 1.0/((exp((v + 71.55)/7.43) + 1.0)**2.0) -hssp = 1.0/((exp((v + 77.55)/7.43) + 1.0)**2.0) -jss = hss -mss = 1.0/((exp((-(v + 56.86))/9.03) + 1.0)**2.0) -th = 1.0/(ah + bh) # ms -tj = 1.0/(aj + bj) # ms -tjp = 1.46*tj # ms -tm = 0.06487*exp(-((v - 1*4.823)/51.12)**2.0) + 0.1292*exp(-((v + 45.79)/15.54)**2.0) # ms -dh_dt = (-h + hss)/th -dhp_dt = (-hp + hssp)/th -dj_dt = (-j + jss)/tj -djp_dt = (-jp + jss)/tjp -dm_dt = (-m + mss)/tm - -expressions("INab") -INab_INab = ((PNab*vffrt)*(nai*exp(vfrt) - nao))/(exp(vfrt) - 1*1.0) # A/F - -expressions("I_katp") -I_katp_I_katp = (bkik*(akik*(fkatp*gkatp)))*(-EK + v) # A/F -akik = (ko/K_o_n)**0.24 -bkik = 1.0/((A_atp/K_atp)**2.0 + 1.0) - -expressions("IpCa") -IpCa_IpCa = (GpCa*cai)/(KmCap + cai) # A/F - -expressions("membrane") -Istim = Conditional(And(Le(i_Stim_Start, time), Ge(i_Stim_PulseDuration, -i_Stim_Period*floor(-(i_Stim_Start - time)/i_Stim_Period) - i_Stim_Start + time)), i_Stim_Amplitude, 0.0) # A/F -vffrt = (F*(F*v))/((R*T)) # C/mol -vfrt = (F*v)/((R*T)) -dv_dt = -(Istim + (I_katp_I_katp + (IClb + (IClCa + (ICab_ICab + (IpCa_IpCa + (IKb_IKb + (INab_INab + (INaK_INaK + (INaCa_ss + (INaCa_i + (IK1_IK1 + (IKs_IKs + (IKr_IKr + (ICaK + (ICaNa + (ICaL_ICaL + (Ito_Ito + (INaL_INaL + INa_INa))))))))))))))))))) # mV - -expressions("diff") -Jdiff = (-cai + cass)/tauCa # mM/ms -JdiffCl = (-cli + clss)/tauNa # mM/ms -JdiffK = (-ki + kss)/tauK # mM/ms -JdiffNa = (-nai + nass)/tauNa # mM/ms - -expressions("SERCA") -Jleak = (0.0048825*cansr)/15.0 # mM/ms -Jup = Jup_b*(-Jleak + (Jupnp*(1.0 - fJupp) + Jupp*fJupp)) # mM/ms -Jupnp = (cai*(upScale*0.005425))/(cai + 0.00092) # mM/ms -Jupp = (cai*((upScale*2.75)*0.005425))/((cai + 0.00092) - 1*0.00017) # mM/ms -fJupp = 1.0/(1.0 + KmCaMK/CaMKa) -upScale = Conditional(Eq(celltype, 1.0), 1.3, 1.0) - -expressions("ryr") -Jrel = Jrel_b*(Jrel_np*(1.0 - fJrelp) + Jrel_p*fJrelp) # mM/ms -Jrel_inf = Conditional(Eq(celltype, 2.0), 1.7*Jrel_inf_b, Jrel_inf_b) # mM/ms -Jrel_inf_b = ((ICaL_ss*(-a_rel))/1.0)/((cajsr_half/cajsr)**8.0 + 1.0) # mM/ms -Jrel_infp = Conditional(Eq(celltype, 2.0), 1.7*Jrel_infp_b, Jrel_infp_b) # mM/ms -Jrel_infp_b = ((ICaL_ss*(-a_relp))/1.0)/((cajsr_half/cajsr)**8.0 + 1.0) # mM/ms -a_rel = (0.5*bt)/1.0 # mM/ms -a_relp = (0.5*btp)/1.0 # mM/ms -btp = 1.25*bt # ms -fJrelp = 1.0/(1.0 + KmCaMK/CaMKa) -tau_rel = Conditional(Lt(tau_rel_b, 0.001), 0.001, tau_rel_b) # ms -tau_rel_b = bt/(1.0 + 0.0123/cajsr) # ms -tau_relp = Conditional(Lt(tau_relp_b, 0.001), 0.001, tau_relp_b) # ms -tau_relp_b = btp/(1.0 + 0.0123/cajsr) # ms -dJrel_np_dt = (Jrel_inf - Jrel_np)/tau_rel # mM/ms -dJrel_p_dt = (Jrel_infp - Jrel_p)/tau_relp # mM/ms - -expressions("trans_flux") -Jtr = (-cajsr + cansr)/60.0 # mM/ms - - -states("intracellular_ions", -cai=0.0001, -CaTrpn=1e-8 -) - -states("mechanics", -XS=0, -XW=0, -TmB=1, -Zetas=0, -Zetaw=0, -Cd=0) - -parameters("mechanics", -emcoupling=1, -lmbda=1, -dLambda=0, -mode=1, -isacs=0, -calib=1, -ktrpn = 0.1, -ntrpn = 2, -Trpn50 = 0.35, -rw = 0.5, -rs = 0.25, -gammas = 0.0085, -gammaw = 0.615, -phi = 2.23, -Tot_A = 25, -Beta0 = 2.3, -Beta1 = -2.4, -cat50_ref = 0.805, -Tref = 120, -kuw = 0.182, -kws = 0.012, -ku=0.04, -ntm=2.4, -p_a = 2.1, -p_b = 9.1, -p_k = 7, -etal = 200, -etas = 20) - -expressions("mechanics") -XS_max = Conditional(Gt(XS, 0), XS, 0) -XW_max = Conditional(Gt(XW, 0), XW, 0) -CaTrpn_max = Conditional(Gt(CaTrpn, 0), CaTrpn, 0) -kwu = kuw*(1/rw-1)-kws -ksu = kws*rw*(1/rs-1) -Aw = Tot_A*rs/((1-rs)*rw+rs) -As = Aw -cw = phi*kuw*((1-rs)*(1-rw))/((1-rs)*rw) -cs = phi*kws*((1-rs)*rw)/rs -lambda_min12 = Conditional(Lt(lmbda, 1.2), lmbda, 1.2) -lambda_min087 = Conditional(Lt(lambda_min12, 0.87), lambda_min12, 0.87) -h_lambda_prima = 1+Beta0*(lambda_min12+lambda_min087-1.87) -h_lambda = Conditional(Gt(h_lambda_prima, 0), h_lambda_prima, 0) -XU = (1-TmB)-XS-XW -gammawu = gammaw*Abs(Zetaw) -gammasu = gammas*Conditional(Gt(Gt(Zetas,0)*Zetas, Lt(Zetas, -1)*(-Zetas-1)), Gt(Zetas,0)*Zetas, Lt(Zetas, -1)*(-Zetas-1)) -dXS_dt = kws*XW - ksu*XS - gammasu*XS -dXW_dt = kuw*XU - kwu*XW - kws*XW - gammawu*XW -kb = ku*Trpn50**ntm/(1-rs-(1-rs)*rw) -dTmB_dt = kb*Conditional(Lt(CaTrpn**(-ntm/2), 100), CaTrpn**(-ntm/2), 100)*XU-ku*CaTrpn**(ntm/2)*TmB -dZetas_dt = As*dLambda - cs*Zetas -dZetaw_dt = Aw*dLambda - cw*Zetaw -Ta = h_lambda*(Tref/rs)*(XS*(Zetas+1) + XW*Zetaw) -C = lambda_min12 - 1 -dCd = C - Cd -eta = Conditional(Lt(dCd, 0), etas, etal) -dCd_dt = p_k * (C - Cd) / eta -Fd = eta * dCd -F1 = (exp( p_b * C) - 1) -Tp = p_a * (F1 + Fd) -Ttot = Ta + Tp diff --git a/demos/split-cai_catrpn/3D/config.toml b/demos/split-cai_catrpn/3D/config.toml deleted file mode 100644 index 2e2581d..0000000 --- a/demos/split-cai_catrpn/3D/config.toml +++ /dev/null @@ -1,118 +0,0 @@ -# Configuration file for running a simulation - -# SIMULATION PARAMETERS -sim.mech_mesh = "mesh_mech_0.5dx_0.5Lx_1Ly_2Lz" # mechanics mesh filepath without extension -sim.outdir = "5ms_N1_cai_catrpn_split_mesh_mech_0.5dx_0.5Lx_1Ly_2Lz" # Output directory -sim.sim_dur = 5 # Duration of simulation. Integer -sim.dt = 0.05 # Timestep for ep solve -sim.N = 1 # Solve mechanics step every nth ep solve - -# MODEL PARAMETERS -sim.modelfile = "ORdmm_Land.ode" - -# OUTPUT PARAMETERS -write_all_ep.numbers = 2 -write_all_ep.0.name = "cai" -write_all_ep.1.name = "v" - -write_all_mech.numbers = 2 -write_all_mech.0.name = "Ta" -write_all_mech.1.name = "lambda" - -# Currently also outputting volume averages for these: -write_point_ep.numbers = 3 -write_point_ep.0.name = "cai" -write_point_ep.0.x = 0.0 -write_point_ep.0.y = 0 -write_point_ep.0.z = 0 -write_point_ep.1.name = "v" -write_point_ep.1.x = 0 -write_point_ep.1.y = 0 -write_point_ep.1.z = 0 -write_point_ep.2.name = "CaTrpn" -write_point_ep.2.x = 0 -write_point_ep.2.y = 0 -write_point_ep.2.z = 0 - -write_point_mech.numbers = 5 -write_point_mech.0.name = "Ta" -write_point_mech.0.x = 0 -write_point_mech.0.y = 0 -write_point_mech.0.z = 0 -write_point_mech.1.name = "Zetas" -write_point_mech.1.x = 0 -write_point_mech.1.y = 0 -write_point_mech.1.z = 0 -write_point_mech.2.name = "XS" -write_point_mech.2.x = 0 -write_point_mech.2.y = 0 -write_point_mech.2.z = 0 -write_point_mech.3.name = "TmB" -write_point_mech.3.x = 0 -write_point_mech.3.y = 0 -write_point_mech.3.z = 0 -write_point_mech.4.name = "lambda" -write_point_mech.4.x = 0 -write_point_mech.4.y = 0 -write_point_mech.4.z = 0 - - - -# Tissue conductivity values. Currently only a single region, from p.4339 of Niederer benchmark -ep.sigma_il = 0.17 # mS / mm -ep.sigma_it = 0.019 # mS / mm -ep.sigma_el = 0.62 # mS / mm -ep.sigma_et = 0.24 # mS / mm - -# Material parameters -# TODO: make material parameters more generic -mech.a=2.28 -mech.a_f=1.686 -mech.b=9.726 -mech.b_f=15.779 -mech.a_s=0.0 -mech.b_s=0.0 -mech.a_fs=0.0 -mech.b_fs=0.0 - -# STIMULUS PARAMETERS -stim.start = 0.0 -stim.amplitude = 50000.0 # mu A/cm^3 -stim.duration = 2 # ms -stim.xmin = 0.0 -stim.xmax = 0.5 -stim.ymin = 0.0 -stim.ymax = 0.5 -stim.zmin = 0.0 -stim.zmax = 0.5 - -# BOUNDARY CONDITIONS -bcs.numbers = 3 -bcs.markerfile = "mesh_mech_0.5dx_0.5Lx_1Ly_2Lz_surface_ffun" - -# Mesh markers used for assigning bcs -bcs.0.marker = 1 -bcs.0.type = "Dirichlet" -bcs.0.V = "u_x" -bcs.0.expression = 0 -bcs.0.param_numbers = 0 - -bcs.1.marker = 3 # if same marker for ux,uy,uz, (e.g. marker = 1), then fixes the entire plane (plane with marker == 1) -bcs.1.type = "Dirichlet" -bcs.1.V = "u_y" -bcs.1.expression = 0 -bcs.1.param_numbers = 0 - -bcs.2.marker = 5 -bcs.2.type = "Dirichlet" -bcs.2.V = "u_z" -bcs.2.expression = 0 -bcs.2.param_numbers = 0 - -#bcs.3.marker = 2 -#bcs.3.type = "Neumann" -#bcs.3.expression = 'a*t' # Value can be a function of t -#bcs.3.param_numbers = 1 -#bcs.3.param.0.name = 'a' -#bcs.3.param.0.value = -0.2 -#bcs.3.degree = 1 diff --git a/demos/split-cai_catrpn/3D/main_using_config.py b/demos/split-cai_catrpn/3D/main_using_config.py deleted file mode 100644 index 61b175f..0000000 --- a/demos/split-cai_catrpn/3D/main_using_config.py +++ /dev/null @@ -1,681 +0,0 @@ -import logging -import gotranx -from pathlib import Path -from typing import Sequence -import numpy as np -import dolfin -import pulse -import beat -import argparse -import toml -import matplotlib.pyplot as plt - - -from simcardems2 import utils -from simcardems2 import mechanicssolver -from simcardems2 import interpolation -from simcardems2.land_CaTrpnsplit import LandModel -from simcardems2.validate_input_types import validate_input_types - - -try: - raise ImportError - from numba import jit -except ImportError: - - def jit(*args, **kwargs): - def wrapper(func): - return func - - return wrapper - - -logging.getLogger("beat").setLevel(logging.ERROR) - - -def parse_parameters(argv: Sequence[str] | None = None) -> int: - parser = argparse.ArgumentParser(description="Simcardems CLI") - parser.add_argument("config-file", type=Path, help="Config file") - - args = vars(parser.parse_args(argv)) - try: - config = toml.loads(args["config-file"].read_text()) - except toml.TomlDecodeError as e: - print(f"Error when parsing input parameters. Check config file. Error: {e}") - exit(1) - return config - - -config = parse_parameters() - -validate_input_types(config) - -stim_region = ( - [config["stim"]["xmin"], config["stim"]["xmax"]], - [config["stim"]["ymin"], config["stim"]["ymax"]], - [config["stim"]["zmin"], config["stim"]["zmax"]], -) -out_ep_var_names = [ - config["write_all_ep"][f"{i}"]["name"] for i in range(config["write_all_ep"]["numbers"]) -] -out_mech_var_names = [ - config["write_all_mech"][f"{i}"]["name"] for i in range(config["write_all_mech"]["numbers"]) -] -out_ep_coord_names = [ - config["write_point_ep"][f"{i}"]["name"] for i in range(config["write_point_ep"]["numbers"]) -] -ep_coords = [ - [config["write_point_ep"][f"{varnr}"][f"{coord}"] for coord in ["x", "y", "z"]] - for varnr in range(config["write_point_ep"]["numbers"]) -] -out_mech_coord_names = [ - config["write_point_mech"][f"{i}"]["name"] for i in range(config["write_point_mech"]["numbers"]) -] -mech_coords = [ - [config["write_point_mech"][f"{varnr}"][f"{coord}"] for coord in ["x", "y", "z"]] - for varnr in range(config["write_point_mech"]["numbers"]) -] - - -outdir = Path(config["sim"]["outdir"]) -outdir.mkdir(parents=True, exist_ok=True) - -with open(Path(outdir / "config.txt"), "w") as f: - f.write(toml.dumps(config)) - - -# TODO: do a different dirichlet/neumann check than this later. something smoother -t_bcs = dolfin.Constant(0) -bcs_dirichlet = [] -bcs_neumann = [] -bcs_expressions = {} -for bc in range(config["bcs"]["numbers"]): - if config["bcs"][f"{bc}"]["type"] == "Dirichlet": - bcs_dirichlet.append(bc) - elif config["bcs"][f"{bc}"]["type"] == "Neumann": - bcs_neumann.append(bc) - else: - raise KeyError( - f'{config["bcs"][str(bc)]["type"]} is not a valid type of boundary ' - 'condition. Use Dirichlet or Neumann. Check config file' - ) - - if config["bcs"][f"{bc}"]["param_numbers"] > 0: - bcs_parameters = {} - for param_nr in range(config["bcs"][f"{bc}"]["param_numbers"]): - param_name = config["bcs"][f"{bc}"]["param"][f"{param_nr}"]["name"] - param_value = config["bcs"][f"{bc}"]["param"][f"{param_nr}"]["value"] - bcs_parameters[param_name] = param_value - bcs_expressions[f"{bc}"] = dolfin.Expression( - config["bcs"][f"{bc}"]["expression"], - **bcs_parameters, - t=t_bcs, - degree=config["bcs"][f"{bc}"]["degree"], - ) - else: - bcs_expressions[f"{bc}"] = dolfin.Constant(0) - - -mesh = dolfin.Mesh() -with dolfin.XDMFFile(f'{config["sim"]["mech_mesh"]}.xdmf') as infile: - infile.read(mesh) -print(f'Loaded mesh: {config["sim"]["mech_mesh"]}') - - -ffun_bcs = dolfin.MeshFunction("size_t", mesh, mesh.topology().dim() - 1) -with dolfin.XDMFFile(f'{config["bcs"]["markerfile"]}.xdmf') as infile: - infile.read(ffun_bcs) -print(f'Loaded markerfile for bcs: {config["bcs"]["markerfile"]}') - - -tol = 5e-4 -# Surface to volume ratio -chi = 140.0 # mm^{-1} -# Membrane capacitance -C_m = 0.01 # mu F / mm^2 -cm2mm = 10.0 - -t = np.arange(0, config["sim"]["sim_dur"], config["sim"]["dt"]) -sigma = [ - config["ep"]["sigma_il"], - config["ep"]["sigma_it"], - config["ep"]["sigma_el"], - config["ep"]["sigma_et"], -] -material_parameters = dict( - a=config["mech"]["a"], - a_f=config["mech"]["a_f"], - b=config["mech"]["b"], - b_f=config["mech"]["b_f"], - a_s=config["mech"]["a_s"], - b_s=config["mech"]["b_s"], - a_fs=config["mech"]["a_fs"], - b_fs=config["mech"]["b_fs"], -) - - -dolfin.parameters["form_compiler"]["representation"] = "uflacs" -dolfin.parameters["form_compiler"]["cpp_optimize"] = True -dolfin.parameters["form_compiler"]["quadrature_degree"] = 4 - - -def define_conductivity_tensor(sigma, chi, C_m): - # Compute monodomain approximation by taking harmonic mean in each - # direction of intracellular and extracellular part - def harmonic_mean(a, b): - return a * b / (a + b) - - sigma_l = harmonic_mean(sigma[0], sigma[2]) - sigma_t = harmonic_mean(sigma[1], sigma[3]) - - # Scale conducitivites by 1/(C_m * chi) - s_l = sigma_l / (C_m * chi) # mm^2 / ms - s_t = sigma_t / (C_m * chi) # mm^2 / ms - - # Define conductivity tensor - M = dolfin.as_tensor(((s_l, 0, 0), (0, s_t, 0), (0, 0, s_t))) - - return M - - -def define_stimulus( - mesh, - chi, - C_m, - time, - stim_region=stim_region, - stim_start=config["stim"]["start"], - A=config["stim"]["amplitude"], - duration=config["stim"]["duration"], -): - S1_marker = 1 - S1_subdomain = dolfin.CompiledSubDomain( - " ".join( - ( - f"x[0] >= {stim_region[0][0]}", - f"&& x[0] <= {stim_region[0][1]}", - f"&& x[1] >= {stim_region[1][0]}", - f"&& x[1] <= {stim_region[1][1]}", - f"&& x[2] >= {stim_region[2][0]}", - f"&& x[2] <= {stim_region[2][1]}", - ) - ) - ) - - S1_markers = dolfin.MeshFunction("size_t", mesh, mesh.topology().dim()) - S1_subdomain.mark(S1_markers, S1_marker) - with dolfin.XDMFFile((outdir / "stim_region_markers.xdmf").as_posix()) as xdmf: - xdmf.write(S1_markers) - - # Define stimulation (NB: region of interest carried by the mesh - # and assumptions in cbcbeat) - factor = 1.0 / (chi * C_m) # NB: cbcbeat convention - amplitude = factor * A * (1.0 / cm2mm) ** 3 # mV/ms - - I_s = dolfin.Expression( - "time >= start ? (time <= (duration + start) ? amplitude : 0.0) : 0.0", - time=time, - start=config["stim"]["start"], - duration=duration, - amplitude=amplitude, - degree=0, - ) - - dx = dolfin.Measure("dx", domain=mesh, subdomain_data=S1_markers)(S1_marker) - return beat.base_model.Stimulus(dz=dx, expr=I_s) - - -# Load the model -if not Path("ep_model.py").exists(): - ode = gotranx.load_ode(config["sim"]["modelfile"]) - - mechanics_comp = ode.get_component("mechanics") - mechanics_ode = mechanics_comp.to_ode() - - ep_ode = ode - mechanics_comp - - # Generate code for the electrophysiology model - code_ep = gotranx.cli.gotran2py.get_code( - ep_ode, - scheme=[gotranx.schemes.Scheme.forward_generalized_rush_larsen], - missing_values=mechanics_ode.missing_variables, - ) - # Generate code for the mechanics model - code_mechanics = gotranx.cli.gotran2py.get_code( - mechanics_ode, - scheme=[gotranx.schemes.Scheme.forward_generalized_rush_larsen], - missing_values=ep_ode.missing_variables, - ) - - Path("ep_model.py").write_text(code_ep) - # Currently 3D mech needs to be written manually - -import ep_model as _ep_model - -ep_model = _ep_model.__dict__ - - -# Validate ep variables to output -for i in list(set(out_ep_coord_names) | set(out_ep_var_names)): - try: - var = ep_model["state_index"](i) - except KeyError: - print(f"{i} is not an ep state. Check config file") - raise - -# Forwared generalized rush larsen scheme for the electrophysiology model -fgr_ep = jit(nopython=True)(ep_model["forward_generalized_rush_larsen"]) -# Monitor function for the electrophysiology model -mon_ep = ep_model["monitor_values"] -# Missing values function for the electrophysiology model -mv_ep = ep_model["missing_values"] -lmbda_index_ep = ep_model["parameter_index"]("lmbda") - - -# Get initial values from the EP model -y_ep_ = ep_model["init_state_values"]() -p_ep_ = ep_model["init_parameter_values"](amp=0.0) - - -# ep_mesh = dolfin.adapt(dolfin.adapt(dolfin.adapt(mesh))) -ep_mesh = mesh - -time = dolfin.Constant(0.0) -I_s = define_stimulus( - mesh=ep_mesh, - chi=chi, - C_m=C_m, - time=time, - stim_region=stim_region, - stim_start=config["stim"]["start"], - A=config["stim"]["amplitude"], - duration=config["stim"]["duration"], -) -M = define_conductivity_tensor(sigma, chi, C_m) -params = {"preconditioner": "sor", "use_custom_preconditioner": False} -ep_ode_space = dolfin.FunctionSpace(ep_mesh, "DG", 1) -v_ode = dolfin.Function(ep_ode_space) -num_points_ep = v_ode.vector().local_size() -lmbda = dolfin.Function(ep_ode_space) - - -y_ep = np.zeros((len(y_ep_), num_points_ep)) -y_ep.T[:] = y_ep_ # Set to y_ep with initial values defined in ep_model - - -# mechanics_missing_values_ = np.zeros(1) -mechanics_missing_values_ = np.array([0.0001]) - - -# Set the activation -activation_space = dolfin.FunctionSpace(mesh, "DG", 1) -activation = dolfin.Function(activation_space) -num_points_mech = activation.vector().local_size() - -missing_mech = interpolation.MissingValue( - element=activation.ufl_element(), - interpolation_element=ep_ode_space.ufl_element(), - mechanics_mesh=mesh, - ep_mesh=ep_mesh, - num_values=len(mechanics_missing_values_), -) - -missing_mech.values_ep.T[:] = mechanics_missing_values_ -missing_mech.values_mechanics.T[:] = mechanics_missing_values_ -missing_mech.mechanics_values_to_function() # Assign initial values to mech functions - - -# Use previous Catrpn in mech to be consistent with zeta split -prev_missing_mech = interpolation.MissingValue( - element=activation.ufl_element(), - interpolation_element=ep_ode_space.ufl_element(), - mechanics_mesh=mesh, - ep_mesh=ep_mesh, - num_values=len(mechanics_missing_values_), -) -for i in range(len(mechanics_missing_values_)): - prev_missing_mech.u_mechanics[i].vector().set_local(missing_mech.values_mechanics[i]) - - -# Create function spaces for ep variables to output -out_ep_funcs = {} -for out_ep_var in list(set(out_ep_var_names) | set(out_ep_coord_names)): - out_ep_funcs[out_ep_var] = dolfin.Function(ep_ode_space) - -p_ep = np.zeros((len(p_ep_), num_points_ep)) -p_ep.T[:] = p_ep_ # Initialise p_ep with initial values defined in ep_model - -pde = beat.MonodomainModel(time=time, mesh=ep_mesh, M=M, I_s=I_s, params=params) -ode = beat.odesolver.DolfinODESolver( - v_ode=dolfin.Function(ep_ode_space), - v_pde=pde.state, - fun=fgr_ep, - parameters=p_ep, - init_states=y_ep, - num_states=len(y_ep), - v_index=ep_model["state_index"]("v"), - missing_variables=None, - num_missing_variables=0, -) - -# ep_solver = beat.MonodomainSplittingSolver(pde=pde, ode=ode, theta=0.5) -ep_solver = beat.MonodomainSplittingSolver(pde=pde, ode=ode, theta=1) # Test - -marker_functions = pulse.MarkerFunctions(ffun=ffun_bcs) - - -def create_boundary_conditions( - ffun_bcs, bcs_dirichlet, bcs_neumann, bcs_dict, bcs_expressions -): # TODO: update to not need separate dirichlet and neumann list - def dirichlet_bc(W): - bcs_W = { - "u_x": W.sub(0).sub(0), - "u_y": W.sub(0).sub(1), - "u_z": W.sub(0).sub(2), - # TODO: add the rest (check dolfin doc) - } - - bcs = [] - for bc in bcs_dirichlet: - bcs.append( - dolfin.DirichletBC( - bcs_W[bcs_dict[f"{bc}"]["V"]], - bcs_expressions[f"{bc}"], # TODO: use dolfin expression - ffun_bcs, - bcs_dict[f"{bc}"]["marker"], - ) - ) - return bcs - - neumann_bc = [] - if bcs_neumann is not None: - for bc in bcs_neumann: - neumann_bc.append( - pulse.NeumannBC( - traction=utils.float_to_constant(bcs_expressions[f"{bc}"]), - marker=bcs_dict[f"{bc}"]["marker"], - ) - ) - - # Collect Boundary Conditions - bcs = pulse.BoundaryConditions(dirichlet=(dirichlet_bc,), neumann=neumann_bc) - return bcs - - -f0 = dolfin.as_vector([1.0, 0.0, 0.0]) -s0 = dolfin.as_vector([0.0, 1.0, 0.0]) -n0 = dolfin.as_vector([0.0, 0.0, 1.0]) -microstructure = pulse.Microstructure(f0=f0, s0=s0, n0=n0) -geometry = pulse.Geometry( - mesh=mesh, marker_functions=marker_functions, microstructure=microstructure -) - -active_model = LandModel( - f0=f0, - s0=s0, - n0=n0, - # CaTrpn=missing_mech.u_mechanics[0], - CaTrpn=prev_missing_mech.u_mechanics[ - 0 - ], # Use prev Catrpn in mech to be consistent with zeta split - mesh=mesh, - eta=0, # Fraction of transverse active tension for active stress formulation. - # 0 = active only along fiber, 1 = equal forces in all directions - # (default=0.0). - dLambda_tol=1e-12, -) -active_model.t = 0.0 - - -mech_variables = { - "Ta": active_model.Ta_current, - "Zetas": active_model._Zetas, - "Zetaw": active_model._Zetaw, - "lambda": active_model.lmbda, - "XS": active_model._XS, - "XW": active_model._XW, - "TmB": active_model._TmB, -} - -# Validate mechanics variables to output -for out_mech_var in list(set(out_mech_coord_names) | set(out_mech_var_names)): - assert ( - out_mech_var in mech_variables - ), f"Error: '{out_mech_var}' is not a valid variable name. Check config file" - -material = pulse.HolzapfelOgden( - parameters=material_parameters, - active_model=active_model, - f0=f0, - s0=s0, - n0=n0, -) - - -def compute_function_average_over_mesh(func, mesh): - volume = dolfin.assemble(dolfin.Constant(1.0) * dolfin.dx(domain=mesh)) - return dolfin.assemble(func * dolfin.dx(domain=mesh)) / volume - - -# Collect Boundary Conditions -bcs = create_boundary_conditions( - ffun_bcs, bcs_dirichlet, bcs_neumann, config["bcs"], bcs_expressions -) - -problem = mechanicssolver.MechanicsProblem(geometry, material, bcs) -print("problem set up") -problem.solve(0.0, 0.0) - -disp_file = Path(outdir / "disp.xdmf") -disp_file.unlink(missing_ok=True) -disp_file.with_suffix(".h5").unlink(missing_ok=True) - -out_ep_files = {} -for out_ep_var in out_ep_var_names: - out_ep_files[out_ep_var] = Path(outdir / f"{out_ep_var}_out_ep.xdmf") - out_ep_files[out_ep_var].unlink(missing_ok=True) - out_ep_files[out_ep_var].with_suffix(".h5").unlink(missing_ok=True) - -out_mech_files = {} -for out_mech_var in out_mech_var_names: - out_mech_files[out_mech_var] = Path(outdir / f"{out_mech_var}_out_mech.xdmf") - out_mech_files[out_mech_var].unlink(missing_ok=True) - out_mech_files[out_mech_var].with_suffix(".h5").unlink(missing_ok=True) - - -# Create arrays for storing values to plot time series for example nodes -out_ep_example_nodes = {} -for out_ep_var in out_ep_coord_names: - out_ep_example_nodes[out_ep_var] = np.zeros(len(t)) - -out_mech_example_nodes = {} -for out_mech_var in out_mech_coord_names: - out_mech_example_nodes[out_mech_var] = np.zeros(len(t)) - -# Create arrays for storing values to plot time series for volume averages -out_ep_volume_average_timeseries = {} -for out_ep_var in out_ep_coord_names: - out_ep_volume_average_timeseries[out_ep_var] = np.zeros(len(t)) - -out_mech_volume_average_timeseries = {} -for out_mech_var in out_mech_coord_names: - out_mech_volume_average_timeseries[out_mech_var] = np.zeros(len(t)) - - -inds = [] # Array with time-steps for which we solve mechanics -j = 0 -timer = dolfin.Timer("solve_loop") - -for i, ti in enumerate(t): - print(f"Solving time {ti:.2f} ms") - t_bcs.assign(ti) # Use ti+ dt here instead? - ep_solver.step((ti, ti + config["sim"]["dt"])) - - # Assign values to ep function - for out_ep_var in list(set(out_ep_var_names) | set(out_ep_coord_names)): - out_ep_funcs[out_ep_var].vector()[:] = ode._values[ep_model["state_index"](out_ep_var)] - - # Store values to plot time series for given coord - for var_nr in range(config["write_point_ep"]["numbers"]): - # Trace variable in coordinate - out_ep_var = config["write_point_ep"][f"{var_nr}"]["name"] - out_ep_example_nodes[out_ep_var][i] = out_ep_funcs[out_ep_var](ep_coords[var_nr]) - # Compute volume averages - out_ep_volume_average_timeseries[out_ep_var][i] = compute_function_average_over_mesh( - out_ep_funcs[out_ep_var], ep_mesh - ) - - if i % config["sim"]["N"] != 0: - continue - - # Extract missing values for the mechanics step from the ep model (ep function space) - missing_ep_values = mv_ep(ti + config["sim"]["dt"], ode._values, ode.parameters) - # Assign the extracted values as missing_mech for the mech step (ep function space) - for k in range(missing_mech.num_values): - missing_mech.u_ep_int[k].vector()[:] = missing_ep_values[k, :] - - # Interpolate missing variables from ep to mech function space - missing_mech.interpolate_ep_to_mechanics() - missing_mech.mechanics_function_to_values() - inds.append(i) - - print("Solve mechanics") - active_model.t = ti + config["sim"]["N"] * config["sim"]["dt"] # Addition! - problem.solve(ti, config["sim"]["N"] * config["sim"]["dt"]) - active_model.update_prev() - - lmbda.interpolate(active_model.lmbda) - p_ep[lmbda_index_ep, :] = lmbda.vector().get_local() # p_ep are the ep parameters - print( - active_model.lmbda.vector().get_local().min(), - active_model.lmbda.vector().get_local().max(), - ) - - U, p = problem.state.split(deepcopy=True) - - for var_nr in range(config["write_point_mech"]["numbers"]): - # Trace variable in coordinate - out_mech_var = config["write_point_mech"][f"{var_nr}"]["name"] - - out_mech_example_nodes[out_mech_var][i] = mech_variables[out_mech_var](mech_coords[var_nr]) - - # Compute volume averages - out_mech_volume_average_timeseries[out_mech_var][i] = compute_function_average_over_mesh( - mech_variables[out_mech_var], mesh - ) - - # Use previous Catrpn in mech to be consistent with zeta split - for i in range(len(mechanics_missing_values_)): - prev_missing_mech.u_mechanics[i].vector().set_local(missing_mech.values_mechanics[i]) - - with dolfin.XDMFFile(disp_file.as_posix()) as file: - file.write_checkpoint(U, "disp", j, dolfin.XDMFFile.Encoding.HDF5, True) - for out_ep_var in out_ep_var_names: - with dolfin.XDMFFile(out_ep_files[out_ep_var].as_posix()) as file: - file.write_checkpoint( - out_ep_funcs[out_ep_var], - out_ep_var, - j, - dolfin.XDMFFile.Encoding.HDF5, - True, - ) - for out_mech_var in out_mech_var_names: - with dolfin.XDMFFile(out_mech_files[out_mech_var].as_posix()) as file: - file.write_checkpoint( - mech_variables[out_mech_var], - out_mech_var, - j, - dolfin.XDMFFile.Encoding.HDF5, - True, - ) - - j += 1 -timer.stop() -timings = dolfin.timings( - dolfin.TimingClear.keep, - [dolfin.TimingType.wall, dolfin.TimingType.user, dolfin.TimingType.system], -).str(True) -print(timings) -with open(Path(outdir / "solve_timings.txt"), "w") as f: - f.write(timings) - -# Write averaged results for later analysis -for out_ep_var in out_ep_coord_names: - with open(Path(outdir / f"{out_ep_var}_out_ep_volume_average.txt"), "w") as f: - np.savetxt(f, out_ep_volume_average_timeseries[out_ep_var][inds]) - -for out_mech_var in out_mech_coord_names: - with open(Path(outdir / f"{out_mech_var}_out_mech_volume_average.txt"), "w") as f: - np.savetxt(f, out_mech_volume_average_timeseries[out_mech_var][inds]) - -# Write point traces for later analysis -for var_nr in range(config["write_point_ep"]["numbers"]): - out_ep_var = config["write_point_ep"][f"{var_nr}"]["name"] - with open( - Path( - outdir - / f"{out_ep_var}_ep_coord{ep_coords[var_nr][0]},{ep_coords[var_nr][1]},{ep_coords[var_nr][2]}.txt".replace( - " ", "" - ) - ), - "w", - ) as f: - np.savetxt(f, out_ep_example_nodes[out_ep_var][inds]) - -for var_nr in range(config["write_point_mech"]["numbers"]): - out_mech_var = config["write_point_mech"][f"{var_nr}"]["name"] - with open( - Path( - outdir - / f"{out_mech_var}_mech_coord{mech_coords[var_nr][0]},{mech_coords[var_nr][1]},{mech_coords[var_nr][2]}.txt" - ), - "w", - ) as f: - np.savetxt(f, out_mech_example_nodes[out_mech_var][inds]) - -print(f"Solved on {100 * len(inds) / len(t)}% of the time steps") -inds = np.array(inds) - -# Plot the results -fig, ax = plt.subplots(len(out_ep_coord_names), 1, figsize=(10, 10)) -if len(out_ep_coord_names) == 1: - ax = np.array([ax]) -for i, out_ep_var in enumerate(out_ep_coord_names): - ax[i].plot(t[inds], out_ep_volume_average_timeseries[out_ep_var][inds]) - ax[i].set_title(f"{out_ep_var} volume average") - ax[i].set_xlabel("Time (ms)") -fig.tight_layout() -fig.savefig(Path(outdir / "out_ep_volume_averages.png")) - -fig, ax = plt.subplots(len(out_ep_coord_names), 1, figsize=(10, 10)) -if len(out_ep_coord_names) == 1: - ax = np.array([ax]) -for var_nr in range(config["write_point_ep"]["numbers"]): - out_ep_var = config["write_point_ep"][f"{var_nr}"]["name"] - ax[var_nr].plot(t[inds], out_ep_example_nodes[out_ep_var][inds]) - ax[var_nr].set_title(f"{out_ep_var} in coord {ep_coords[var_nr]}") - ax[var_nr].set_xlabel("Time (ms)") -fig.tight_layout() -fig.savefig(Path(outdir / "out_ep_coord.png")) - -fig, ax = plt.subplots(len(out_mech_coord_names), 1, figsize=(10, 10)) -if len(out_mech_coord_names) == 1: - ax = np.array([ax]) -for i, out_mech_var in enumerate(out_mech_coord_names): - ax[i].plot(t[inds], out_mech_volume_average_timeseries[out_mech_var][inds]) - ax[i].set_title(f"{out_mech_var} volume average") - ax[i].set_xlabel("Time (ms)") -fig.tight_layout() -fig.savefig(Path(outdir / "out_mech_volume_averages.png")) - -fig, ax = plt.subplots(len(out_mech_coord_names), 1, figsize=(10, 10)) -if len(out_mech_coord_names) == 1: - ax = np.array([ax]) - -for var_nr in range(config["write_point_mech"]["numbers"]): - out_mech_var = config["write_point_mech"][f"{var_nr}"]["name"] - ax[var_nr].plot(t[inds], out_mech_example_nodes[out_mech_var][inds]) - ax[var_nr].set_title(f"{out_mech_var} in coord {mech_coords[var_nr]}") - ax[var_nr].set_xlabel("Time (ms)") -fig.tight_layout() -fig.savefig(Path(outdir / "out_mech_coord.png")) diff --git a/demos/split-cai_catrpn/3D/main_using_config_time.py b/demos/split-cai_catrpn/3D/main_using_config_time.py deleted file mode 100644 index d542580..0000000 --- a/demos/split-cai_catrpn/3D/main_using_config_time.py +++ /dev/null @@ -1,720 +0,0 @@ -import logging -import gotranx -from pathlib import Path -from typing import Sequence -import numpy as np -import dolfin -import pulse -import beat -import argparse -import toml -import matplotlib.pyplot as plt - - -from simcardems2 import utils -from simcardems2 import mechanicssolver -from simcardems2 import interpolation -from simcardems2.land_CaTrpnsplit import LandModel -from simcardems2.validate_input_types import validate_input_types - -plot_results = True -write_disp = True - -try: - raise ImportError - from numba import jit -except ImportError: - - def jit(*args, **kwargs): - def wrapper(func): - return func - - return wrapper - - -logging.getLogger("beat").setLevel(logging.ERROR) - - -def parse_parameters(argv: Sequence[str] | None = None) -> int: - parser = argparse.ArgumentParser(description="Simcardems CLI") - parser.add_argument("config-file", type=Path, help="Config file") - - args = vars(parser.parse_args(argv)) - try: - config = toml.loads(args["config-file"].read_text()) - except toml.TomlDecodeError as e: - print(f"Error when parsing input parameters. Check config file. Error: {e}") - exit(1) - return config - - -config = parse_parameters() - -validate_input_types(config) - -stim_region = ( - [config["stim"]["xmin"], config["stim"]["xmax"]], - [config["stim"]["ymin"], config["stim"]["ymax"]], - [config["stim"]["zmin"], config["stim"]["zmax"]], -) -out_ep_var_names = [ - config["write_all_ep"][f"{i}"]["name"] for i in range(config["write_all_ep"]["numbers"]) -] -out_mech_var_names = [ - config["write_all_mech"][f"{i}"]["name"] for i in range(config["write_all_mech"]["numbers"]) -] -out_ep_coord_names = [ - config["write_point_ep"][f"{i}"]["name"] for i in range(config["write_point_ep"]["numbers"]) -] -ep_coords = [ - [config["write_point_ep"][f"{varnr}"][f"{coord}"] for coord in ["x", "y", "z"]] - for varnr in range(config["write_point_ep"]["numbers"]) -] -out_mech_coord_names = [ - config["write_point_mech"][f"{i}"]["name"] for i in range(config["write_point_mech"]["numbers"]) -] -mech_coords = [ - [config["write_point_mech"][f"{varnr}"][f"{coord}"] for coord in ["x", "y", "z"]] - for varnr in range(config["write_point_mech"]["numbers"]) -] - - -outdir = Path(config["sim"]["outdir"]) -outdir.mkdir(parents=True, exist_ok=True) - -with open(Path(outdir / "config.txt"), "w") as f: - f.write(toml.dumps(config)) - - -# TODO: do a different dirichlet/neumann check than this later. something smoother -t_bcs = dolfin.Constant(0) -bcs_dirichlet = [] -bcs_neumann = [] -bcs_expressions = {} -for bc in range(config["bcs"]["numbers"]): - if config["bcs"][f"{bc}"]["type"] == "Dirichlet": - bcs_dirichlet.append(bc) - elif config["bcs"][f"{bc}"]["type"] == "Neumann": - bcs_neumann.append(bc) - else: - raise KeyError( - f'{config["bcs"][str(bc)]["type"]} is not a valid type of boundary ' - 'condition. Use Dirichlet or Neumann. Check config file' - ) - - if config["bcs"][f"{bc}"]["param_numbers"] > 0: - bcs_parameters = {} - for param_nr in range(config["bcs"][f"{bc}"]["param_numbers"]): - param_name = config["bcs"][f"{bc}"]["param"][f"{param_nr}"]["name"] - param_value = config["bcs"][f"{bc}"]["param"][f"{param_nr}"]["value"] - bcs_parameters[param_name] = param_value - bcs_expressions[f"{bc}"] = dolfin.Expression( - config["bcs"][f"{bc}"]["expression"], - **bcs_parameters, - t=t_bcs, - degree=config["bcs"][f"{bc}"]["degree"], - ) - else: - bcs_expressions[f"{bc}"] = dolfin.Constant(0) - - -mesh = dolfin.Mesh() -with dolfin.XDMFFile(f'{config["sim"]["mech_mesh"]}.xdmf') as infile: - infile.read(mesh) -print(f'Loaded mesh: {config["sim"]["mech_mesh"]}') - - -ffun_bcs = dolfin.MeshFunction("size_t", mesh, mesh.topology().dim() - 1) -with dolfin.XDMFFile(f'{config["bcs"]["markerfile"]}.xdmf') as infile: - infile.read(ffun_bcs) -print(f'Loaded markerfile for bcs: {config["bcs"]["markerfile"]}') - - -tol = 5e-4 -# Surface to volume ratio -chi = 140.0 # mm^{-1} -# Membrane capacitance -C_m = 0.01 # mu F / mm^2 -cm2mm = 10.0 - -t = np.arange(0, config["sim"]["sim_dur"], config["sim"]["dt"]) -sigma = [ - config["ep"]["sigma_il"], - config["ep"]["sigma_it"], - config["ep"]["sigma_el"], - config["ep"]["sigma_et"], -] -material_parameters = dict( - a=config["mech"]["a"], - a_f=config["mech"]["a_f"], - b=config["mech"]["b"], - b_f=config["mech"]["b_f"], - a_s=config["mech"]["a_s"], - b_s=config["mech"]["b_s"], - a_fs=config["mech"]["a_fs"], - b_fs=config["mech"]["b_fs"], -) - - -dolfin.parameters["form_compiler"]["representation"] = "uflacs" -dolfin.parameters["form_compiler"]["cpp_optimize"] = True -dolfin.parameters["form_compiler"]["quadrature_degree"] = 4 - - -def define_conductivity_tensor(sigma, chi, C_m): - # Compute monodomain approximation by taking harmonic mean in each - # direction of intracellular and extracellular part - def harmonic_mean(a, b): - return a * b / (a + b) - - sigma_l = harmonic_mean(sigma[0], sigma[2]) - sigma_t = harmonic_mean(sigma[1], sigma[3]) - - # Scale conducitivites by 1/(C_m * chi) - s_l = sigma_l / (C_m * chi) # mm^2 / ms - s_t = sigma_t / (C_m * chi) # mm^2 / ms - - # Define conductivity tensor - M = dolfin.as_tensor(((s_l, 0, 0), (0, s_t, 0), (0, 0, s_t))) - - return M - - -def define_stimulus( - mesh, - chi, - C_m, - time, - stim_region=stim_region, - stim_start=config["stim"]["start"], - A=config["stim"]["amplitude"], - duration=config["stim"]["duration"], -): - S1_marker = 1 - S1_subdomain = dolfin.CompiledSubDomain( - " ".join( - ( - f"x[0] >= {stim_region[0][0]}", - f"&& x[0] <= {stim_region[0][1]}", - f"&& x[1] >= {stim_region[1][0]}", - f"&& x[1] <= {stim_region[1][1]}", - f"&& x[2] >= {stim_region[2][0]}", - f"&& x[2] <= {stim_region[2][1]}", - ) - ) - ) - - S1_markers = dolfin.MeshFunction("size_t", mesh, mesh.topology().dim()) - S1_subdomain.mark(S1_markers, S1_marker) - with dolfin.XDMFFile((outdir / "stim_region_markers.xdmf").as_posix()) as xdmf: - xdmf.write(S1_markers) - - # Define stimulation (NB: region of interest carried by the mesh - # and assumptions in cbcbeat) - factor = 1.0 / (chi * C_m) # NB: cbcbeat convention - amplitude = factor * A * (1.0 / cm2mm) ** 3 # mV/ms - - I_s = dolfin.Expression( - "time >= start ? (time <= (duration + start) ? amplitude : 0.0) : 0.0", - time=time, - start=config["stim"]["start"], - duration=duration, - amplitude=amplitude, - degree=0, - ) - - dx = dolfin.Measure("dx", domain=mesh, subdomain_data=S1_markers)(S1_marker) - return beat.base_model.Stimulus(dz=dx, expr=I_s) - - -# Load the model -if not Path("ep_model.py").exists(): - ode = gotranx.load_ode(config["sim"]["modelfile"]) - - mechanics_comp = ode.get_component("mechanics") - mechanics_ode = mechanics_comp.to_ode() - - ep_ode = ode - mechanics_comp - - # Generate code for the electrophysiology model - code_ep = gotranx.cli.gotran2py.get_code( - ep_ode, - scheme=[gotranx.schemes.Scheme.forward_generalized_rush_larsen], - missing_values=mechanics_ode.missing_variables, - ) - # Generate code for the mechanics model - code_mechanics = gotranx.cli.gotran2py.get_code( - mechanics_ode, - scheme=[gotranx.schemes.Scheme.forward_generalized_rush_larsen], - missing_values=ep_ode.missing_variables, - ) - - Path("ep_model.py").write_text(code_ep) - # Currently 3D mech needs to be written manually - -import ep_model as _ep_model - -ep_model = _ep_model.__dict__ - - -# Validate ep variables to output -for i in list(set(out_ep_coord_names) | set(out_ep_var_names)): - try: - var = ep_model["state_index"](i) - except KeyError: - print(f"{i} is not an ep state. Check config file") - raise - -# Forwared generalized rush larsen scheme for the electrophysiology model -fgr_ep = jit(nopython=True)(ep_model["forward_generalized_rush_larsen"]) -# Monitor function for the electrophysiology model -mon_ep = ep_model["monitor_values"] -# Missing values function for the electrophysiology model -mv_ep = ep_model["missing_values"] -lmbda_index_ep = ep_model["parameter_index"]("lmbda") - - -# Get initial values from the EP model -y_ep_ = ep_model["init_state_values"]() -p_ep_ = ep_model["init_parameter_values"](i_Stim_Amplitude=0.0) - - -# ep_mesh = dolfin.adapt(dolfin.adapt(dolfin.adapt(mesh))) -ep_mesh = mesh - -time = dolfin.Constant(0.0) -I_s = define_stimulus( - mesh=ep_mesh, - chi=chi, - C_m=C_m, - time=time, - stim_region=stim_region, - stim_start=config["stim"]["start"], - A=config["stim"]["amplitude"], - duration=config["stim"]["duration"], -) -M = define_conductivity_tensor(sigma, chi, C_m) -params = {"preconditioner": "sor", "use_custom_preconditioner": False} -ep_ode_space = dolfin.FunctionSpace(ep_mesh, "DG", 1) -v_ode = dolfin.Function(ep_ode_space) -num_points_ep = v_ode.vector().local_size() -lmbda = dolfin.Function(ep_ode_space) - - -y_ep = np.zeros((len(y_ep_), num_points_ep)) -y_ep.T[:] = y_ep_ # Set to y_ep with initial values defined in ep_model - - -# mechanics_missing_values_ = np.zeros(1) -mechanics_missing_values_ = np.array([0.0001]) - - -# Set the activation -activation_space = dolfin.FunctionSpace(mesh, "DG", 1) -activation = dolfin.Function(activation_space) -num_points_mech = activation.vector().local_size() - -missing_mech = interpolation.MissingValue( - element=activation.ufl_element(), - interpolation_element=ep_ode_space.ufl_element(), - mechanics_mesh=mesh, - ep_mesh=ep_mesh, - num_values=len(mechanics_missing_values_), -) - -missing_mech.values_ep.T[:] = mechanics_missing_values_ -missing_mech.values_mechanics.T[:] = mechanics_missing_values_ -missing_mech.mechanics_values_to_function() # Assign initial values to mech functions - - -# Use previous Catrpn in mech to be consistent with zeta split -prev_missing_mech = interpolation.MissingValue( - element=activation.ufl_element(), - interpolation_element=ep_ode_space.ufl_element(), - mechanics_mesh=mesh, - ep_mesh=ep_mesh, - num_values=len(mechanics_missing_values_), -) -for i in range(len(mechanics_missing_values_)): - prev_missing_mech.u_mechanics[i].vector().set_local(missing_mech.values_mechanics[i]) - - -# Create function spaces for ep variables to output -out_ep_funcs = {} -for out_ep_var in list(set(out_ep_var_names) | set(out_ep_coord_names)): - out_ep_funcs[out_ep_var] = dolfin.Function(ep_ode_space) - -p_ep = np.zeros((len(p_ep_), num_points_ep)) -p_ep.T[:] = p_ep_ # Initialise p_ep with initial values defined in ep_model - -pde = beat.MonodomainModel(time=time, mesh=ep_mesh, M=M, I_s=I_s, params=params) -ode = beat.odesolver.DolfinODESolver( - v_ode=dolfin.Function(ep_ode_space), - v_pde=pde.state, - fun=fgr_ep, - parameters=p_ep, - init_states=y_ep, - num_states=len(y_ep), - v_index=ep_model["state_index"]("v"), - missing_variables=None, - num_missing_variables=0, -) - -# ep_solver = beat.MonodomainSplittingSolver(pde=pde, ode=ode, theta=0.5) -ep_solver = beat.MonodomainSplittingSolver(pde=pde, ode=ode, theta=1) # Test - -marker_functions = pulse.MarkerFunctions(ffun=ffun_bcs) - - -def create_boundary_conditions( - ffun_bcs, bcs_dirichlet, bcs_neumann, bcs_dict, bcs_expressions -): # TODO: update to not need separate dirichlet and neumann list - def dirichlet_bc(W): - bcs_W = { - "u_x": W.sub(0).sub(0), - "u_y": W.sub(0).sub(1), - "u_z": W.sub(0).sub(2), - # TODO: add the rest (check dolfin doc) - } - - bcs = [] - for bc in bcs_dirichlet: - bcs.append( - dolfin.DirichletBC( - bcs_W[bcs_dict[f"{bc}"]["V"]], - bcs_expressions[f"{bc}"], # TODO: use dolfin expression - ffun_bcs, - bcs_dict[f"{bc}"]["marker"], - ) - ) - return bcs - - neumann_bc = [] - if bcs_neumann is not None: - for bc in bcs_neumann: - neumann_bc.append( - pulse.NeumannBC( - traction=utils.float_to_constant(bcs_expressions[f"{bc}"]), - marker=bcs_dict[f"{bc}"]["marker"], - ) - ) - - # Collect Boundary Conditions - bcs = pulse.BoundaryConditions(dirichlet=(dirichlet_bc,), neumann=neumann_bc) - return bcs - - -f0 = dolfin.as_vector([1.0, 0.0, 0.0]) -s0 = dolfin.as_vector([0.0, 1.0, 0.0]) -n0 = dolfin.as_vector([0.0, 0.0, 1.0]) -microstructure = pulse.Microstructure(f0=f0, s0=s0, n0=n0) -geometry = pulse.Geometry( - mesh=mesh, marker_functions=marker_functions, microstructure=microstructure -) - -active_model = LandModel( - f0=f0, - s0=s0, - n0=n0, - # CaTrpn=missing_mech.u_mechanics[0], - CaTrpn=prev_missing_mech.u_mechanics[ - 0 - ], # Use prev Catrpn in mech to be consistent with zeta split - mesh=mesh, - eta=0, # Fraction of transverse active tension for active stress formulation. - # 0 = active only along fiber, 1 = equal forces in all directions - # (default=0.0). - dLambda_tol=1e-12, -) -active_model.t = 0.0 - - -mech_variables = { - "Ta": active_model.Ta_current, - "Zetas": active_model._Zetas, - "Zetaw": active_model._Zetaw, - "lambda": active_model.lmbda, - "XS": active_model._XS, - "XW": active_model._XW, - "TmB": active_model._TmB, -} - -# Validate mechanics variables to output -for out_mech_var in list(set(out_mech_coord_names) | set(out_mech_var_names)): - assert ( - out_mech_var in mech_variables - ), f"Error: '{out_mech_var}' is not a valid variable name. Check config file" - -material = pulse.HolzapfelOgden( - parameters=material_parameters, - active_model=active_model, - f0=f0, - s0=s0, - n0=n0, -) - - -def compute_function_average_over_mesh(func, mesh): - volume = dolfin.assemble(dolfin.Constant(1.0) * dolfin.dx(domain=mesh)) - return dolfin.assemble(func * dolfin.dx(domain=mesh)) / volume - - -# Collect Boundary Conditions -bcs = create_boundary_conditions( - ffun_bcs, bcs_dirichlet, bcs_neumann, config["bcs"], bcs_expressions -) - -problem = mechanicssolver.MechanicsProblem(geometry, material, bcs) -print("problem set up") -problem.solve(0.0, 0.0) - -disp_file = Path(outdir / "disp.xdmf") -disp_file.unlink(missing_ok=True) -disp_file.with_suffix(".h5").unlink(missing_ok=True) - -out_ep_files = {} -for out_ep_var in out_ep_var_names: - out_ep_files[out_ep_var] = Path(outdir / f"{out_ep_var}_out_ep.xdmf") - out_ep_files[out_ep_var].unlink(missing_ok=True) - out_ep_files[out_ep_var].with_suffix(".h5").unlink(missing_ok=True) - -out_mech_files = {} -for out_mech_var in out_mech_var_names: - out_mech_files[out_mech_var] = Path(outdir / f"{out_mech_var}_out_mech.xdmf") - out_mech_files[out_mech_var].unlink(missing_ok=True) - out_mech_files[out_mech_var].with_suffix(".h5").unlink(missing_ok=True) - - -# Create arrays for storing values to plot time series for example nodes -out_ep_example_nodes = {} -for out_ep_var in out_ep_coord_names: - out_ep_example_nodes[out_ep_var] = np.zeros(len(t)) - -out_mech_example_nodes = {} -for out_mech_var in out_mech_coord_names: - out_mech_example_nodes[out_mech_var] = np.zeros(len(t)) - -# Create arrays for storing values to plot time series for volume averages -out_ep_volume_average_timeseries = {} -for out_ep_var in out_ep_coord_names: - out_ep_volume_average_timeseries[out_ep_var] = np.zeros(len(t)) - -out_mech_volume_average_timeseries = {} -for out_mech_var in out_mech_coord_names: - out_mech_volume_average_timeseries[out_mech_var] = np.zeros(len(t)) - - -inds = [] # Array with time-steps for which we solve mechanics -j = 0 -total_timer = dolfin.Timer("total") -timings_solveloop = [] -timings_ep_steps = [] -timings_mech_steps = [] -no_of_newton_iterations = [] -timings_var_transfer = [] -for i, ti in enumerate(t): - timing_single_loop = dolfin.Timer("single_loop") - print(f"Solving time {ti:.2f} ms") - t_bcs.assign(ti) # Use ti+ dt here instead? - - timing_ep = dolfin.Timer("ep time") - ep_solver.step((ti, ti + config["sim"]["dt"])) - timing_ep.stop() - timings_ep_steps.append(timing_ep.elapsed()[0]) - - # Assign values to ep function - for out_ep_var in list(set(out_ep_var_names) | set(out_ep_coord_names)): - out_ep_funcs[out_ep_var].vector()[:] = ode._values[ep_model["state_index"](out_ep_var)] - - # Store values to plot time series for given coord - for var_nr in range(config["write_point_ep"]["numbers"]): - # Trace variable in coordinate - out_ep_var = config["write_point_ep"][f"{var_nr}"]["name"] - out_ep_example_nodes[out_ep_var][i] = out_ep_funcs[out_ep_var](ep_coords[var_nr]) - # Compute volume averages - out_ep_volume_average_timeseries[out_ep_var][i] = compute_function_average_over_mesh( - out_ep_funcs[out_ep_var], ep_mesh - ) - - if i % config["sim"]["N"] != 0: - timing_single_loop.stop() - timings_solveloop.append(timing_single_loop.elapsed()[0]) - continue - - timing_var_transfer = dolfin.Timer("mv and lambda transfer time") - # Extract missing values for the mechanics step from the ep model (ep function space) - missing_ep_values = mv_ep(ti + config["sim"]["dt"], ode._values, ode.parameters) - # Assign the extracted values as missing_mech for the mech step (ep function space) - for k in range(missing_mech.num_values): - missing_mech.u_ep_int[k].vector()[:] = missing_ep_values[k, :] - - # Interpolate missing variables from ep to mech function space - missing_mech.interpolate_ep_to_mechanics() - missing_mech.mechanics_function_to_values() - inds.append(i) - timing_var_transfer.stop() - - print("Solve mechanics") - timing_mech = dolfin.Timer("mech time") - active_model.t = ti + config["sim"]["N"] * config["sim"]["dt"] # Addition! - nit, conv = problem.solve(ti, config["sim"]["N"] * config["sim"]["dt"]) - no_of_newton_iterations.append(nit) - print(f"No of iterations: {nit}") - active_model.update_prev() - lmbda.interpolate(active_model.lmbda) - timing_mech.stop() - timings_mech_steps.append(timing_mech.elapsed()[0]) - - timing_var_transfer.start() - p_ep[lmbda_index_ep, :] = lmbda.vector().get_local() # p_ep are the ep parameters - timing_var_transfer.stop() - - if write_disp: - U, p = problem.state.split(deepcopy=True) - - for var_nr in range(config["write_point_mech"]["numbers"]): - # Trace variable in coordinate - out_mech_var = config["write_point_mech"][f"{var_nr}"]["name"] - - out_mech_example_nodes[out_mech_var][i] = mech_variables[out_mech_var](mech_coords[var_nr]) - - # Compute volume averages - out_mech_volume_average_timeseries[out_mech_var][i] = compute_function_average_over_mesh( - mech_variables[out_mech_var], mesh - ) - - timing_var_transfer.start() - # Use previous Catrpn in mech to be consistent with zeta split - for i in range(len(mechanics_missing_values_)): - prev_missing_mech.u_mechanics[i].vector().set_local(missing_mech.values_mechanics[i]) - timing_var_transfer.stop() - timings_var_transfer.append(timing_var_transfer.elapsed()[0]) - - if write_disp: - with dolfin.XDMFFile(disp_file.as_posix()) as file: - file.write_checkpoint(U, "disp", j, dolfin.XDMFFile.Encoding.HDF5, True) - for out_ep_var in out_ep_var_names: - with dolfin.XDMFFile(out_ep_files[out_ep_var].as_posix()) as file: - file.write_checkpoint( - out_ep_funcs[out_ep_var], - out_ep_var, - j, - dolfin.XDMFFile.Encoding.HDF5, - True, - ) - for out_mech_var in out_mech_var_names: - with dolfin.XDMFFile(out_mech_files[out_mech_var].as_posix()) as file: - file.write_checkpoint( - mech_variables[out_mech_var], - out_mech_var, - j, - dolfin.XDMFFile.Encoding.HDF5, - True, - ) - - j += 1 - - timing_single_loop.stop() - timings_solveloop.append(timing_single_loop.elapsed()[0]) - -total_timer.stop() -timings = dolfin.timings( - dolfin.TimingClear.keep, - [dolfin.TimingType.wall, dolfin.TimingType.user, dolfin.TimingType.system], -).str(True) -print(timings) -with open(Path(outdir / "solve_timings.txt"), "w") as f: - f.write("Loop total times\n") - np.savetxt(f, timings_solveloop) - f.write("Ep steps times\n") - np.savetxt(f, timings_ep_steps) - f.write("Mech steps times\n") - np.savetxt(f, timings_mech_steps) - f.write("No of mech iterations\n") - np.savetxt(f, no_of_newton_iterations, fmt="%s") - f.write("mv and lambda transfer time\n") - np.savetxt(f, timings_var_transfer) - f.write("Total time\n") - f.write(f"{total_timer.elapsed()[0]}\n") - f.write(timings) - -# Write averaged results for later analysis -for out_ep_var in out_ep_coord_names: - with open(Path(outdir / f"{out_ep_var}_out_ep_volume_average.txt"), "w") as f: - np.savetxt(f, out_ep_volume_average_timeseries[out_ep_var][inds]) - -for out_mech_var in out_mech_coord_names: - with open(Path(outdir / f"{out_mech_var}_out_mech_volume_average.txt"), "w") as f: - np.savetxt(f, out_mech_volume_average_timeseries[out_mech_var][inds]) - -# Write point traces for later analysis -for var_nr in range(config["write_point_ep"]["numbers"]): - out_ep_var = config["write_point_ep"][f"{var_nr}"]["name"] - with open( - Path( - outdir - / f"{out_ep_var}_ep_coord{ep_coords[var_nr][0]},{ep_coords[var_nr][1]},{ep_coords[var_nr][2]}.txt".replace( - " ", "" - ) - ), - "w", - ) as f: - np.savetxt(f, out_ep_example_nodes[out_ep_var][inds]) - -for var_nr in range(config["write_point_mech"]["numbers"]): - out_mech_var = config["write_point_mech"][f"{var_nr}"]["name"] - with open( - Path( - outdir - / f"{out_mech_var}_mech_coord{mech_coords[var_nr][0]},{mech_coords[var_nr][1]},{mech_coords[var_nr][2]}.txt" - ), - "w", - ) as f: - np.savetxt(f, out_mech_example_nodes[out_mech_var][inds]) - -print(f"Solved on {100 * len(inds) / len(t)}% of the time steps") -inds = np.array(inds) - -if plot_results: - fig, ax = plt.subplots(len(out_ep_coord_names), 1, figsize=(10, 10)) - if len(out_ep_coord_names) == 1: - ax = np.array([ax]) - for i, out_ep_var in enumerate(out_ep_coord_names): - ax[i].plot(t[inds], out_ep_volume_average_timeseries[out_ep_var][inds]) - ax[i].set_title(f"{out_ep_var} volume average") - ax[i].set_xlabel("Time (ms)") - fig.tight_layout() - fig.savefig(Path(outdir / "out_ep_volume_averages.png")) - - fig, ax = plt.subplots(len(out_ep_coord_names), 1, figsize=(10, 10)) - if len(out_ep_coord_names) == 1: - ax = np.array([ax]) - for var_nr in range(config["write_point_ep"]["numbers"]): - out_ep_var = config["write_point_ep"][f"{var_nr}"]["name"] - ax[var_nr].plot(t[inds], out_ep_example_nodes[out_ep_var][inds]) - ax[var_nr].set_title(f"{out_ep_var} in coord {ep_coords[var_nr]}") - ax[var_nr].set_xlabel("Time (ms)") - fig.tight_layout() - fig.savefig(Path(outdir / "out_ep_coord.png")) - - fig, ax = plt.subplots(len(out_mech_coord_names), 1, figsize=(10, 10)) - if len(out_mech_coord_names) == 1: - ax = np.array([ax]) - for i, out_mech_var in enumerate(out_mech_coord_names): - ax[i].plot(t[inds], out_mech_volume_average_timeseries[out_mech_var][inds]) - ax[i].set_title(f"{out_mech_var} volume average") - ax[i].set_xlabel("Time (ms)") - fig.tight_layout() - fig.savefig(Path(outdir / "out_mech_volume_averages.png")) - - fig, ax = plt.subplots(len(out_mech_coord_names), 1, figsize=(10, 10)) - if len(out_mech_coord_names) == 1: - ax = np.array([ax]) - - for var_nr in range(config["write_point_mech"]["numbers"]): - out_mech_var = config["write_point_mech"][f"{var_nr}"]["name"] - ax[var_nr].plot(t[inds], out_mech_example_nodes[out_mech_var][inds]) - ax[var_nr].set_title(f"{out_mech_var} in coord {mech_coords[var_nr]}") - ax[var_nr].set_xlabel("Time (ms)") - fig.tight_layout() - fig.savefig(Path(outdir / "out_mech_coord.png")) diff --git a/demos/split-zeta/0D/ORdmm_Land.ode b/demos/split-zeta/0D/ORdmm_Land.ode deleted file mode 100644 index dc53677..0000000 --- a/demos/split-zeta/0D/ORdmm_Land.ode +++ /dev/null @@ -1,669 +0,0 @@ -# ORd modified by MMora (October-2016) -# Modifications in INa. The original formulation of INa has been -# optimised, according to Passini, in order to look like TT04. -# Modifications: -# 1) mss,hss,jss and hssp -# 2) gNa -# + -# Re-scaled conductances (Dutta et al 2016 CinC) -# + -# -# Land 2017(mechanical model)- Introduced by MMora (Jan2020) -# Tension -# Changes in Cai effect of troponin -# + -# -# Isacs -# -# -# In this version we fix mech.emcoupling=1, -# mode="intact", isacs=0 and celltype = 0 -# -# -# Modifications by Ilse (January 2023) -# Add scaling facotrs for heart failure and drugs - - -parameters("Scales", -scale_IKr = 1.119, -scale_IKs = 1.648, -scale_IK1 = 1.414, -scale_ICaL = 1.018, -scale_INaL = 2.274) - - - -parameters("settings", -celltype=0) - -parameters("extracellular ionic concentrations", -nao=140.0, -cao=1.8, -ko=5.4) - -parameters("physical constants", "mechanics", -R=8314.0, -T=310.0, -F=96485.0) - - -parameters("cell geometry", "mechanics", -L=0.01, -rad=0.0011) - - -expressions("cell geometry", "mechanics") -vcell=1000*3.14*rad*rad*L -Ageo=2*3.14*rad*rad+2*3.14*rad*L -Acap=2*Ageo -vmyo=0.68*vcell -vnsr=0.0552*vcell -vjsr=0.0048*vcell -vss=0.02*vcell - - -# Scaling factors for heart failure -parameters("scaling factors HF", -scale_HF_CaMKa=1.0, -scale_HF_Jrel_inf=1.0, -scale_HF_Jleak=1.0, -scale_HF_Jup=1.0, -scale_HF_GNaL=1.0, -scale_HF_GK1=1.0, -scale_HF_thL=1.0, -scale_HF_Gto=1.0, -scale_HF_Gncx=1.0, -scale_HF_Pnak=1.0) - -# Scaling factors for drug effects -parameters("scaling factors drug", -scale_drug_INa=1.0, -scale_drug_INaL=1.0, -scale_drug_Ito=1.0, -scale_drug_ICaL=1.0, -scale_drug_IKr=1.0, -scale_drug_IKs=1.0, -scale_drug_IK1=1.0, -scale_drug_IKb=1.0, -scale_drug_INab=1.0, -scale_drug_ICab=1.0, -scale_drug_IpCa=1.0, -scale_drug_Isacns=1.0, -scale_drug_Isack=1.0) - -######## EP states -states("CaMKt", -CaMKt=0 -) - -states("I_Na", -m=0, -hf=1, -hs=1, -j=1, -hsp=1, -jp=1) - -states("INaL", -mL=0, -hL=1, -hLp=1) - -states("Ito", -a=0, -iF=1, -iS=1, -ap=0, -iFp=1, -iSp=1) - -states("ICaL ICaNa ICaK", -d=0, -ff=1, -fs=1, -fcaf=1, -fcas=1, -jca=1, -nca=0, -ffp=1, -fcafp=1) - - -states("IKr", -xrf=0, -xrs=0) - - -states("IKs", -xs1=0, -xs2=0, -xk1=1) - -states("membrane potential", -v=-87) - - -states("ryanodione receptor", -Jrelnp=0, -Jrelp=0) - - -states("intracellular concentrations", -cai=0.0001, -nai=7, -nass=7, -ki=145, -kss=145, -cass=0.0001, -cansr=1.2, -cajsr=1.2) - -states("mechanics-ep", -XS=0.0001, -XW=0.0001, -CaTrpn=0.0001, -TmB=1) - - -states("mechanics", -Zetas=0, -Zetaw=0) - - - -############################## - -parameters("CaMK constants", -KmCaMK=0.15, -aCaMK=0.05, -bCaMK=0.00068, -CaMKo=0.05, -KmCaM=0.0015) - -expressions("CaMKt") -CaMKb=CaMKo*(1.0-CaMKt)/(1.0+KmCaM/cass) -CaMKa=(CaMKb+CaMKt)*scale_HF_CaMKa -dCaMKt_dt=aCaMK*CaMKb*(CaMKb+CaMKt)-bCaMK*CaMKt - -parameters("reversal potentials", -PKNa=0.01833) - -expressions("reversal potentials") -ENa=(R*T/F)*log(nao/nai) -EK=(R*T/F)*log(ko/ki) -EKs=(R*T/F)*log((ko+PKNa*nao)/(ki+PKNa*nai)) -vffrt=v*F*F/(R*T) -vfrt=v*F/(R*T) - -parameters("I_Na", -Ahf=0.99, -GNa=31) - -expressions("I_Na") -mss=1.0/(1.0+exp((-(v+39.57+9.4))/7.5)) -tm=1.0/(6.765*exp((v+11.64)/34.77)+8.552*exp(-(v+77.42)/5.955)) -dm_dt=(mss-m)/tm -hss=1.0/(1+exp((v+78.5)/6.22)) -thf=1.0/(1.432e-5*exp(-(v+1.196)/6.285)+6.149*exp((v+0.5096)/20.27)) -ths=1.0/(0.009794*exp(-(v+17.95)/28.05)+0.3343*exp((v+5.730)/56.66)) -Ahs=1.0-Ahf -dhf_dt=(hss-hf)/thf -dhs_dt=(hss-hs)/ths -h=Ahf*hf+Ahs*hs -jss=hss -tj=2.038+1.0/(0.02136*exp(-(v+100.6)/8.281)+0.3052*exp((v+0.9941)/38.45)) -dj_dt=(jss-j)/tj -hssp=1.0/(1+exp((v+78.5+6.2)/6.22)) -thsp=3.0*ths -dhsp_dt=(hssp-hsp)/thsp -hp=Ahf*hf+Ahs*hsp -tjp=1.46*tj -djp_dt=(jss-jp)/tjp -fINap=(1.0/(1.0+KmCaMK/CaMKa)) -INa=GNa*scale_drug_INa*(v-ENa)*m**3.0*((1.0-fINap)*h*j+fINap*hp*jp) - -parameters("INaL", -thL=200.0) - -expressions("INaL") -mLss=1.0/(1.0+exp((-(v+42.85))/5.264)) -tmL=tm -dmL_dt=(mLss-mL)/tmL -hLss=1.0/(1.0+exp((v+87.61)/7.488)) -dhL_dt=(hLss-hL)/(thL*scale_HF_thL) -hLssp=1.0/(1.0+exp((v+93.81)/7.488)) -thLp=3.0*thL*scale_HF_thL -dhLp_dt=(hLssp-hLp)/thLp -GNaL=0.0075*scale_INaL*scale_drug_INaL*scale_HF_GNaL -fINaLp=(1.0/(1.0+KmCaMK/CaMKa)) -INaL=GNaL*(v-ENa)*mL*((1.0-fINaLp)*hL+fINaLp*hLp) - -parameters("Ito", -delta_epi=1.0, -Gto=0.02) - -expressions("Ito") -ass=1.0/(1.0+exp((-(v-14.34))/14.82)) -ta=1.0515/(1.0/(1.2089*(1.0+exp(-(v-18.4099)/29.3814)))+3.5/(1.0+exp((v+100.0)/29.3814))) -da_dt=(ass-a)/ta -iss=1.0/(1.0+exp((v+43.94)/5.711)) -tiF=4.562+1/(0.3933*exp((-(v+100.0))/100.0)+0.08004*exp((v+50.0)/16.59)) * delta_epi -tiS=23.62+1/(0.001416*exp((-(v+96.52))/59.05)+1.780e-8*exp((v+114.1)/8.079)) * delta_epi -AiF=1.0/(1.0+exp((v-213.6)/151.2)) -AiS=1.0-AiF -diF_dt=(iss-iF)/tiF -diS_dt=(iss-iS)/tiS -i=AiF*iF+AiS*iS -assp=1.0/(1.0+exp((-(v-24.34))/14.82)) -dap_dt=(assp-ap)/ta -dti_develop=1.354+1.0e-4/(exp((v-167.4)/15.89)+exp(-(v-12.23)/0.2154)) -dti_recover=1.0-0.5/(1.0+exp((v+70.0)/20.0)) -tiFp=dti_develop*dti_recover*tiF -tiSp=dti_develop*dti_recover*tiS -diFp_dt=(iss-iFp)/tiFp -diSp_dt=(iss-iSp)/tiSp -ip=AiF*iFp+AiS*iSp -fItop=(1.0/(1.0+KmCaMK/CaMKa)) -Ito=Gto*scale_drug_Ito*scale_HF_Gto*(v-EK)*((1.0-fItop)*a*i+fItop*ap*ip) - - -parameters("ICaL ICaNa ICaK", -Aff=0.6, -tjca=75.0, -Kmn=0.002, -k2n=1000.0, -zca=2.0) - -expressions("ICaL ICaNa ICaK") -dss=1.0/(1.0+exp((-(v+3.940))/4.230)) -td=0.6+1.0/(exp(-0.05*(v+6.0))+exp(0.09*(v+14.0))) -dd_dt=(dss-d)/td -fss=1.0/(1.0+exp((v+19.58)/3.696)) -tff=7.0+1.0/(0.0045*exp(-(v+20.0)/10.0)+0.0045*exp((v+20.0)/10.0)) -tfs=1000.0+1.0/(0.000035*exp(-(v+5.0)/4.0)+0.000035*exp((v+5.0)/6.0)) -Afs=1.0-Aff -dff_dt=(fss-ff)/tff -dfs_dt=(fss-fs)/tfs -f=Aff*ff+Afs*fs -fcass=fss -tfcaf=7.0+1.0/(0.04*exp(-(v-4.0)/7.0)+0.04*exp((v-4.0)/7.0)) -tfcas=100.0+1.0/(0.00012*exp(-v/3.0)+0.00012*exp(v/7.0)) -Afcaf=0.3+0.6/(1.0+exp((v-10.0)/10.0)) -Afcas=1.0-Afcaf -dfcaf_dt=(fcass-fcaf)/tfcaf -dfcas_dt=(fcass-fcas)/tfcas -fca=Afcaf*fcaf+Afcas*fcas -djca_dt=(fcass-jca)/tjca -tffp=2.5*tff -dffp_dt=(fss-ffp)/tffp -fp=Aff*ffp+Afs*fs -tfcafp=2.5*tfcaf -dfcafp_dt=(fcass-fcafp)/tfcafp -fcap=Afcaf*fcafp+Afcas*fcas -km2n=jca*1.0 -anca=1.0/(k2n/km2n+(1.0+Kmn/cass)**4.0) -dnca_dt=anca*k2n-nca*km2n -PhiCaL=4.0*vffrt*(cass*exp(2.0*vfrt)-0.341*cao)/(exp(2.0*vfrt)-1.0) -PhiCaNa=1.0*vffrt*(0.75*nass*exp(1.0*vfrt)-0.75*nao)/(exp(1.0*vfrt)-1.0) -PhiCaK=1.0*vffrt*(0.75*kss*exp(1.0*vfrt)-0.75*ko)/(exp(1.0*vfrt)-1.0) -PCa=0.0001*scale_ICaL*scale_drug_ICaL -PCap=1.1*PCa -PCaNa=0.00125*PCa -PCaK=3.574e-4*PCa -PCaNap=0.00125*PCap -PCaKp=3.574e-4*PCap -fICaLp=(1.0/(1.0+KmCaMK/CaMKa)) -ICaL=(1.0-fICaLp)*PCa*PhiCaL*d*(f*(1.0-nca)+jca*fca*nca)+fICaLp*PCap*PhiCaL*d*(fp*(1.0-nca)+jca*fcap*nca) -ICaNa=(1.0-fICaLp)*PCaNa*PhiCaNa*d*(f*(1.0-nca)+jca*fca*nca)+fICaLp*PCaNap*PhiCaNa*d*(fp*(1.0-nca)+jca*fcap*nca) -ICaK=(1.0-fICaLp)*PCaK*PhiCaK*d*(f*(1.0-nca)+jca*fca*nca)+fICaLp*PCaKp*PhiCaK*d*(fp*(1.0-nca)+jca*fcap*nca) - -expressions("IKr") -xrss=1.0/(1.0+exp((-(v+8.337))/6.789)) -txrf=12.98+1.0/(0.3652*exp((v-31.66)/3.869)+4.123e-5*exp((-(v-47.78))/20.38)) -txrs=1.865+1.0/(0.06629*exp((v-34.70)/7.355)+1.128e-5*exp((-(v-29.74))/25.94)) -Axrf=1.0/(1.0+exp((v+54.81)/38.21)) -Axrs=1.0-Axrf -dxrf_dt=(xrss-xrf)/txrf -dxrs_dt=(xrss-xrs)/txrs -xr=Axrf*xrf+Axrs*xrs -rkr=1.0/(1.0+exp((v+55.0)/75.0))*1.0/(1.0+exp((v-10.0)/30.0)) -GKr=0.046*scale_IKr*scale_drug_IKr -IKr=GKr*sqrt(ko/5.4)*xr*rkr*(v-EK) - -expressions("IKs") -xs1ss=1.0/(1.0+exp((-(v+11.60))/8.932)) -txs1=817.3+1.0/(2.326e-4*exp((v+48.28)/17.80)+0.001292*exp((-(v+210.0))/230.0)) -dxs1_dt=(xs1ss-xs1)/txs1 -xs2ss=xs1ss -txs2=1.0/(0.01*exp((v-50.0)/20.0)+0.0193*exp((-(v+66.54))/31.0)) -dxs2_dt=(xs2ss-xs2)/txs2 -KsCa=1.0+0.6/(1.0+(3.8e-5/cai)**1.4) -GKs=0.0034*scale_IKs*scale_drug_IKs -IKs=GKs*KsCa*xs1*xs2*(v-EKs) -xk1ss=1.0/(1.0+exp(-(v+2.5538*ko+144.59)/(1.5692*ko+3.8115))) -txk1=122.2/(exp((-(v+127.2))/20.36)+exp((v+236.8)/69.33)) -dxk1_dt=(xk1ss-xk1)/txk1 -rk1=1.0/(1.0+exp((v+105.8-2.6*ko)/9.493)) -GK1=0.1908*scale_IK1*scale_drug_IK1*scale_HF_GK1 -IK1=GK1*sqrt(ko)*rk1*xk1*(v-EK) - - -parameters("INaCa_i", -kna1=15.0, -kna2=5.0, -kna3=88.12, -kasymm=12.5, -wna=6.0e4, -wca=6.0e4, -wnaca=5.0e3, -kcaon=1.5e6, -kcaoff=5.0e3, -qna=0.5224, -qca=0.1670, -KmCaAct=150.0e-6, -Gncx=0.0008) - -expressions("INaCa_i") -hca=exp((qca*v*F)/(R*T)) -hna=exp((qna*v*F)/(R*T)) -h1_i=1+nai/kna3*(1+hna) -h2_i=(nai*hna)/(kna3*h1_i) -h3_i=1.0/h1_i -h4_i=1.0+nai/kna1*(1+nai/kna2) -h5_i=nai*nai/(h4_i*kna1*kna2) -h6_i=1.0/h4_i -h7_i=1.0+nao/kna3*(1.0+1.0/hna) -h8_i=nao/(kna3*hna*h7_i) -h9_i=1.0/h7_i -h10_i=kasymm+1.0+nao/kna1*(1.0+nao/kna2) -h11_i=nao*nao/(h10_i*kna1*kna2) -h12_i=1.0/h10_i -k1_i=h12_i*cao*kcaon -k2_i=kcaoff -k3p_i=h9_i*wca -k3pp_i=h8_i*wnaca -k3_i=k3p_i+k3pp_i -k4p_i=h3_i*wca/hca -k4pp_i=h2_i*wnaca -k4_i=k4p_i+k4pp_i -k5_i=kcaoff -k6_i=h6_i*cai*kcaon -k7_i=h5_i*h2_i*wna -k8_i=h8_i*h11_i*wna -x1_i=k2_i*k4_i*(k7_i+k6_i)+k5_i*k7_i*(k2_i+k3_i) -x2_i=k1_i*k7_i*(k4_i+k5_i)+k4_i*k6_i*(k1_i+k8_i) -x3_i=k1_i*k3_i*(k7_i+k6_i)+k8_i*k6_i*(k2_i+k3_i) -x4_i=k2_i*k8_i*(k4_i+k5_i)+k3_i*k5_i*(k1_i+k8_i) -E1_i=x1_i/(x1_i+x2_i+x3_i+x4_i) -E2_i=x2_i/(x1_i+x2_i+x3_i+x4_i) -E3_i=x3_i/(x1_i+x2_i+x3_i+x4_i) -E4_i=x4_i/(x1_i+x2_i+x3_i+x4_i) -allo_i=1.0/(1.0+(KmCaAct/cai)**2.0) -zna=1.0 -JncxNa_i=3.0*(E4_i*k7_i-E1_i*k8_i)+E3_i*k4pp_i-E2_i*k3pp_i -JncxCa_i=E2_i*k2_i-E1_i*k1_i -INaCa_i=0.8*Gncx*scale_HF_Gncx*allo_i*(zna*JncxNa_i+zca*JncxCa_i) - -expressions("INaCa_ss") -h1=1+nass/kna3*(1+hna) -h2=(nass*hna)/(kna3*h1) -h3=1.0/h1 -h4=1.0+nass/kna1*(1+nass/kna2) -h5=nass*nass/(h4*kna1*kna2) -h6=1.0/h4 -h7=1.0+nao/kna3*(1.0+1.0/hna) -h8=nao/(kna3*hna*h7) -h9=1.0/h7 -h10=kasymm+1.0+nao/kna1*(1+nao/kna2) -h11=nao*nao/(h10*kna1*kna2) -h12=1.0/h10 -k1=h12*cao*kcaon -k2=kcaoff -k3p_ss=h9*wca -k3pp=h8*wnaca -k3=k3p_ss+k3pp -k4p_ss=h3*wca/hca -k4pp=h2*wnaca -k4=k4p_ss+k4pp -k5=kcaoff -k6=h6*cass*kcaon -k7=h5*h2*wna -k8=h8*h11*wna -x1_ss=k2*k4*(k7+k6)+k5*k7*(k2+k3) -x2_ss=k1*k7*(k4+k5)+k4*k6*(k1+k8) -x3_ss=k1*k3*(k7+k6)+k8*k6*(k2+k3) -x4_ss=k2*k8*(k4+k5)+k3*k5*(k1+k8) -E1_ss=x1_ss/(x1_ss+x2_ss+x3_ss+x4_ss) -E2_ss=x2_ss/(x1_ss+x2_ss+x3_ss+x4_ss) -E3_ss=x3_ss/(x1_ss+x2_ss+x3_ss+x4_ss) -E4_ss=x4_ss/(x1_ss+x2_ss+x3_ss+x4_ss) -allo_ss=1.0/(1.0+(KmCaAct/cass)**2.0) -JncxNa_ss=3.0*(E4_ss*k7-E1_ss*k8)+E3_ss*k4pp-E2_ss*k3pp -JncxCa_ss=E2_ss*k2-E1_ss*k1 -INaCa_ss=0.2*Gncx*scale_HF_Gncx*allo_ss*(zna*JncxNa_ss+zca*JncxCa_ss) - - -parameters("INaK", -k1p=949.5, -k1m=182.4, -k2p=687.2, -k2m=39.4, -k3p=1899.0, -k3m=79300.0, -k4p=639.0, -k4m=40.0, -Knai0=9.073, -Knao0=27.78, -delta=-0.1550, -Kki=0.5, -Kko=0.3582, -MgADP=0.05, -MgATP=9.8, -Kmgatp=1.698e-7, -H=1.0e-7, -eP=4.2, -Khp=1.698e-7, -Knap=224.0, -Kxkur=292.0, -zk=1.0, -Pnak=30) - -expressions("INaK") -Knai=Knai0*exp((delta*v*F)/(3.0*R*T)) -Knao=Knao0*exp(((1.0-delta)*v*F)/(3.0*R*T)) -P=eP/(1.0+H/Khp+nai/Knap+ki/Kxkur) -a1=(k1p*(nai/Knai)**3.0)/((1.0+nai/Knai)**3.0+(1.0+ki/Kki)**2.0-1.0) -b1=k1m*MgADP -a2=k2p -b2=(k2m*(nao/Knao)**3.0)/((1.0+nao/Knao)**3.0+(1.0+ko/Kko)**2.0-1.0) -a3=(k3p*(ko/Kko)**2.0)/((1.0+nao/Knao)**3.0+(1.0+ko/Kko)**2.0-1.0) -b3=(k3m*P*H)/(1.0+MgATP/Kmgatp) -a4=(k4p*MgATP/Kmgatp)/(1.0+MgATP/Kmgatp) -b4=(k4m*(ki/Kki)**2.0)/((1.0+nai/Knai)**3.0+(1.0+ki/Kki)**2.0-1.0) -x1=a4*a1*a2+b2*b4*b3+a2*b4*b3+b3*a1*a2 -x2=b2*b1*b4+a1*a2*a3+a3*b1*b4+a2*a3*b4 -x3=a2*a3*a4+b3*b2*b1+b2*b1*a4+a3*a4*b1 -x4=b4*b3*b2+a3*a4*a1+b2*a4*a1+b3*b2*a1 -E1=x1/(x1+x2+x3+x4) -E2=x2/(x1+x2+x3+x4) -E3=x3/(x1+x2+x3+x4) -E4=x4/(x1+x2+x3+x4) -JnakNa=3.0*(E1*a3-E2*b3) -JnakK=2.0*(E4*b1-E3*a1) -INaK=Pnak*scale_HF_Pnak*(zna*JnakNa+zk*JnakK) - - -parameters("IKb", -GKb=0.003) - -expressions("IKb") -xkb=1.0/(1.0+exp(-(v-14.48)/18.34)) -IKb=GKb*scale_drug_IKb*xkb*(v-EK) - -parameters("INab", -PNab=3.75e-10) - -expressions("INab") -INab=PNab*scale_drug_INab*vffrt*(nai*exp(vfrt)-nao)/(exp(vfrt)-1.0) - - -parameters("ICab", -PCab=2.5e-8) - -expressions("ICab") -ICab=PCab*scale_drug_ICab*4.0*vffrt*(cai*exp(2.0*vfrt)-0.341*cao)/(exp(2.0*vfrt)-1.0) - -parameters("IpCa", -GpCa=0.0005) - -expressions("IpCa") -IpCa=GpCa*scale_drug_IpCa*cai/(0.0005+cai) - - -parameters("Isac (Pueyo)--> ns + k", -Gsac_ns=0.006, -Esac_ns=-10, -lambda_max=1.1, -Gsac_k=0.2882*800/210) - -expressions("Isac (Pueyo)--> ns + k") -Isac_P_ns=0 -Isac_P_k=0 - - -parameters("Istim", -amp=-80.0, -duration=0.5) - -expressions("Istim") -Istim = Conditional(Le(t, duration), amp, 0) - -expressions("membrane potential") -dv_dt=-(INa+INaL+Ito+ICaL+ICaNa+ICaK+IKr+IKs+IK1+INaCa_i+INaCa_ss+INaK+INab+IKb+IpCa+ICab+Istim+Isac_P_ns+Isac_P_k) - -expressions("diffusion fluxes") -JdiffNa=(nass-nai)/2.0 -JdiffK=(kss-ki)/2.0 -Jdiff=(cass-cai)/0.2 - -parameters("ryanodione receptor", -bt=4.75) - -expressions("ryanodione receptor") -a_rel=0.5*bt -Jrel_inf=a_rel*(-ICaL)/(1.0+(1.5*scale_HF_Jrel_inf/cajsr)**8.0) -tau_rel_tmp=bt/(1.0+0.0123/cajsr) -tau_rel=Conditional(Lt(tau_rel_tmp, 0.001), 0.001, tau_rel_tmp) -dJrelnp_dt=(Jrel_inf-Jrelnp)/tau_rel -btp=1.25*bt -a_relp=0.5*btp -Jrel_infp=a_relp*(-ICaL)/(1.0+(1.5*scale_HF_Jrel_inf/cajsr)**8.0) -tau_relp_tmp=btp/(1.0+0.0123/cajsr) -tau_relp=Conditional(Lt(tau_relp_tmp, 0.001), 0.001, tau_relp_tmp) -dJrelp_dt=(Jrel_infp-Jrelp)/tau_relp -fJrelp=(1.0/(1.0+KmCaMK/CaMKa)) -Jrel=(1.0-fJrelp)*Jrelnp+fJrelp*Jrelp - -expressions("calcium buffers") -Jupnp=0.004375*cai/(cai+0.00092) -Jupp=2.75*0.004375*cai/(cai+0.00092-0.00017) -fJupp=(1.0/(1.0+KmCaMK/CaMKa)) -Jleak=0.0039375*cansr*scale_HF_Jleak/15.0 -Jup=(1.0-fJupp)*Jupnp+fJupp*Jupp*scale_HF_Jup-Jleak -Jtr=(cansr-cajsr)/100.0 - -parameters("calcium buffers", "mechanics", -cmdnmax=0.05, -kmcmdn=0.00238, -trpnmax=0.07, -kmtrpn=0.0005, -BSRmax=0.047, -KmBSR=0.00087, -BSLmax=1.124, -KmBSL=0.0087, -csqnmax=10.0, -kmcsqn=0.8) - -expressions("intracellular concentrations") -dnai_dt=-(INa+INaL+3.0*INaCa_i+3.0*INaK+INab+Isac_P_ns/3)*Acap/(F*vmyo)+JdiffNa*vss/vmyo -dnass_dt=-(ICaNa+3.0*INaCa_ss)*Acap/(F*vss)-JdiffNa -dki_dt=-(Ito+IKr+IKs+IK1+IKb+Isac_P_k+Isac_P_ns/3+Istim-2.0*INaK)*Acap/(F*vmyo)+JdiffK*vss/vmyo -dkss_dt=-(ICaK)*Acap/(F*vss)-JdiffK -Bcass=1.0/(1.0+BSRmax*KmBSR/(KmBSR+cass)**2.0+BSLmax*KmBSL/(KmBSL+cass)**2.0) -dcass_dt=Bcass*(-(ICaL-2.0*INaCa_ss)*Acap/(2.0*F*vss)+Jrel*vjsr/vss-Jdiff) -dcansr_dt=Jup-Jtr*vjsr/vnsr -Bcajsr=1.0/(1.0+csqnmax*kmcsqn/(kmcsqn+cajsr)**2.0) -dcajsr_dt=Bcajsr*(Jtr-Jrel) -Bcai=1.0/(1.0+cmdnmax*kmcmdn/(kmcmdn+cai)**2.0) -dcai_dt=Bcai*(-(IpCa+ICab-2.0*INaCa_i+Isac_P_ns/3)*Acap/(2.0*F*vmyo)-Jup*vnsr/vmyo+Jdiff*vss/vmyo - J_TRPN) - - -parameters("mechanics-ep", "mechanics", -emcoupling=1, -lmbda=1, -dLambda=0, -mode=1, -isacs=0, -calib=1, -ktrpn = 0.1, -ntrpn = 2, -Trpn50 = 0.35, -rw = 0.5, -rs = 0.25, -gammas = 0.0085, -gammaw = 0.615, -phi = 2.23, -Tot_A = 25, -Beta0 = 2.3, -Beta1 = -2.4, -cat50_ref = 0.805, -scale_HF_cat50_ref=1.0, -Tref = 120, -kuw = 0.182, -kws = 0.012, -ku=0.04, -ntm=2.4, -p_a = 2.1, -p_b = 9.1, -p_k = 7, -etal = 200, -etas = 20) - -expressions("mechanics-ep", "mechanics") -lambda_min12 = Conditional(Lt(lmbda, 1.2), lmbda, 1.2) - - -expressions("mechanics-ep") -XS_max = Conditional(Gt(XS, 0), XS, 0) -XW_max = Conditional(Gt(XW, 0), XW, 0) -CaTrpn_max = Conditional(Gt(CaTrpn, 0), CaTrpn, 0) -kwu = kuw*(1/rw-1)-kws -ksu = kws*rw*(1/rs-1) -Aw = Tot_A*rs/((1-rs)*rw+rs) -As = Aw -cw = phi*kuw*((1-rs)*(1-rw))/((1-rs)*rw) -cs = phi*kws*((1-rs)*rw)/rs -XU = (1-TmB)-XS-XW -gammawu = gammaw*abs(Zetaw) -gammasu = gammas*Conditional(Gt(Gt(Zetas,0)*Zetas, Lt(Zetas, -1)*(-Zetas-1)), Gt(Zetas,0)*Zetas, Lt(Zetas, -1)*(-Zetas-1)) -dXS_dt = kws*XW - ksu*XS - gammasu*XS -dXW_dt = kuw*XU - kwu*XW - kws*XW - gammawu*XW -cat50 = (cat50_ref+Beta1*(lambda_min12-1))*scale_HF_cat50_ref -dCaTrpn_dt = ktrpn*(((cai*1000/cat50)**ntrpn)*(1-CaTrpn)-CaTrpn) -kb = ku*Trpn50**ntm/(1-rs-(1-rs)*rw) -dTmB_dt = kb*Conditional(Lt(CaTrpn**(-ntm/2), 100), CaTrpn**(-ntm/2), 100)*XU-ku*CaTrpn**(ntm/2)*TmB -J_TRPN = dCaTrpn_dt*trpnmax - - - -expressions("mechanics") -Aw = Tot_A*rs/((1-rs)*rw+rs) -As = Aw -cw = phi*kuw*((1-rs)*(1-rw))/((1-rs)*rw) -cs = phi*kws*((1-rs)*rw)/rs -dZetas_dt = As*dLambda - cs*Zetas -dZetaw_dt = Aw*dLambda - cw*Zetaw -lambda_min087 = Conditional(Lt(lambda_min12, 0.87), lambda_min12, 0.87) -h_lambda_prima = 1+Beta0*(lambda_min12+lambda_min087-1.87) -h_lambda = Conditional(Gt(h_lambda_prima, 0), h_lambda_prima, 0) -Ta = h_lambda*(Tref/rs)*(XS*(Zetas+1) + XW*Zetaw) diff --git a/demos/split-zeta/0D/main.py b/demos/split-zeta/0D/main.py deleted file mode 100644 index 1990bcd..0000000 --- a/demos/split-zeta/0D/main.py +++ /dev/null @@ -1,488 +0,0 @@ -from pathlib import Path -import gotranx -import numpy as np -import matplotlib.pyplot as plt - - -def twitch(t, tstart=0.05, ca_ampl=-0.2): - tau1 = 0.05 * 1000 - tau2 = 0.110 * 1000 - - ca_diast = 0.0 - - beta = (tau1 / tau2) ** (-1 / (tau1 / tau2 - 1)) - (tau1 / tau2) ** (-1 / (1 - tau2 / tau1)) - ca = np.zeros_like(t) - - ca[t <= tstart] = ca_diast - - ca[t > tstart] = (ca_ampl - ca_diast) / beta * ( - np.exp(-(t[t > tstart] - tstart) / tau1) - np.exp(-(t[t > tstart] - tstart) / tau2) - ) + ca_diast - return ca + 1.0 - - -def update_lambda_and_dlambda(t, prev_lmbda, dt): - lmbda_ti = twitch(t) - p[lmbda_index] = lmbda_ti - p_mechanics[lmbda_index_mechanics] = lmbda_ti - p_ep[lmbda_index_ep] = lmbda_ti - - dLambda = (lmbda_ti - prev_lmbda) / dt - p[dLambda_index] = dLambda - p_mechanics[dLambda_index_mechanics] = dLambda - p_ep[dLambda_index_ep] = dLambda - prev_lmbda = lmbda_ti - return p, p_mechanics, p_ep, prev_lmbda - - -# Load the model -ode = gotranx.load_ode("ORdmm_Land.ode") - -mechanics_comp = ode.get_component("mechanics") -mechanics_ode = mechanics_comp.to_ode() - - -ep_ode = ode - mechanics_comp -ep_file = Path("ORdmm_Land_ep.py") - - -# Generate model code from .ode file -rebuild = False -if not ep_file.is_file() or rebuild: - # Generate code for full model. The full model output is plotted together with the splitting - code = gotranx.cli.gotran2py.get_code( - ode, - scheme=[gotranx.schemes.Scheme.forward_generalized_rush_larsen], - ) - - # Generate code for the electrophysiology model - code_ep = gotranx.cli.gotran2py.get_code( - ep_ode, - scheme=[gotranx.schemes.Scheme.forward_generalized_rush_larsen], - missing_values=mechanics_ode.missing_variables, - ) - - # Generate code for the mechanics model - code_mechanics = gotranx.cli.gotran2py.get_code( - mechanics_ode, - scheme=[gotranx.schemes.Scheme.forward_generalized_rush_larsen], - missing_values=ep_ode.missing_variables, - ) - - # Create ep, mechanics and full model to files: - ep_file.write_text(code_ep) - Path("ORdmm_Land_mechanics.py").write_text(code_mechanics) - Path("ORdmm_Land.py").write_text(code) - - -# Import ep, mechanics and full model -import ORdmm_Land_ep -import ORdmm_Land_mechanics -import ORdmm_Land - -model = ORdmm_Land.__dict__ -ep_model = ORdmm_Land_ep.__dict__ -mechanics_model = ORdmm_Land_mechanics.__dict__ - -# Set time step to 0.1 ms -dt = 0.1 # 05 -simdur = 700 # Simulation duration -t = np.arange(0, simdur, dt) - - -# Get the index of the membrane potential -V_index_ep = ep_model["state_index"]("v") -# Forwared generalized rush larsen scheme for the electrophysiology model -fgr_ep = ep_model["forward_generalized_rush_larsen"] -# Monitor function for the electrophysiology model -mon_ep = ep_model["monitor_values"] -# Missing values function for the electrophysiology model -mv_ep = ep_model["missing_values"] -# Index of the calcium concentration -Ca_index_ep = ep_model["state_index"]("cai") - - -CaTrpn_index_ep = ep_model["state_index"]("CaTrpn") -dLambda_index_ep = ep_model["parameter_index"]("dLambda") -lmbda_index_ep = ep_model["parameter_index"]("lmbda") - -# From split-cai 0D (not in zeta 3D): -# Forwared generalized rush larsen scheme for the mechanics model -fgr_mechanics = mechanics_model["forward_generalized_rush_larsen"] -# Monitor function for the mechanics model -mon_mechanics = mechanics_model["monitor_values"] -# Missing values function for the mechanics model -mv_mechanics = mechanics_model["missing_values"] - -Ta_index_mechanics = mechanics_model["monitor_index"]("Ta") -J_TRPN_index_ep = ep_model["monitor_index"]("J_TRPN") -XS_index_ep = ep_model["state_index"]("XS") -TmB_index_ep = ep_model["state_index"]("TmB") -XU_index_ep = ep_model["monitor_index"]("XU") - - -lmbda_index_mechanics = mechanics_model["parameter_index"]("lmbda") -Zetas_index_mechanics = mechanics_model["state_index"]("Zetas") -dLambda_index_mechanics = mechanics_model["parameter_index"]("dLambda") - - -# From split-cai 0D (not in zeta 3D): -# Forwared generalized rush larsen scheme for the full model -fgr = model["forward_generalized_rush_larsen"] -# Monitor function for the full model -mon = model["monitor_values"] -Ta_index = model["monitor_index"]("Ta") -J_TRPN_index = model["monitor_index"]("J_TRPN") -CaTrpn_index = model["state_index"]("CaTrpn") -TmB_index = model["state_index"]("TmB") -XU_index = model["monitor_index"]("XU") - -lmbda_index = model["parameter_index"]("lmbda") -dLambda_index = model["parameter_index"]("dLambda") -XS_index = model["state_index"]("XS") -Zetas_index = model["state_index"]("Zetas") - - -# Tolerances to test for when to perform steps in the mechanics model -tols = [ - 1e-15, - 5e-4, - 1e-3, - 2.5e-3, - 5e-3, - 7.5e-3, - 1e-2, - 2.5e-2, - 5e-2, -] - - -# Colors for the plots -from itertools import cycle - -colors = cycle(["r", "g", "b", "c", "m"]) -linestyles = cycle(["-", "--", "-.", ":"]) - -# Create arrays to store the results -V_ep = np.zeros(len(t)) -Ca_ep = np.zeros(len(t)) -CaTrpn_ep = np.zeros(len(t)) - -CaTrpn_full = np.zeros(len(t)) -J_TRPN_full = np.zeros(len(t)) -Ta_full = np.zeros(len(t)) -Zetas_full = np.zeros(len(t)) -XS_full = np.zeros(len(t)) -dLambda_full = np.zeros(len(t)) -TmB_full = np.zeros(len(t)) -XU_full = np.zeros(len(t)) - -Ta_mechanics = np.zeros(len(t)) -J_TRPN_ep = np.zeros(len(t)) -lmbda_mechanics = np.zeros(len(t)) -Zetas_mechanics = np.zeros(len(t)) -Zetaw_mechanics = np.zeros(len(t)) -dLambda_mechanics = np.zeros(len(t)) - -XS_ep = np.zeros(len(t)) -TmB_ep = np.zeros(len(t)) -XU_ep = np.zeros(len(t)) - - -fig, ax = plt.subplots(9, 2, sharex=True, figsize=(14, 10)) -lines = [] -labels = [] - - -for j, (col, ls, tol) in enumerate(zip(colors, linestyles, tols)): - # Get initial values from the EP model - y_ep = ep_model["init_state_values"]() - p_ep = ep_model["init_parameter_values"]() - ep_missing_values = np.repeat(0.0001, len(ep_ode.missing_variables)) - - # From split-cai 0D (not in zeta 3D): - # Get initial values from the mechanics model - y_mechanics = mechanics_model["init_state_values"]() - p_mechanics = mechanics_model["init_parameter_values"]() - mechanics_missing_values = np.repeat(0.0001, len(mechanics_ode.missing_variables)) - - # Get the initial values from the full model - y = model["init_state_values"]() - p = model["init_parameter_values"]() - - # TODO: figure out what the alternative is for this: - # The mechanics missing varables are XS and XW, which are states. Do the same as with cai? - # In the 3D case, they were also initialized to zero - mechanics_missing_values[:] = mv_ep(0, y_ep, p_ep, ep_missing_values) - ep_missing_values[:] = mv_mechanics(0, y_mechanics, p_mechanics, mechanics_missing_values) - - # We will store the previous missing values to check for convergence - prev_mechanics_missing_values = np.zeros_like(mechanics_missing_values) - prev_mechanics_missing_values[:] = mechanics_missing_values - - inds = [] - count = 1 - max_count = 10 - prev_lmbda = p[lmbda_index] - p, p_mechanics, p_ep, prev_lmbda = update_lambda_and_dlambda(np.float64(0), prev_lmbda, dt) - for i, ti in enumerate(t): - # Forward step for the full model - y[:] = fgr(y, ti, dt, p) - monitor = mon(ti, y, p) - J_TRPN_full[i] = monitor[J_TRPN_index] - Ta_full[i] = monitor[Ta_index] - XS_full[i] = y[XS_index] - Zetas_full[i] = y[Zetas_index] - dLambda_full[i] = p[dLambda_index] - CaTrpn_full[i] = y[CaTrpn_index] - TmB_full[i] = y[TmB_index] - XU_full[i] = monitor[XU_index] - - # Forward step for the EP model (from cai split) - y_ep[:] = fgr_ep(y_ep, ti, dt, p_ep, ep_missing_values) - V_ep[i] = y_ep[V_index_ep] - Ca_ep[i] = y_ep[Ca_index_ep] - CaTrpn_ep[i] = y_ep[CaTrpn_index_ep] - monitor_ep = mon_ep(ti, y_ep, p_ep, ep_missing_values) - TmB_ep[i] = y_ep[TmB_index_ep] - XU_ep[i] = monitor_ep[XU_index_ep] - J_TRPN_ep[i] = monitor_ep[J_TRPN_index_ep] - XS_ep[i] = y_ep[XS_index_ep] - - # Update missing values for the mechanics model - mechanics_missing_values[:] = mv_ep(t, y_ep, p_ep, ep_missing_values) - - # Compute the change in the missing values - change = np.linalg.norm( - mechanics_missing_values - prev_mechanics_missing_values - ) / np.linalg.norm(prev_mechanics_missing_values) - - # Check if the change is small enough to continue to the next time step - if change < tol: - count += 1 - # Very small change to just continue to next time step - if count < max_count: - p, p_mechanics, p_ep, prev_lmbda = update_lambda_and_dlambda( - ti + dt, prev_lmbda, dt - ) - continue - - # Store the index of the time step where we performed a step - inds.append(i) - - # Forward step for the mechanics model - # y_mechanics[:] = fgr_mechanics( - # y_mechanics, ti, count * dt, p_mechanics, mechanics_missing_values - # ) - y_mechanics[:] = fgr_mechanics( - y_mechanics, ti, count * dt, p_mechanics, prev_mechanics_missing_values - ) - count = 1 - monitor_mechanics = mon_mechanics( - ti, - y_mechanics, - p_mechanics, - mechanics_missing_values, - ) - - # lambda_min12 = monitor_mechanics[lambda_min12_index] - # print(lambda_min12) - - Ta_mechanics[i] = monitor_mechanics[Ta_index_mechanics] - Zetas_mechanics[i] = y_mechanics[Zetas_index_mechanics] - dLambda_mechanics[i] = p_mechanics[dLambda_index_mechanics] - lmbda_mechanics[i] = p_mechanics[lmbda_index_mechanics] - - p, p_mechanics, p_ep, prev_lmbda = update_lambda_and_dlambda(ti + dt, prev_lmbda, dt) - # Update missing values for the EP model - ep_missing_values[:] = mv_mechanics(t, y_mechanics, p_mechanics, mechanics_missing_values) - - prev_mechanics_missing_values[:] = mechanics_missing_values - - # Plot the results - perc = 100 * len(inds) / len(t) - print(f"Solved on {perc}% of the time steps") - inds = np.array(inds) - - if j == 0: - # Plot the full model with a dashed line only for the first run - (l,) = ax[8, 0].plot(t, Ta_full, color="k", linestyle="--", label="Full") - ax[2, 0].plot(t, J_TRPN_full, color="k", linestyle="--", label="Full") - ax[3, 0].plot(t, CaTrpn_full, color="k", linestyle="--", label="Full") - ax[4, 0].plot(t, TmB_full, color="k", linestyle="--", label="Full") - ax[5, 0].plot(t, XU_full, color="k", linestyle="--", label="Full") - ax[6, 0].plot(t, XS_full, color="k", linestyle="--", label="Full") - ax[7, 0].plot(t, Zetas_full, color="k", linestyle="--", label="Full") - - lines.append(l) - labels.append("Full") - - (l,) = ax[0, 0].plot(t, V_ep, color=col, linestyle=ls, label=f"tol={tol}") - lines.append(l) - labels.append(f"tol={tol}, perc={perc:.2f}%") - - ax[0, 1].plot( - t, - Ca_ep, - color=col, - linestyle=ls, - # label=f"tol={tol}", - ) - - ax[0, 0].set_ylabel("V (mV)") - ax[0, 1].set_ylabel("Ca (mM)") - - ax[1, 0].plot( - t[inds], - lmbda_mechanics[inds], - color=col, - linestyle=ls, # label=f"tol={tol}" - # marker='.' - ) - - ax[1, 1].plot( - t[inds], - dLambda_mechanics[inds], - color=col, - linestyle=ls, # label=f"tol={tol}" - ) - ax[1, 0].set_ylabel("Lambda mech") - ax[1, 1].set_ylabel("dLambda mech") - - err_Ta = np.linalg.norm(Ta_full[inds] - Ta_mechanics[inds]) / np.linalg.norm(Ta_mechanics) - err_J_TRPN = np.linalg.norm(J_TRPN_full[inds] - J_TRPN_ep[inds]) / np.linalg.norm(J_TRPN_ep) - ax[2, 0].plot( - t[inds], - J_TRPN_ep[inds], - color=col, - linestyle=ls, # label=f"tol={tol}" - ) - ax[2, 0].set_ylabel("J TRPN ") - - ax[2, 1].plot( - t[inds], - J_TRPN_full[inds] - J_TRPN_ep[inds], - # label=f"err={err_J_TRPN:.2e}, tol={tol}", - color=col, - linestyle=ls, - ) - ax[2, 1].set_ylabel("J TRPN ep \n error ") - - ax[3, 0].plot( - t[inds], - CaTrpn_ep[inds], - color=col, - linestyle=ls, # label=f"tol={tol}" - # marker='.' - ) - - ax[3, 1].plot( - t[inds], - CaTrpn_full[inds] - CaTrpn_ep[inds], - # label=f"err={err_J_TRPN:.2e}, tol={tol}", - color=col, - linestyle=ls, - # marker='.' - ) - ax[3, 0].set_ylabel("CaTrpn ep") - ax[3, 1].set_ylabel("CaTrpn ep \n error") - - ax[4, 0].plot( - t[inds], - TmB_ep[inds], - color=col, - linestyle=ls, # label=f"tol={tol}" - ) - ax[4, 0].set_ylabel("TmB ep") - - ax[4, 1].plot( - t[inds], - np.around(TmB_full[inds] - TmB_ep[inds], 16), # round to float precision - # label=f"err={err_J_TRPN:.2e}, tol={tol}", - color=col, - linestyle=ls, - ) - ax[4, 1].set_ylabel("TmB ep \n error") - - ax[5, 0].plot( - t[inds], - XU_ep[inds], - color=col, - linestyle=ls, # label=f"tol={tol}" - ) - ax[5, 1].plot( - t[inds], - np.around(XU_full[inds] - XU_ep[inds], 16), # round to float precision - # label=f"err={err_J_TRPN:.2e}, tol={tol}", - color=col, - linestyle=ls, - ) - ax[5, 0].set_ylabel("XU ep") - ax[5, 1].set_ylabel("XU ep \n error") - - ax[6, 0].set_ylabel("ep XS") - ax[6, 1].set_ylabel("XS ep \n error \n (missing)") - - ax[6, 0].plot( - t[inds], - XS_ep[inds], - color=col, - linestyle=ls, # label=f"tol={tol}" - ) - ax[6, 1].plot( - t[inds], - XS_full[inds] - XS_ep[inds], - # label=f"err={err_J_TRPN:.2e}, tol={tol}", - color=col, - linestyle=ls, - ) - - ax[7, 0].plot( - t[inds], - Zetas_mechanics[inds], - color=col, - linestyle=ls, # label=f"tol={tol}" - ) - - ax[7, 1].plot( - t[inds], - Zetas_full[inds] - Zetas_mechanics[inds], - # label=f"err={err_J_TRPN:.2e}, tol={tol}", - color=col, - linestyle=ls, - ) - ax[7, 0].set_ylabel("Zetas mech") - ax[7, 1].set_ylabel("Zetas \n mech error") - - ax[8, 0].plot( - t[inds], - Ta_mechanics[inds], - color=col, - linestyle=ls, # label=f"tol={tol}" - ) - ax[8, 0].set_ylabel("Ta (kPa)") - - ax[8, 1].plot( - t[inds], - Ta_full[inds] - Ta_mechanics[inds], - # label=f"tol={tol}, perc={perc}%", - color=col, - linestyle=ls, - ) - ax[8, 1].set_ylabel("Ta \n error (kPa)") - - ax[8, 0].set_xlabel("Time (ms)") - ax[8, 1].set_xlabel("Time (ms)") - - # for axi in ax.flatten(): - # axi.legend() - - # fig.tight_layout() - if j == len(tols) - 1: - fig.subplots_adjust(right=0.95) - lgd = fig.legend(lines, labels, loc="center left", bbox_to_anchor=(1.0, 0.5)) - fig.tight_layout() - fig.savefig("V_and_Ta.png", bbox_extra_artists=(lgd,), bbox_inches="tight") - else: - fig.tight_layout() - fig.savefig("V_and_Ta.png") diff --git a/demos/split-zeta/0D/main_time_and_Ns.py b/demos/split-zeta/0D/main_time_and_Ns.py deleted file mode 100644 index 1fe2a63..0000000 --- a/demos/split-zeta/0D/main_time_and_Ns.py +++ /dev/null @@ -1,339 +0,0 @@ -from pathlib import Path -import gotranx -import numpy as np -import time - -save_traces = False -run_full_model = False - - -def twitch(t, tstart=0.05, ca_ampl=-0.2): - tau1 = 0.05 * 1000 - tau2 = 0.110 * 1000 - - ca_diast = 0.0 - - beta = (tau1 / tau2) ** (-1 / (tau1 / tau2 - 1)) - (tau1 / tau2) ** (-1 / (1 - tau2 / tau1)) - ca = np.zeros_like(t) - - ca[t <= tstart] = ca_diast - - ca[t > tstart] = (ca_ampl - ca_diast) / beta * ( - np.exp(-(t[t > tstart] - tstart) / tau1) - np.exp(-(t[t > tstart] - tstart) / tau2) - ) + ca_diast - return ca + 1.0 - - -def update_lambda_and_dlambda(t, prev_lmbda, dt): - lmbda_ti = twitch(t) - p[lmbda_index] = lmbda_ti - p_mechanics[lmbda_index_mechanics] = lmbda_ti - p_ep[lmbda_index_ep] = lmbda_ti - - dLambda = (lmbda_ti - prev_lmbda) / dt - p[dLambda_index] = dLambda - p_mechanics[dLambda_index_mechanics] = dLambda - p_ep[dLambda_index_ep] = dLambda - prev_lmbda = lmbda_ti - return p, p_mechanics, p_ep, prev_lmbda - - -# Load the model -ode = gotranx.load_ode("ORdmm_Land.ode") - -mechanics_comp = ode.get_component("mechanics") -mechanics_ode = mechanics_comp.to_ode() - - -ep_ode = ode - mechanics_comp -ep_file = Path("ORdmm_Land_ep.py") - - -# Generate model code from .ode file -rebuild = False -if not ep_file.is_file() or rebuild: - # Generate code for full model. For comparison - code = gotranx.cli.gotran2py.get_code( - ode, - scheme=[gotranx.schemes.Scheme.forward_generalized_rush_larsen], - ) - - # Generate code for the electrophysiology model - code_ep = gotranx.cli.gotran2py.get_code( - ep_ode, - scheme=[gotranx.schemes.Scheme.forward_generalized_rush_larsen], - missing_values=mechanics_ode.missing_variables, - ) - - # Generate code for the mechanics model - code_mechanics = gotranx.cli.gotran2py.get_code( - mechanics_ode, - scheme=[gotranx.schemes.Scheme.forward_generalized_rush_larsen], - missing_values=ep_ode.missing_variables, - ) - - # Create ep, mechanics and full model to files: - ep_file.write_text(code_ep) - Path("ORdmm_Land_mechanics.py").write_text(code_mechanics) - Path("ORdmm_Land.py").write_text(code) - - -# Import ep, mechanics and full model -import ORdmm_Land_ep -import ORdmm_Land_mechanics -import ORdmm_Land - -model = ORdmm_Land.__dict__ -ep_model = ORdmm_Land_ep.__dict__ -mechanics_model = ORdmm_Land_mechanics.__dict__ - -# Set ep-time step to 0.05 ms -dt = 0.05 -simdur = 10 # Simulation duration -t = np.arange(0, simdur, dt) - - -with open("lmbda_function.txt", "w") as f: - np.savetxt(f, twitch(t)) - - -# Get the index of the membrane potential -V_index_ep = ep_model["state_index"]("v") -# Forwared generalized rush larsen scheme for the electrophysiology model -fgr_ep = ep_model["forward_generalized_rush_larsen"] -# Monitor function for the electrophysiology model -mon_ep = ep_model["monitor_values"] -# Missing values function for the electrophysiology model -mv_ep = ep_model["missing_values"] -# Index of the calcium concentration -Ca_index_ep = ep_model["state_index"]("cai") - - -CaTrpn_index_ep = ep_model["state_index"]("CaTrpn") -dLambda_index_ep = ep_model["parameter_index"]("dLambda") -lmbda_index_ep = ep_model["parameter_index"]("lmbda") - -# From split-cai 0D (not in zeta 3D): -# Forwared generalized rush larsen scheme for the mechanics model -fgr_mechanics = mechanics_model["forward_generalized_rush_larsen"] -# Monitor function for the mechanics model -mon_mechanics = mechanics_model["monitor_values"] -# Missing values function for the mechanics model -mv_mechanics = mechanics_model["missing_values"] - -Ta_index_mechanics = mechanics_model["monitor_index"]("Ta") -J_TRPN_index_ep = ep_model["monitor_index"]("J_TRPN") -XS_index_ep = ep_model["state_index"]("XS") -TmB_index_ep = ep_model["state_index"]("TmB") -XU_index_ep = ep_model["monitor_index"]("XU") - - -lmbda_index_mechanics = mechanics_model["parameter_index"]("lmbda") -Zetas_index_mechanics = mechanics_model["state_index"]("Zetas") -dLambda_index_mechanics = mechanics_model["parameter_index"]("dLambda") - - -# From split-cai 0D (not in zeta 3D): -# Forwared generalized rush larsen scheme for the full model -fgr = model["forward_generalized_rush_larsen"] -# Monitor function for the full model -mon = model["monitor_values"] -Ca_index = model["state_index"]("cai") -V_index = model["state_index"]("v") -Ta_index = model["monitor_index"]("Ta") -J_TRPN_index = model["monitor_index"]("J_TRPN") -CaTrpn_index = model["state_index"]("CaTrpn") -TmB_index = model["state_index"]("TmB") -XU_index = model["monitor_index"]("XU") - -lmbda_index = model["parameter_index"]("lmbda") -dLambda_index = model["parameter_index"]("dLambda") -XS_index = model["state_index"]("XS") -Zetas_index = model["state_index"]("Zetas") - - -Ns = np.array([1, 2, 4, 6, 8, 10, 20, 50, 100, 200]) - -# Create arrays to store the results -V_ep = np.zeros(len(t)) -Ca_ep = np.zeros(len(t)) -CaTrpn_ep = np.zeros(len(t)) - -if run_full_model: - Ca_full = np.zeros(len(t)) - V_full = np.zeros(len(t)) - CaTrpn_full = np.zeros(len(t)) - J_TRPN_full = np.zeros(len(t)) - Ta_full = np.zeros(len(t)) - Zetas_full = np.zeros(len(t)) - XS_full = np.zeros(len(t)) - dLambda_full = np.zeros(len(t)) - TmB_full = np.zeros(len(t)) - XU_full = np.zeros(len(t)) - -Ta_mechanics = np.zeros(len(t)) -J_TRPN_ep = np.zeros(len(t)) -lmbda_mechanics = np.zeros(len(t)) -Zetas_mechanics = np.zeros(len(t)) -Zetaw_mechanics = np.zeros(len(t)) -dLambda_mechanics = np.zeros(len(t)) - -XS_ep = np.zeros(len(t)) -TmB_ep = np.zeros(len(t)) -XU_ep = np.zeros(len(t)) - - -for N in Ns: - timing_init = time.perf_counter() - # Get initial values from the EP model - y_ep = ep_model["init_state_values"]() - p_ep = ep_model["init_parameter_values"]() - ep_missing_values = np.repeat(0.0001, len(ep_ode.missing_variables)) - - # Get initial values from the mechanics model - y_mechanics = mechanics_model["init_state_values"]() - p_mechanics = mechanics_model["init_parameter_values"]() - mechanics_missing_values = np.repeat(0.0001, len(mechanics_ode.missing_variables)) - - # Get the initial values from the full model - y = model["init_state_values"]() - p = model["init_parameter_values"]() # Used in lambda update - - mechanics_missing_values[:] = mv_ep(0, y_ep, p_ep, ep_missing_values) - ep_missing_values[:] = mv_mechanics(0, y_mechanics, p_mechanics, mechanics_missing_values) - - # We will store the previous missing values to check for convergence - prev_mechanics_missing_values = np.zeros_like(mechanics_missing_values) - prev_mechanics_missing_values[:] = mechanics_missing_values - - inds = [] - count = 1 - max_count = 10 - prev_lmbda = p[lmbda_index] - p, p_mechanics, p_ep, prev_lmbda = update_lambda_and_dlambda(np.float64(0), prev_lmbda, dt) - - timings_solveloop = [] - timings_ep_steps = [] - timings_mech_steps = [] - for i, ti in enumerate(t): - timing_loopstart = time.perf_counter() - - if run_full_model: - # Forward step for the full model - y[:] = fgr(y, ti, dt, p) - monitor = mon(ti, y, p) - V_full[i] = y[V_index] - Ca_full[i] = y[Ca_index] - J_TRPN_full[i] = monitor[J_TRPN_index] - Ta_full[i] = monitor[Ta_index] - XS_full[i] = y[XS_index] - Zetas_full[i] = y[Zetas_index] - dLambda_full[i] = p[dLambda_index] - CaTrpn_full[i] = y[CaTrpn_index] - TmB_full[i] = y[TmB_index] - XU_full[i] = monitor[XU_index] - - # Forward step for the EP model (from cai split) - timing_ep_start = time.perf_counter() - y_ep[:] = fgr_ep(y_ep, ti, dt, p_ep, ep_missing_values) - V_ep[i] = y_ep[V_index_ep] - Ca_ep[i] = y_ep[Ca_index_ep] - CaTrpn_ep[i] = y_ep[CaTrpn_index_ep] - monitor_ep = mon_ep(ti, y_ep, p_ep, ep_missing_values) - TmB_ep[i] = y_ep[TmB_index_ep] - XU_ep[i] = monitor_ep[XU_index_ep] - J_TRPN_ep[i] = monitor_ep[J_TRPN_index_ep] - XS_ep[i] = y_ep[XS_index_ep] - - timing_ep_end = time.perf_counter() - timings_ep_steps.append(timing_ep_end - timing_ep_start) - - # Update missing values for the mechanics model - mechanics_missing_values[:] = mv_ep(t, y_ep, p_ep, ep_missing_values) - - if i % N != 0: - count += 1 - p, p_mechanics, p_ep, prev_lmbda = update_lambda_and_dlambda(ti + dt, prev_lmbda, dt) - timings_solveloop.append(time.perf_counter() - timing_loopstart) - continue - - # Store the index of the time step where we performed a step - inds.append(i) - - timing_mech_start = time.perf_counter() - y_mechanics[:] = fgr_mechanics( - y_mechanics, ti, count * dt, p_mechanics, prev_mechanics_missing_values - ) - - count = 1 - monitor_mechanics = mon_mechanics( - ti, - y_mechanics, - p_mechanics, - mechanics_missing_values, - ) - - Ta_mechanics[i] = monitor_mechanics[Ta_index_mechanics] - Zetas_mechanics[i] = y_mechanics[Zetas_index_mechanics] - dLambda_mechanics[i] = p_mechanics[dLambda_index_mechanics] - lmbda_mechanics[i] = p_mechanics[lmbda_index_mechanics] - - timing_mech_end = time.perf_counter() - timings_mech_steps.append(timing_mech_end - timing_mech_start) - - p, p_mechanics, p_ep, prev_lmbda = update_lambda_and_dlambda(ti + dt, prev_lmbda, dt) - # Update missing values for the EP model - ep_missing_values[:] = mv_mechanics(t, y_mechanics, p_mechanics, mechanics_missing_values) - - prev_mechanics_missing_values[:] = mechanics_missing_values - - timings_solveloop.append(time.perf_counter() - timing_loopstart) - - timing_total = time.perf_counter() - timing_init - perc = 100 * len(inds) / len(t) - print(f"Solved on {perc}% of the time steps") - inds = np.array(inds) - - with open(f"timings_N{N}", "w") as f: - f.write("Init time\n") - f.write(f"{timing_init}\n") - f.write("Loop total times\n") - np.savetxt(f, timings_solveloop) - f.write("Ep steps times\n") - np.savetxt(f, timings_ep_steps) - f.write("Mech steps times\n") - np.savetxt(f, timings_mech_steps) - f.write("Total time\n") - f.write(f"{timing_total}\n") - - if save_traces: - with open(f"V_ep_N{N}.txt", "w") as f: - np.savetxt(f, V_ep[inds]) - with open(f"Ta_mech_N{N}.txt", "w") as f: - np.savetxt(f, Ta_mechanics[inds]) - with open(f"Ca_ep_N{N}.txt", "w") as f: - np.savetxt(f, Ca_ep[inds]) - with open(f"CaTrpn_ep_N{N}.txt", "w") as f: - np.savetxt(f, CaTrpn_ep[inds]) - with open(f"J_TRPN_ep_N{N}.txt", "w") as f: - np.savetxt(f, J_TRPN_ep[inds]) - with open(f"XS_ep_N{N}.txt", "w") as f: - np.savetxt(f, XS_ep[inds]) - with open(f"Zetas_mech_N{N}.txt", "w") as f: - np.savetxt(f, Zetas_mechanics[inds]) - - if run_full_model: - with open("V_full.txt", "w") as f: - np.savetxt(f, V_full) - with open("Ta_full.txt", "w") as f: - np.savetxt(f, Ta_full) - with open("Ca_full.txt", "w") as f: - np.savetxt(f, Ca_full) - with open("CaTrpn_full.txt", "w") as f: - np.savetxt(f, CaTrpn_full) - with open("J_TRPN_full.txt", "w") as f: - np.savetxt(f, J_TRPN_full) - with open("XS_full.txt", "w") as f: - np.savetxt(f, XS_full) - with open("Zetas_full.txt", "w") as f: - np.savetxt(f, Zetas_full) diff --git a/demos/split-zeta/0D_ToRORd/ToRORd_dynCl_endo_zetasplit.ode b/demos/split-zeta/0D_ToRORd/ToRORd_dynCl_endo_zetasplit.ode deleted file mode 100644 index 11e38f0..0000000 --- a/demos/split-zeta/0D_ToRORd/ToRORd_dynCl_endo_zetasplit.ode +++ /dev/null @@ -1,722 +0,0 @@ -states("IKr", -C1=ScalarParam(0.9982511, unit="1", description=""), -C2=ScalarParam( 7.93602000000000023e-4, unit="1", description=""), -C3=ScalarParam( 6.53214300000000045e-4, unit="1", description=""), -I_=ScalarParam( 9.80408300000000003e-6, unit="1", description=""), -O_=ScalarParam( 2.92244900000000025e-4, unit="1", description="") -) - -states("CaMK", -CaMKt=ScalarParam( 1.09502599999999999e-2, unit="mM", description="") -) - -states("ryr", -Jrel_np=ScalarParam( 1.80824799999999996e-22, unit="mM/ms", description=""), -Jrel_p=ScalarParam( 4.35860800000000030e-21, unit="mM/ms", description="") -) - -states("Ito", -a=ScalarParam( 8.89925900000000051e-4, unit="1", description=""), -ap=ScalarParam( 4.53416500000000005e-4, unit="1", description=""), -iF=ScalarParam(0.9996716, unit="1", description=""), -iFp=ScalarParam(0.9996716, unit="1", description=""), -iS=ScalarParam(0.5988908, unit="1", description=""), -iSp=ScalarParam(0.6620692, unit="1", description="") -) - -states("intracellular_ions", -cajsr=ScalarParam(1.525693, unit="mM", description=""), -cansr=ScalarParam(1.528001, unit="mM", description=""), -cass=ScalarParam( 6.49734100000000044e-5, unit="mM", description=""), -cli=ScalarParam(29.20698, unit="mM", description=""), -clss=ScalarParam(29.20696, unit="mM", description=""), -ki=ScalarParam(147.7115, unit="mM", description=""), -kss=ScalarParam(147.7114, unit="mM", description=""), -nai=ScalarParam(12.39736, unit="mM", description=""), -nass=ScalarParam(12.3977, unit="mM", description="") -) - -states("ICaL", -d=ScalarParam( 1.58884100000000000e-31, unit="1", description=""), -fcaf=ScalarParam(1, unit="1", description=""), -fcafp=ScalarParam(1, unit="1", description=""), -fcas=ScalarParam(0.9999014, unit="1", description=""), -ff_=ScalarParam(1, unit="1", description=""), -ffp=ScalarParam(1, unit="1", description=""), -fs=ScalarParam(0.9401791, unit="1", description=""), -jca=ScalarParam(0.9999846, unit="1", description=""), -nca_i=ScalarParam( 8.32600900000000053e-4, unit="1", description=""), -nca_ss=ScalarParam( 4.89937800000000024e-4, unit="1", description="") -) - -states("INa", -h=ScalarParam(0.8473267, unit="1", description=""), -hp=ScalarParam(0.7018454, unit="1", description=""), -j=ScalarParam(0.8471657, unit="1", description=""), -jp=ScalarParam(0.8469014, unit="1", description=""), -m=ScalarParam( 6.51715400000000005e-4, unit="1", description="") -) - -states("INaL", -hL=ScalarParam(0.5566017, unit="1", description=""), -hLp=ScalarParam(0.3115491, unit="1", description=""), -mL=ScalarParam( 1.35120299999999988e-4, unit="1", description="") -) - -states("membrane", -v=ScalarParam(-89.74808, unit="mV", description="") -) - -states("IKs", -xs1=ScalarParam(0.243959, unit="1", description=""), -xs2=ScalarParam( 1.58616700000000009e-4, unit="1", description="") -) - -parameters("I_katp", -A_atp=ScalarParam(2.0, unit="mM", description=""), -K_atp=ScalarParam(0.25, unit="mM", description=""), -K_o_n=ScalarParam(5.0, unit="mM", description=""), -fkatp=ScalarParam(0.0, unit="1", description=""), -gkatp=ScalarParam(4.3195, unit="mS/uF", description="") -) - -parameters("ICaL", -Aff=ScalarParam(0.6, unit="1", description=""), -ICaL_fractionSS=ScalarParam(0.8, unit="1", description=""), -Kmn=ScalarParam(0.002, unit="mM", description=""), -PCa_b=ScalarParam(8.3757e-05, unit="1", description=""), -dielConstant=ScalarParam(74.0, unit="1/K", description=""), -k2n=ScalarParam(500.0, unit="mS/uF", description=""), -offset=ScalarParam(0.0, unit="ms", description=""), -tjca=ScalarParam(72.5, unit="ms", description=""), -vShift=ScalarParam(0.0, unit="mV", description="") -) - -parameters("intracellular_ions","mechanics", -BSLmax=ScalarParam(1.124, unit="mM", description=""), -BSRmax=ScalarParam(0.047, unit="mM", description=""), -KmBSL=ScalarParam(0.0087, unit="mM", description=""), -KmBSR=ScalarParam(0.00087, unit="mM", description=""), -cmdnmax_b=ScalarParam(0.05, unit="mM", description=""), -csqnmax=ScalarParam(10.0, unit="mM", description=""), -kmcmdn=ScalarParam(0.00238, unit="mM", description=""), -kmcsqn=ScalarParam(0.8, unit="mM", description=""), -kmtrpn=ScalarParam(0.0005, unit="mM", description=""), -trpnmax=ScalarParam(0.07, unit="mM", description="") -) - -parameters("CaMK", -CaMKo=ScalarParam(0.05, unit="1", description=""), -KmCaM=ScalarParam(0.0015, unit="mM", description=""), -KmCaMK=ScalarParam(0.15, unit="mM", description=""), -aCaMK=ScalarParam(0.05, unit="1/mM/ms", description=""), -bCaMK=ScalarParam(0.00068, unit="mS/uF", description="") -) - -parameters("Ito", -EKshift=ScalarParam(0.0, unit="mV", description=""), -Gto_b=ScalarParam(0.16, unit="mS/uF", description="") -) - -parameters("physical_constants","mechanics", -F=ScalarParam(96485.0, unit="C/mol", description=""), -R=ScalarParam(8314.0, unit="mJ/mol/K", description=""), -T=ScalarParam(310.0, unit="K", description=""), -zca=ScalarParam(2.0, unit="1", description=""), -zcl=ScalarParam(-1.0, unit="1", description=""), -zk=ScalarParam(1.0, unit="1", description=""), -zna=ScalarParam(1.0, unit="1", description="") -) - -parameters("ICl", -Fjunc=ScalarParam(1.0, unit="1", description=""), -GClCa=ScalarParam(0.2843, unit="mS/uF", description=""), -GClb=ScalarParam(0.00198, unit="mS/uF", description=""), -KdClCa=ScalarParam(0.1, unit="mM", description="") -) - -parameters("IK1", -GK1_b=ScalarParam(0.6992, unit="mS/uF", description="") -) - -parameters("IKb", -GKb_b=ScalarParam(0.0189, unit="mS/uF", description="") -) - -parameters("IKr", -GKr_b=ScalarParam(0.0321, unit="mS/uF", description=""), -alpha_1=ScalarParam(0.154375, unit="mS/uF", description=""), -beta_1=ScalarParam(0.1911, unit="mS/uF", description="") -) - -parameters("IKs", -GKs_b=ScalarParam(0.0011, unit="mS/uF", description="") -) - -parameters("INa", -GNa=ScalarParam(11.7802, unit="mS/uF", description="") -) - -parameters("INaL", -GNaL_b=ScalarParam(0.0279, unit="mS/uF", description=""), -thL=ScalarParam(200.0, unit="ms", description="") -) - -parameters("INaCa", -Gncx_b=ScalarParam(0.0034, unit="mS/uF", description=""), -INaCa_fractionSS=ScalarParam(0.35, unit="1", description=""), -KmCaAct=ScalarParam(0.00015, unit="mM", description=""), -kasymm=ScalarParam(12.5, unit="1", description=""), -kcaoff=ScalarParam(5000.0, unit="mS/uF", description=""), -kcaon=ScalarParam(1500000.0, unit="mS/uF", description=""), -kna1=ScalarParam(15.0, unit="mS/uF", description=""), -kna2=ScalarParam(5.0, unit="mS/uF", description=""), -kna3=ScalarParam(88.12, unit="mS/uF", description=""), -qca=ScalarParam(0.167, unit="1", description=""), -qna=ScalarParam(0.5224, unit="1", description=""), -wca=ScalarParam(60000.0, unit="1", description=""), -wna=ScalarParam(60000.0, unit="1", description=""), -wnaca=ScalarParam(5000.0, unit="1", description="") -) - -parameters("IpCa", -GpCa=ScalarParam(0.0005, unit="mS/uF", description=""), -KmCap=ScalarParam(0.0005, unit="mM", description="") -) - -parameters("INaK", -H=ScalarParam(1e-07, unit="mM", description=""), -Khp=ScalarParam(1.698e-07, unit="mM", description=""), -Kki=ScalarParam(0.5, unit="mS/uF", description=""), -Kko=ScalarParam(0.3582, unit="mS/uF", description=""), -Kmgatp=ScalarParam(1.698e-07, unit="mM", description=""), -Knai0=ScalarParam(9.073, unit="mM", description=""), -Knao0=ScalarParam(27.78, unit="mM", description=""), -Knap=ScalarParam(224.0, unit="mM", description=""), -Kxkur=ScalarParam(292.0, unit="mM", description=""), -MgADP=ScalarParam(0.05, unit="mM", description=""), -MgATP=ScalarParam(9.8, unit="mM", description=""), -Pnak_b=ScalarParam(15.4509, unit="mS/uF", description=""), -delta=ScalarParam(-0.155, unit="mV", description=""), -eP=ScalarParam(4.2, unit="1", description=""), -k1m=ScalarParam(182.4, unit="mS/uF", description=""), -k1p=ScalarParam(949.5, unit="mS/uF", description=""), -k2m=ScalarParam(39.4, unit="mS/uF", description=""), -k2p=ScalarParam(687.2, unit="mS/uF", description=""), -k3m=ScalarParam(79300.0, unit="mS/uF", description=""), -k3p=ScalarParam(1899.0, unit="mS/uF", description=""), -k4m=ScalarParam(40.0, unit="mS/uF", description=""), -k4p=ScalarParam(639.0, unit="mS/uF", description="") -) - -parameters("ryr", -Jrel_b=ScalarParam(1.5378, unit="1", description=""), -bt=ScalarParam(4.75, unit="ms", description=""), -cajsr_half=ScalarParam(1.7, unit="mM", description="") -) - -parameters("SERCA", -Jup_b=ScalarParam(1.0, unit="1", description="") -) - -parameters("cell_geometry","mechanics", -L=ScalarParam(0.01, unit="cm", description=""), -rad_=ScalarParam(0.0011, unit="cm", description="") -) - -parameters("ICab", -PCab=ScalarParam(5.9194e-08, unit="mS/uF", description="") -) - -parameters("reversal_potentials", -PKNa=ScalarParam(0.01833, unit="1", description="") -) - -parameters("INab", -PNab=ScalarParam(1.9239e-09, unit="mS/uF", description="") -) - -parameters("extracellular", -cao=ScalarParam(1.8, unit="mM", description=""), -clo=ScalarParam(150.0, unit="mM", description=""), -ko=ScalarParam(5.0, unit="mM", description=""), -nao=ScalarParam(140.0, unit="mM", description="") -) - -parameters("environment", -celltype=ScalarParam(0.0, unit="1", description="") -) - -parameters("membrane", -i_Stim_Amplitude=ScalarParam(-53.0, unit="A/F", description=""), -i_Stim_End=ScalarParam(1e+17, unit="ms", description=""), -i_Stim_Period=ScalarParam(1000.0, unit="ms", description=""), -i_Stim_PulseDuration=ScalarParam(1.0, unit="ms", description=""), -i_Stim_Start=ScalarParam(0.0, unit="ms", description="") -) - -parameters("diff", -tauCa=ScalarParam(0.2, unit="ms", description=""), -tauCl=ScalarParam(2.0, unit="ms", description=""), -tauK=ScalarParam(2.0, unit="ms", description=""), -tauNa=ScalarParam(2.0, unit="ms", description="") -) - -expressions("cell_geometry", "mechanics") -Acap = 2.0*Ageo # cm**2 -Ageo = L*((2.0*3.14)*rad_) + rad_*((2.0*3.14)*rad_) # cm**2 -vcell = L*(rad_*((1000.0*3.14)*rad_)) # uL -vjsr = 0.0048*vcell # uL -vmyo = 0.68*vcell # uL -vnsr = 0.0552*vcell # uL -vss = 0.02*vcell # uL - -expressions("ICaL") -Afcaf = 0.3 + 0.6/(exp((v - 1*10.0)/10.0) + 1.0) -Afcas = 1.0 - Afcaf -Afs = 1.0 - Aff -ICaK = ICaK_i + ICaK_ss # A/F -ICaK_i = (1.0 - ICaL_fractionSS)*((d*(PhiCaK_i*(PCaK*(1.0 - fICaLp))))*(f*(1.0 - nca_i) + nca_i*(fca*jca)) + (d*(PhiCaK_i*(PCaKp*fICaLp)))*(fp*(1.0 - nca_i) + nca_i*(fcap*jca))) # A/F -ICaK_ss = ICaL_fractionSS*((d*(PhiCaK_ss*(PCaK*(1.0 - fICaLp))))*(f*(1.0 - nca_ss) + nca_ss*(fca*jca)) + (d*(PhiCaK_ss*(PCaKp*fICaLp)))*(fp*(1.0 - nca_ss) + nca_ss*(fcap*jca))) # A/F -ICaL_ICaL = ICaL_i + ICaL_ss # A/F -ICaL_i = (1.0 - ICaL_fractionSS)*((d*(PhiCaL_i*(PCa*(1.0 - fICaLp))))*(f*(1.0 - nca_i) + nca_i*(fca*jca)) + (d*(PhiCaL_i*(PCap*fICaLp)))*(fp*(1.0 - nca_i) + nca_i*(fcap*jca))) # A/F -ICaL_ss = ICaL_fractionSS*((d*(PhiCaL_ss*(PCa*(1.0 - fICaLp))))*(f*(1.0 - nca_ss) + nca_ss*(fca*jca)) + (d*(PhiCaL_ss*(PCap*fICaLp)))*(fp*(1.0 - nca_ss) + nca_ss*(fcap*jca))) # A/F -ICaNa = ICaNa_i + ICaNa_ss # A/F -ICaNa_i = (1.0 - ICaL_fractionSS)*((d*(PhiCaNa_i*(PCaNa*(1.0 - fICaLp))))*(f*(1.0 - nca_i) + nca_i*(fca*jca)) + (d*(PhiCaNa_i*(PCaNap*fICaLp)))*(fp*(1.0 - nca_i) + nca_i*(fcap*jca))) # A/F -ICaNa_ss = ICaL_fractionSS*((d*(PhiCaNa_ss*(PCaNa*(1.0 - fICaLp))))*(f*(1.0 - nca_ss) + nca_ss*(fca*jca)) + (d*(PhiCaNa_ss*(PCaNap*fICaLp)))*(fp*(1.0 - nca_ss) + nca_ss*(fcap*jca))) # A/F -Ii = (0.5*(4.0*cai + (cli + (ki + nai))))/1000.0 -Io = (0.5*(4.0*cao + (clo + (ko + nao))))/1000.0 -Iss = (0.5*(4.0*cass + (clss + (kss + nass))))/1000.0 -PCa = Conditional(Eq(celltype, 1.0), 1.2*PCa_b, Conditional(Eq(celltype, 2.0), 2.0*PCa_b, PCa_b)) -PCaK = 0.0003574*PCa -PCaKp = 0.0003574*PCap -PCaNa = 0.00125*PCa -PCaNap = 0.00125*PCap -PCap = 1.1*PCa -PhiCaK_i = ((1.0*vffrt)*(-gamma_ko*ko + (gamma_ki*ki)*exp(1.0*vfrt)))/(exp(1.0*vfrt) - 1*1.0) -PhiCaK_ss = ((1.0*vffrt)*(-gamma_ko*ko + (gamma_kss*kss)*exp(1.0*vfrt)))/(exp(1.0*vfrt) - 1*1.0) -PhiCaL_i = ((4.0*vffrt)*(-cao*gamma_cao + (cai*gamma_cai)*exp(2.0*vfrt)))/(exp(2.0*vfrt) - 1*1.0) -PhiCaL_ss = ((4.0*vffrt)*(-cao*gamma_cao + (cass*gamma_cass)*exp(2.0*vfrt)))/(exp(2.0*vfrt) - 1*1.0) -PhiCaNa_i = ((1.0*vffrt)*(-gamma_nao*nao + (gamma_nai*nai)*exp(1.0*vfrt)))/(exp(1.0*vfrt) - 1*1.0) -PhiCaNa_ss = ((1.0*vffrt)*(-gamma_nao*nao + (gamma_nass*nass)*exp(1.0*vfrt)))/(exp(1.0*vfrt) - 1*1.0) -anca_i = 1.0/(k2n/km2n + (Kmn/cai + 1.0)**4.0) -anca_ss = 1.0/(k2n/km2n + (Kmn/cass + 1.0)**4.0) -constA = 1820000.0/(T*dielConstant)**1.5 -dss = Conditional(Ge(v, 31.4978), 1.0, 1.0763*exp(-1.007*exp(-0.0829*v))) -f = Aff*ff_ + Afs*fs -fICaLp = 1.0/(1.0 + KmCaMK/CaMKa) -fca = Afcaf*fcaf + Afcas*fcas -fcap = Afcaf*fcafp + Afcas*fcas -fcass = fss -fp = Aff*ffp + Afs*fs -fss = 1.0/(exp((v + 19.58)/3.696) + 1.0) -gamma_cai = exp((-constA*4.0)*(sqrt(Ii)/(sqrt(Ii) + 1.0) - 0.3*Ii)) -gamma_cao = exp((-constA*4.0)*(sqrt(Io)/(sqrt(Io) + 1.0) - 0.3*Io)) -gamma_cass = exp((-constA*4.0)*(sqrt(Iss)/(sqrt(Iss) + 1.0) - 0.3*Iss)) -gamma_ki = exp((-constA*1.0)*(sqrt(Ii)/(sqrt(Ii) + 1.0) - 0.3*Ii)) -gamma_ko = exp((-constA*1.0)*(sqrt(Io)/(sqrt(Io) + 1.0) - 0.3*Io)) -gamma_kss = exp((-constA*1.0)*(sqrt(Iss)/(sqrt(Iss) + 1.0) - 0.3*Iss)) -gamma_nai = exp((-constA*1.0)*(sqrt(Ii)/(sqrt(Ii) + 1.0) - 0.3*Ii)) -gamma_nao = exp((-constA*1.0)*(sqrt(Io)/(sqrt(Io) + 1.0) - 0.3*Io)) -gamma_nass = exp((-constA*1.0)*(sqrt(Iss)/(sqrt(Iss) + 1.0) - 0.3*Iss)) -jcass = 1.0/(exp((v + 18.08)/2.7916) + 1.0) -km2n = jca*1.0 # mS/uF -td = (offset + 0.6) + 1.0/(exp((-1*0.05)*((v + vShift) + 6.0)) + exp(0.09*((v + vShift) + 14.0))) # ms -tfcaf = 7.0 + 1.0/(0.04*exp((-(v - 1*4.0))/7.0) + 0.04*exp((v - 1*4.0)/7.0)) # ms -tfcafp = 2.5*tfcaf # ms -tfcas = 100.0 + 1.0/(0.00012*exp((-v)/3.0) + 0.00012*exp(v/7.0)) # ms -tff = 7.0 + 1.0/(0.0045*exp((-(v + 20.0))/10.0) + 0.0045*exp((v + 20.0)/10.0)) # ms -tffp = 2.5*tff # ms -tfs = 1000.0 + 1.0/(3.5e-5*exp((-(v + 5.0))/4.0) + 3.5e-5*exp((v + 5.0)/6.0)) # ms -dd_dt = (-d + dss)/td -dfcaf_dt = (-fcaf + fcass)/tfcaf -dfcafp_dt = (-fcafp + fcass)/tfcafp -dfcas_dt = (-fcas + fcass)/tfcas -dff__dt = (-ff_ + fss)/tff -dffp_dt = (-ffp + fss)/tffp -dfs_dt = (-fs + fss)/tfs -djca_dt = (-jca + jcass)/tjca -dnca_i_dt = anca_i*k2n - km2n*nca_i -dnca_ss_dt = anca_ss*k2n - km2n*nca_ss - -expressions("Ito") -AiF = 1.0/(exp(((EKshift + v) - 1*213.6)/151.2) + 1.0) -AiS = 1.0 - AiF -Gto = Conditional(Or(Eq(celltype, 1.0), Eq(celltype, 2.0)), 2.0*Gto_b, Gto_b) # mS/uF -Ito_Ito = (Gto*(-EK + v))*(i*(a*(1.0 - fItop)) + ip*(ap*fItop)) # A/F -ass = 1.0/(exp((-((EKshift + v) - 1*14.34))/14.82) + 1.0) -assp = 1.0/(exp((-((EKshift + v) - 1*24.34))/14.82) + 1.0) -delta_epi = Conditional(Eq(celltype, 1.0), 1.0 - 0.95/(exp(((EKshift + v) + 70.0)/5.0) + 1.0), 1.0) -dti_develop = 1.354 + 0.0001/(exp((-((EKshift + v) - 1*12.23))/0.2154) + exp(((EKshift + v) - 1*167.4)/15.89)) -dti_recover = 1.0 - 0.5/(exp(((EKshift + v) + 70.0)/20.0) + 1.0) -fItop = 1.0/(1.0 + KmCaMK/CaMKa) -i = AiF*iF + AiS*iS -ip = AiF*iFp + AiS*iSp -iss = 1.0/(exp(((EKshift + v) + 43.94)/5.711) + 1.0) -ta = 1.0515/(1.0/((1.2089*(exp((-((EKshift + v) - 1*18.4099))/29.3814) + 1.0))) + 3.5/(exp(((EKshift + v) + 100.0)/29.3814) + 1.0)) # ms -tiF = delta_epi*tiF_b # ms -tiF_b = 4.562 + 1.0/(0.3933*exp((-((EKshift + v) + 100.0))/100.0) + 0.08004*exp(((EKshift + v) + 50.0)/16.59)) # ms -tiFp = tiF*(dti_develop*dti_recover) # ms -tiS = delta_epi*tiS_b # ms -tiS_b = 23.62 + 1.0/(0.001416*exp((-((EKshift + v) + 96.52))/59.05) + 1.78e-8*exp(((EKshift + v) + 114.1)/8.079)) # ms -tiSp = tiS*(dti_develop*dti_recover) # ms -da_dt = (-a + ass)/ta -dap_dt = (-ap + assp)/ta -diF_dt = (-iF + iss)/tiF -diFp_dt = (-iFp + iss)/tiFp -diS_dt = (-iS + iss)/tiS -diSp_dt = (-iSp + iss)/tiSp - -expressions("intracellular_ions") -Bcajsr = 1.0/((csqnmax*kmcsqn)/((cajsr + kmcsqn)**2.0) + 1.0) -Bcass = 1.0/((BSLmax*KmBSL)/((KmBSL + cass)**2.0) + ((BSRmax*KmBSR)/((KmBSR + cass)**2.0) + 1.0)) -cmdnmax = Conditional(Eq(celltype, 1.0), 1.3*cmdnmax_b, cmdnmax_b) # mM -dcajsr_dt = Bcajsr*(-Jrel + Jtr) # mM -dcansr_dt = Jup - Jtr*vjsr/vnsr # mM -dcass_dt = Bcass*(-Jdiff + ((Acap*(-(ICaL_ss - 2.0*INaCa_ss)))/(((2.0*F)*vss)) + (Jrel*vjsr)/vss)) # mM -dcli_dt = (Acap*(IClCa_sl + IClb))/((F*vmyo)) + (JdiffCl*vss)/vmyo # mM -dclss_dt = -JdiffCl + (Acap*IClCa_junc)/((F*vss)) # mM -dki_dt = (Acap*(-(ICaK_i + (-2.0*INaK_INaK + (Istim + (I_katp_I_katp + (IKb_IKb + (IK1_IK1 + (IKs_IKs + (IKr_IKr + Ito_Ito))))))))))/((F*vmyo)) + (JdiffK*vss)/vmyo # mM -dkss_dt = -JdiffK + (Acap*(-ICaK_ss))/((F*vss)) # mM -dnai_dt = (Acap*(-(INab_INab + (3.0*INaK_INaK + (ICaNa_i + (3.0*INaCa_i + (INaL_INaL + INa_INa)))))))/((F*vmyo)) + (JdiffNa*vss)/vmyo # mM -dnass_dt = -JdiffNa + (Acap*(-(ICaNa_ss + 3.0*INaCa_ss)))/((F*vss)) # mM - -expressions("CaMK") -CaMKa = CaMKb + CaMKt # mM -CaMKb = (CaMKo*(1.0 - CaMKt))/(KmCaM/cass + 1.0) # mM -dCaMKt_dt = -CaMKt*bCaMK + (CaMKb*aCaMK)*(CaMKb + CaMKt) # mM - -expressions("INaK") -E1_ = x1/(x4 + (x3 + (x1 + x2))) -E2 = x2/(x4 + (x3 + (x1 + x2))) -E3 = x3/(x4 + (x3 + (x1 + x2))) -E4 = x4/(x4 + (x3 + (x1 + x2))) -INaK_INaK = Pnak*(JnakK*zk + JnakNa*zna) # A/F -JnakK = 2.0*(-E3*a1 + E4*b1) # mM/ms -JnakNa = 3.0*(E1_*a3 - E2*b3) # mM/ms -Knai = Knai0*exp((delta*vfrt)/3.0) # mM -Knao = Knao0*exp((vfrt*(1.0 - delta))/3.0) # mM -P = eP/(((H/Khp + 1.0) + nai/Knap) + ki/Kxkur) -Pnak = Conditional(Eq(celltype, 1.0), 0.9*Pnak_b, Conditional(Eq(celltype, 2.0), 0.7*Pnak_b, Pnak_b)) # mS/uF -a1 = (k1p*(nai/Knai)**3.0)/(((1.0 + ki/Kki)**2.0 + (1.0 + nai/Knai)**3.0) - 1*1.0) -a2 = k2p -a3 = (k3p*(ko/Kko)**2.0)/(((1.0 + ko/Kko)**2.0 + (1.0 + nao/Knao)**3.0) - 1*1.0) -a4 = ((MgATP*k4p)/Kmgatp)/(1.0 + MgATP/Kmgatp) -b1 = MgADP*k1m -b2 = (k2m*(nao/Knao)**3.0)/(((1.0 + ko/Kko)**2.0 + (1.0 + nao/Knao)**3.0) - 1*1.0) -b3 = (H*(P*k3m))/(1.0 + MgATP/Kmgatp) -b4 = (k4m*(ki/Kki)**2.0)/(((1.0 + ki/Kki)**2.0 + (1.0 + nai/Knai)**3.0) - 1*1.0) -x1 = a2*(a1*b3) + (b3*(a2*b4) + (a2*(a1*a4) + b3*(b2*b4))) -x2 = b4*(a2*a3) + (b4*(a3*b1) + (a3*(a1*a2) + b4*(b1*b2))) -x3 = b1*(a3*a4) + (a4*(b1*b2) + (a4*(a2*a3) + b1*(b2*b3))) -x4 = a1*(b2*b3) + (a1*(a4*b2) + (a1*(a3*a4) + b2*(b3*b4))) - -expressions("INaCa") -E1_i = x1_i/(x4_i + (x3_i + (x1_i + x2_i))) -E1_ss = x1_ss/(x4_ss + (x3_ss + (x1_ss + x2_ss))) -E2_i = x2_i/(x4_i + (x3_i + (x1_i + x2_i))) -E2_ss = x2_ss/(x4_ss + (x3_ss + (x1_ss + x2_ss))) -E3_i = x3_i/(x4_i + (x3_i + (x1_i + x2_i))) -E3_ss = x3_ss/(x4_ss + (x3_ss + (x1_ss + x2_ss))) -E4_i = x4_i/(x4_i + (x3_i + (x1_i + x2_i))) -E4_ss = x4_ss/(x4_ss + (x3_ss + (x1_ss + x2_ss))) -Gncx = Conditional(Eq(celltype, 1.0), 1.1*Gncx_b, Conditional(Eq(celltype, 2.0), 1.4*Gncx_b, Gncx_b)) # mS/uF -INaCa_i = (allo_i*(Gncx*(1.0 - INaCa_fractionSS)))*(JncxCa_i*zca + JncxNa_i*zna) # A/F -INaCa_ss = (allo_ss*(Gncx*INaCa_fractionSS))*(JncxCa_ss*zca + JncxNa_ss*zna) # A/F -JncxCa_i = -E1_i*k1_i + E2_i*k2_i # mM/ms -JncxCa_ss = -E1_ss*k1_ss + E2_ss*k2_ss # mM/ms -JncxNa_i = -E2_i*k3pp_i + (E3_i*k4pp_i + 3.0*(-E1_i*k8_i + E4_i*k7_i)) # mM/ms -JncxNa_ss = -E2_ss*k3pp_ss + (E3_ss*k4pp_ss + 3.0*(-E1_ss*k8_ss + E4_ss*k7_ss)) # mM/ms -allo_i = 1.0/((KmCaAct/cai)**2.0 + 1.0) -allo_ss = 1.0/((KmCaAct/cass)**2.0 + 1.0) -h10_i = (nao/kna1)*(1.0 + nao/kna2) + (kasymm + 1.0) -h10_ss = (nao/kna1)*(1.0 + nao/kna2) + (kasymm + 1.0) -h11_i = (nao*nao)/((kna2*(h10_i*kna1))) -h11_ss = (nao*nao)/((kna2*(h10_ss*kna1))) -h12_i = 1.0/h10_i -h12_ss = 1.0/h10_ss -h1_i = (nai/kna3)*(hna + 1.0) + 1.0 -h1_ss = (nass/kna3)*(hna + 1.0) + 1.0 -h2_i = (hna*nai)/((h1_i*kna3)) -h2_ss = (hna*nass)/((h1_ss*kna3)) -h3_i = 1.0/h1_i -h3_ss = 1.0/h1_ss -h4_i = (nai/kna1)*(1.0 + nai/kna2) + 1.0 -h4_ss = (nass/kna1)*(1.0 + nass/kna2) + 1.0 -h5_i = (nai*nai)/((kna2*(h4_i*kna1))) -h5_ss = (nass*nass)/((kna2*(h4_ss*kna1))) -h6_i = 1.0/h4_i -h6_ss = 1.0/h4_ss -h7_i = (nao/kna3)*(1.0 + 1.0/hna) + 1.0 -h7_ss = (nao/kna3)*(1.0 + 1.0/hna) + 1.0 -h8_i = nao/((h7_i*(hna*kna3))) -h8_ss = nao/((h7_ss*(hna*kna3))) -h9_i = 1.0/h7_i -h9_ss = 1.0/h7_ss -hca = exp(qca*vfrt) -hna = exp(qna*vfrt) -k1_i = kcaon*(cao*h12_i) -k1_ss = kcaon*(cao*h12_ss) -k2_i = kcaoff -k2_ss = kcaoff -k3_i = k3p_i + k3pp_i -k3_ss = k3p_ss + k3pp_ss -k3p_i = h9_i*wca -k3p_ss = h9_ss*wca -k3pp_i = h8_i*wnaca -k3pp_ss = h8_ss*wnaca -k4_i = k4p_i + k4pp_i -k4_ss = k4p_ss + k4pp_ss -k4p_i = (h3_i*wca)/hca -k4p_ss = (h3_ss*wca)/hca -k4pp_i = h2_i*wnaca -k4pp_ss = h2_ss*wnaca -k5_i = kcaoff -k5_ss = kcaoff -k6_i = kcaon*(cai*h6_i) -k6_ss = kcaon*(cass*h6_ss) -k7_i = wna*(h2_i*h5_i) -k7_ss = wna*(h2_ss*h5_ss) -k8_i = wna*(h11_i*h8_i) -k8_ss = wna*(h11_ss*h8_ss) -x1_i = (k2_i*k4_i)*(k6_i + k7_i) + (k5_i*k7_i)*(k2_i + k3_i) -x1_ss = (k2_ss*k4_ss)*(k6_ss + k7_ss) + (k5_ss*k7_ss)*(k2_ss + k3_ss) -x2_i = (k1_i*k7_i)*(k4_i + k5_i) + (k4_i*k6_i)*(k1_i + k8_i) -x2_ss = (k1_ss*k7_ss)*(k4_ss + k5_ss) + (k4_ss*k6_ss)*(k1_ss + k8_ss) -x3_i = (k1_i*k3_i)*(k6_i + k7_i) + (k6_i*k8_i)*(k2_i + k3_i) -x3_ss = (k1_ss*k3_ss)*(k6_ss + k7_ss) + (k6_ss*k8_ss)*(k2_ss + k3_ss) -x4_i = (k2_i*k8_i)*(k4_i + k5_i) + (k3_i*k5_i)*(k1_i + k8_i) -x4_ss = (k2_ss*k8_ss)*(k4_ss + k5_ss) + (k3_ss*k5_ss)*(k1_ss + k8_ss) - -expressions("reversal_potentials") -ECl = ((R*T)/((F*zcl)))*log(clo/cli) # mV -EClss = ((R*T)/((F*zcl)))*log(clo/clss) # mV -EK = ((R*T)/((F*zk)))*log(ko/ki) # mV -EKs = ((R*T)/((F*zk)))*log((PKNa*nao + ko)/(PKNa*nai + ki)) # mV -ENa = ((R*T)/((F*zna)))*log(nao/nai) # mV - -expressions("IK1") -GK1 = Conditional(Eq(celltype, 1.0), 1.2*GK1_b, Conditional(Eq(celltype, 2.0), 1.3*GK1_b, GK1_b)) # mS/uF -IK1_IK1 = (K1ss*(GK1*sqrt(ko/5.0)))*(-EK + v) # A/F -K1ss = aK1/(aK1 + bK1) -aK1 = 4.094/(exp(0.1217*((-EK + v) - 1*49.934)) + 1.0) -bK1 = (15.72*exp(0.0674*((-EK + v) - 1*3.257)) + exp(0.0618*((-EK + v) - 1*594.31)))/(exp((-1*0.1629)*((-EK + v) + 14.207)) + 1.0) - -expressions("IKb") -GKb = Conditional(Eq(celltype, 1.0), 0.6*GKb_b, GKb_b) # mS/uF -IKb_IKb = (GKb*xkb)*(-EK + v) # A/F -xkb = 1.0/(exp((-(v - 1*10.8968))/23.9871) + 1.0) - -expressions("IKr") -GKr = Conditional(Eq(celltype, 1.0), 1.3*GKr_b, Conditional(Eq(celltype, 2.0), 0.8*GKr_b, GKr_b)) # mS/uF -IKr_IKr = (O_*(GKr*sqrt(ko/5.0)))*(-EK + v) # A/F -alpha = 0.1161*exp(0.299*vfrt) # mS/uF -alpha_2 = 0.0578*exp(0.971*vfrt) # mS/uF -alpha_C2ToI = 5.2e-5*exp(1.525*vfrt) # mS/uF -alpha_i = 0.2533*exp(0.5953*vfrt) # mS/uF -beta_ = 0.2442*exp((-1*1.604)*vfrt) # mS/uF -beta_2 = 0.000349*exp((-1*1.062)*vfrt) # mS/uF -beta_ItoC2 = (alpha_C2ToI*(beta_2*beta_i))/((alpha_2*alpha_i)) # mS/uF -beta_i = 0.06525*exp((-1*0.8209)*vfrt) # mS/uF -dC1_dt = -C1*(alpha_C2ToI + (alpha_2 + beta_1)) + (I_*beta_ItoC2 + (C2*alpha_1 + O_*beta_2)) -dC2_dt = -C2*(alpha_1 + beta_) + (C1*beta_1 + C3*alpha) -dC3_dt = C2*beta_ - C3*alpha -dI__dt = -I_*(beta_ItoC2 + beta_i) + (C1*alpha_C2ToI + O_*alpha_i) -dO__dt = -O_*(alpha_i + beta_2) + (C1*alpha_2 + I_*beta_i) - -expressions("IKs") -GKs = Conditional(Eq(celltype, 1.0), 1.4*GKs_b, GKs_b) # mS/uF -IKs_IKs = (xs2*(xs1*(GKs*KsCa)))*(-EKs + v) # A/F -KsCa = 1.0 + 0.6/((3.8e-5/cai)**1.4 + 1.0) -txs1 = 817.3 + 1.0/(0.0002326*exp((v + 48.28)/17.8) + 0.001292*exp((-(v + 210.0))/230.0)) # ms -txs2 = 1.0/(0.01*exp((v - 1*50.0)/20.0) + 0.0193*exp((-(v + 66.54))/31.0)) # ms -xs1ss = 1.0/(exp((-(v + 11.6))/8.932) + 1.0) -xs2ss = xs1ss -dxs1_dt = (-xs1 + xs1ss)/txs1 -dxs2_dt = (-xs2 + xs2ss)/txs2 - -expressions("INaL") -GNaL = Conditional(Eq(celltype, 1.0), 0.6*GNaL_b, GNaL_b) # mS/uF -INaL_INaL = (mL*(GNaL*(-ENa + v)))*(fINaLp*hLp + hL*(1.0 - fINaLp)) # A/F -fINaLp = 1.0/(1.0 + KmCaMK/CaMKa) -hLss = 1.0/(exp((v + 87.61)/7.488) + 1.0) -hLssp = 1.0/(exp((v + 93.81)/7.488) + 1.0) -mLss = 1.0/(exp((-(v + 42.85))/5.264) + 1.0) -thLp = 3.0*thL # ms -tmL = 0.06487*exp(-((v - 1*4.823)/51.12)**2.0) + 0.1292*exp(-((v + 45.79)/15.54)**2.0) # ms -dhL_dt = (-hL + hLss)/thL -dhLp_dt = (-hLp + hLssp)/thLp -dmL_dt = (-mL + mLss)/tmL - -expressions("ICab") -ICab_ICab = ((vffrt*(PCab*4.0))*(-cao*gamma_cao + (cai*gamma_cai)*exp(2.0*vfrt)))/(exp(2.0*vfrt) - 1*1.0) # A/F - -expressions("ICl") -IClCa = IClCa_junc + IClCa_sl # A/F -IClCa_junc = ((Fjunc*GClCa)/(KdClCa/cass + 1.0))*(-EClss + v) # A/F -IClCa_sl = ((GClCa*(1.0 - Fjunc))/(KdClCa/cai + 1.0))*(-ECl + v) # A/F -IClb = GClb*(-ECl + v) # A/F - -expressions("INa") -INa_INa = (m**3.0*(GNa*(-ENa + v)))*(j*(h*(1.0 - fINap)) + jp*(fINap*hp)) # A/F -ah = Conditional(Gt(v, -1*40.0), 0.0, 4.43126792958051e-7*exp(-0.147058823529412*v)) -aj = Conditional(Gt(v, -1*40.0), 0.0, -(v + 37.78)*(25428.0*exp(0.28831*v) + 6.948e-6)*exp(-0.04391*v)/(50262745825.954*exp(0.311*v) + 1.0)) -bh = Conditional(Gt(v, -1*40.0), 0.77*exp(0.0900900900900901*v)/(0.13*exp(0.0900900900900901*v) + 0.0497581410839387), 2.7*exp(0.079*v) + 310000.0*exp(0.3485*v)) -bj = Conditional(Gt(v, -1*40.0), 0.6*exp(0.157*v)/(1.0*exp(0.1*v) + 0.0407622039783662), 0.02424*exp(0.12728*v)/(1.0*exp(0.1378*v) + 0.00396086833990426)) -fINap = 1.0/(1.0 + KmCaMK/CaMKa) -hss = 1.0/((exp((v + 71.55)/7.43) + 1.0)**2.0) -hssp = 1.0/((exp((v + 77.55)/7.43) + 1.0)**2.0) -jss = hss -mss = 1.0/((exp((-(v + 56.86))/9.03) + 1.0)**2.0) -th = 1.0/(ah + bh) # ms -tj = 1.0/(aj + bj) # ms -tjp = 1.46*tj # ms -tm = 0.06487*exp(-((v - 1*4.823)/51.12)**2.0) + 0.1292*exp(-((v + 45.79)/15.54)**2.0) # ms -dh_dt = (-h + hss)/th -dhp_dt = (-hp + hssp)/th -dj_dt = (-j + jss)/tj -djp_dt = (-jp + jss)/tjp -dm_dt = (-m + mss)/tm - -expressions("INab") -INab_INab = ((PNab*vffrt)*(nai*exp(vfrt) - nao))/(exp(vfrt) - 1*1.0) # A/F - -expressions("I_katp") -I_katp_I_katp = (bkik*(akik*(fkatp*gkatp)))*(-EK + v) # A/F -akik = (ko/K_o_n)**0.24 -bkik = 1.0/((A_atp/K_atp)**2.0 + 1.0) - -expressions("IpCa") -IpCa_IpCa = (GpCa*cai)/(KmCap + cai) # A/F - -expressions("membrane") -Istim = Conditional(And(Le(i_Stim_Start, time), Ge(i_Stim_PulseDuration, -i_Stim_Period*floor(-(i_Stim_Start - time)/i_Stim_Period) - i_Stim_Start + time)), i_Stim_Amplitude, 0.0) # A/F -vffrt = (F*(F*v))/((R*T)) # C/mol -vfrt = (F*v)/((R*T)) -dv_dt = -(Istim + (I_katp_I_katp + (IClb + (IClCa + (ICab_ICab + (IpCa_IpCa + (IKb_IKb + (INab_INab + (INaK_INaK + (INaCa_ss + (INaCa_i + (IK1_IK1 + (IKs_IKs + (IKr_IKr + (ICaK + (ICaNa + (ICaL_ICaL + (Ito_Ito + (INaL_INaL + INa_INa))))))))))))))))))) # mV - -expressions("diff") -Jdiff = (-cai + cass)/tauCa # mM/ms -JdiffCl = (-cli + clss)/tauNa # mM/ms -JdiffK = (-ki + kss)/tauK # mM/ms -JdiffNa = (-nai + nass)/tauNa # mM/ms - -expressions("SERCA") -Jleak = (0.0048825*cansr)/15.0 # mM/ms -Jup = Jup_b*(-Jleak + (Jupnp*(1.0 - fJupp) + Jupp*fJupp)) # mM/ms -Jupnp = (cai*(upScale*0.005425))/(cai + 0.00092) # mM/ms -Jupp = (cai*((upScale*2.75)*0.005425))/((cai + 0.00092) - 1*0.00017) # mM/ms -fJupp = 1.0/(1.0 + KmCaMK/CaMKa) -upScale = Conditional(Eq(celltype, 1.0), 1.3, 1.0) - -expressions("ryr") -Jrel = Jrel_b*(Jrel_np*(1.0 - fJrelp) + Jrel_p*fJrelp) # mM/ms -Jrel_inf = Conditional(Eq(celltype, 2.0), 1.7*Jrel_inf_b, Jrel_inf_b) # mM/ms -Jrel_inf_b = ((ICaL_ss*(-a_rel))/1.0)/((cajsr_half/cajsr)**8.0 + 1.0) # mM/ms -Jrel_infp = Conditional(Eq(celltype, 2.0), 1.7*Jrel_infp_b, Jrel_infp_b) # mM/ms -Jrel_infp_b = ((ICaL_ss*(-a_relp))/1.0)/((cajsr_half/cajsr)**8.0 + 1.0) # mM/ms -a_rel = (0.5*bt)/1.0 # mM/ms -a_relp = (0.5*btp)/1.0 # mM/ms -btp = 1.25*bt # ms -fJrelp = 1.0/(1.0 + KmCaMK/CaMKa) -tau_rel = Conditional(Lt(tau_rel_b, 0.001), 0.001, tau_rel_b) # ms -tau_rel_b = bt/(1.0 + 0.0123/cajsr) # ms -tau_relp = Conditional(Lt(tau_relp_b, 0.001), 0.001, tau_relp_b) # ms -tau_relp_b = btp/(1.0 + 0.0123/cajsr) # ms -dJrel_np_dt = (Jrel_inf - Jrel_np)/tau_rel # mM/ms -dJrel_p_dt = (Jrel_infp - Jrel_p)/tau_relp # mM/ms - -expressions("trans_flux") -Jtr = (-cajsr + cansr)/60.0 # mM/ms - - -states("mechanics-ep", -cai=0.0001, -XS=0, -XW=0, -CaTrpn=1e-8, -TmB=1 -) - -states("mechanics", -Zetas=0, -Zetaw=0, -Cd=0 -) - -parameters("mechanics-ep","mechanics", -emcoupling=1, -lmbda=1, -dLambda=0, -mode=1, -isacs=0, -calib=1, -ktrpn = 0.1, -ntrpn = 2, -Trpn50 = 0.35, -rw = 0.5, -rs = 0.25, -gammas = 0.0085, -gammaw = 0.615, -phi = 2.23, -Tot_A = 25, -Beta0 = 2.3, -Beta1 = -2.4, -cat50_ref = 0.805, -Tref = 120, -kuw = 0.182, -kws = 0.012, -ku=0.04, -ntm=2.4, -p_a = 2.1, -p_b = 9.1, -p_k = 7, -etal = 200, -etas = 20) - -expressions("mechanics-ep") -XS_max = Conditional(Gt(XS, 0), XS, 0) -XW_max = Conditional(Gt(XW, 0), XW, 0) -CaTrpn_max = Conditional(Gt(CaTrpn, 0), CaTrpn, 0) -kwu = kuw*(1/rw-1)-kws -ksu = kws*rw*(1/rs-1) -Aw = Tot_A*rs/((1-rs)*rw+rs) -As = Aw -cw = phi*kuw*((1-rs)*(1-rw))/((1-rs)*rw) -cs = phi*kws*((1-rs)*rw)/rs -XU = (1-TmB)-XS-XW -gammawu = gammaw*Abs(Zetaw) -gammasu = gammas*Conditional(Gt(Gt(Zetas,0)*Zetas, Lt(Zetas, -1)*(-Zetas-1)), Gt(Zetas,0)*Zetas, Lt(Zetas, -1)*(-Zetas-1)) -dXS_dt = kws*XW - ksu*XS - gammasu*XS -dXW_dt = kuw*XU - kwu*XW - kws*XW - gammawu*XW -cat50 = (cat50_ref+Beta1*(lambda_min12-1)) -dCaTrpn_dt = ktrpn*(((cai*1000/cat50)**ntrpn)*(1-CaTrpn)-CaTrpn) -kb = ku*Trpn50**ntm/(1-rs-(1-rs)*rw) -dTmB_dt = kb*Conditional(Lt(CaTrpn**(-ntm/2), 100), CaTrpn**(-ntm/2), 100)*XU-ku*CaTrpn**(ntm/2)*TmB -Bcai=1.0/(1.0+cmdnmax*kmcmdn/(kmcmdn+cai)**2.0) -J_TRPN = dCaTrpn_dt*trpnmax -dcai_dt=Bcai*(-(IpCa_IpCa+ICab_ICab-2.0*INaCa_i/3)*Acap/(2.0*F*vmyo)-Jup*vnsr/vmyo+Jdiff*vss/vmyo - J_TRPN) - - -expressions("mechanics-ep", "mechanics") -lambda_min12 = Conditional(Lt(lmbda, 1.2), lmbda, 1.2) - -expressions("mechanics") -Aw = Tot_A*rs/((1-rs)*rw+rs) -As = Aw -cw = phi*kuw*((1-rs)*(1-rw))/((1-rs)*rw) -cs = phi*kws*((1-rs)*rw)/rs -dZetas_dt = As*dLambda - cs*Zetas -dZetaw_dt = Aw*dLambda - cw*Zetaw -lambda_min087 = Conditional(Lt(lambda_min12, 0.87), lambda_min12, 0.87) -h_lambda_prima = 1+Beta0*(lambda_min12+lambda_min087-1.87) -h_lambda = Conditional(Gt(h_lambda_prima, 0), h_lambda_prima, 0) -Ta = h_lambda*(Tref/rs)*(XS*(Zetas+1) + XW*Zetaw) -C = lambda_min12 - 1 -dCd = C - Cd -eta = Conditional(Lt(dCd, 0), etas, etal) -dCd_dt = p_k * (C - Cd) / eta -Fd = eta * dCd -F1 = (exp( p_b * C) - 1) -Tp = p_a * (F1 + Fd) -Ttot = Ta + Tp diff --git a/demos/split-zeta/3D/ORdmm_Land.ode b/demos/split-zeta/3D/ORdmm_Land.ode deleted file mode 100644 index ac95032..0000000 --- a/demos/split-zeta/3D/ORdmm_Land.ode +++ /dev/null @@ -1,669 +0,0 @@ -# ORd modified by MMora (October-2016) -# Modifications in INa. The original formulation of INa has been -# optimised, according to Passini, in order to look like TT04. -# Modifications: -# 1) mss,hss,jss and hssp -# 2) gNa -# + -# Re-scaled conductances (Dutta et al 2016 CinC) -# + -# -# Land 2017(mechanical model)- Introduced by MMora (Jan2020) -# Tension -# Changes in Cai effect of troponin -# + -# -# Isacs -# -# -# In this version we fix mech.emcoupling=1, -# mode="intact", isacs=0 and celltype = 0 -# -# -# Modifications by Ilse (January 2023) -# Add scaling facotrs for heart failure and drugs - - -parameters("Scales", -scale_IKr = 1.119, -scale_IKs = 1.648, -scale_IK1 = 1.414, -scale_ICaL = 1.018, -scale_INaL = 2.274) - - - -parameters("settings", -celltype=0) - -parameters("extracellular ionic concentrations", -nao=140.0, -cao=1.8, -ko=5.4) - -parameters("physical constants", "mechanics", -R=8314.0, -T=310.0, -F=96485.0) - - -parameters("cell geometry", "mechanics", -L=0.01, -rad=0.0011) - - -expressions("cell geometry", "mechanics") -vcell=1000*3.14*rad*rad*L -Ageo=2*3.14*rad*rad+2*3.14*rad*L -Acap=2*Ageo -vmyo=0.68*vcell -vnsr=0.0552*vcell -vjsr=0.0048*vcell -vss=0.02*vcell - - -# Scaling factors for heart failure -parameters("scaling factors HF", -scale_HF_CaMKa=1.0, -scale_HF_Jrel_inf=1.0, -scale_HF_Jleak=1.0, -scale_HF_Jup=1.0, -scale_HF_GNaL=1.0, -scale_HF_GK1=1.0, -scale_HF_thL=1.0, -scale_HF_Gto=1.0, -scale_HF_Gncx=1.0, -scale_HF_Pnak=1.0) - -# Scaling factors for drug effects -parameters("scaling factors drug", -scale_drug_INa=1.0, -scale_drug_INaL=1.0, -scale_drug_Ito=1.0, -scale_drug_ICaL=1.0, -scale_drug_IKr=1.0, -scale_drug_IKs=1.0, -scale_drug_IK1=1.0, -scale_drug_IKb=1.0, -scale_drug_INab=1.0, -scale_drug_ICab=1.0, -scale_drug_IpCa=1.0, -scale_drug_Isacns=1.0, -scale_drug_Isack=1.0) - -######## EP states -states("CaMKt", -CaMKt=0 -) - -states("I_Na", -m=0, -hf=1, -hs=1, -j=1, -hsp=1, -jp=1) - -states("INaL", -mL=0, -hL=1, -hLp=1) - -states("Ito", -a=0, -iF=1, -iS=1, -ap=0, -iFp=1, -iSp=1) - -states("ICaL ICaNa ICaK", -d=0, -ff=1, -fs=1, -fcaf=1, -fcas=1, -jca=1, -nca=0, -ffp=1, -fcafp=1) - - -states("IKr", -xrf=0, -xrs=0) - - -states("IKs", -xs1=0, -xs2=0, -xk1=1) - -states("membrane potential", -v=-87) - - -states("ryanodione receptor", -Jrelnp=0, -Jrelp=0) - - -states("intracellular concentrations", -cai=0.0001, -nai=7, -nass=7, -ki=145, -kss=145, -cass=0.0001, -cansr=1.2, -cajsr=1.2) - -states("mechanics-ep", -XS=0, -XW=0, -CaTrpn=0.0001, -TmB=1) - - -states("mechanics", -Zetas=0, -Zetaw=0) - - - -############################## - -parameters("CaMK constants", -KmCaMK=0.15, -aCaMK=0.05, -bCaMK=0.00068, -CaMKo=0.05, -KmCaM=0.0015) - -expressions("CaMKt") -CaMKb=CaMKo*(1.0-CaMKt)/(1.0+KmCaM/cass) -CaMKa=(CaMKb+CaMKt)*scale_HF_CaMKa -dCaMKt_dt=aCaMK*CaMKb*(CaMKb+CaMKt)-bCaMK*CaMKt - -parameters("reversal potentials", -PKNa=0.01833) - -expressions("reversal potentials") -ENa=(R*T/F)*log(nao/nai) -EK=(R*T/F)*log(ko/ki) -EKs=(R*T/F)*log((ko+PKNa*nao)/(ki+PKNa*nai)) -vffrt=v*F*F/(R*T) -vfrt=v*F/(R*T) - -parameters("I_Na", -Ahf=0.99, -GNa=31) - -expressions("I_Na") -mss=1.0/(1.0+exp((-(v+39.57+9.4))/7.5)) -tm=1.0/(6.765*exp((v+11.64)/34.77)+8.552*exp(-(v+77.42)/5.955)) -dm_dt=(mss-m)/tm -hss=1.0/(1+exp((v+78.5)/6.22)) -thf=1.0/(1.432e-5*exp(-(v+1.196)/6.285)+6.149*exp((v+0.5096)/20.27)) -ths=1.0/(0.009794*exp(-(v+17.95)/28.05)+0.3343*exp((v+5.730)/56.66)) -Ahs=1.0-Ahf -dhf_dt=(hss-hf)/thf -dhs_dt=(hss-hs)/ths -h=Ahf*hf+Ahs*hs -jss=hss -tj=2.038+1.0/(0.02136*exp(-(v+100.6)/8.281)+0.3052*exp((v+0.9941)/38.45)) -dj_dt=(jss-j)/tj -hssp=1.0/(1+exp((v+78.5+6.2)/6.22)) -thsp=3.0*ths -dhsp_dt=(hssp-hsp)/thsp -hp=Ahf*hf+Ahs*hsp -tjp=1.46*tj -djp_dt=(jss-jp)/tjp -fINap=(1.0/(1.0+KmCaMK/CaMKa)) -INa=GNa*scale_drug_INa*(v-ENa)*m**3.0*((1.0-fINap)*h*j+fINap*hp*jp) - -parameters("INaL", -thL=200.0) - -expressions("INaL") -mLss=1.0/(1.0+exp((-(v+42.85))/5.264)) -tmL=tm -dmL_dt=(mLss-mL)/tmL -hLss=1.0/(1.0+exp((v+87.61)/7.488)) -dhL_dt=(hLss-hL)/(thL*scale_HF_thL) -hLssp=1.0/(1.0+exp((v+93.81)/7.488)) -thLp=3.0*thL*scale_HF_thL -dhLp_dt=(hLssp-hLp)/thLp -GNaL=0.0075*scale_INaL*scale_drug_INaL*scale_HF_GNaL -fINaLp=(1.0/(1.0+KmCaMK/CaMKa)) -INaL=GNaL*(v-ENa)*mL*((1.0-fINaLp)*hL+fINaLp*hLp) - -parameters("Ito", -delta_epi=1.0, -Gto=0.02) - -expressions("Ito") -ass=1.0/(1.0+exp((-(v-14.34))/14.82)) -ta=1.0515/(1.0/(1.2089*(1.0+exp(-(v-18.4099)/29.3814)))+3.5/(1.0+exp((v+100.0)/29.3814))) -da_dt=(ass-a)/ta -iss=1.0/(1.0+exp((v+43.94)/5.711)) -tiF=4.562+1/(0.3933*exp((-(v+100.0))/100.0)+0.08004*exp((v+50.0)/16.59)) * delta_epi -tiS=23.62+1/(0.001416*exp((-(v+96.52))/59.05)+1.780e-8*exp((v+114.1)/8.079)) * delta_epi -AiF=1.0/(1.0+exp((v-213.6)/151.2)) -AiS=1.0-AiF -diF_dt=(iss-iF)/tiF -diS_dt=(iss-iS)/tiS -i=AiF*iF+AiS*iS -assp=1.0/(1.0+exp((-(v-24.34))/14.82)) -dap_dt=(assp-ap)/ta -dti_develop=1.354+1.0e-4/(exp((v-167.4)/15.89)+exp(-(v-12.23)/0.2154)) -dti_recover=1.0-0.5/(1.0+exp((v+70.0)/20.0)) -tiFp=dti_develop*dti_recover*tiF -tiSp=dti_develop*dti_recover*tiS -diFp_dt=(iss-iFp)/tiFp -diSp_dt=(iss-iSp)/tiSp -ip=AiF*iFp+AiS*iSp -fItop=(1.0/(1.0+KmCaMK/CaMKa)) -Ito=Gto*scale_drug_Ito*scale_HF_Gto*(v-EK)*((1.0-fItop)*a*i+fItop*ap*ip) - - -parameters("ICaL ICaNa ICaK", -Aff=0.6, -tjca=75.0, -Kmn=0.002, -k2n=1000.0, -zca=2.0) - -expressions("ICaL ICaNa ICaK") -dss=1.0/(1.0+exp((-(v+3.940))/4.230)) -td=0.6+1.0/(exp(-0.05*(v+6.0))+exp(0.09*(v+14.0))) -dd_dt=(dss-d)/td -fss=1.0/(1.0+exp((v+19.58)/3.696)) -tff=7.0+1.0/(0.0045*exp(-(v+20.0)/10.0)+0.0045*exp((v+20.0)/10.0)) -tfs=1000.0+1.0/(0.000035*exp(-(v+5.0)/4.0)+0.000035*exp((v+5.0)/6.0)) -Afs=1.0-Aff -dff_dt=(fss-ff)/tff -dfs_dt=(fss-fs)/tfs -f=Aff*ff+Afs*fs -fcass=fss -tfcaf=7.0+1.0/(0.04*exp(-(v-4.0)/7.0)+0.04*exp((v-4.0)/7.0)) -tfcas=100.0+1.0/(0.00012*exp(-v/3.0)+0.00012*exp(v/7.0)) -Afcaf=0.3+0.6/(1.0+exp((v-10.0)/10.0)) -Afcas=1.0-Afcaf -dfcaf_dt=(fcass-fcaf)/tfcaf -dfcas_dt=(fcass-fcas)/tfcas -fca=Afcaf*fcaf+Afcas*fcas -djca_dt=(fcass-jca)/tjca -tffp=2.5*tff -dffp_dt=(fss-ffp)/tffp -fp=Aff*ffp+Afs*fs -tfcafp=2.5*tfcaf -dfcafp_dt=(fcass-fcafp)/tfcafp -fcap=Afcaf*fcafp+Afcas*fcas -km2n=jca*1.0 -anca=1.0/(k2n/km2n+(1.0+Kmn/cass)**4.0) -dnca_dt=anca*k2n-nca*km2n -PhiCaL=4.0*vffrt*(cass*exp(2.0*vfrt)-0.341*cao)/(exp(2.0*vfrt)-1.0) -PhiCaNa=1.0*vffrt*(0.75*nass*exp(1.0*vfrt)-0.75*nao)/(exp(1.0*vfrt)-1.0) -PhiCaK=1.0*vffrt*(0.75*kss*exp(1.0*vfrt)-0.75*ko)/(exp(1.0*vfrt)-1.0) -PCa=0.0001*scale_ICaL*scale_drug_ICaL -PCap=1.1*PCa -PCaNa=0.00125*PCa -PCaK=3.574e-4*PCa -PCaNap=0.00125*PCap -PCaKp=3.574e-4*PCap -fICaLp=(1.0/(1.0+KmCaMK/CaMKa)) -ICaL=(1.0-fICaLp)*PCa*PhiCaL*d*(f*(1.0-nca)+jca*fca*nca)+fICaLp*PCap*PhiCaL*d*(fp*(1.0-nca)+jca*fcap*nca) -ICaNa=(1.0-fICaLp)*PCaNa*PhiCaNa*d*(f*(1.0-nca)+jca*fca*nca)+fICaLp*PCaNap*PhiCaNa*d*(fp*(1.0-nca)+jca*fcap*nca) -ICaK=(1.0-fICaLp)*PCaK*PhiCaK*d*(f*(1.0-nca)+jca*fca*nca)+fICaLp*PCaKp*PhiCaK*d*(fp*(1.0-nca)+jca*fcap*nca) - -expressions("IKr") -xrss=1.0/(1.0+exp((-(v+8.337))/6.789)) -txrf=12.98+1.0/(0.3652*exp((v-31.66)/3.869)+4.123e-5*exp((-(v-47.78))/20.38)) -txrs=1.865+1.0/(0.06629*exp((v-34.70)/7.355)+1.128e-5*exp((-(v-29.74))/25.94)) -Axrf=1.0/(1.0+exp((v+54.81)/38.21)) -Axrs=1.0-Axrf -dxrf_dt=(xrss-xrf)/txrf -dxrs_dt=(xrss-xrs)/txrs -xr=Axrf*xrf+Axrs*xrs -rkr=1.0/(1.0+exp((v+55.0)/75.0))*1.0/(1.0+exp((v-10.0)/30.0)) -GKr=0.046*scale_IKr*scale_drug_IKr -IKr=GKr*sqrt(ko/5.4)*xr*rkr*(v-EK) - -expressions("IKs") -xs1ss=1.0/(1.0+exp((-(v+11.60))/8.932)) -txs1=817.3+1.0/(2.326e-4*exp((v+48.28)/17.80)+0.001292*exp((-(v+210.0))/230.0)) -dxs1_dt=(xs1ss-xs1)/txs1 -xs2ss=xs1ss -txs2=1.0/(0.01*exp((v-50.0)/20.0)+0.0193*exp((-(v+66.54))/31.0)) -dxs2_dt=(xs2ss-xs2)/txs2 -KsCa=1.0+0.6/(1.0+(3.8e-5/cai)**1.4) -GKs=0.0034*scale_IKs*scale_drug_IKs -IKs=GKs*KsCa*xs1*xs2*(v-EKs) -xk1ss=1.0/(1.0+exp(-(v+2.5538*ko+144.59)/(1.5692*ko+3.8115))) -txk1=122.2/(exp((-(v+127.2))/20.36)+exp((v+236.8)/69.33)) -dxk1_dt=(xk1ss-xk1)/txk1 -rk1=1.0/(1.0+exp((v+105.8-2.6*ko)/9.493)) -GK1=0.1908*scale_IK1*scale_drug_IK1*scale_HF_GK1 -IK1=GK1*sqrt(ko)*rk1*xk1*(v-EK) - - -parameters("INaCa_i", -kna1=15.0, -kna2=5.0, -kna3=88.12, -kasymm=12.5, -wna=6.0e4, -wca=6.0e4, -wnaca=5.0e3, -kcaon=1.5e6, -kcaoff=5.0e3, -qna=0.5224, -qca=0.1670, -KmCaAct=150.0e-6, -Gncx=0.0008) - -expressions("INaCa_i") -hca=exp((qca*v*F)/(R*T)) -hna=exp((qna*v*F)/(R*T)) -h1_i=1+nai/kna3*(1+hna) -h2_i=(nai*hna)/(kna3*h1_i) -h3_i=1.0/h1_i -h4_i=1.0+nai/kna1*(1+nai/kna2) -h5_i=nai*nai/(h4_i*kna1*kna2) -h6_i=1.0/h4_i -h7_i=1.0+nao/kna3*(1.0+1.0/hna) -h8_i=nao/(kna3*hna*h7_i) -h9_i=1.0/h7_i -h10_i=kasymm+1.0+nao/kna1*(1.0+nao/kna2) -h11_i=nao*nao/(h10_i*kna1*kna2) -h12_i=1.0/h10_i -k1_i=h12_i*cao*kcaon -k2_i=kcaoff -k3p_i=h9_i*wca -k3pp_i=h8_i*wnaca -k3_i=k3p_i+k3pp_i -k4p_i=h3_i*wca/hca -k4pp_i=h2_i*wnaca -k4_i=k4p_i+k4pp_i -k5_i=kcaoff -k6_i=h6_i*cai*kcaon -k7_i=h5_i*h2_i*wna -k8_i=h8_i*h11_i*wna -x1_i=k2_i*k4_i*(k7_i+k6_i)+k5_i*k7_i*(k2_i+k3_i) -x2_i=k1_i*k7_i*(k4_i+k5_i)+k4_i*k6_i*(k1_i+k8_i) -x3_i=k1_i*k3_i*(k7_i+k6_i)+k8_i*k6_i*(k2_i+k3_i) -x4_i=k2_i*k8_i*(k4_i+k5_i)+k3_i*k5_i*(k1_i+k8_i) -E1_i=x1_i/(x1_i+x2_i+x3_i+x4_i) -E2_i=x2_i/(x1_i+x2_i+x3_i+x4_i) -E3_i=x3_i/(x1_i+x2_i+x3_i+x4_i) -E4_i=x4_i/(x1_i+x2_i+x3_i+x4_i) -allo_i=1.0/(1.0+(KmCaAct/cai)**2.0) -zna=1.0 -JncxNa_i=3.0*(E4_i*k7_i-E1_i*k8_i)+E3_i*k4pp_i-E2_i*k3pp_i -JncxCa_i=E2_i*k2_i-E1_i*k1_i -INaCa_i=0.8*Gncx*scale_HF_Gncx*allo_i*(zna*JncxNa_i+zca*JncxCa_i) - -expressions("INaCa_ss") -h1=1+nass/kna3*(1+hna) -h2=(nass*hna)/(kna3*h1) -h3=1.0/h1 -h4=1.0+nass/kna1*(1+nass/kna2) -h5=nass*nass/(h4*kna1*kna2) -h6=1.0/h4 -h7=1.0+nao/kna3*(1.0+1.0/hna) -h8=nao/(kna3*hna*h7) -h9=1.0/h7 -h10=kasymm+1.0+nao/kna1*(1+nao/kna2) -h11=nao*nao/(h10*kna1*kna2) -h12=1.0/h10 -k1=h12*cao*kcaon -k2=kcaoff -k3p_ss=h9*wca -k3pp=h8*wnaca -k3=k3p_ss+k3pp -k4p_ss=h3*wca/hca -k4pp=h2*wnaca -k4=k4p_ss+k4pp -k5=kcaoff -k6=h6*cass*kcaon -k7=h5*h2*wna -k8=h8*h11*wna -x1_ss=k2*k4*(k7+k6)+k5*k7*(k2+k3) -x2_ss=k1*k7*(k4+k5)+k4*k6*(k1+k8) -x3_ss=k1*k3*(k7+k6)+k8*k6*(k2+k3) -x4_ss=k2*k8*(k4+k5)+k3*k5*(k1+k8) -E1_ss=x1_ss/(x1_ss+x2_ss+x3_ss+x4_ss) -E2_ss=x2_ss/(x1_ss+x2_ss+x3_ss+x4_ss) -E3_ss=x3_ss/(x1_ss+x2_ss+x3_ss+x4_ss) -E4_ss=x4_ss/(x1_ss+x2_ss+x3_ss+x4_ss) -allo_ss=1.0/(1.0+(KmCaAct/cass)**2.0) -JncxNa_ss=3.0*(E4_ss*k7-E1_ss*k8)+E3_ss*k4pp-E2_ss*k3pp -JncxCa_ss=E2_ss*k2-E1_ss*k1 -INaCa_ss=0.2*Gncx*scale_HF_Gncx*allo_ss*(zna*JncxNa_ss+zca*JncxCa_ss) - - -parameters("INaK", -k1p=949.5, -k1m=182.4, -k2p=687.2, -k2m=39.4, -k3p=1899.0, -k3m=79300.0, -k4p=639.0, -k4m=40.0, -Knai0=9.073, -Knao0=27.78, -delta=-0.1550, -Kki=0.5, -Kko=0.3582, -MgADP=0.05, -MgATP=9.8, -Kmgatp=1.698e-7, -H=1.0e-7, -eP=4.2, -Khp=1.698e-7, -Knap=224.0, -Kxkur=292.0, -zk=1.0, -Pnak=30) - -expressions("INaK") -Knai=Knai0*exp((delta*v*F)/(3.0*R*T)) -Knao=Knao0*exp(((1.0-delta)*v*F)/(3.0*R*T)) -P=eP/(1.0+H/Khp+nai/Knap+ki/Kxkur) -a1=(k1p*(nai/Knai)**3.0)/((1.0+nai/Knai)**3.0+(1.0+ki/Kki)**2.0-1.0) -b1=k1m*MgADP -a2=k2p -b2=(k2m*(nao/Knao)**3.0)/((1.0+nao/Knao)**3.0+(1.0+ko/Kko)**2.0-1.0) -a3=(k3p*(ko/Kko)**2.0)/((1.0+nao/Knao)**3.0+(1.0+ko/Kko)**2.0-1.0) -b3=(k3m*P*H)/(1.0+MgATP/Kmgatp) -a4=(k4p*MgATP/Kmgatp)/(1.0+MgATP/Kmgatp) -b4=(k4m*(ki/Kki)**2.0)/((1.0+nai/Knai)**3.0+(1.0+ki/Kki)**2.0-1.0) -x1=a4*a1*a2+b2*b4*b3+a2*b4*b3+b3*a1*a2 -x2=b2*b1*b4+a1*a2*a3+a3*b1*b4+a2*a3*b4 -x3=a2*a3*a4+b3*b2*b1+b2*b1*a4+a3*a4*b1 -x4=b4*b3*b2+a3*a4*a1+b2*a4*a1+b3*b2*a1 -E1=x1/(x1+x2+x3+x4) -E2=x2/(x1+x2+x3+x4) -E3=x3/(x1+x2+x3+x4) -E4=x4/(x1+x2+x3+x4) -JnakNa=3.0*(E1*a3-E2*b3) -JnakK=2.0*(E4*b1-E3*a1) -INaK=Pnak*scale_HF_Pnak*(zna*JnakNa+zk*JnakK) - - -parameters("IKb", -GKb=0.003) - -expressions("IKb") -xkb=1.0/(1.0+exp(-(v-14.48)/18.34)) -IKb=GKb*scale_drug_IKb*xkb*(v-EK) - -parameters("INab", -PNab=3.75e-10) - -expressions("INab") -INab=PNab*scale_drug_INab*vffrt*(nai*exp(vfrt)-nao)/(exp(vfrt)-1.0) - - -parameters("ICab", -PCab=2.5e-8) - -expressions("ICab") -ICab=PCab*scale_drug_ICab*4.0*vffrt*(cai*exp(2.0*vfrt)-0.341*cao)/(exp(2.0*vfrt)-1.0) - -parameters("IpCa", -GpCa=0.0005) - -expressions("IpCa") -IpCa=GpCa*scale_drug_IpCa*cai/(0.0005+cai) - - -parameters("Isac (Pueyo)--> ns + k", -Gsac_ns=0.006, -Esac_ns=-10, -lambda_max=1.1, -Gsac_k=0.2882*800/210) - -expressions("Isac (Pueyo)--> ns + k") -Isac_P_ns=0 -Isac_P_k=0 - - -parameters("Istim", -amp=-80.0, -duration=0.5) - -expressions("Istim") -Istim = Conditional(Le(t, duration), amp, 0) - -expressions("membrane potential") -dv_dt=-(INa+INaL+Ito+ICaL+ICaNa+ICaK+IKr+IKs+IK1+INaCa_i+INaCa_ss+INaK+INab+IKb+IpCa+ICab+Istim+Isac_P_ns+Isac_P_k) - -expressions("diffusion fluxes") -JdiffNa=(nass-nai)/2.0 -JdiffK=(kss-ki)/2.0 -Jdiff=(cass-cai)/0.2 - -parameters("ryanodione receptor", -bt=4.75) - -expressions("ryanodione receptor") -a_rel=0.5*bt -Jrel_inf=a_rel*(-ICaL)/(1.0+(1.5*scale_HF_Jrel_inf/cajsr)**8.0) -tau_rel_tmp=bt/(1.0+0.0123/cajsr) -tau_rel=Conditional(Lt(tau_rel_tmp, 0.001), 0.001, tau_rel_tmp) -dJrelnp_dt=(Jrel_inf-Jrelnp)/tau_rel -btp=1.25*bt -a_relp=0.5*btp -Jrel_infp=a_relp*(-ICaL)/(1.0+(1.5*scale_HF_Jrel_inf/cajsr)**8.0) -tau_relp_tmp=btp/(1.0+0.0123/cajsr) -tau_relp=Conditional(Lt(tau_relp_tmp, 0.001), 0.001, tau_relp_tmp) -dJrelp_dt=(Jrel_infp-Jrelp)/tau_relp -fJrelp=(1.0/(1.0+KmCaMK/CaMKa)) -Jrel=(1.0-fJrelp)*Jrelnp+fJrelp*Jrelp - -expressions("calcium buffers") -Jupnp=0.004375*cai/(cai+0.00092) -Jupp=2.75*0.004375*cai/(cai+0.00092-0.00017) -fJupp=(1.0/(1.0+KmCaMK/CaMKa)) -Jleak=0.0039375*cansr*scale_HF_Jleak/15.0 -Jup=(1.0-fJupp)*Jupnp+fJupp*Jupp*scale_HF_Jup-Jleak -Jtr=(cansr-cajsr)/100.0 - -parameters("calcium buffers", "mechanics", -cmdnmax=0.05, -kmcmdn=0.00238, -trpnmax=0.07, -kmtrpn=0.0005, -BSRmax=0.047, -KmBSR=0.00087, -BSLmax=1.124, -KmBSL=0.0087, -csqnmax=10.0, -kmcsqn=0.8) - -expressions("intracellular concentrations") -dnai_dt=-(INa+INaL+3.0*INaCa_i+3.0*INaK+INab+Isac_P_ns/3)*Acap/(F*vmyo)+JdiffNa*vss/vmyo -dnass_dt=-(ICaNa+3.0*INaCa_ss)*Acap/(F*vss)-JdiffNa -dki_dt=-(Ito+IKr+IKs+IK1+IKb+Isac_P_k+Isac_P_ns/3+Istim-2.0*INaK)*Acap/(F*vmyo)+JdiffK*vss/vmyo -dkss_dt=-(ICaK)*Acap/(F*vss)-JdiffK -Bcass=1.0/(1.0+BSRmax*KmBSR/(KmBSR+cass)**2.0+BSLmax*KmBSL/(KmBSL+cass)**2.0) -dcass_dt=Bcass*(-(ICaL-2.0*INaCa_ss)*Acap/(2.0*F*vss)+Jrel*vjsr/vss-Jdiff) -dcansr_dt=Jup-Jtr*vjsr/vnsr -Bcajsr=1.0/(1.0+csqnmax*kmcsqn/(kmcsqn+cajsr)**2.0) -dcajsr_dt=Bcajsr*(Jtr-Jrel) -Bcai=1.0/(1.0+cmdnmax*kmcmdn/(kmcmdn+cai)**2.0) -dcai_dt=Bcai*(-(IpCa+ICab-2.0*INaCa_i+Isac_P_ns/3)*Acap/(2.0*F*vmyo)-Jup*vnsr/vmyo+Jdiff*vss/vmyo - J_TRPN) - - -parameters("mechanics-ep", "mechanics", -emcoupling=1, -lmbda=1, -dLambda=0, -mode=1, -isacs=0, -calib=1, -ktrpn = 0.1, -ntrpn = 2, -Trpn50 = 0.35, -rw = 0.5, -rs = 0.25, -gammas = 0.0085, -gammaw = 0.615, -phi = 2.23, -Tot_A = 25, -Beta0 = 2.3, -Beta1 = -2.4, -cat50_ref = 0.805, -scale_HF_cat50_ref=1.0, -Tref = 120, -kuw = 0.182, -kws = 0.012, -ku=0.04, -ntm=2.4, -p_a = 2.1, -p_b = 9.1, -p_k = 7, -etal = 200, -etas = 20) - -expressions("mechanics-ep", "mechanics") -lambda_min12 = Conditional(Lt(lmbda, 1.2), lmbda, 1.2) - - -expressions("mechanics-ep") -XS_max = Conditional(Gt(XS, 0), XS, 0) -XW_max = Conditional(Gt(XW, 0), XW, 0) -CaTrpn_max = Conditional(Gt(CaTrpn, 0), CaTrpn, 0) -kwu = kuw*(1/rw-1)-kws -ksu = kws*rw*(1/rs-1) -Aw = Tot_A*rs/((1-rs)*rw+rs) -As = Aw -cw = phi*kuw*((1-rs)*(1-rw))/((1-rs)*rw) -cs = phi*kws*((1-rs)*rw)/rs -XU = (1-TmB)-XS-XW -gammawu = gammaw*Abs(Zetaw) -gammasu = gammas*Conditional(Gt(Gt(Zetas,0)*Zetas, Lt(Zetas, -1)*(-Zetas-1)), Gt(Zetas,0)*Zetas, Lt(Zetas, -1)*(-Zetas-1)) -dXS_dt = kws*XW - ksu*XS - gammasu*XS -dXW_dt = kuw*XU - kwu*XW - kws*XW - gammawu*XW -cat50 = (cat50_ref+Beta1*(lambda_min12-1))*scale_HF_cat50_ref -dCaTrpn_dt = ktrpn*(((cai*1000/cat50)**ntrpn)*(1-CaTrpn)-CaTrpn) -kb = ku*Trpn50**ntm/(1-rs-(1-rs)*rw) -dTmB_dt = kb*Conditional(Lt(CaTrpn**(-ntm/2), 100), CaTrpn**(-ntm/2), 100)*XU-ku*CaTrpn**(ntm/2)*TmB -J_TRPN = dCaTrpn_dt*trpnmax - - - -expressions("mechanics") -Aw = Tot_A*rs/((1-rs)*rw+rs) -As = Aw -cw = phi*kuw*((1-rs)*(1-rw))/((1-rs)*rw) -cs = phi*kws*((1-rs)*rw)/rs -dZetas_dt = As*dLambda - cs*Zetas -dZetaw_dt = Aw*dLambda - cw*Zetaw -lambda_min087 = Conditional(Lt(lambda_min12, 0.87), lambda_min12, 0.87) -h_lambda_prima = 1+Beta0*(lambda_min12+lambda_min087-1.87) -h_lambda = Conditional(Gt(h_lambda_prima, 0), h_lambda_prima, 0) -Ta = h_lambda*(Tref/rs)*(XS*(Zetas+1) + XW*Zetaw) diff --git a/demos/split-zeta/3D/ToRORd_dynCl_endo_zetasplit.ode b/demos/split-zeta/3D/ToRORd_dynCl_endo_zetasplit.ode deleted file mode 100644 index 11e38f0..0000000 --- a/demos/split-zeta/3D/ToRORd_dynCl_endo_zetasplit.ode +++ /dev/null @@ -1,722 +0,0 @@ -states("IKr", -C1=ScalarParam(0.9982511, unit="1", description=""), -C2=ScalarParam( 7.93602000000000023e-4, unit="1", description=""), -C3=ScalarParam( 6.53214300000000045e-4, unit="1", description=""), -I_=ScalarParam( 9.80408300000000003e-6, unit="1", description=""), -O_=ScalarParam( 2.92244900000000025e-4, unit="1", description="") -) - -states("CaMK", -CaMKt=ScalarParam( 1.09502599999999999e-2, unit="mM", description="") -) - -states("ryr", -Jrel_np=ScalarParam( 1.80824799999999996e-22, unit="mM/ms", description=""), -Jrel_p=ScalarParam( 4.35860800000000030e-21, unit="mM/ms", description="") -) - -states("Ito", -a=ScalarParam( 8.89925900000000051e-4, unit="1", description=""), -ap=ScalarParam( 4.53416500000000005e-4, unit="1", description=""), -iF=ScalarParam(0.9996716, unit="1", description=""), -iFp=ScalarParam(0.9996716, unit="1", description=""), -iS=ScalarParam(0.5988908, unit="1", description=""), -iSp=ScalarParam(0.6620692, unit="1", description="") -) - -states("intracellular_ions", -cajsr=ScalarParam(1.525693, unit="mM", description=""), -cansr=ScalarParam(1.528001, unit="mM", description=""), -cass=ScalarParam( 6.49734100000000044e-5, unit="mM", description=""), -cli=ScalarParam(29.20698, unit="mM", description=""), -clss=ScalarParam(29.20696, unit="mM", description=""), -ki=ScalarParam(147.7115, unit="mM", description=""), -kss=ScalarParam(147.7114, unit="mM", description=""), -nai=ScalarParam(12.39736, unit="mM", description=""), -nass=ScalarParam(12.3977, unit="mM", description="") -) - -states("ICaL", -d=ScalarParam( 1.58884100000000000e-31, unit="1", description=""), -fcaf=ScalarParam(1, unit="1", description=""), -fcafp=ScalarParam(1, unit="1", description=""), -fcas=ScalarParam(0.9999014, unit="1", description=""), -ff_=ScalarParam(1, unit="1", description=""), -ffp=ScalarParam(1, unit="1", description=""), -fs=ScalarParam(0.9401791, unit="1", description=""), -jca=ScalarParam(0.9999846, unit="1", description=""), -nca_i=ScalarParam( 8.32600900000000053e-4, unit="1", description=""), -nca_ss=ScalarParam( 4.89937800000000024e-4, unit="1", description="") -) - -states("INa", -h=ScalarParam(0.8473267, unit="1", description=""), -hp=ScalarParam(0.7018454, unit="1", description=""), -j=ScalarParam(0.8471657, unit="1", description=""), -jp=ScalarParam(0.8469014, unit="1", description=""), -m=ScalarParam( 6.51715400000000005e-4, unit="1", description="") -) - -states("INaL", -hL=ScalarParam(0.5566017, unit="1", description=""), -hLp=ScalarParam(0.3115491, unit="1", description=""), -mL=ScalarParam( 1.35120299999999988e-4, unit="1", description="") -) - -states("membrane", -v=ScalarParam(-89.74808, unit="mV", description="") -) - -states("IKs", -xs1=ScalarParam(0.243959, unit="1", description=""), -xs2=ScalarParam( 1.58616700000000009e-4, unit="1", description="") -) - -parameters("I_katp", -A_atp=ScalarParam(2.0, unit="mM", description=""), -K_atp=ScalarParam(0.25, unit="mM", description=""), -K_o_n=ScalarParam(5.0, unit="mM", description=""), -fkatp=ScalarParam(0.0, unit="1", description=""), -gkatp=ScalarParam(4.3195, unit="mS/uF", description="") -) - -parameters("ICaL", -Aff=ScalarParam(0.6, unit="1", description=""), -ICaL_fractionSS=ScalarParam(0.8, unit="1", description=""), -Kmn=ScalarParam(0.002, unit="mM", description=""), -PCa_b=ScalarParam(8.3757e-05, unit="1", description=""), -dielConstant=ScalarParam(74.0, unit="1/K", description=""), -k2n=ScalarParam(500.0, unit="mS/uF", description=""), -offset=ScalarParam(0.0, unit="ms", description=""), -tjca=ScalarParam(72.5, unit="ms", description=""), -vShift=ScalarParam(0.0, unit="mV", description="") -) - -parameters("intracellular_ions","mechanics", -BSLmax=ScalarParam(1.124, unit="mM", description=""), -BSRmax=ScalarParam(0.047, unit="mM", description=""), -KmBSL=ScalarParam(0.0087, unit="mM", description=""), -KmBSR=ScalarParam(0.00087, unit="mM", description=""), -cmdnmax_b=ScalarParam(0.05, unit="mM", description=""), -csqnmax=ScalarParam(10.0, unit="mM", description=""), -kmcmdn=ScalarParam(0.00238, unit="mM", description=""), -kmcsqn=ScalarParam(0.8, unit="mM", description=""), -kmtrpn=ScalarParam(0.0005, unit="mM", description=""), -trpnmax=ScalarParam(0.07, unit="mM", description="") -) - -parameters("CaMK", -CaMKo=ScalarParam(0.05, unit="1", description=""), -KmCaM=ScalarParam(0.0015, unit="mM", description=""), -KmCaMK=ScalarParam(0.15, unit="mM", description=""), -aCaMK=ScalarParam(0.05, unit="1/mM/ms", description=""), -bCaMK=ScalarParam(0.00068, unit="mS/uF", description="") -) - -parameters("Ito", -EKshift=ScalarParam(0.0, unit="mV", description=""), -Gto_b=ScalarParam(0.16, unit="mS/uF", description="") -) - -parameters("physical_constants","mechanics", -F=ScalarParam(96485.0, unit="C/mol", description=""), -R=ScalarParam(8314.0, unit="mJ/mol/K", description=""), -T=ScalarParam(310.0, unit="K", description=""), -zca=ScalarParam(2.0, unit="1", description=""), -zcl=ScalarParam(-1.0, unit="1", description=""), -zk=ScalarParam(1.0, unit="1", description=""), -zna=ScalarParam(1.0, unit="1", description="") -) - -parameters("ICl", -Fjunc=ScalarParam(1.0, unit="1", description=""), -GClCa=ScalarParam(0.2843, unit="mS/uF", description=""), -GClb=ScalarParam(0.00198, unit="mS/uF", description=""), -KdClCa=ScalarParam(0.1, unit="mM", description="") -) - -parameters("IK1", -GK1_b=ScalarParam(0.6992, unit="mS/uF", description="") -) - -parameters("IKb", -GKb_b=ScalarParam(0.0189, unit="mS/uF", description="") -) - -parameters("IKr", -GKr_b=ScalarParam(0.0321, unit="mS/uF", description=""), -alpha_1=ScalarParam(0.154375, unit="mS/uF", description=""), -beta_1=ScalarParam(0.1911, unit="mS/uF", description="") -) - -parameters("IKs", -GKs_b=ScalarParam(0.0011, unit="mS/uF", description="") -) - -parameters("INa", -GNa=ScalarParam(11.7802, unit="mS/uF", description="") -) - -parameters("INaL", -GNaL_b=ScalarParam(0.0279, unit="mS/uF", description=""), -thL=ScalarParam(200.0, unit="ms", description="") -) - -parameters("INaCa", -Gncx_b=ScalarParam(0.0034, unit="mS/uF", description=""), -INaCa_fractionSS=ScalarParam(0.35, unit="1", description=""), -KmCaAct=ScalarParam(0.00015, unit="mM", description=""), -kasymm=ScalarParam(12.5, unit="1", description=""), -kcaoff=ScalarParam(5000.0, unit="mS/uF", description=""), -kcaon=ScalarParam(1500000.0, unit="mS/uF", description=""), -kna1=ScalarParam(15.0, unit="mS/uF", description=""), -kna2=ScalarParam(5.0, unit="mS/uF", description=""), -kna3=ScalarParam(88.12, unit="mS/uF", description=""), -qca=ScalarParam(0.167, unit="1", description=""), -qna=ScalarParam(0.5224, unit="1", description=""), -wca=ScalarParam(60000.0, unit="1", description=""), -wna=ScalarParam(60000.0, unit="1", description=""), -wnaca=ScalarParam(5000.0, unit="1", description="") -) - -parameters("IpCa", -GpCa=ScalarParam(0.0005, unit="mS/uF", description=""), -KmCap=ScalarParam(0.0005, unit="mM", description="") -) - -parameters("INaK", -H=ScalarParam(1e-07, unit="mM", description=""), -Khp=ScalarParam(1.698e-07, unit="mM", description=""), -Kki=ScalarParam(0.5, unit="mS/uF", description=""), -Kko=ScalarParam(0.3582, unit="mS/uF", description=""), -Kmgatp=ScalarParam(1.698e-07, unit="mM", description=""), -Knai0=ScalarParam(9.073, unit="mM", description=""), -Knao0=ScalarParam(27.78, unit="mM", description=""), -Knap=ScalarParam(224.0, unit="mM", description=""), -Kxkur=ScalarParam(292.0, unit="mM", description=""), -MgADP=ScalarParam(0.05, unit="mM", description=""), -MgATP=ScalarParam(9.8, unit="mM", description=""), -Pnak_b=ScalarParam(15.4509, unit="mS/uF", description=""), -delta=ScalarParam(-0.155, unit="mV", description=""), -eP=ScalarParam(4.2, unit="1", description=""), -k1m=ScalarParam(182.4, unit="mS/uF", description=""), -k1p=ScalarParam(949.5, unit="mS/uF", description=""), -k2m=ScalarParam(39.4, unit="mS/uF", description=""), -k2p=ScalarParam(687.2, unit="mS/uF", description=""), -k3m=ScalarParam(79300.0, unit="mS/uF", description=""), -k3p=ScalarParam(1899.0, unit="mS/uF", description=""), -k4m=ScalarParam(40.0, unit="mS/uF", description=""), -k4p=ScalarParam(639.0, unit="mS/uF", description="") -) - -parameters("ryr", -Jrel_b=ScalarParam(1.5378, unit="1", description=""), -bt=ScalarParam(4.75, unit="ms", description=""), -cajsr_half=ScalarParam(1.7, unit="mM", description="") -) - -parameters("SERCA", -Jup_b=ScalarParam(1.0, unit="1", description="") -) - -parameters("cell_geometry","mechanics", -L=ScalarParam(0.01, unit="cm", description=""), -rad_=ScalarParam(0.0011, unit="cm", description="") -) - -parameters("ICab", -PCab=ScalarParam(5.9194e-08, unit="mS/uF", description="") -) - -parameters("reversal_potentials", -PKNa=ScalarParam(0.01833, unit="1", description="") -) - -parameters("INab", -PNab=ScalarParam(1.9239e-09, unit="mS/uF", description="") -) - -parameters("extracellular", -cao=ScalarParam(1.8, unit="mM", description=""), -clo=ScalarParam(150.0, unit="mM", description=""), -ko=ScalarParam(5.0, unit="mM", description=""), -nao=ScalarParam(140.0, unit="mM", description="") -) - -parameters("environment", -celltype=ScalarParam(0.0, unit="1", description="") -) - -parameters("membrane", -i_Stim_Amplitude=ScalarParam(-53.0, unit="A/F", description=""), -i_Stim_End=ScalarParam(1e+17, unit="ms", description=""), -i_Stim_Period=ScalarParam(1000.0, unit="ms", description=""), -i_Stim_PulseDuration=ScalarParam(1.0, unit="ms", description=""), -i_Stim_Start=ScalarParam(0.0, unit="ms", description="") -) - -parameters("diff", -tauCa=ScalarParam(0.2, unit="ms", description=""), -tauCl=ScalarParam(2.0, unit="ms", description=""), -tauK=ScalarParam(2.0, unit="ms", description=""), -tauNa=ScalarParam(2.0, unit="ms", description="") -) - -expressions("cell_geometry", "mechanics") -Acap = 2.0*Ageo # cm**2 -Ageo = L*((2.0*3.14)*rad_) + rad_*((2.0*3.14)*rad_) # cm**2 -vcell = L*(rad_*((1000.0*3.14)*rad_)) # uL -vjsr = 0.0048*vcell # uL -vmyo = 0.68*vcell # uL -vnsr = 0.0552*vcell # uL -vss = 0.02*vcell # uL - -expressions("ICaL") -Afcaf = 0.3 + 0.6/(exp((v - 1*10.0)/10.0) + 1.0) -Afcas = 1.0 - Afcaf -Afs = 1.0 - Aff -ICaK = ICaK_i + ICaK_ss # A/F -ICaK_i = (1.0 - ICaL_fractionSS)*((d*(PhiCaK_i*(PCaK*(1.0 - fICaLp))))*(f*(1.0 - nca_i) + nca_i*(fca*jca)) + (d*(PhiCaK_i*(PCaKp*fICaLp)))*(fp*(1.0 - nca_i) + nca_i*(fcap*jca))) # A/F -ICaK_ss = ICaL_fractionSS*((d*(PhiCaK_ss*(PCaK*(1.0 - fICaLp))))*(f*(1.0 - nca_ss) + nca_ss*(fca*jca)) + (d*(PhiCaK_ss*(PCaKp*fICaLp)))*(fp*(1.0 - nca_ss) + nca_ss*(fcap*jca))) # A/F -ICaL_ICaL = ICaL_i + ICaL_ss # A/F -ICaL_i = (1.0 - ICaL_fractionSS)*((d*(PhiCaL_i*(PCa*(1.0 - fICaLp))))*(f*(1.0 - nca_i) + nca_i*(fca*jca)) + (d*(PhiCaL_i*(PCap*fICaLp)))*(fp*(1.0 - nca_i) + nca_i*(fcap*jca))) # A/F -ICaL_ss = ICaL_fractionSS*((d*(PhiCaL_ss*(PCa*(1.0 - fICaLp))))*(f*(1.0 - nca_ss) + nca_ss*(fca*jca)) + (d*(PhiCaL_ss*(PCap*fICaLp)))*(fp*(1.0 - nca_ss) + nca_ss*(fcap*jca))) # A/F -ICaNa = ICaNa_i + ICaNa_ss # A/F -ICaNa_i = (1.0 - ICaL_fractionSS)*((d*(PhiCaNa_i*(PCaNa*(1.0 - fICaLp))))*(f*(1.0 - nca_i) + nca_i*(fca*jca)) + (d*(PhiCaNa_i*(PCaNap*fICaLp)))*(fp*(1.0 - nca_i) + nca_i*(fcap*jca))) # A/F -ICaNa_ss = ICaL_fractionSS*((d*(PhiCaNa_ss*(PCaNa*(1.0 - fICaLp))))*(f*(1.0 - nca_ss) + nca_ss*(fca*jca)) + (d*(PhiCaNa_ss*(PCaNap*fICaLp)))*(fp*(1.0 - nca_ss) + nca_ss*(fcap*jca))) # A/F -Ii = (0.5*(4.0*cai + (cli + (ki + nai))))/1000.0 -Io = (0.5*(4.0*cao + (clo + (ko + nao))))/1000.0 -Iss = (0.5*(4.0*cass + (clss + (kss + nass))))/1000.0 -PCa = Conditional(Eq(celltype, 1.0), 1.2*PCa_b, Conditional(Eq(celltype, 2.0), 2.0*PCa_b, PCa_b)) -PCaK = 0.0003574*PCa -PCaKp = 0.0003574*PCap -PCaNa = 0.00125*PCa -PCaNap = 0.00125*PCap -PCap = 1.1*PCa -PhiCaK_i = ((1.0*vffrt)*(-gamma_ko*ko + (gamma_ki*ki)*exp(1.0*vfrt)))/(exp(1.0*vfrt) - 1*1.0) -PhiCaK_ss = ((1.0*vffrt)*(-gamma_ko*ko + (gamma_kss*kss)*exp(1.0*vfrt)))/(exp(1.0*vfrt) - 1*1.0) -PhiCaL_i = ((4.0*vffrt)*(-cao*gamma_cao + (cai*gamma_cai)*exp(2.0*vfrt)))/(exp(2.0*vfrt) - 1*1.0) -PhiCaL_ss = ((4.0*vffrt)*(-cao*gamma_cao + (cass*gamma_cass)*exp(2.0*vfrt)))/(exp(2.0*vfrt) - 1*1.0) -PhiCaNa_i = ((1.0*vffrt)*(-gamma_nao*nao + (gamma_nai*nai)*exp(1.0*vfrt)))/(exp(1.0*vfrt) - 1*1.0) -PhiCaNa_ss = ((1.0*vffrt)*(-gamma_nao*nao + (gamma_nass*nass)*exp(1.0*vfrt)))/(exp(1.0*vfrt) - 1*1.0) -anca_i = 1.0/(k2n/km2n + (Kmn/cai + 1.0)**4.0) -anca_ss = 1.0/(k2n/km2n + (Kmn/cass + 1.0)**4.0) -constA = 1820000.0/(T*dielConstant)**1.5 -dss = Conditional(Ge(v, 31.4978), 1.0, 1.0763*exp(-1.007*exp(-0.0829*v))) -f = Aff*ff_ + Afs*fs -fICaLp = 1.0/(1.0 + KmCaMK/CaMKa) -fca = Afcaf*fcaf + Afcas*fcas -fcap = Afcaf*fcafp + Afcas*fcas -fcass = fss -fp = Aff*ffp + Afs*fs -fss = 1.0/(exp((v + 19.58)/3.696) + 1.0) -gamma_cai = exp((-constA*4.0)*(sqrt(Ii)/(sqrt(Ii) + 1.0) - 0.3*Ii)) -gamma_cao = exp((-constA*4.0)*(sqrt(Io)/(sqrt(Io) + 1.0) - 0.3*Io)) -gamma_cass = exp((-constA*4.0)*(sqrt(Iss)/(sqrt(Iss) + 1.0) - 0.3*Iss)) -gamma_ki = exp((-constA*1.0)*(sqrt(Ii)/(sqrt(Ii) + 1.0) - 0.3*Ii)) -gamma_ko = exp((-constA*1.0)*(sqrt(Io)/(sqrt(Io) + 1.0) - 0.3*Io)) -gamma_kss = exp((-constA*1.0)*(sqrt(Iss)/(sqrt(Iss) + 1.0) - 0.3*Iss)) -gamma_nai = exp((-constA*1.0)*(sqrt(Ii)/(sqrt(Ii) + 1.0) - 0.3*Ii)) -gamma_nao = exp((-constA*1.0)*(sqrt(Io)/(sqrt(Io) + 1.0) - 0.3*Io)) -gamma_nass = exp((-constA*1.0)*(sqrt(Iss)/(sqrt(Iss) + 1.0) - 0.3*Iss)) -jcass = 1.0/(exp((v + 18.08)/2.7916) + 1.0) -km2n = jca*1.0 # mS/uF -td = (offset + 0.6) + 1.0/(exp((-1*0.05)*((v + vShift) + 6.0)) + exp(0.09*((v + vShift) + 14.0))) # ms -tfcaf = 7.0 + 1.0/(0.04*exp((-(v - 1*4.0))/7.0) + 0.04*exp((v - 1*4.0)/7.0)) # ms -tfcafp = 2.5*tfcaf # ms -tfcas = 100.0 + 1.0/(0.00012*exp((-v)/3.0) + 0.00012*exp(v/7.0)) # ms -tff = 7.0 + 1.0/(0.0045*exp((-(v + 20.0))/10.0) + 0.0045*exp((v + 20.0)/10.0)) # ms -tffp = 2.5*tff # ms -tfs = 1000.0 + 1.0/(3.5e-5*exp((-(v + 5.0))/4.0) + 3.5e-5*exp((v + 5.0)/6.0)) # ms -dd_dt = (-d + dss)/td -dfcaf_dt = (-fcaf + fcass)/tfcaf -dfcafp_dt = (-fcafp + fcass)/tfcafp -dfcas_dt = (-fcas + fcass)/tfcas -dff__dt = (-ff_ + fss)/tff -dffp_dt = (-ffp + fss)/tffp -dfs_dt = (-fs + fss)/tfs -djca_dt = (-jca + jcass)/tjca -dnca_i_dt = anca_i*k2n - km2n*nca_i -dnca_ss_dt = anca_ss*k2n - km2n*nca_ss - -expressions("Ito") -AiF = 1.0/(exp(((EKshift + v) - 1*213.6)/151.2) + 1.0) -AiS = 1.0 - AiF -Gto = Conditional(Or(Eq(celltype, 1.0), Eq(celltype, 2.0)), 2.0*Gto_b, Gto_b) # mS/uF -Ito_Ito = (Gto*(-EK + v))*(i*(a*(1.0 - fItop)) + ip*(ap*fItop)) # A/F -ass = 1.0/(exp((-((EKshift + v) - 1*14.34))/14.82) + 1.0) -assp = 1.0/(exp((-((EKshift + v) - 1*24.34))/14.82) + 1.0) -delta_epi = Conditional(Eq(celltype, 1.0), 1.0 - 0.95/(exp(((EKshift + v) + 70.0)/5.0) + 1.0), 1.0) -dti_develop = 1.354 + 0.0001/(exp((-((EKshift + v) - 1*12.23))/0.2154) + exp(((EKshift + v) - 1*167.4)/15.89)) -dti_recover = 1.0 - 0.5/(exp(((EKshift + v) + 70.0)/20.0) + 1.0) -fItop = 1.0/(1.0 + KmCaMK/CaMKa) -i = AiF*iF + AiS*iS -ip = AiF*iFp + AiS*iSp -iss = 1.0/(exp(((EKshift + v) + 43.94)/5.711) + 1.0) -ta = 1.0515/(1.0/((1.2089*(exp((-((EKshift + v) - 1*18.4099))/29.3814) + 1.0))) + 3.5/(exp(((EKshift + v) + 100.0)/29.3814) + 1.0)) # ms -tiF = delta_epi*tiF_b # ms -tiF_b = 4.562 + 1.0/(0.3933*exp((-((EKshift + v) + 100.0))/100.0) + 0.08004*exp(((EKshift + v) + 50.0)/16.59)) # ms -tiFp = tiF*(dti_develop*dti_recover) # ms -tiS = delta_epi*tiS_b # ms -tiS_b = 23.62 + 1.0/(0.001416*exp((-((EKshift + v) + 96.52))/59.05) + 1.78e-8*exp(((EKshift + v) + 114.1)/8.079)) # ms -tiSp = tiS*(dti_develop*dti_recover) # ms -da_dt = (-a + ass)/ta -dap_dt = (-ap + assp)/ta -diF_dt = (-iF + iss)/tiF -diFp_dt = (-iFp + iss)/tiFp -diS_dt = (-iS + iss)/tiS -diSp_dt = (-iSp + iss)/tiSp - -expressions("intracellular_ions") -Bcajsr = 1.0/((csqnmax*kmcsqn)/((cajsr + kmcsqn)**2.0) + 1.0) -Bcass = 1.0/((BSLmax*KmBSL)/((KmBSL + cass)**2.0) + ((BSRmax*KmBSR)/((KmBSR + cass)**2.0) + 1.0)) -cmdnmax = Conditional(Eq(celltype, 1.0), 1.3*cmdnmax_b, cmdnmax_b) # mM -dcajsr_dt = Bcajsr*(-Jrel + Jtr) # mM -dcansr_dt = Jup - Jtr*vjsr/vnsr # mM -dcass_dt = Bcass*(-Jdiff + ((Acap*(-(ICaL_ss - 2.0*INaCa_ss)))/(((2.0*F)*vss)) + (Jrel*vjsr)/vss)) # mM -dcli_dt = (Acap*(IClCa_sl + IClb))/((F*vmyo)) + (JdiffCl*vss)/vmyo # mM -dclss_dt = -JdiffCl + (Acap*IClCa_junc)/((F*vss)) # mM -dki_dt = (Acap*(-(ICaK_i + (-2.0*INaK_INaK + (Istim + (I_katp_I_katp + (IKb_IKb + (IK1_IK1 + (IKs_IKs + (IKr_IKr + Ito_Ito))))))))))/((F*vmyo)) + (JdiffK*vss)/vmyo # mM -dkss_dt = -JdiffK + (Acap*(-ICaK_ss))/((F*vss)) # mM -dnai_dt = (Acap*(-(INab_INab + (3.0*INaK_INaK + (ICaNa_i + (3.0*INaCa_i + (INaL_INaL + INa_INa)))))))/((F*vmyo)) + (JdiffNa*vss)/vmyo # mM -dnass_dt = -JdiffNa + (Acap*(-(ICaNa_ss + 3.0*INaCa_ss)))/((F*vss)) # mM - -expressions("CaMK") -CaMKa = CaMKb + CaMKt # mM -CaMKb = (CaMKo*(1.0 - CaMKt))/(KmCaM/cass + 1.0) # mM -dCaMKt_dt = -CaMKt*bCaMK + (CaMKb*aCaMK)*(CaMKb + CaMKt) # mM - -expressions("INaK") -E1_ = x1/(x4 + (x3 + (x1 + x2))) -E2 = x2/(x4 + (x3 + (x1 + x2))) -E3 = x3/(x4 + (x3 + (x1 + x2))) -E4 = x4/(x4 + (x3 + (x1 + x2))) -INaK_INaK = Pnak*(JnakK*zk + JnakNa*zna) # A/F -JnakK = 2.0*(-E3*a1 + E4*b1) # mM/ms -JnakNa = 3.0*(E1_*a3 - E2*b3) # mM/ms -Knai = Knai0*exp((delta*vfrt)/3.0) # mM -Knao = Knao0*exp((vfrt*(1.0 - delta))/3.0) # mM -P = eP/(((H/Khp + 1.0) + nai/Knap) + ki/Kxkur) -Pnak = Conditional(Eq(celltype, 1.0), 0.9*Pnak_b, Conditional(Eq(celltype, 2.0), 0.7*Pnak_b, Pnak_b)) # mS/uF -a1 = (k1p*(nai/Knai)**3.0)/(((1.0 + ki/Kki)**2.0 + (1.0 + nai/Knai)**3.0) - 1*1.0) -a2 = k2p -a3 = (k3p*(ko/Kko)**2.0)/(((1.0 + ko/Kko)**2.0 + (1.0 + nao/Knao)**3.0) - 1*1.0) -a4 = ((MgATP*k4p)/Kmgatp)/(1.0 + MgATP/Kmgatp) -b1 = MgADP*k1m -b2 = (k2m*(nao/Knao)**3.0)/(((1.0 + ko/Kko)**2.0 + (1.0 + nao/Knao)**3.0) - 1*1.0) -b3 = (H*(P*k3m))/(1.0 + MgATP/Kmgatp) -b4 = (k4m*(ki/Kki)**2.0)/(((1.0 + ki/Kki)**2.0 + (1.0 + nai/Knai)**3.0) - 1*1.0) -x1 = a2*(a1*b3) + (b3*(a2*b4) + (a2*(a1*a4) + b3*(b2*b4))) -x2 = b4*(a2*a3) + (b4*(a3*b1) + (a3*(a1*a2) + b4*(b1*b2))) -x3 = b1*(a3*a4) + (a4*(b1*b2) + (a4*(a2*a3) + b1*(b2*b3))) -x4 = a1*(b2*b3) + (a1*(a4*b2) + (a1*(a3*a4) + b2*(b3*b4))) - -expressions("INaCa") -E1_i = x1_i/(x4_i + (x3_i + (x1_i + x2_i))) -E1_ss = x1_ss/(x4_ss + (x3_ss + (x1_ss + x2_ss))) -E2_i = x2_i/(x4_i + (x3_i + (x1_i + x2_i))) -E2_ss = x2_ss/(x4_ss + (x3_ss + (x1_ss + x2_ss))) -E3_i = x3_i/(x4_i + (x3_i + (x1_i + x2_i))) -E3_ss = x3_ss/(x4_ss + (x3_ss + (x1_ss + x2_ss))) -E4_i = x4_i/(x4_i + (x3_i + (x1_i + x2_i))) -E4_ss = x4_ss/(x4_ss + (x3_ss + (x1_ss + x2_ss))) -Gncx = Conditional(Eq(celltype, 1.0), 1.1*Gncx_b, Conditional(Eq(celltype, 2.0), 1.4*Gncx_b, Gncx_b)) # mS/uF -INaCa_i = (allo_i*(Gncx*(1.0 - INaCa_fractionSS)))*(JncxCa_i*zca + JncxNa_i*zna) # A/F -INaCa_ss = (allo_ss*(Gncx*INaCa_fractionSS))*(JncxCa_ss*zca + JncxNa_ss*zna) # A/F -JncxCa_i = -E1_i*k1_i + E2_i*k2_i # mM/ms -JncxCa_ss = -E1_ss*k1_ss + E2_ss*k2_ss # mM/ms -JncxNa_i = -E2_i*k3pp_i + (E3_i*k4pp_i + 3.0*(-E1_i*k8_i + E4_i*k7_i)) # mM/ms -JncxNa_ss = -E2_ss*k3pp_ss + (E3_ss*k4pp_ss + 3.0*(-E1_ss*k8_ss + E4_ss*k7_ss)) # mM/ms -allo_i = 1.0/((KmCaAct/cai)**2.0 + 1.0) -allo_ss = 1.0/((KmCaAct/cass)**2.0 + 1.0) -h10_i = (nao/kna1)*(1.0 + nao/kna2) + (kasymm + 1.0) -h10_ss = (nao/kna1)*(1.0 + nao/kna2) + (kasymm + 1.0) -h11_i = (nao*nao)/((kna2*(h10_i*kna1))) -h11_ss = (nao*nao)/((kna2*(h10_ss*kna1))) -h12_i = 1.0/h10_i -h12_ss = 1.0/h10_ss -h1_i = (nai/kna3)*(hna + 1.0) + 1.0 -h1_ss = (nass/kna3)*(hna + 1.0) + 1.0 -h2_i = (hna*nai)/((h1_i*kna3)) -h2_ss = (hna*nass)/((h1_ss*kna3)) -h3_i = 1.0/h1_i -h3_ss = 1.0/h1_ss -h4_i = (nai/kna1)*(1.0 + nai/kna2) + 1.0 -h4_ss = (nass/kna1)*(1.0 + nass/kna2) + 1.0 -h5_i = (nai*nai)/((kna2*(h4_i*kna1))) -h5_ss = (nass*nass)/((kna2*(h4_ss*kna1))) -h6_i = 1.0/h4_i -h6_ss = 1.0/h4_ss -h7_i = (nao/kna3)*(1.0 + 1.0/hna) + 1.0 -h7_ss = (nao/kna3)*(1.0 + 1.0/hna) + 1.0 -h8_i = nao/((h7_i*(hna*kna3))) -h8_ss = nao/((h7_ss*(hna*kna3))) -h9_i = 1.0/h7_i -h9_ss = 1.0/h7_ss -hca = exp(qca*vfrt) -hna = exp(qna*vfrt) -k1_i = kcaon*(cao*h12_i) -k1_ss = kcaon*(cao*h12_ss) -k2_i = kcaoff -k2_ss = kcaoff -k3_i = k3p_i + k3pp_i -k3_ss = k3p_ss + k3pp_ss -k3p_i = h9_i*wca -k3p_ss = h9_ss*wca -k3pp_i = h8_i*wnaca -k3pp_ss = h8_ss*wnaca -k4_i = k4p_i + k4pp_i -k4_ss = k4p_ss + k4pp_ss -k4p_i = (h3_i*wca)/hca -k4p_ss = (h3_ss*wca)/hca -k4pp_i = h2_i*wnaca -k4pp_ss = h2_ss*wnaca -k5_i = kcaoff -k5_ss = kcaoff -k6_i = kcaon*(cai*h6_i) -k6_ss = kcaon*(cass*h6_ss) -k7_i = wna*(h2_i*h5_i) -k7_ss = wna*(h2_ss*h5_ss) -k8_i = wna*(h11_i*h8_i) -k8_ss = wna*(h11_ss*h8_ss) -x1_i = (k2_i*k4_i)*(k6_i + k7_i) + (k5_i*k7_i)*(k2_i + k3_i) -x1_ss = (k2_ss*k4_ss)*(k6_ss + k7_ss) + (k5_ss*k7_ss)*(k2_ss + k3_ss) -x2_i = (k1_i*k7_i)*(k4_i + k5_i) + (k4_i*k6_i)*(k1_i + k8_i) -x2_ss = (k1_ss*k7_ss)*(k4_ss + k5_ss) + (k4_ss*k6_ss)*(k1_ss + k8_ss) -x3_i = (k1_i*k3_i)*(k6_i + k7_i) + (k6_i*k8_i)*(k2_i + k3_i) -x3_ss = (k1_ss*k3_ss)*(k6_ss + k7_ss) + (k6_ss*k8_ss)*(k2_ss + k3_ss) -x4_i = (k2_i*k8_i)*(k4_i + k5_i) + (k3_i*k5_i)*(k1_i + k8_i) -x4_ss = (k2_ss*k8_ss)*(k4_ss + k5_ss) + (k3_ss*k5_ss)*(k1_ss + k8_ss) - -expressions("reversal_potentials") -ECl = ((R*T)/((F*zcl)))*log(clo/cli) # mV -EClss = ((R*T)/((F*zcl)))*log(clo/clss) # mV -EK = ((R*T)/((F*zk)))*log(ko/ki) # mV -EKs = ((R*T)/((F*zk)))*log((PKNa*nao + ko)/(PKNa*nai + ki)) # mV -ENa = ((R*T)/((F*zna)))*log(nao/nai) # mV - -expressions("IK1") -GK1 = Conditional(Eq(celltype, 1.0), 1.2*GK1_b, Conditional(Eq(celltype, 2.0), 1.3*GK1_b, GK1_b)) # mS/uF -IK1_IK1 = (K1ss*(GK1*sqrt(ko/5.0)))*(-EK + v) # A/F -K1ss = aK1/(aK1 + bK1) -aK1 = 4.094/(exp(0.1217*((-EK + v) - 1*49.934)) + 1.0) -bK1 = (15.72*exp(0.0674*((-EK + v) - 1*3.257)) + exp(0.0618*((-EK + v) - 1*594.31)))/(exp((-1*0.1629)*((-EK + v) + 14.207)) + 1.0) - -expressions("IKb") -GKb = Conditional(Eq(celltype, 1.0), 0.6*GKb_b, GKb_b) # mS/uF -IKb_IKb = (GKb*xkb)*(-EK + v) # A/F -xkb = 1.0/(exp((-(v - 1*10.8968))/23.9871) + 1.0) - -expressions("IKr") -GKr = Conditional(Eq(celltype, 1.0), 1.3*GKr_b, Conditional(Eq(celltype, 2.0), 0.8*GKr_b, GKr_b)) # mS/uF -IKr_IKr = (O_*(GKr*sqrt(ko/5.0)))*(-EK + v) # A/F -alpha = 0.1161*exp(0.299*vfrt) # mS/uF -alpha_2 = 0.0578*exp(0.971*vfrt) # mS/uF -alpha_C2ToI = 5.2e-5*exp(1.525*vfrt) # mS/uF -alpha_i = 0.2533*exp(0.5953*vfrt) # mS/uF -beta_ = 0.2442*exp((-1*1.604)*vfrt) # mS/uF -beta_2 = 0.000349*exp((-1*1.062)*vfrt) # mS/uF -beta_ItoC2 = (alpha_C2ToI*(beta_2*beta_i))/((alpha_2*alpha_i)) # mS/uF -beta_i = 0.06525*exp((-1*0.8209)*vfrt) # mS/uF -dC1_dt = -C1*(alpha_C2ToI + (alpha_2 + beta_1)) + (I_*beta_ItoC2 + (C2*alpha_1 + O_*beta_2)) -dC2_dt = -C2*(alpha_1 + beta_) + (C1*beta_1 + C3*alpha) -dC3_dt = C2*beta_ - C3*alpha -dI__dt = -I_*(beta_ItoC2 + beta_i) + (C1*alpha_C2ToI + O_*alpha_i) -dO__dt = -O_*(alpha_i + beta_2) + (C1*alpha_2 + I_*beta_i) - -expressions("IKs") -GKs = Conditional(Eq(celltype, 1.0), 1.4*GKs_b, GKs_b) # mS/uF -IKs_IKs = (xs2*(xs1*(GKs*KsCa)))*(-EKs + v) # A/F -KsCa = 1.0 + 0.6/((3.8e-5/cai)**1.4 + 1.0) -txs1 = 817.3 + 1.0/(0.0002326*exp((v + 48.28)/17.8) + 0.001292*exp((-(v + 210.0))/230.0)) # ms -txs2 = 1.0/(0.01*exp((v - 1*50.0)/20.0) + 0.0193*exp((-(v + 66.54))/31.0)) # ms -xs1ss = 1.0/(exp((-(v + 11.6))/8.932) + 1.0) -xs2ss = xs1ss -dxs1_dt = (-xs1 + xs1ss)/txs1 -dxs2_dt = (-xs2 + xs2ss)/txs2 - -expressions("INaL") -GNaL = Conditional(Eq(celltype, 1.0), 0.6*GNaL_b, GNaL_b) # mS/uF -INaL_INaL = (mL*(GNaL*(-ENa + v)))*(fINaLp*hLp + hL*(1.0 - fINaLp)) # A/F -fINaLp = 1.0/(1.0 + KmCaMK/CaMKa) -hLss = 1.0/(exp((v + 87.61)/7.488) + 1.0) -hLssp = 1.0/(exp((v + 93.81)/7.488) + 1.0) -mLss = 1.0/(exp((-(v + 42.85))/5.264) + 1.0) -thLp = 3.0*thL # ms -tmL = 0.06487*exp(-((v - 1*4.823)/51.12)**2.0) + 0.1292*exp(-((v + 45.79)/15.54)**2.0) # ms -dhL_dt = (-hL + hLss)/thL -dhLp_dt = (-hLp + hLssp)/thLp -dmL_dt = (-mL + mLss)/tmL - -expressions("ICab") -ICab_ICab = ((vffrt*(PCab*4.0))*(-cao*gamma_cao + (cai*gamma_cai)*exp(2.0*vfrt)))/(exp(2.0*vfrt) - 1*1.0) # A/F - -expressions("ICl") -IClCa = IClCa_junc + IClCa_sl # A/F -IClCa_junc = ((Fjunc*GClCa)/(KdClCa/cass + 1.0))*(-EClss + v) # A/F -IClCa_sl = ((GClCa*(1.0 - Fjunc))/(KdClCa/cai + 1.0))*(-ECl + v) # A/F -IClb = GClb*(-ECl + v) # A/F - -expressions("INa") -INa_INa = (m**3.0*(GNa*(-ENa + v)))*(j*(h*(1.0 - fINap)) + jp*(fINap*hp)) # A/F -ah = Conditional(Gt(v, -1*40.0), 0.0, 4.43126792958051e-7*exp(-0.147058823529412*v)) -aj = Conditional(Gt(v, -1*40.0), 0.0, -(v + 37.78)*(25428.0*exp(0.28831*v) + 6.948e-6)*exp(-0.04391*v)/(50262745825.954*exp(0.311*v) + 1.0)) -bh = Conditional(Gt(v, -1*40.0), 0.77*exp(0.0900900900900901*v)/(0.13*exp(0.0900900900900901*v) + 0.0497581410839387), 2.7*exp(0.079*v) + 310000.0*exp(0.3485*v)) -bj = Conditional(Gt(v, -1*40.0), 0.6*exp(0.157*v)/(1.0*exp(0.1*v) + 0.0407622039783662), 0.02424*exp(0.12728*v)/(1.0*exp(0.1378*v) + 0.00396086833990426)) -fINap = 1.0/(1.0 + KmCaMK/CaMKa) -hss = 1.0/((exp((v + 71.55)/7.43) + 1.0)**2.0) -hssp = 1.0/((exp((v + 77.55)/7.43) + 1.0)**2.0) -jss = hss -mss = 1.0/((exp((-(v + 56.86))/9.03) + 1.0)**2.0) -th = 1.0/(ah + bh) # ms -tj = 1.0/(aj + bj) # ms -tjp = 1.46*tj # ms -tm = 0.06487*exp(-((v - 1*4.823)/51.12)**2.0) + 0.1292*exp(-((v + 45.79)/15.54)**2.0) # ms -dh_dt = (-h + hss)/th -dhp_dt = (-hp + hssp)/th -dj_dt = (-j + jss)/tj -djp_dt = (-jp + jss)/tjp -dm_dt = (-m + mss)/tm - -expressions("INab") -INab_INab = ((PNab*vffrt)*(nai*exp(vfrt) - nao))/(exp(vfrt) - 1*1.0) # A/F - -expressions("I_katp") -I_katp_I_katp = (bkik*(akik*(fkatp*gkatp)))*(-EK + v) # A/F -akik = (ko/K_o_n)**0.24 -bkik = 1.0/((A_atp/K_atp)**2.0 + 1.0) - -expressions("IpCa") -IpCa_IpCa = (GpCa*cai)/(KmCap + cai) # A/F - -expressions("membrane") -Istim = Conditional(And(Le(i_Stim_Start, time), Ge(i_Stim_PulseDuration, -i_Stim_Period*floor(-(i_Stim_Start - time)/i_Stim_Period) - i_Stim_Start + time)), i_Stim_Amplitude, 0.0) # A/F -vffrt = (F*(F*v))/((R*T)) # C/mol -vfrt = (F*v)/((R*T)) -dv_dt = -(Istim + (I_katp_I_katp + (IClb + (IClCa + (ICab_ICab + (IpCa_IpCa + (IKb_IKb + (INab_INab + (INaK_INaK + (INaCa_ss + (INaCa_i + (IK1_IK1 + (IKs_IKs + (IKr_IKr + (ICaK + (ICaNa + (ICaL_ICaL + (Ito_Ito + (INaL_INaL + INa_INa))))))))))))))))))) # mV - -expressions("diff") -Jdiff = (-cai + cass)/tauCa # mM/ms -JdiffCl = (-cli + clss)/tauNa # mM/ms -JdiffK = (-ki + kss)/tauK # mM/ms -JdiffNa = (-nai + nass)/tauNa # mM/ms - -expressions("SERCA") -Jleak = (0.0048825*cansr)/15.0 # mM/ms -Jup = Jup_b*(-Jleak + (Jupnp*(1.0 - fJupp) + Jupp*fJupp)) # mM/ms -Jupnp = (cai*(upScale*0.005425))/(cai + 0.00092) # mM/ms -Jupp = (cai*((upScale*2.75)*0.005425))/((cai + 0.00092) - 1*0.00017) # mM/ms -fJupp = 1.0/(1.0 + KmCaMK/CaMKa) -upScale = Conditional(Eq(celltype, 1.0), 1.3, 1.0) - -expressions("ryr") -Jrel = Jrel_b*(Jrel_np*(1.0 - fJrelp) + Jrel_p*fJrelp) # mM/ms -Jrel_inf = Conditional(Eq(celltype, 2.0), 1.7*Jrel_inf_b, Jrel_inf_b) # mM/ms -Jrel_inf_b = ((ICaL_ss*(-a_rel))/1.0)/((cajsr_half/cajsr)**8.0 + 1.0) # mM/ms -Jrel_infp = Conditional(Eq(celltype, 2.0), 1.7*Jrel_infp_b, Jrel_infp_b) # mM/ms -Jrel_infp_b = ((ICaL_ss*(-a_relp))/1.0)/((cajsr_half/cajsr)**8.0 + 1.0) # mM/ms -a_rel = (0.5*bt)/1.0 # mM/ms -a_relp = (0.5*btp)/1.0 # mM/ms -btp = 1.25*bt # ms -fJrelp = 1.0/(1.0 + KmCaMK/CaMKa) -tau_rel = Conditional(Lt(tau_rel_b, 0.001), 0.001, tau_rel_b) # ms -tau_rel_b = bt/(1.0 + 0.0123/cajsr) # ms -tau_relp = Conditional(Lt(tau_relp_b, 0.001), 0.001, tau_relp_b) # ms -tau_relp_b = btp/(1.0 + 0.0123/cajsr) # ms -dJrel_np_dt = (Jrel_inf - Jrel_np)/tau_rel # mM/ms -dJrel_p_dt = (Jrel_infp - Jrel_p)/tau_relp # mM/ms - -expressions("trans_flux") -Jtr = (-cajsr + cansr)/60.0 # mM/ms - - -states("mechanics-ep", -cai=0.0001, -XS=0, -XW=0, -CaTrpn=1e-8, -TmB=1 -) - -states("mechanics", -Zetas=0, -Zetaw=0, -Cd=0 -) - -parameters("mechanics-ep","mechanics", -emcoupling=1, -lmbda=1, -dLambda=0, -mode=1, -isacs=0, -calib=1, -ktrpn = 0.1, -ntrpn = 2, -Trpn50 = 0.35, -rw = 0.5, -rs = 0.25, -gammas = 0.0085, -gammaw = 0.615, -phi = 2.23, -Tot_A = 25, -Beta0 = 2.3, -Beta1 = -2.4, -cat50_ref = 0.805, -Tref = 120, -kuw = 0.182, -kws = 0.012, -ku=0.04, -ntm=2.4, -p_a = 2.1, -p_b = 9.1, -p_k = 7, -etal = 200, -etas = 20) - -expressions("mechanics-ep") -XS_max = Conditional(Gt(XS, 0), XS, 0) -XW_max = Conditional(Gt(XW, 0), XW, 0) -CaTrpn_max = Conditional(Gt(CaTrpn, 0), CaTrpn, 0) -kwu = kuw*(1/rw-1)-kws -ksu = kws*rw*(1/rs-1) -Aw = Tot_A*rs/((1-rs)*rw+rs) -As = Aw -cw = phi*kuw*((1-rs)*(1-rw))/((1-rs)*rw) -cs = phi*kws*((1-rs)*rw)/rs -XU = (1-TmB)-XS-XW -gammawu = gammaw*Abs(Zetaw) -gammasu = gammas*Conditional(Gt(Gt(Zetas,0)*Zetas, Lt(Zetas, -1)*(-Zetas-1)), Gt(Zetas,0)*Zetas, Lt(Zetas, -1)*(-Zetas-1)) -dXS_dt = kws*XW - ksu*XS - gammasu*XS -dXW_dt = kuw*XU - kwu*XW - kws*XW - gammawu*XW -cat50 = (cat50_ref+Beta1*(lambda_min12-1)) -dCaTrpn_dt = ktrpn*(((cai*1000/cat50)**ntrpn)*(1-CaTrpn)-CaTrpn) -kb = ku*Trpn50**ntm/(1-rs-(1-rs)*rw) -dTmB_dt = kb*Conditional(Lt(CaTrpn**(-ntm/2), 100), CaTrpn**(-ntm/2), 100)*XU-ku*CaTrpn**(ntm/2)*TmB -Bcai=1.0/(1.0+cmdnmax*kmcmdn/(kmcmdn+cai)**2.0) -J_TRPN = dCaTrpn_dt*trpnmax -dcai_dt=Bcai*(-(IpCa_IpCa+ICab_ICab-2.0*INaCa_i/3)*Acap/(2.0*F*vmyo)-Jup*vnsr/vmyo+Jdiff*vss/vmyo - J_TRPN) - - -expressions("mechanics-ep", "mechanics") -lambda_min12 = Conditional(Lt(lmbda, 1.2), lmbda, 1.2) - -expressions("mechanics") -Aw = Tot_A*rs/((1-rs)*rw+rs) -As = Aw -cw = phi*kuw*((1-rs)*(1-rw))/((1-rs)*rw) -cs = phi*kws*((1-rs)*rw)/rs -dZetas_dt = As*dLambda - cs*Zetas -dZetaw_dt = Aw*dLambda - cw*Zetaw -lambda_min087 = Conditional(Lt(lambda_min12, 0.87), lambda_min12, 0.87) -h_lambda_prima = 1+Beta0*(lambda_min12+lambda_min087-1.87) -h_lambda = Conditional(Gt(h_lambda_prima, 0), h_lambda_prima, 0) -Ta = h_lambda*(Tref/rs)*(XS*(Zetas+1) + XW*Zetaw) -C = lambda_min12 - 1 -dCd = C - Cd -eta = Conditional(Lt(dCd, 0), etas, etal) -dCd_dt = p_k * (C - Cd) / eta -Fd = eta * dCd -F1 = (exp( p_b * C) - 1) -Tp = p_a * (F1 + Fd) -Ttot = Ta + Tp diff --git a/demos/split-zeta/3D/config.toml b/demos/split-zeta/3D/config.toml deleted file mode 100644 index 55f5f73..0000000 --- a/demos/split-zeta/3D/config.toml +++ /dev/null @@ -1,129 +0,0 @@ -# Configuration file for running a simulation - -# SIMULATION PARAMETERS -sim.mech_mesh = "mesh_mech_0.5dx_0.5Lx_1Ly_2Lz" # mechanics mesh filepath without extension -sim.outdir = "100ms_N10_zeta_split" # Output directory -sim.sim_dur = 400 # Duration of simulation. Integer -sim.dt = 0.05 # Timestep for ep solve -sim.N = 400 # Solve mechanics step every nth ep solve - -# MODEL PARAMETERS -sim.modelfile = "ToRORd_dynCl_endo_zetasplit.ode" - -# OUTPUT PARAMETERS -write_all_ep.numbers = 2 -write_all_ep.0.name = "cai" -write_all_ep.1.name = "v" - -write_all_mech.numbers = 7 -write_all_mech.0.name = "Ta" -write_all_mech.1.name = "lambda" -write_all_mech.2.name = "dLambda" -write_all_mech.3.name = "XS" -write_all_mech.4.name = "XW" -write_all_mech.5.name = "Zetas" -write_all_mech.6.name = "Zetaw" - -# Currently also outputting volume averages for these: -write_point_ep.numbers = 4 -write_point_ep.0.name = "cai" -write_point_ep.0.x = 0.0 -write_point_ep.0.y = 0 -write_point_ep.0.z = 0 -write_point_ep.1.name = "v" -write_point_ep.1.x = 0 -write_point_ep.1.y = 0 -write_point_ep.1.z = 0 -write_point_ep.2.name = "CaTrpn" -write_point_ep.2.x = 0 -write_point_ep.2.y = 0 -write_point_ep.2.z = 0 -write_point_ep.3.name = "TmB" -write_point_ep.3.x = 0 -write_point_ep.3.y = 0 -write_point_ep.3.z = 0 - -write_point_mech.numbers = 6 -write_point_mech.0.name = "Ta" -write_point_mech.0.x = 0 -write_point_mech.0.y = 0 -write_point_mech.0.z = 0 -write_point_mech.1.name = "Zetas" -write_point_mech.1.x = 0 -write_point_mech.1.y = 0 -write_point_mech.1.z = 0 -write_point_mech.2.name = "XS" -write_point_mech.2.x = 0 -write_point_mech.2.y = 0 -write_point_mech.2.z = 0 -write_point_mech.3.name = "lambda" -write_point_mech.3.x = 0 -write_point_mech.3.y = 0 -write_point_mech.3.z = 0 -write_point_mech.4.name = "dLambda" -write_point_mech.4.x = 0 -write_point_mech.4.y = 0 -write_point_mech.4.z = 0 -write_point_mech.5.name = "p" -write_point_mech.5.x = 0 -write_point_mech.5.y = 0 -write_point_mech.5.z = 0 - -# Tissue conductivity values. Currently only a single region, from p.4339 of Niederer benchmark -ep.sigma_il = 0.17 # mS / mm -ep.sigma_it = 0.019 # mS / mm -ep.sigma_el = 0.62 # mS / mm -ep.sigma_et = 0.24 # mS / mm - -# Material parameters -# TODO: make material parameters more generic -mech.a=2.28 -mech.a_f=1.685 -mech.b=9.726 -mech.b_f=15.779 -mech.a_s=0.0 -mech.b_s=0.0 -mech.a_fs=0.0 -mech.b_fs=0.0 - -# STIMULUS PARAMETERS -stim.start = 0.0 -stim.amplitude = 50000.0 # mu A/cm^3 -stim.duration = 2 # ms -stim.xmin = 0.0 -stim.xmax = 1.5 -stim.ymin = 0.0 -stim.ymax = 1.5 -stim.zmin = 0.0 -stim.zmax = 1.5 - -# BOUNDARY CONDITIONS -bcs.numbers = 3 -bcs.markerfile = "mesh_mech_0.5dx_0.5Lx_1Ly_2Lz_surface_ffun" - -# Mesh markers used for assigning bcs -bcs.0.marker = 1 -bcs.0.type = "Dirichlet" -bcs.0.V = "u_x" -bcs.0.expression = 0 -bcs.0.param_numbers = 0 - -bcs.1.marker = 3 # if same marker for ux,uy,uz, (e.g. marker = 1), then fixes the entire plane (plane with marker == 1) -bcs.1.type = "Dirichlet" -bcs.1.V = "u_y" -bcs.1.expression = 0 -bcs.1.param_numbers = 0 - -bcs.2.marker = 5 -bcs.2.type = "Dirichlet" -bcs.2.V = "u_z" -bcs.2.expression = 0 -bcs.2.param_numbers = 0 - -#bcs.3.marker = 2 -#bcs.3.type = "Neumann" -#bcs.3.expression = 'a*t' # Value can be a function of t -#bcs.3.param_numbers = 1 -#bcs.3.param.0.name = 'a' -#bcs.3.param.0.value = -0.2 -#bcs.3.degree = 1 diff --git a/demos/split-zeta/3D/main_check_Ta.py b/demos/split-zeta/3D/main_check_Ta.py deleted file mode 100644 index ee9c148..0000000 --- a/demos/split-zeta/3D/main_check_Ta.py +++ /dev/null @@ -1,243 +0,0 @@ -import dolfin -import ufl_legacy as ufl -import pulse -import numpy as np -import matplotlib.pyplot as plt - - -# def load_timesteps_from_xdmf(xdmffile): -# times = {} -# i = 0 -# tree = ET.parse(xdmffile) -# for elem in tree.iter(): -# if elem.tag == "Time": -# times[i] = float(elem.get("Value")) -# i += 1 - -# return times - - -mesh = dolfin.Mesh() -with dolfin.XDMFFile("mesh_mech_0.5dx_0.5Lx_1Ly_2Lz.xdmf") as infile: - infile.read(mesh) - - -ffun_bcs = dolfin.MeshFunction("size_t", mesh, mesh.topology().dim() - 1) -with dolfin.XDMFFile("mesh_mech_0.5dx_0.5Lx_1Ly_2Lz_surface_ffun.xdmf") as infile: - infile.read(ffun_bcs) - - -material_parameters = dict( - a=2.28, - a_f=1.685, - b=9.726, - b_f=15.779, - a_s=0.0, - b_s=0.0, - a_fs=0.0, - b_fs=0.0, -) - - -dolfin.parameters["form_compiler"]["representation"] = "uflacs" -dolfin.parameters["form_compiler"]["cpp_optimize"] = True -dolfin.parameters["form_compiler"]["quadrature_degree"] = 4 - - -marker_functions = pulse.MarkerFunctions(ffun=ffun_bcs) - - -def create_boundary_conditions( - ffun_bcs, -): # TODO: update to not need separate dirichlet and neumann list - def dirichlet_bc(W): - bcs_W = { - "u_x": W.sub(0).sub(0), - "u_y": W.sub(0).sub(1), - "u_z": W.sub(0).sub(2), - # TODO: add the rest (check dolfin doc) - } - - bcs = [] - for V, marker in [("u_x", 1), ("u_y", 3), ("u_z", 5)]: - bcs.append( - dolfin.DirichletBC( - bcs_W[V], - 0.0, - ffun_bcs, - marker, - ) - ) - return bcs - - # Collect Boundary Conditions - bcs = pulse.BoundaryConditions(dirichlet=(dirichlet_bc,)) - return bcs - - -f0 = dolfin.as_vector([1.0, 0.0, 0.0]) -s0 = dolfin.as_vector([0.0, 1.0, 0.0]) -n0 = dolfin.as_vector([0.0, 0.0, 1.0]) -microstructure = pulse.Microstructure(f0=f0, s0=s0, n0=n0) -geometry = pulse.Geometry( - mesh=mesh, marker_functions=marker_functions, microstructure=microstructure -) - -fig_mean, ax_mean = plt.subplots(3, 1, sharex=True) -fig_u, ax_u = plt.subplots(3, 2, sharex=True, sharey="row") -for k, N in enumerate([1, 400]): - xdmffile_ta = f"check_Ta/N{N}/Ta_out_mech.xdmf" - xdmffile_u = f"check_Ta/N{N}/disp.xdmf" - - if N == 1: - times = [400 * i for i in range(25)] - elif N == 400: - times = list(range(25)) - - timepoint = 50 - W = dolfin.FunctionSpace(mesh, "DG", 1) - V = dolfin.VectorFunctionSpace(mesh, "CG", 2) - U = dolfin.Function(V) - Ta_mean = [] - lmbda_mean = [] - lmbda_U_mean = [] - Tas = [] - lmbdas = [] - lmbdas_U = [] - dlmbdas = [] - dlmbdas_U = [] - Ta = dolfin.Function(W) - lmbda = dolfin.Function(W) - lmbda_U = dolfin.Function(W) - - lmbda_prev = dolfin.Function(W) - lmbda_U_prev = dolfin.Function(W) - lmbda_prev.vector()[:] = 1.0 - lmbda_U_prev.vector()[:] = 1.0 - - dlmbda = dolfin.Function(W) - dlmbda_U = dolfin.Function(W) - - ux = [] - uy = [] - uz = [] - Ux = [] - Uy = [] - Uz = [] - - material = pulse.HolzapfelOgden( - parameters=material_parameters, - active_model="active_stress", - activation=Ta, - f0=f0, - s0=s0, - n0=n0, - ) - - # Collect Boundary Conditions - bcs = create_boundary_conditions(ffun_bcs) - - problem = pulse.MechanicsProblem(geometry, material, bcs) - - problem.solve() - - for i in times: - with dolfin.XDMFFile(xdmffile_ta) as infile: - infile.read_checkpoint(Ta, "Ta", i) - - with dolfin.XDMFFile(xdmffile_u) as infile: - infile.read_checkpoint(U, "disp", i) - - problem.solve() - u, p = problem.state.split(deepcopy=True) - F = ufl.grad(u) + ufl.Identity(3) - lmda_expr = ufl.sqrt(ufl.inner(F * f0, F * f0)) - lmbda.assign(dolfin.project(lmda_expr, W)) - - dlmbda.assign(lmbda - lmbda_prev) - lmbda_prev.vector()[:] = lmbda.vector()[:] - - F_U = ufl.grad(U) + ufl.Identity(3) - lmda_expr_U = ufl.sqrt(ufl.inner(F_U * f0, F_U * f0)) - lmbda_U.assign(dolfin.project(lmda_expr_U, W)) - - dlmbda_U.assign(lmbda_U - lmbda_U_prev) - lmbda_U_prev.vector()[:] = lmbda_U.vector()[:] - - ux.append(dolfin.assemble(u.sub(0) * dolfin.dx)) - uy.append(dolfin.assemble(u.sub(1) * dolfin.dx)) - uz.append(dolfin.assemble(u.sub(2) * dolfin.dx)) - Ux.append(dolfin.assemble(U.sub(0) * dolfin.dx)) - Uy.append(dolfin.assemble(U.sub(1) * dolfin.dx)) - Uz.append(dolfin.assemble(U.sub(2) * dolfin.dx)) - - # ux.append(u.vector().get_local()[0::3]) - # uy.append(u.vector().get_local()[1::3]) - # uz.append(u.vector().get_local()[2::3]) - # Ux.append(U.vector().get_local()[0::3]) - # Uy.append(U.vector().get_local()[1::3]) - # Uz.append(U.vector().get_local()[2::3]) - - Tas.append(Ta.vector().get_local()) - lmbdas.append(lmbda.vector().get_local()) - lmbdas_U.append(lmbda_U.vector().get_local()) - Ta_mean.append(dolfin.assemble(Ta * dolfin.dx)) - lmbda_mean.append(dolfin.assemble(lmda_expr * dolfin.dx)) - lmbda_U_mean.append(dolfin.assemble(lmda_expr_U * dolfin.dx)) - dlmbdas.append(dolfin.assemble(dlmbda * dolfin.dx)) - dlmbdas_U.append(dolfin.assemble(dlmbda_U * dolfin.dx)) - - Tas = np.array(Tas) - lmbdas = np.array(lmbdas) - lmbdas_U = np.array(lmbdas_U) - # ux = np.array(ux) - # uy = np.array(uy) - # uz = np.array(uz) - - ax_u[0, k].plot(ux, label="computed") - ax_u[0, k].plot(Ux, label="saved") - ax_u[0, k].set_title(N) - ax_u[1, k].plot(uy, label="computed") - ax_u[1, k].plot(Uy, label="saved") - ax_u[2, k].plot(uz, label="computed") - ax_u[2, k].plot(Uz, label="saved") - - fig, ax = plt.subplots(2, 2, sharex=True) - ax[0, 0].plot(Tas[:, ::4]) - ax[0, 0].set_title("Ta") - ax[0, 1].plot(lmbdas[:, ::4]) - ax[0, 1].set_title("lmbda") - ax[1, 0].plot(Ta_mean) - ax[1, 0].set_title("Ta mean") - ax[1, 1].plot(lmbda_mean, label="lmbda") - ax[1, 1].plot(lmbda_U_mean, label="lmbda (saved)") - ax[1, 1].legend() - ax[1, 1].set_title("lmbda mean") - - for axi in ax.flatten(): - axi.grid() - fig.savefig(f"check_Ta/N{N}/Ta_points.png") - - ax_mean[0].plot(Ta_mean, label=f"N={N}") - ax_mean[1].plot(lmbda_mean, label=f"N={N}") - ax_mean[1].plot(lmbda_U_mean, label=f"N={N} (saved)") - ax_mean[2].plot(dlmbdas, label=f"N={N}") - ax_mean[2].plot(dlmbdas_U, label=f"N={N} (saved)") - -for axi in ax_mean: - axi.grid() -ax_mean[0].set_title("Ta mean") -ax_mean[1].set_title("lmbda mean") -ax_mean[0].legend() -ax_mean[1].legend() -fig_mean.savefig("check_Ta/mean.png") - -ax_u[0, 0].set_ylabel("ux") -ax_u[1, 0].set_ylabel("uy") -ax_u[2, 0].set_ylabel("uz") -for axi in ax_u.flatten(): - axi.grid() -ax_u[1, 1].legend() -fig_u.savefig("check_Ta/u.png") - -exit() diff --git a/demos/split-zeta/3D/main_using_config.py b/demos/split-zeta/3D/main_using_config.py deleted file mode 100644 index 53ab868..0000000 --- a/demos/split-zeta/3D/main_using_config.py +++ /dev/null @@ -1,684 +0,0 @@ -import logging -import gotranx -from pathlib import Path -from typing import Sequence -import numpy as np -import dolfin -import pulse -import beat -import argparse -import toml -import matplotlib.pyplot as plt - - -from simcardems2 import utils -from simcardems2 import mechanicssolver -from simcardems2 import interpolation -from simcardems2.land_Zetasplit import LandModel -from simcardems2.validate_input_types import validate_input_types - - -try: - raise ImportError - from numba import jit -except ImportError: - - def jit(*args, **kwargs): - def wrapper(func): - return func - - return wrapper - - -logging.getLogger("beat").setLevel(logging.ERROR) - - -def parse_parameters(argv: Sequence[str] | None = None) -> int: - parser = argparse.ArgumentParser(description="Simcardems CLI") - parser.add_argument("config-file", type=Path, help="Config file") - - args = vars(parser.parse_args(argv)) - try: - config = toml.loads(args["config-file"].read_text()) - except toml.TomlDecodeError as e: - print(f"Error when parsing input parameters. Check config file. Error: {e}") - exit(1) - return config - - -config = parse_parameters() - -validate_input_types(config) - -stim_region = ( - [config["stim"]["xmin"], config["stim"]["xmax"]], - [config["stim"]["ymin"], config["stim"]["ymax"]], - [config["stim"]["zmin"], config["stim"]["zmax"]], -) -out_ep_var_names = [ - config["write_all_ep"][f"{i}"]["name"] for i in range(config["write_all_ep"]["numbers"]) -] -out_mech_var_names = [ - config["write_all_mech"][f"{i}"]["name"] for i in range(config["write_all_mech"]["numbers"]) -] -out_ep_coord_names = [ - config["write_point_ep"][f"{i}"]["name"] for i in range(config["write_point_ep"]["numbers"]) -] -ep_coords = [ - [config["write_point_ep"][f"{varnr}"][f"{coord}"] for coord in ["x", "y", "z"]] - for varnr in range(config["write_point_ep"]["numbers"]) -] -out_mech_coord_names = [ - config["write_point_mech"][f"{i}"]["name"] for i in range(config["write_point_mech"]["numbers"]) -] -mech_coords = [ - [config["write_point_mech"][f"{varnr}"][f"{coord}"] for coord in ["x", "y", "z"]] - for varnr in range(config["write_point_mech"]["numbers"]) -] - - -outdir = Path(config["sim"]["outdir"]) -outdir.mkdir(parents=True, exist_ok=True) - -with open(Path(outdir / "config.txt"), "w") as f: - f.write(toml.dumps(config)) - - -# TODO: do a different dirichlet/neumann check than this later. something smoother -t_bcs = dolfin.Constant(0) -bcs_dirichlet = [] -bcs_neumann = [] -bcs_expressions = {} -for bc in range(config["bcs"]["numbers"]): - if config["bcs"][f"{bc}"]["type"] == "Dirichlet": - bcs_dirichlet.append(bc) - elif config["bcs"][f"{bc}"]["type"] == "Neumann": - bcs_neumann.append(bc) - else: - raise KeyError( - f'{config["bcs"][str(bc)]["type"]} is not a valid type of boundary ' - 'condition. Use Dirichlet or Neumann. Check config file' - ) - - if config["bcs"][f"{bc}"]["param_numbers"] > 0: - bcs_parameters = {} - for param_nr in range(config["bcs"][f"{bc}"]["param_numbers"]): - param_name = config["bcs"][f"{bc}"]["param"][f"{param_nr}"]["name"] - param_value = config["bcs"][f"{bc}"]["param"][f"{param_nr}"]["value"] - bcs_parameters[param_name] = param_value - bcs_expressions[f"{bc}"] = dolfin.Expression( - config["bcs"][f"{bc}"]["expression"], - **bcs_parameters, - t=t_bcs, - degree=config["bcs"][f"{bc}"]["degree"], - ) - else: - bcs_expressions[f"{bc}"] = dolfin.Constant(0) - - -mesh = dolfin.Mesh() -with dolfin.XDMFFile(f'{config["sim"]["mech_mesh"]}.xdmf') as infile: - infile.read(mesh) -print(f'Loaded mesh: {config["sim"]["mech_mesh"]}') - - -ffun_bcs = dolfin.MeshFunction("size_t", mesh, mesh.topology().dim() - 1) -with dolfin.XDMFFile(f'{config["bcs"]["markerfile"]}.xdmf') as infile: - infile.read(ffun_bcs) -print(f'Loaded markerfile for bcs: {config["bcs"]["markerfile"]}') - - -tol = 5e-4 -# Surface to volume ratio -chi = 140.0 # mm^{-1} -# Membrane capacitance -C_m = 0.01 # mu F / mm^2 -cm2mm = 10.0 - -t = np.arange(0, config["sim"]["sim_dur"], config["sim"]["dt"]) -sigma = [ - config["ep"]["sigma_il"], - config["ep"]["sigma_it"], - config["ep"]["sigma_el"], - config["ep"]["sigma_et"], -] -material_parameters = dict( - a=config["mech"]["a"], - a_f=config["mech"]["a_f"], - b=config["mech"]["b"], - b_f=config["mech"]["b_f"], - a_s=config["mech"]["a_s"], - b_s=config["mech"]["b_s"], - a_fs=config["mech"]["a_fs"], - b_fs=config["mech"]["b_fs"], -) - - -dolfin.parameters["form_compiler"]["representation"] = "uflacs" -dolfin.parameters["form_compiler"]["cpp_optimize"] = True -dolfin.parameters["form_compiler"]["quadrature_degree"] = 4 - - -def define_conductivity_tensor(sigma, chi, C_m): - # Compute monodomain approximation by taking harmonic mean in each - # direction of intracellular and extracellular part - def harmonic_mean(a, b): - return a * b / (a + b) - - sigma_l = harmonic_mean(sigma[0], sigma[2]) - sigma_t = harmonic_mean(sigma[1], sigma[3]) - - # Scale conducitivites by 1/(C_m * chi) - s_l = sigma_l / (C_m * chi) # mm^2 / ms - s_t = sigma_t / (C_m * chi) # mm^2 / ms - - # Define conductivity tensor - M = dolfin.as_tensor(((s_l, 0, 0), (0, s_t, 0), (0, 0, s_t))) - - return M - - -def define_stimulus( - mesh, - chi, - C_m, - time, - stim_region=stim_region, - stim_start=config["stim"]["start"], - A=config["stim"]["amplitude"], - duration=config["stim"]["duration"], -): - S1_marker = 1 - S1_subdomain = dolfin.CompiledSubDomain( - " ".join( - ( - f"x[0] >= {stim_region[0][0]}", - f"&& x[0] <= {stim_region[0][1]}", - f"&& x[1] >= {stim_region[1][0]}", - f"&& x[1] <= {stim_region[1][1]}", - f"&& x[2] >= {stim_region[2][0]}", - f"&& x[2] <= {stim_region[2][1]}", - ) - ) - ) - - S1_markers = dolfin.MeshFunction("size_t", mesh, mesh.topology().dim()) - S1_subdomain.mark(S1_markers, S1_marker) - with dolfin.XDMFFile((outdir / "stim_region_markers.xdmf").as_posix()) as xdmf: - xdmf.write(S1_markers) - - # Define stimulation (NB: region of interest carried by the mesh - # and assumptions in cbcbeat) - factor = 1.0 / (chi * C_m) # NB: cbcbeat convention - amplitude = factor * A * (1.0 / cm2mm) ** 3 # mV/ms - - I_s = dolfin.Expression( - "time >= start ? (time <= (duration + start) ? amplitude : 0.0) : 0.0", - time=time, - start=config["stim"]["start"], - duration=duration, - amplitude=amplitude, - degree=0, - ) - - dx = dolfin.Measure("dx", domain=mesh, subdomain_data=S1_markers)(S1_marker) - return beat.base_model.Stimulus(dz=dx, expr=I_s) - - -# Load the model -if not Path("ep_model.py").exists(): - ode = gotranx.load_ode(config["sim"]["modelfile"]) - - mechanics_comp = ode.get_component("mechanics") - mechanics_ode = mechanics_comp.to_ode() - - ep_ode = ode - mechanics_comp - - # Generate code for the electrophysiology model - code_ep = gotranx.cli.gotran2py.get_code( - ep_ode, - scheme=[gotranx.schemes.Scheme.forward_generalized_rush_larsen], - missing_values=mechanics_ode.missing_variables, - ) - # Generate code for the mechanics model - code_mechanics = gotranx.cli.gotran2py.get_code( - mechanics_ode, - scheme=[gotranx.schemes.Scheme.forward_generalized_rush_larsen], - missing_values=ep_ode.missing_variables, - ) - - Path("ep_model.py").write_text(code_ep) - # Currently 3D mech needs to be written manually - -import ep_model as _ep_model - -ep_model = _ep_model.__dict__ - - -# Validate ep variables to output -for i in list(set(out_ep_coord_names) | set(out_ep_var_names)): - try: - var = ep_model["state_index"](i) - except KeyError: - print(f"{i} is not an ep state. Check config file") - raise - -# Forwared generalized rush larsen scheme for the electrophysiology model -fgr_ep = jit(nopython=True)(ep_model["forward_generalized_rush_larsen"]) -# Monitor function for the electrophysiology model -mon_ep = ep_model["monitor_values"] -# Missing values function for the electrophysiology model -mv_ep = ep_model["missing_values"] -lmbda_index_ep = ep_model["parameter_index"]("lmbda") - - -# Get initial values from the EP model -y_ep_ = ep_model["init_state_values"]() -p_ep_ = ep_model["init_parameter_values"](i_Stim_Amplitude=0.0) -# breakpoint() - -ep_missing_values_ = np.zeros(len(ep_model["missing"])) - - -# ep_mesh = dolfin.adapt(dolfin.adapt(dolfin.adapt(mesh))) -ep_mesh = mesh # For testing consistency across splits! Otherwise refine -# ep_mesh = dolfin.adapt(mesh) - -time = dolfin.Constant(0.0) -I_s = define_stimulus( - mesh=ep_mesh, - chi=chi, - C_m=C_m, - time=time, - stim_region=stim_region, - stim_start=config["stim"]["start"], - A=config["stim"]["amplitude"], - duration=config["stim"]["duration"], -) -M = define_conductivity_tensor(sigma, chi, C_m) -params = {"preconditioner": "sor", "use_custom_preconditioner": False} -ep_ode_space = dolfin.FunctionSpace(ep_mesh, "DG", 1) -v_ode = dolfin.Function(ep_ode_space) -num_points_ep = v_ode.vector().local_size() -lmbda = dolfin.Function(ep_ode_space) - -y_ep = np.zeros((len(y_ep_), num_points_ep)) -y_ep.T[:] = y_ep_ - -mechanics_missing_values_ = np.zeros(2) - -# Set the activation -activation_space = dolfin.FunctionSpace(mesh, "DG", 1) -activation = dolfin.Function(activation_space) -num_points_mech = activation.vector().local_size() - - -missing_mech = interpolation.MissingValue( - element=activation.ufl_element(), - interpolation_element=ep_ode_space.ufl_element(), - mechanics_mesh=mesh, - ep_mesh=ep_mesh, - num_values=len(mechanics_missing_values_), -) - -missing_ep = interpolation.MissingValue( - element=ep_ode_space.ufl_element(), - interpolation_element=activation.ufl_element(), - mechanics_mesh=mesh, - ep_mesh=ep_mesh, - num_values=len(ep_missing_values_), -) - - -missing_mech.values_ep.T[:] = mechanics_missing_values_ -missing_ep.values_mechanics.T[:] = ep_missing_values_ -missing_ep.values_ep.T[:] = ep_missing_values_ -missing_mech.values_mechanics.T[:] = mechanics_missing_values_ - - -# Create function spaces for ep state parameters to output -out_ep_funcs = {} -for out_ep_var in list(set(out_ep_var_names) | set(out_ep_coord_names)): - out_ep_funcs[out_ep_var] = dolfin.Function(ep_ode_space) - - -p_ep = np.zeros((len(p_ep_), num_points_ep)) -p_ep.T[:] = p_ep_ - -pde = beat.MonodomainModel(time=time, mesh=ep_mesh, M=M, I_s=I_s, params=params) -ode = beat.odesolver.DolfinODESolver( - v_ode=dolfin.Function(ep_ode_space), - v_pde=pde.state, - fun=fgr_ep, - parameters=p_ep, - init_states=y_ep, - num_states=len(y_ep), - v_index=ep_model["state_index"]("v"), - missing_variables=missing_ep.values_ep, - num_missing_variables=len(ep_model["missing"]), -) - -# ep_solver = beat.MonodomainSplittingSolver(pde=pde, ode=ode, theta=0.5) -ep_solver = beat.MonodomainSplittingSolver(pde=pde, ode=ode, theta=1) - -marker_functions = pulse.MarkerFunctions(ffun=ffun_bcs) - - -def create_boundary_conditions( - ffun_bcs, bcs_dirichlet, bcs_neumann, bcs_dict, bcs_expressions -): # TODO: update to not need separate dirichlet and neumann list - def dirichlet_bc(W): - bcs_W = { - "u_x": W.sub(0).sub(0), - "u_y": W.sub(0).sub(1), - "u_z": W.sub(0).sub(2), - # TODO: add the rest (check dolfin doc) - } - - bcs = [] - for bc in bcs_dirichlet: - bcs.append( - dolfin.DirichletBC( - bcs_W[bcs_dict[f"{bc}"]["V"]], - bcs_expressions[f"{bc}"], # TODO: use dolfin expression - ffun_bcs, - bcs_dict[f"{bc}"]["marker"], - ) - ) - return bcs - - neumann_bc = [] - if bcs_neumann is not None: - for bc in bcs_neumann: - neumann_bc.append( - pulse.NeumannBC( - traction=utils.float_to_constant(bcs_expressions[f"{bc}"]), - marker=bcs_dict[f"{bc}"]["marker"], - ) - ) - - # Collect Boundary Conditions - bcs = pulse.BoundaryConditions(dirichlet=(dirichlet_bc,), neumann=neumann_bc) - return bcs - - -f0 = dolfin.as_vector([1.0, 0.0, 0.0]) -s0 = dolfin.as_vector([0.0, 1.0, 0.0]) -n0 = dolfin.as_vector([0.0, 0.0, 1.0]) -microstructure = pulse.Microstructure(f0=f0, s0=s0, n0=n0) -geometry = pulse.Geometry( - mesh=mesh, marker_functions=marker_functions, microstructure=microstructure -) - -active_model = LandModel( - f0=f0, - s0=s0, - n0=n0, - XS=missing_mech.u_mechanics[0], - XW=missing_mech.u_mechanics[1], - mesh=mesh, - eta=0, - dLambda_tol=1e-12, -) -active_model.t = 0.0 - -sigma_ff = dolfin.Function(activation_space) -sigma_ff_active = dolfin.Function(activation_space) -sigma_ff_passive = dolfin.Function(activation_space) - - -mech_variables = { - "Ta": active_model.Ta_current, - "Zetas": active_model._Zetas, - "Zetaw": active_model._Zetaw, - "lambda": active_model.lmbda, - "XS": active_model.XS, - "XW": active_model.XW, - "dLambda": active_model._dLambda, - "sigma_ff": sigma_ff, - "sigma_ff_active": sigma_ff_active, - "sigma_ff_passive": sigma_ff_passive, -} - -material = pulse.HolzapfelOgden( - parameters=material_parameters, - active_model=active_model, - f0=f0, - s0=s0, - n0=n0, -) - - -def compute_function_average_over_mesh(func, mesh): - volume = dolfin.assemble(dolfin.Constant(1.0) * dolfin.dx(domain=mesh)) - return dolfin.assemble(func * dolfin.dx(domain=mesh)) / volume - - -# Collect Boundary Conditions -bcs = create_boundary_conditions( - ffun_bcs, bcs_dirichlet, bcs_neumann, config["bcs"], bcs_expressions -) - -problem = mechanicssolver.MechanicsProblem(geometry, material, bcs) -problem.solve(0.0, 0.0) - -mech_variables["p"] = problem.state.split()[1] - - -# Validate mechanics variables to output -for out_mech_var in list(set(out_mech_coord_names) | set(out_mech_var_names)): - assert ( - out_mech_var in mech_variables - ), f"Error: '{out_mech_var}' is not a valid variable name. Check config file" - - -disp_file = Path(outdir / "disp.xdmf") -disp_file.unlink(missing_ok=True) -disp_file.with_suffix(".h5").unlink(missing_ok=True) - -out_ep_files = {} -for out_ep_var in out_ep_var_names: - out_ep_files[out_ep_var] = Path(outdir / f"{out_ep_var}_out_ep.xdmf") - out_ep_files[out_ep_var].unlink(missing_ok=True) - out_ep_files[out_ep_var].with_suffix(".h5").unlink(missing_ok=True) - -out_mech_files = {} -for out_mech_var in out_mech_var_names: - out_mech_files[out_mech_var] = Path(outdir / f"{out_mech_var}_out_mech.xdmf") - out_mech_files[out_mech_var].unlink(missing_ok=True) - out_mech_files[out_mech_var].with_suffix(".h5").unlink(missing_ok=True) - - -# Create arrays for storing values to plot time series for example nodes -out_ep_example_nodes = {} -for out_ep_var in out_ep_coord_names: - out_ep_example_nodes[out_ep_var] = np.zeros(len(t)) - -out_mech_example_nodes = {} -for out_mech_var in out_mech_coord_names: - out_mech_example_nodes[out_mech_var] = np.zeros(len(t)) - -# Create arrays for storing values to plot time series for volume averages -out_ep_volume_average_timeseries = {} -for out_ep_var in out_ep_coord_names: - out_ep_volume_average_timeseries[out_ep_var] = np.zeros(len(t)) - -out_mech_volume_average_timeseries = {} -for out_mech_var in out_mech_coord_names: - out_mech_volume_average_timeseries[out_mech_var] = np.zeros(len(t)) - - -inds = [] # Array with time-steps for which we solve mechanics -j = 0 -timer = dolfin.Timer("solve_loop") -for i, ti in enumerate(t): - print(f"Solving time {ti:.2f} ms") - t_bcs.assign(ti) - ep_solver.step((ti, ti + config["sim"]["dt"])) - - # Assign values to ep function - for out_ep_var in list(set(out_ep_var_names) | set(out_ep_coord_names)): - # out_ep_funcs[out_ep_var].vector()[:] = ode._values[out_indices[out_ep_var]] - out_ep_funcs[out_ep_var].vector()[:] = ode._values[ep_model["state_index"](out_ep_var)] - - # Store values to plot time series for given coord - for var_nr in range(config["write_point_ep"]["numbers"]): - out_ep_var = config["write_point_ep"][f"{var_nr}"]["name"] - out_ep_example_nodes[out_ep_var][i] = out_ep_funcs[out_ep_var](ep_coords[var_nr]) - # Compute volume averages - out_ep_volume_average_timeseries[out_ep_var][i] = compute_function_average_over_mesh( - out_ep_funcs[out_ep_var], ep_mesh - ) - - if i % config["sim"]["N"] != 0: - continue - - missing_ep_values = mv_ep( - ti + config["sim"]["dt"], ode._values, ode.parameters, missing_ep.values_ep - ) - - for k in range(missing_mech.num_values): - missing_mech.u_ep_int[k].vector()[:] = missing_ep_values[k, :] - - missing_mech.interpolate_ep_to_mechanics() - missing_mech.mechanics_function_to_values() - inds.append(i) - - print("Solve mechanics") - active_model.t = ti + config["sim"]["N"] * config["sim"]["dt"] # Addition! - problem.solve(ti, config["sim"]["N"] * config["sim"]["dt"]) - - missing_ep.u_mechanics_int[0].interpolate(active_model._Zetas) - missing_ep.u_mechanics_int[1].interpolate(active_model._Zetaw) - - missing_ep.interpolate_mechanics_to_ep() - missing_ep.ep_function_to_values() - lmbda.interpolate(active_model.lmbda) - p_ep[lmbda_index_ep, :] = lmbda.vector().get_local() # p_ep are the ep parameters - print( - active_model.lmbda.vector().get_local().min(), - active_model.lmbda.vector().get_local().max(), - ) - - U, p = problem.state.split(deepcopy=True) - - for var_nr in range(config["write_point_mech"]["numbers"]): - out_mech_var = config["write_point_mech"][f"{var_nr}"]["name"] - out_mech_example_nodes[out_mech_var][i] = mech_variables[out_mech_var](mech_coords[var_nr]) - - # Compute volume averages - out_mech_volume_average_timeseries[out_mech_var][i] = compute_function_average_over_mesh( - mech_variables[out_mech_var], mesh - ) - - with dolfin.XDMFFile(disp_file.as_posix()) as file: - file.write_checkpoint(U, "disp", j, dolfin.XDMFFile.Encoding.HDF5, True) - for out_ep_var in out_ep_var_names: - with dolfin.XDMFFile(out_ep_files[out_ep_var].as_posix()) as file: - file.write_checkpoint( - out_ep_funcs[out_ep_var], - out_ep_var, - j, - dolfin.XDMFFile.Encoding.HDF5, - True, - ) - for out_mech_var in out_mech_var_names: - with dolfin.XDMFFile(out_mech_files[out_mech_var].as_posix()) as file: - file.write_checkpoint( - mech_variables[out_mech_var], - out_mech_var, - j, - dolfin.XDMFFile.Encoding.HDF5, - True, - ) - - j += 1 -timer.stop() -timings = dolfin.timings( - dolfin.TimingClear.keep, - [dolfin.TimingType.wall, dolfin.TimingType.user, dolfin.TimingType.system], -).str(True) -print(timings) -with open(Path(outdir / "solve_timings.txt"), "w") as f: - f.write(timings) - -# Write averaged results for later analysis -for out_ep_var in out_ep_coord_names: - with open(Path(outdir / f"{out_ep_var}_out_ep_volume_average.txt"), "w") as f: - np.savetxt(f, out_ep_volume_average_timeseries[out_ep_var][inds]) - -for out_mech_var in out_mech_coord_names: - with open(Path(outdir / f"{out_mech_var}_out_mech_volume_average.txt"), "w") as f: - np.savetxt(f, out_mech_volume_average_timeseries[out_mech_var][inds]) - -# Write point traces for later analysis -for var_nr in range(config["write_point_ep"]["numbers"]): - out_ep_var = config["write_point_ep"][f"{var_nr}"]["name"] - with open( - Path( - outdir - / f"{out_ep_var}_ep_coord{ep_coords[var_nr][0]},{ep_coords[var_nr][1]},{ep_coords[var_nr][2]}.txt".replace( - " ", "" - ) - ), - "w", - ) as f: - np.savetxt(f, out_ep_example_nodes[out_ep_var][inds]) - -for var_nr in range(config["write_point_mech"]["numbers"]): - out_mech_var = config["write_point_mech"][f"{var_nr}"]["name"] - with open( - Path( - outdir - / f"{out_mech_var}_mech_coord{mech_coords[var_nr][0]},{mech_coords[var_nr][1]},{mech_coords[var_nr][2]}.txt" - ), - "w", - ) as f: - np.savetxt(f, out_mech_example_nodes[out_mech_var][inds]) - -print(f"Solved on {100 * len(inds) / len(t)}% of the time steps") -inds = np.array(inds) - -# Plot the results -fig, ax = plt.subplots(len(out_ep_coord_names), 1, figsize=(10, 10)) -if len(out_ep_coord_names) == 1: - ax = np.array([ax]) -for i, out_ep_var in enumerate(out_ep_coord_names): - ax[i].plot(t[inds], out_ep_volume_average_timeseries[out_ep_var][inds]) - ax[i].set_title(f"{out_ep_var} volume average") - ax[i].set_xlabel("Time (ms)") -fig.tight_layout() -fig.savefig(Path(outdir / "out_ep_volume_averages.png")) - -fig, ax = plt.subplots(len(out_ep_coord_names), 1, figsize=(10, 10)) -if len(out_ep_coord_names) == 1: - ax = np.array([ax]) -for var_nr in range(config["write_point_ep"]["numbers"]): - out_ep_var = config["write_point_ep"][f"{var_nr}"]["name"] - ax[var_nr].plot(t[inds], out_ep_example_nodes[out_ep_var][inds]) - ax[var_nr].set_title(f"{out_ep_var} in coord {ep_coords[var_nr]}") - ax[var_nr].set_xlabel("Time (ms)") -fig.tight_layout() -fig.savefig(Path(outdir / "out_ep_coord.png")) - -fig, ax = plt.subplots(len(out_mech_coord_names), 1, figsize=(10, 10)) -if len(out_mech_coord_names) == 1: - ax = np.array([ax]) -for i, out_mech_var in enumerate(out_mech_coord_names): - ax[i].plot(t[inds], out_mech_volume_average_timeseries[out_mech_var][inds]) - ax[i].set_title(f"{out_mech_var} volume average") - ax[i].set_xlabel("Time (ms)") -fig.tight_layout() -fig.savefig(Path(outdir / "out_mech_volume_averages.png")) - -fig, ax = plt.subplots(len(out_mech_coord_names), 1, figsize=(10, 10)) -if len(out_mech_coord_names) == 1: - ax = np.array([ax]) - -for var_nr in range(config["write_point_mech"]["numbers"]): - out_mech_var = config["write_point_mech"][f"{var_nr}"]["name"] - ax[var_nr].plot(t[inds], out_mech_example_nodes[out_mech_var][inds]) - ax[var_nr].set_title(f"{out_mech_var} in coord {mech_coords[var_nr]}") - ax[var_nr].set_xlabel("Time (ms)") -fig.tight_layout() -fig.savefig(Path(outdir / "out_mech_coord.png")) diff --git a/demos/split-zeta/3D/main_using_config_no_ep.py b/demos/split-zeta/3D/main_using_config_no_ep.py deleted file mode 100644 index 425a91e..0000000 --- a/demos/split-zeta/3D/main_using_config_no_ep.py +++ /dev/null @@ -1,234 +0,0 @@ -import logging -from pathlib import Path -import numpy as np -import dolfin -import pulse -import matplotlib.pyplot as plt - - -from simcardems2 import mechanicssolver -from simcardems2.land_Zetasplit import LandModel - - -try: - raise ImportError - from numba import jit -except ImportError: - - def jit(*args, **kwargs): - def wrapper(func): - return func - - return wrapper - - -logging.getLogger("beat").setLevel(logging.ERROR) - -mesh = dolfin.Mesh() -with dolfin.XDMFFile("mesh_mech_0.5dx_0.5Lx_1Ly_2Lz.xdmf") as infile: - infile.read(mesh) - - -ffun_bcs = dolfin.MeshFunction("size_t", mesh, mesh.topology().dim() - 1) -with dolfin.XDMFFile("mesh_mech_0.5dx_0.5Lx_1Ly_2Lz_surface_ffun.xdmf") as infile: - infile.read(ffun_bcs) - - -material_parameters = dict( - a=2.28, - a_f=1.685, - b=9.726, - b_f=15.779, - a_s=0.0, - b_s=0.0, - a_fs=0.0, - b_fs=0.0, -) -dolfin.parameters["form_compiler"]["representation"] = "uflacs" -dolfin.parameters["form_compiler"]["cpp_optimize"] = True -dolfin.parameters["form_compiler"]["quadrature_degree"] = 4 - - -time = dolfin.Constant(0.0) - -mechanics_missing_values_ = np.zeros(2) - -# Set the activation -activation_space = dolfin.FunctionSpace(mesh, "DG", 1) -activation = dolfin.Function(activation_space) -num_points_mech = activation.vector().local_size() -marker_functions = pulse.MarkerFunctions(ffun=ffun_bcs) - - -def create_boundary_conditions( - ffun_bcs, -): # TODO: update to not need separate dirichlet and neumann list - def dirichlet_bc(W): - bcs_W = { - "u_x": W.sub(0).sub(0), - "u_y": W.sub(0).sub(1), - "u_z": W.sub(0).sub(2), - # TODO: add the rest (check dolfin doc) - } - - bcs = [] - for V, marker in [("u_x", 1), ("u_y", 3), ("u_z", 5)]: - bcs.append( - dolfin.DirichletBC( - bcs_W[V], - 0.0, - ffun_bcs, - marker, - ) - ) - return bcs - - # Collect Boundary Conditions - bcs = pulse.BoundaryConditions(dirichlet=(dirichlet_bc,)) - return bcs - - -f0 = dolfin.as_vector([1.0, 0.0, 0.0]) -s0 = dolfin.as_vector([0.0, 1.0, 0.0]) -n0 = dolfin.as_vector([0.0, 0.0, 1.0]) -microstructure = pulse.Microstructure(f0=f0, s0=s0, n0=n0) -geometry = pulse.Geometry( - mesh=mesh, marker_functions=marker_functions, microstructure=microstructure -) - -XS = dolfin.Function(activation_space) -XW = dolfin.Function(activation_space) - -active_model = LandModel( - f0=f0, - s0=s0, - n0=n0, - XS=XS, - XW=XW, - mesh=mesh, - eta=0, - dLambda_tol=1e-12, -) -active_model.t = 0.0 - -sigma_ff = dolfin.Function(activation_space) -sigma_ff_active = dolfin.Function(activation_space) -sigma_ff_passive = dolfin.Function(activation_space) - - -mech_variables = { - "Ta": active_model.Ta_current, - "Zetas": active_model._Zetas, - "Zetaw": active_model._Zetaw, - "lambda": active_model.lmbda, - "XS": active_model.XS, - "XW": active_model.XW, - "dLambda": active_model._dLambda, - "sigma_ff": sigma_ff, - "sigma_ff_active": sigma_ff_active, - "sigma_ff_passive": sigma_ff_passive, -} - -material = pulse.HolzapfelOgden( - parameters=material_parameters, - active_model=active_model, - f0=f0, - s0=s0, - n0=n0, -) - - -def compute_function_average_over_mesh(func, mesh): - volume = dolfin.assemble(dolfin.Constant(1.0) * dolfin.dx(domain=mesh)) - return dolfin.assemble(func * dolfin.dx(domain=mesh)) / volume - - -# Collect Boundary Conditions -bcs = create_boundary_conditions(ffun_bcs) - -problem = mechanicssolver.MechanicsProblem(geometry, material, bcs) -problem.solve(0.0, 0.0) - - -N = 400 -dt_ep = 0.05 - -dt = 0.05 * N - -inds = [] # Array with time-steps for which we solve mechanics -j = 0 - -outdir = Path("no-ep") -outdir.mkdir(exist_ok=True) -disp_file = outdir / "disp.xdmf" -disp_file.unlink(missing_ok=True) -disp_file.with_suffix(".h5").unlink(missing_ok=True) - -lmbda_saved = dolfin.Function(activation_space) - -timer = dolfin.Timer("solve_loop") -Tas = [] -Tas_saved = [] -lmbdas = [] -lmbdas_saved = [] -for i in range(20): - ti = i * dt - print(f"Solving time {ti:.2f} ms") - - with dolfin.XDMFFile("100ms_N10_zeta_split/XW_out_mech.xdmf") as infile: - infile.read_checkpoint(XW, "XW", i) - - with dolfin.XDMFFile("100ms_N10_zeta_split/XS_out_mech.xdmf") as infile: - infile.read_checkpoint(XS, "XS", i) - - with dolfin.XDMFFile("100ms_N10_zeta_split/Zetas_out_mech.xdmf") as infile: - infile.read_checkpoint(active_model._Zetas, "Zetas", i) - - with dolfin.XDMFFile("100ms_N10_zeta_split/Zetaw_out_mech.xdmf") as infile: - infile.read_checkpoint(active_model._Zetaw, "Zetaw", i) - - with dolfin.XDMFFile("100ms_N10_zeta_split/Ta_out_mech.xdmf") as infile: - infile.read_checkpoint(active_model.Ta_current, "Ta", i) - - with dolfin.XDMFFile("100ms_N10_zeta_split/lambda_out_mech.xdmf") as infile: - infile.read_checkpoint(lmbda_saved, "lambda", i) - - print("Solve mechanics") - # active_model._t_prev = ti - - active_model.t = ti + dt - problem.solve(ti, dt) - active_model.update_prev() - - U, p = problem.state.split(deepcopy=True) - - Ta = active_model.Ta(active_model.lmbda) - Ta_mean = dolfin.assemble(Ta * dolfin.dx) - lmbda_mean = dolfin.assemble(active_model.lmbda * dolfin.dx) - lmbdas.append(lmbda_mean) - lmbdas_saved.append(dolfin.assemble(lmbda_saved * dolfin.dx)) - Tas.append(Ta_mean) - Tas_saved.append(dolfin.assemble(active_model.Ta_current * dolfin.dx)) - - with dolfin.XDMFFile(disp_file.as_posix()) as file: - file.write_checkpoint(U, "disp", j, dolfin.XDMFFile.Encoding.HDF5, True) - - -print(np.argmax(Tas)) -print(np.argmin(lmbdas)) -fig, ax = plt.subplots(2, 1, sharex=True) -ax[0].plot(Tas, label="Computed") -ax[0].plot(Tas_saved, linestyle="--", label="Saved") -# ax[0].plot(active_model.Ta_before, label="Ta before") -# ax[0].plot(active_model.Ta_after, linestyle="--", label="Ta after") -ax[0].set_ylabel("Ta") -ax[1].plot(lmbdas, label="Computed") -ax[1].plot(lmbdas_saved, linestyle="--", label="Saved") -# ax[1].plot(active_model.lmbda_before, label="Lambda before") -# ax[1].plot(active_model.lmbda_after, linestyle="--", label="Lambda after") -ax[1].set_ylabel("Lambda") -for axi in ax: - axi.grid() - axi.legend() -fig.savefig(outdir / "Ta.png") -# breakpoint() diff --git a/demos/split-zeta/3D/main_using_config_time.py b/demos/split-zeta/3D/main_using_config_time.py deleted file mode 100644 index a13ad93..0000000 --- a/demos/split-zeta/3D/main_using_config_time.py +++ /dev/null @@ -1,720 +0,0 @@ -import logging -import gotranx -from pathlib import Path -from typing import Sequence -import numpy as np -import dolfin -import pulse -import beat -import argparse -import toml -import matplotlib.pyplot as plt - -from simcardems2 import utils -from simcardems2 import mechanicssolver -from simcardems2 import interpolation -from simcardems2.land_Zetasplit import LandModel -from simcardems2.validate_input_types import validate_input_types - -plot_results = True -write_disp = True - - -try: - raise ImportError - from numba import jit -except ImportError: - - def jit(*args, **kwargs): - def wrapper(func): - return func - - return wrapper - - -logging.getLogger("beat").setLevel(logging.ERROR) - - -def parse_parameters(argv: Sequence[str] | None = None) -> int: - parser = argparse.ArgumentParser(description="Simcardems CLI") - parser.add_argument("config-file", type=Path, help="Config file") - - args = vars(parser.parse_args(argv)) - try: - config = toml.loads(args["config-file"].read_text()) - except toml.TomlDecodeError as e: - print(f"Error when parsing input parameters. Check config file. Error: {e}") - exit(1) - return config - - -config = parse_parameters() - -validate_input_types(config) - -stim_region = ( - [config["stim"]["xmin"], config["stim"]["xmax"]], - [config["stim"]["ymin"], config["stim"]["ymax"]], - [config["stim"]["zmin"], config["stim"]["zmax"]], -) -out_ep_var_names = [ - config["write_all_ep"][f"{i}"]["name"] for i in range(config["write_all_ep"]["numbers"]) -] -out_mech_var_names = [ - config["write_all_mech"][f"{i}"]["name"] for i in range(config["write_all_mech"]["numbers"]) -] -out_ep_coord_names = [ - config["write_point_ep"][f"{i}"]["name"] for i in range(config["write_point_ep"]["numbers"]) -] -ep_coords = [ - [config["write_point_ep"][f"{varnr}"][f"{coord}"] for coord in ["x", "y", "z"]] - for varnr in range(config["write_point_ep"]["numbers"]) -] -out_mech_coord_names = [ - config["write_point_mech"][f"{i}"]["name"] for i in range(config["write_point_mech"]["numbers"]) -] -mech_coords = [ - [config["write_point_mech"][f"{varnr}"][f"{coord}"] for coord in ["x", "y", "z"]] - for varnr in range(config["write_point_mech"]["numbers"]) -] - - -outdir = Path(config["sim"]["outdir"]) -outdir.mkdir(parents=True, exist_ok=True) - -with open(Path(outdir / "config.txt"), "w") as f: - f.write(toml.dumps(config)) - - -# TODO: do a different dirichlet/neumann check than this later. something smoother -t_bcs = dolfin.Constant(0) -bcs_dirichlet = [] -bcs_neumann = [] -bcs_expressions = {} -for bc in range(config["bcs"]["numbers"]): - if config["bcs"][f"{bc}"]["type"] == "Dirichlet": - bcs_dirichlet.append(bc) - elif config["bcs"][f"{bc}"]["type"] == "Neumann": - bcs_neumann.append(bc) - else: - raise KeyError( - f'{config["bcs"][str(bc)]["type"]} is not a valid type of boundary ' - 'condition. Use Dirichlet or Neumann. Check config file' - ) - - if config["bcs"][f"{bc}"]["param_numbers"] > 0: - bcs_parameters = {} - for param_nr in range(config["bcs"][f"{bc}"]["param_numbers"]): - param_name = config["bcs"][f"{bc}"]["param"][f"{param_nr}"]["name"] - param_value = config["bcs"][f"{bc}"]["param"][f"{param_nr}"]["value"] - bcs_parameters[param_name] = param_value - bcs_expressions[f"{bc}"] = dolfin.Expression( - config["bcs"][f"{bc}"]["expression"], - **bcs_parameters, - t=t_bcs, - degree=config["bcs"][f"{bc}"]["degree"], - ) - else: - bcs_expressions[f"{bc}"] = dolfin.Constant(0) - - -mesh = dolfin.Mesh() -with dolfin.XDMFFile(f'{config["sim"]["mech_mesh"]}.xdmf') as infile: - infile.read(mesh) -print(f'Loaded mesh: {config["sim"]["mech_mesh"]}') - - -ffun_bcs = dolfin.MeshFunction("size_t", mesh, mesh.topology().dim() - 1) -with dolfin.XDMFFile(f'{config["bcs"]["markerfile"]}.xdmf') as infile: - infile.read(ffun_bcs) -print(f'Loaded markerfile for bcs: {config["bcs"]["markerfile"]}') - - -tol = 5e-4 -# Surface to volume ratio -chi = 140.0 # mm^{-1} -# Membrane capacitance -C_m = 0.01 # mu F / mm^2 -cm2mm = 10.0 - -t = np.arange(0, config["sim"]["sim_dur"], config["sim"]["dt"]) - -sigma = [ - config["ep"]["sigma_il"], - config["ep"]["sigma_it"], - config["ep"]["sigma_el"], - config["ep"]["sigma_et"], -] -material_parameters = dict( - a=config["mech"]["a"], - a_f=config["mech"]["a_f"], - b=config["mech"]["b"], - b_f=config["mech"]["b_f"], - a_s=config["mech"]["a_s"], - b_s=config["mech"]["b_s"], - a_fs=config["mech"]["a_fs"], - b_fs=config["mech"]["b_fs"], -) - - -dolfin.parameters["form_compiler"]["representation"] = "uflacs" -dolfin.parameters["form_compiler"]["cpp_optimize"] = True -dolfin.parameters["form_compiler"]["quadrature_degree"] = 4 - - -def define_conductivity_tensor(sigma, chi, C_m): - # Compute monodomain approximation by taking harmonic mean in each - # direction of intracellular and extracellular part - def harmonic_mean(a, b): - return a * b / (a + b) - - sigma_l = harmonic_mean(sigma[0], sigma[2]) - sigma_t = harmonic_mean(sigma[1], sigma[3]) - - # Scale conducitivites by 1/(C_m * chi) - s_l = sigma_l / (C_m * chi) # mm^2 / ms - s_t = sigma_t / (C_m * chi) # mm^2 / ms - - # Define conductivity tensor - M = dolfin.as_tensor(((s_l, 0, 0), (0, s_t, 0), (0, 0, s_t))) - - return M - - -def define_stimulus( - mesh, - chi, - C_m, - time, - stim_region=stim_region, - stim_start=config["stim"]["start"], - A=config["stim"]["amplitude"], - duration=config["stim"]["duration"], -): - S1_marker = 1 - S1_subdomain = dolfin.CompiledSubDomain( - " ".join( - ( - f"x[0] >= {stim_region[0][0]}", - f"&& x[0] <= {stim_region[0][1]}", - f"&& x[1] >= {stim_region[1][0]}", - f"&& x[1] <= {stim_region[1][1]}", - f"&& x[2] >= {stim_region[2][0]}", - f"&& x[2] <= {stim_region[2][1]}", - ) - ) - ) - - S1_markers = dolfin.MeshFunction("size_t", mesh, mesh.topology().dim()) - S1_subdomain.mark(S1_markers, S1_marker) - with dolfin.XDMFFile((outdir / "stim_region_markers.xdmf").as_posix()) as xdmf: - xdmf.write(S1_markers) - - # Define stimulation (NB: region of interest carried by the mesh - # and assumptions in cbcbeat) - factor = 1.0 / (chi * C_m) # NB: cbcbeat convention - amplitude = factor * A * (1.0 / cm2mm) ** 3 # mV/ms - - I_s = dolfin.Expression( - "time >= start ? (time <= (duration + start) ? amplitude : 0.0) : 0.0", - time=time, - start=config["stim"]["start"], - duration=duration, - amplitude=amplitude, - degree=0, - ) - - dx = dolfin.Measure("dx", domain=mesh, subdomain_data=S1_markers)(S1_marker) - return beat.base_model.Stimulus(dz=dx, expr=I_s) - - -# Load the model -if not Path("ep_model.py").exists(): - ode = gotranx.load_ode(config["sim"]["modelfile"]) - - mechanics_comp = ode.get_component("mechanics") - mechanics_ode = mechanics_comp.to_ode() - - ep_ode = ode - mechanics_comp - - # Generate code for the electrophysiology model - code_ep = gotranx.cli.gotran2py.get_code( - ep_ode, - scheme=[gotranx.schemes.Scheme.forward_generalized_rush_larsen], - missing_values=mechanics_ode.missing_variables, - ) - # Generate code for the mechanics model - code_mechanics = gotranx.cli.gotran2py.get_code( - mechanics_ode, - scheme=[gotranx.schemes.Scheme.forward_generalized_rush_larsen], - missing_values=ep_ode.missing_variables, - ) - - Path("ep_model.py").write_text(code_ep) - # Currently 3D mech needs to be written manually - -import ep_model as _ep_model - -ep_model = _ep_model.__dict__ - - -# Validate ep variables to output -for i in list(set(out_ep_coord_names) | set(out_ep_var_names)): - try: - var = ep_model["state_index"](i) - except KeyError: - print(f"{i} is not an ep state. Check config file") - raise - -# Forwared generalized rush larsen scheme for the electrophysiology model -fgr_ep = jit(nopython=True)(ep_model["forward_generalized_rush_larsen"]) -# Monitor function for the electrophysiology model -mon_ep = ep_model["monitor_values"] -# Missing values function for the electrophysiology model -mv_ep = ep_model["missing_values"] -lmbda_index_ep = ep_model["parameter_index"]("lmbda") - - -# Get initial values from the EP model -y_ep_ = ep_model["init_state_values"]() -p_ep_ = ep_model["init_parameter_values"](i_Stim_Amplitude=0.0) - -ep_missing_values_ = np.zeros(len(ep_model["missing"])) - -ep_mesh = mesh -# ep_mesh = dolfin.adapt(mesh) -# ep_mesh = dolfin.adapt(dolfin.adapt(mesh)) -# ep_mesh = dolfin.adapt(dolfin.adapt(dolfin.adapt(mesh))) -# ep_mesh = dolfin.adapt(dolfin.adapt(dolfin.adapt(dolfin.adapt(mesh)))) - - -time = dolfin.Constant(0.0) -I_s = define_stimulus( - mesh=ep_mesh, - chi=chi, - C_m=C_m, - time=time, - stim_region=stim_region, - stim_start=config["stim"]["start"], - A=config["stim"]["amplitude"], - duration=config["stim"]["duration"], -) -M = define_conductivity_tensor(sigma, chi, C_m) -params = {"preconditioner": "sor", "use_custom_preconditioner": False} -ep_ode_space = dolfin.FunctionSpace(ep_mesh, "DG", 1) -v_ode = dolfin.Function(ep_ode_space) -num_points_ep = v_ode.vector().local_size() -lmbda = dolfin.Function(ep_ode_space) - -y_ep = np.zeros((len(y_ep_), num_points_ep)) -y_ep.T[:] = y_ep_ - -mechanics_missing_values_ = np.zeros(2) - -# Set the activation -activation_space = dolfin.FunctionSpace(mesh, "DG", 1) -activation = dolfin.Function(activation_space) -num_points_mech = activation.vector().local_size() - - -missing_mech = interpolation.MissingValue( - element=activation.ufl_element(), - interpolation_element=ep_ode_space.ufl_element(), - mechanics_mesh=mesh, - ep_mesh=ep_mesh, - num_values=len(mechanics_missing_values_), -) - -missing_ep = interpolation.MissingValue( - element=ep_ode_space.ufl_element(), - interpolation_element=activation.ufl_element(), - mechanics_mesh=mesh, - ep_mesh=ep_mesh, - num_values=len(ep_missing_values_), -) - - -missing_mech.values_ep.T[:] = mechanics_missing_values_ -missing_ep.values_mechanics.T[:] = ep_missing_values_ -missing_ep.values_ep.T[:] = ep_missing_values_ -missing_mech.values_mechanics.T[:] = mechanics_missing_values_ - - -# Create function spaces for ep state parameters to output -out_ep_funcs = {} -for out_ep_var in list(set(out_ep_var_names) | set(out_ep_coord_names)): - out_ep_funcs[out_ep_var] = dolfin.Function(ep_ode_space) - - -p_ep = np.zeros((len(p_ep_), num_points_ep)) -p_ep.T[:] = p_ep_ - -pde = beat.MonodomainModel(time=time, mesh=ep_mesh, M=M, I_s=I_s, params=params) -ode = beat.odesolver.DolfinODESolver( - v_ode=dolfin.Function(ep_ode_space), - v_pde=pde.state, - fun=fgr_ep, - parameters=p_ep, - init_states=y_ep, - num_states=len(y_ep), - v_index=ep_model["state_index"]("v"), - missing_variables=missing_ep.values_ep, - num_missing_variables=len(ep_model["missing"]), -) - -# ep_solver = beat.MonodomainSplittingSolver(pde=pde, ode=ode, theta=0.5) -ep_solver = beat.MonodomainSplittingSolver(pde=pde, ode=ode, theta=1) - -marker_functions = pulse.MarkerFunctions(ffun=ffun_bcs) - - -def create_boundary_conditions( - ffun_bcs, bcs_dirichlet, bcs_neumann, bcs_dict, bcs_expressions -): # TODO: update to not need separate dirichlet and neumann list - def dirichlet_bc(W): - bcs_W = { - "u_x": W.sub(0).sub(0), - "u_y": W.sub(0).sub(1), - "u_z": W.sub(0).sub(2), - # TODO: add the rest (check dolfin doc) - } - - bcs = [] - for bc in bcs_dirichlet: - bcs.append( - dolfin.DirichletBC( - bcs_W[bcs_dict[f"{bc}"]["V"]], - bcs_expressions[f"{bc}"], # TODO: use dolfin expression - ffun_bcs, - bcs_dict[f"{bc}"]["marker"], - ) - ) - return bcs - - neumann_bc = [] - if bcs_neumann is not None: - for bc in bcs_neumann: - neumann_bc.append( - pulse.NeumannBC( - traction=utils.float_to_constant(bcs_expressions[f"{bc}"]), - marker=bcs_dict[f"{bc}"]["marker"], - ) - ) - - # Collect Boundary Conditions - bcs = pulse.BoundaryConditions(dirichlet=(dirichlet_bc,), neumann=neumann_bc) - return bcs - - -f0 = dolfin.as_vector([1.0, 0.0, 0.0]) -s0 = dolfin.as_vector([0.0, 1.0, 0.0]) -n0 = dolfin.as_vector([0.0, 0.0, 1.0]) -microstructure = pulse.Microstructure(f0=f0, s0=s0, n0=n0) -geometry = pulse.Geometry( - mesh=mesh, marker_functions=marker_functions, microstructure=microstructure -) - -active_model = LandModel( - f0=f0, - s0=s0, - n0=n0, - XS=missing_mech.u_mechanics[0], - XW=missing_mech.u_mechanics[1], - mesh=mesh, - eta=0, - dLambda_tol=1e-12, -) -active_model.t = 0.0 - -sigma_ff = dolfin.Function(activation_space) -sigma_ff_active = dolfin.Function(activation_space) -sigma_ff_passive = dolfin.Function(activation_space) - - -mech_variables = { - "Ta": active_model.Ta_current, - "Zetas": active_model._Zetas, - "Zetaw": active_model._Zetaw, - "lambda": active_model.lmbda, - "XS": active_model.XS, - "XW": active_model.XW, - "dLambda": active_model._dLambda, - "sigma_ff": sigma_ff, - "sigma_ff_active": sigma_ff_active, - "sigma_ff_passive": sigma_ff_passive, -} - -# Validate mechanics variables to output -for out_mech_var in list(set(out_mech_coord_names) | set(out_mech_var_names)): - assert ( - out_mech_var in mech_variables - ), f"Error: '{out_mech_var}' is not a valid variable name. Check config file" - -material = pulse.HolzapfelOgden( - parameters=material_parameters, - active_model=active_model, - f0=f0, - s0=s0, - n0=n0, -) - - -def compute_function_average_over_mesh(func, mesh): - volume = dolfin.assemble(dolfin.Constant(1.0) * dolfin.dx(domain=mesh)) - return dolfin.assemble(func * dolfin.dx(domain=mesh)) / volume - - -# Collect Boundary Conditions -bcs = create_boundary_conditions( - ffun_bcs, bcs_dirichlet, bcs_neumann, config["bcs"], bcs_expressions -) - -problem = mechanicssolver.MechanicsProblem(geometry, material, bcs) -problem.solve(0.0, 0.0) - -disp_file = Path(outdir / "disp.xdmf") -disp_file.unlink(missing_ok=True) -disp_file.with_suffix(".h5").unlink(missing_ok=True) - -out_ep_files = {} -for out_ep_var in out_ep_var_names: - out_ep_files[out_ep_var] = Path(outdir / f"{out_ep_var}_out_ep.xdmf") - out_ep_files[out_ep_var].unlink(missing_ok=True) - out_ep_files[out_ep_var].with_suffix(".h5").unlink(missing_ok=True) - -out_mech_files = {} -for out_mech_var in out_mech_var_names: - out_mech_files[out_mech_var] = Path(outdir / f"{out_mech_var}_out_mech.xdmf") - out_mech_files[out_mech_var].unlink(missing_ok=True) - out_mech_files[out_mech_var].with_suffix(".h5").unlink(missing_ok=True) - - -# Create arrays for storing values to plot time series for example nodes -out_ep_example_nodes = {} -for out_ep_var in out_ep_coord_names: - out_ep_example_nodes[out_ep_var] = np.zeros(len(t)) - -out_mech_example_nodes = {} -for out_mech_var in out_mech_coord_names: - out_mech_example_nodes[out_mech_var] = np.zeros(len(t)) - -# Create arrays for storing values to plot time series for volume averages -out_ep_volume_average_timeseries = {} -for out_ep_var in out_ep_coord_names: - out_ep_volume_average_timeseries[out_ep_var] = np.zeros(len(t)) - -out_mech_volume_average_timeseries = {} -for out_mech_var in out_mech_coord_names: - out_mech_volume_average_timeseries[out_mech_var] = np.zeros(len(t)) - - -inds = [] # Array with time-steps for which we solve mechanics -j = 0 -total_timer = dolfin.Timer("total") -timings_solveloop = [] -timings_ep_steps = [] -timings_mech_steps = [] -no_of_newton_iterations = [] -timings_var_transfer = [] -for i, ti in enumerate(t): - timing_single_loop = dolfin.Timer("single_loop") - print(f"Solving time {ti:.2f} ms") - t_bcs.assign(ti) - - timing_ep = dolfin.Timer("ep time") - ep_solver.step((ti, ti + config["sim"]["dt"])) - timing_ep.stop() - timings_ep_steps.append(timing_ep.elapsed()[0]) - - # Assign values to ep function - for out_ep_var in list(set(out_ep_var_names) | set(out_ep_coord_names)): - # out_ep_funcs[out_ep_var].vector()[:] = ode._values[out_indices[out_ep_var]] - out_ep_funcs[out_ep_var].vector()[:] = ode._values[ep_model["state_index"](out_ep_var)] - - # Store values to plot time series for given coord - for var_nr in range(config["write_point_ep"]["numbers"]): - out_ep_var = config["write_point_ep"][f"{var_nr}"]["name"] - out_ep_example_nodes[out_ep_var][i] = out_ep_funcs[out_ep_var](ep_coords[var_nr]) - # Compute volume averages - out_ep_volume_average_timeseries[out_ep_var][i] = compute_function_average_over_mesh( - out_ep_funcs[out_ep_var], ep_mesh - ) - - if i % config["sim"]["N"] != 0: - timing_single_loop.stop() - timings_solveloop.append(timing_single_loop.elapsed()[0]) - continue - - timing_var_transfer = dolfin.Timer("mv and lambda transfer time") - missing_ep_values = mv_ep( - ti + config["sim"]["dt"], ode._values, ode.parameters, missing_ep.values_ep - ) - - for k in range(missing_mech.num_values): - missing_mech.u_ep_int[k].vector()[:] = missing_ep_values[k, :] - - missing_mech.interpolate_ep_to_mechanics() - missing_mech.mechanics_function_to_values() - inds.append(i) - timing_var_transfer.stop() - - print("Solve mechanics") - timing_mech = dolfin.Timer("mech time") - active_model.t = ti + config["sim"]["N"] * config["sim"]["dt"] # Addition! - nit, conv = problem.solve(ti, config["sim"]["N"] * config["sim"]["dt"]) - no_of_newton_iterations.append(nit) - print(f"No of iterations: {nit}") - active_model.update_prev() - timing_mech.stop() - timings_mech_steps.append(timing_mech.elapsed()[0]) - - timing_var_transfer.start() - missing_ep.u_mechanics_int[0].interpolate(active_model._Zetas) - missing_ep.u_mechanics_int[1].interpolate(active_model._Zetaw) - missing_ep.interpolate_mechanics_to_ep() - missing_ep.ep_function_to_values() - lmbda.interpolate(active_model.lmbda) - p_ep[lmbda_index_ep, :] = lmbda.vector().get_local() # p_ep are the ep parameters - timing_var_transfer.stop() - timings_var_transfer.append(timing_var_transfer.elapsed()[0]) - - if write_disp: - U, p = problem.state.split(deepcopy=True) - - for var_nr in range(config["write_point_mech"]["numbers"]): - out_mech_var = config["write_point_mech"][f"{var_nr}"]["name"] - out_mech_example_nodes[out_mech_var][i] = mech_variables[out_mech_var](mech_coords[var_nr]) - - # Compute volume averages - out_mech_volume_average_timeseries[out_mech_var][i] = compute_function_average_over_mesh( - mech_variables[out_mech_var], mesh - ) - - if write_disp: - with dolfin.XDMFFile(disp_file.as_posix()) as file: - file.write_checkpoint(U, "disp", j, dolfin.XDMFFile.Encoding.HDF5, True) - for out_ep_var in out_ep_var_names: - with dolfin.XDMFFile(out_ep_files[out_ep_var].as_posix()) as file: - file.write_checkpoint( - out_ep_funcs[out_ep_var], - out_ep_var, - j, - dolfin.XDMFFile.Encoding.HDF5, - True, - ) - for out_mech_var in out_mech_var_names: - with dolfin.XDMFFile(out_mech_files[out_mech_var].as_posix()) as file: - file.write_checkpoint( - mech_variables[out_mech_var], - out_mech_var, - j, - dolfin.XDMFFile.Encoding.HDF5, - True, - ) - - j += 1 - timing_single_loop.stop() - timings_solveloop.append(timing_single_loop.elapsed()[0]) - -total_timer.stop() - -timings = dolfin.timings( - dolfin.TimingClear.keep, - [dolfin.TimingType.wall, dolfin.TimingType.user, dolfin.TimingType.system], -).str(True) -print(timings) -with open(Path(outdir / "solve_timings.txt"), "w") as f: - f.write("Loop total times\n") - np.savetxt(f, timings_solveloop) - f.write("Ep steps times\n") - np.savetxt(f, timings_ep_steps) - f.write("Mech steps times\n") - np.savetxt(f, timings_mech_steps) - f.write("No of mech iterations\n") - np.savetxt(f, no_of_newton_iterations, fmt="%s") - f.write("mv and lambda transfer time\n") - np.savetxt(f, timings_var_transfer) - f.write("Total time\n") - f.write(f"{total_timer.elapsed()[0]}\n") - f.write(timings) - -# Write averaged results for later analysis -for out_ep_var in out_ep_coord_names: - with open(Path(outdir / f"{out_ep_var}_out_ep_volume_average.txt"), "w") as f: - np.savetxt(f, out_ep_volume_average_timeseries[out_ep_var][inds]) - -for out_mech_var in out_mech_coord_names: - with open(Path(outdir / f"{out_mech_var}_out_mech_volume_average.txt"), "w") as f: - np.savetxt(f, out_mech_volume_average_timeseries[out_mech_var][inds]) - -# Write point traces for later analysis -for var_nr in range(config["write_point_ep"]["numbers"]): - out_ep_var = config["write_point_ep"][f"{var_nr}"]["name"] - with open( - Path( - outdir - / f"{out_ep_var}_ep_coord{ep_coords[var_nr][0]},{ep_coords[var_nr][1]},{ep_coords[var_nr][2]}.txt".replace( - " ", "" - ) - ), - "w", - ) as f: - np.savetxt(f, out_ep_example_nodes[out_ep_var][inds]) - -for var_nr in range(config["write_point_mech"]["numbers"]): - out_mech_var = config["write_point_mech"][f"{var_nr}"]["name"] - with open( - Path( - outdir - / f"{out_mech_var}_mech_coord{mech_coords[var_nr][0]},{mech_coords[var_nr][1]},{mech_coords[var_nr][2]}.txt" - ), - "w", - ) as f: - np.savetxt(f, out_mech_example_nodes[out_mech_var][inds]) - -print(f"Solved on {100 * len(inds) / len(t)}% of the time steps") -inds = np.array(inds) - -if plot_results: - fig, ax = plt.subplots(len(out_ep_coord_names), 1, figsize=(10, 10)) - if len(out_ep_coord_names) == 1: - ax = np.array([ax]) - for i, out_ep_var in enumerate(out_ep_coord_names): - ax[i].plot(t[inds], out_ep_volume_average_timeseries[out_ep_var][inds]) - ax[i].set_title(f"{out_ep_var} volume average") - ax[i].set_xlabel("Time (ms)") - fig.tight_layout() - fig.savefig(Path(outdir / "out_ep_volume_averages.png")) - - fig, ax = plt.subplots(len(out_ep_coord_names), 1, figsize=(10, 10)) - if len(out_ep_coord_names) == 1: - ax = np.array([ax]) - for var_nr in range(config["write_point_ep"]["numbers"]): - out_ep_var = config["write_point_ep"][f"{var_nr}"]["name"] - ax[var_nr].plot(t[inds], out_ep_example_nodes[out_ep_var][inds]) - ax[var_nr].set_title(f"{out_ep_var} in coord {ep_coords[var_nr]}") - ax[var_nr].set_xlabel("Time (ms)") - fig.tight_layout() - fig.savefig(Path(outdir / "out_ep_coord.png")) - - fig, ax = plt.subplots(len(out_mech_coord_names), 1, figsize=(10, 10)) - if len(out_mech_coord_names) == 1: - ax = np.array([ax]) - for i, out_mech_var in enumerate(out_mech_coord_names): - ax[i].plot(t[inds], out_mech_volume_average_timeseries[out_mech_var][inds]) - ax[i].set_title(f"{out_mech_var} volume average") - ax[i].set_xlabel("Time (ms)") - fig.tight_layout() - fig.savefig(Path(outdir / "out_mech_volume_averages.png")) - - fig, ax = plt.subplots(len(out_mech_coord_names), 1, figsize=(10, 10)) - if len(out_mech_coord_names) == 1: - ax = np.array([ax]) - - for var_nr in range(config["write_point_mech"]["numbers"]): - out_mech_var = config["write_point_mech"][f"{var_nr}"]["name"] - ax[var_nr].plot(t[inds], out_mech_example_nodes[out_mech_var][inds]) - ax[var_nr].set_title(f"{out_mech_var} in coord {mech_coords[var_nr]}") - ax[var_nr].set_xlabel("Time (ms)") - fig.tight_layout() - fig.savefig(Path(outdir / "out_mech_coord.png")) diff --git a/demos/steady_state/main_full_to_steady_state.py b/demos/steady_state/main_full_to_steady_state.py deleted file mode 100644 index 70074fe..0000000 --- a/demos/steady_state/main_full_to_steady_state.py +++ /dev/null @@ -1,134 +0,0 @@ -from pathlib import Path -import gotranx -import numpy as np -import time - -# Simulation parameters -with_twitch = False -dt = 0.1 -bcs = 1000 -beats = 200 - -# Parameters for starting from an already saved state -from_init_state = True -init_beats = 0 # 200 # Number of beats already run, if starting from init state - - -if from_init_state: - init_state_file = "state_1beats_twitchTrue_dt0.1.txt" - # init_state_file = "state_200beats_without_twitch.txt" - full_init_states = np.loadtxt(init_state_file) - - -def twitch(t, tstart=0.05, ca_ampl=-0.2): - tau1 = 0.05 * 1000 - tau2 = 0.110 * 1000 - - ca_diast = 0.0 - - beta = (tau1 / tau2) ** (-1 / (tau1 / tau2 - 1)) - (tau1 / tau2) ** (-1 / (1 - tau2 / tau1)) - ca = np.zeros_like(t) - - ca[t <= tstart] = ca_diast - - ca[t > tstart] = (ca_ampl - ca_diast) / beta * ( - np.exp(-(t[t > tstart] - tstart) / tau1) - np.exp(-(t[t > tstart] - tstart) / tau2) - ) + ca_diast - return ca + 1.0 - - -def update_lambda_and_dlambda(t, prev_lmbda, dt): - lmbda_ti = twitch(t) - p[lmbda_index] = lmbda_ti - - dLambda = (lmbda_ti - prev_lmbda) / dt - p[dLambda_index] = dLambda - prev_lmbda = lmbda_ti - return p, prev_lmbda - - -# Load the model -ode = gotranx.load_ode("ToRORd_dynCl_endo_zetasplit.ode") -file = Path("ToRORd_dynCl_endo_zetasplit.py") - -# Generate model code from .ode file -rebuild = False -if not file.is_file() or rebuild: - # Generate code for full model. - code = gotranx.cli.gotran2py.get_code( - ode, - scheme=[gotranx.schemes.Scheme.forward_generalized_rush_larsen], - ) - Path("ToRORd_dynCl_endo_zetasplit.py").write_text(code) - - -import ToRORd_dynCl_endo_zetasplit - -model = ToRORd_dynCl_endo_zetasplit.__dict__ - -t = np.arange(0, bcs, dt) - -if with_twitch: - with open("lmbda_function.txt", "w") as f: - np.savetxt(f, twitch(t)) - -# Forwared generalized rush larsen scheme for the full model -fgr = model["forward_generalized_rush_larsen"] -# Monitor function for the full model -mon = model["monitor_values"] -Ca_index = model["state_index"]("cai") -V_index = model["state_index"]("v") -Ta_index = model["monitor_index"]("Ta") - -lmbda_index = model["parameter_index"]("lmbda") -dLambda_index = model["parameter_index"]("dLambda") - - -Cais = np.zeros(len(t) * beats) -Vs = np.zeros(len(t) * beats) -Tas = np.zeros(len(t) * beats) - -# Get the initial values from the full model -if from_init_state: - y = full_init_states # from init state -else: - y = model["init_state_values"]() -p = model["init_parameter_values"]() # Used in lambda update - -timing_init = time.perf_counter() -for beat in range(beats): - V_tmp = Vs[beat * len(t) : (beat + 1) * len(t)] - Cai_tmp = Cais[beat * len(t) : (beat + 1) * len(t)] - Ta_tmp = Tas[beat * len(t) : (beat + 1) * len(t)] - - if with_twitch: - prev_lmbda = p[lmbda_index] - p, prev_lmbda = update_lambda_and_dlambda(np.float64(0), prev_lmbda, dt) - - for i, ti in enumerate(t): - y[:] = fgr(y, ti, dt, p) - monitor = mon(ti, y, p) - V_tmp[i] = y[V_index] - Cai_tmp[i] = y[Ca_index] - Ta_tmp[i] = monitor[Ta_index] - - if with_twitch: - p, prev_lmbda = update_lambda_and_dlambda(ti + dt, prev_lmbda, dt) - print(f"t: {ti:.12}, beat {beat+1}") - -timing_total = time.perf_counter() - timing_init - -# Save states -with open(f"state_{beats+init_beats}beats_twitch{with_twitch}_dt{dt}.txt", "w") as f: - np.savetxt(f, y[:]) - -with open(f"timings_full_to_beats{beats+init_beats}_twitch{with_twitch}_dt{dt}", "w") as f: - f.write("Total time\n") - f.write(f"{timing_total}\n") - -with open(f"V_full_beats{beats+init_beats}_twitch{with_twitch}_dt{dt}.txt", "w") as f: - np.savetxt(f, Vs) -with open(f"Ta_full_beats{beats+init_beats}_twitch{with_twitch}_dt{dt}.txt", "w") as f: - np.savetxt(f, Tas) -with open(f"Ca_full_beats{beats+init_beats}_twitch{with_twitch}_dt{dt}.txt", "w") as f: - np.savetxt(f, Cais) From 090122a72a11eafdca009f08c3032dd45bd7fa29 Mon Sep 17 00:00:00 2001 From: Henrik Finsberg Date: Mon, 10 Feb 2025 08:40:37 +0100 Subject: [PATCH 5/5] Specify simulation duration to 100 ms --- numerical_experiments/0D/utils.py | 3 --- numerical_experiments/3D/split-cai.py | 1 + numerical_experiments/3D/split-cai_catrpn.py | 1 + numerical_experiments/3D/split-zeta.py | 1 + numerical_experiments/3D/utils.py | 8 ++++---- src/simcardems2/mechanicssolver.py | 6 ++---- 6 files changed, 9 insertions(+), 11 deletions(-) diff --git a/numerical_experiments/0D/utils.py b/numerical_experiments/0D/utils.py index cba769f..a9d34cc 100644 --- a/numerical_experiments/0D/utils.py +++ b/numerical_experiments/0D/utils.py @@ -252,9 +252,6 @@ def run_0D( ep_model = __import__(ep_file.stem).__dict__ mechanics_model = __import__(mechanics_file.stem).__dict__ - # Set time step - dt = 0.05 - simdur = 10 # Simulation duration t = np.arange(0, simdur, dt) # Forwared generalized rush larsen scheme for the electrophysiology model diff --git a/numerical_experiments/3D/split-cai.py b/numerical_experiments/3D/split-cai.py index 84314df..f03e14f 100644 --- a/numerical_experiments/3D/split-cai.py +++ b/numerical_experiments/3D/split-cai.py @@ -5,6 +5,7 @@ "sim": { "N": 2, "dt": 0.05, + "sim_dur": 100.0, "mech_mesh": "meshes/mesh_mech_0.5dx_0.5Lx_1.0Ly_2.0Lz", "markerfile": "meshes/mesh_mech_0.5dx_0.5Lx_1.0Ly_2.0Lz_surface_ffun", "modelfile": "../odefiles/ToRORd_dynCl_endo_caisplit.ode", diff --git a/numerical_experiments/3D/split-cai_catrpn.py b/numerical_experiments/3D/split-cai_catrpn.py index 0b1c2c7..ff76eee 100644 --- a/numerical_experiments/3D/split-cai_catrpn.py +++ b/numerical_experiments/3D/split-cai_catrpn.py @@ -5,6 +5,7 @@ "sim": { "N": 2, "dt": 0.05, + "sim_dur": 100.0, "mech_mesh": "meshes/mesh_mech_0.5dx_0.5Lx_1.0Ly_2.0Lz", "markerfile": "meshes/mesh_mech_0.5dx_0.5Lx_1.0Ly_2.0Lz_surface_ffun", "modelfile": "../odefiles/ToRORd_dynCl_endo_catrpnsplit.ode", diff --git a/numerical_experiments/3D/split-zeta.py b/numerical_experiments/3D/split-zeta.py index c5990bb..f1a2a79 100644 --- a/numerical_experiments/3D/split-zeta.py +++ b/numerical_experiments/3D/split-zeta.py @@ -5,6 +5,7 @@ "sim": { "N": 2, "dt": 0.05, + "sim_dur": 100.0, "mech_mesh": "meshes/mesh_mech_0.5dx_0.5Lx_1.0Ly_2.0Lz", "markerfile": "meshes/mesh_mech_0.5dx_0.5Lx_1.0Ly_2.0Lz_surface_ffun", "modelfile": "../odefiles/ToRORd_dynCl_endo_zetasplit.ode", diff --git a/numerical_experiments/3D/utils.py b/numerical_experiments/3D/utils.py index 798b022..482cfb6 100644 --- a/numerical_experiments/3D/utils.py +++ b/numerical_experiments/3D/utils.py @@ -142,17 +142,17 @@ def run_3D(config: dict[str, Any] | None = None): t_bcs = dolfin.Constant(0) if config["sim"]["split_scheme"] == "cai": - land_params = {"cai": mechanics_missing_values_[0]} + land_params = {"cai": missing_mech.u_mechanics[0]} LandModel = simcardems2.land_caisplit.LandModel elif config["sim"]["split_scheme"] == "zeta": land_params = { - "XS": mechanics_missing_values_[0], - "XW": mechanics_missing_values_[1], + "XS": missing_mech.u_mechanics[0], + "XW": missing_mech.u_mechanics[1], } LandModel = simcardems2.land_Zetasplit.LandModel elif config["sim"]["split_scheme"] == "cai_catrpn": - land_params = {"CaTrpn": mechanics_missing_values_[0]} + land_params = {"CaTrpn": missing_mech.u_mechanics[0]} LandModel = simcardems2.land_CaTrpnsplit.LandModel else: raise ValueError(f"Unknown split scheme: {config['sim']['split_scheme']}") diff --git a/src/simcardems2/mechanicssolver.py b/src/simcardems2/mechanicssolver.py index bcf291d..1abc66a 100644 --- a/src/simcardems2/mechanicssolver.py +++ b/src/simcardems2/mechanicssolver.py @@ -61,7 +61,7 @@ def __init__( logger.info(f"Initialize NewtonSolver with parameters: {parameters!r}") dolfin.PETScOptions.clear() self.dx = dolfin.Measure("dx", domain=state.function_space().mesh()) - # self.volume = dolfin.assemble(dolfin.Constant(1) * self.dx) + self.volume = dolfin.assemble(dolfin.Constant(1) * self.dx) self._problem = problem self._state = state self._update_cb = update_cb @@ -187,9 +187,7 @@ def solve(self, t0: float, dt: float) -> Tuple[int, bool]: self.active._dLambda, (lmbda - self.active.lmbda_prev) / self.active.dt ) - Ta = self.active.Ta(lmbda) - if not isinstance(Ta, ufl.constantvalue.Zero): - self.active._projector.project(self.active.Ta_current, self.active.Ta(lmbda)) + self.active._projector.project(self.active.Ta_current, self.active.Ta(lmbda)) self.active.update_current(lmbda=lmbda) self.active.update_prev() if not conv: