svMultiPhysics
Loading...
Searching...
No Matches
ActiveStressRegazzoni.h
1// SPDX-FileCopyrightText: Copyright (c) Stanford University, The Regents of the
2// University of California, and others. SPDX-License-Identifier: BSD-3-Clause
3
4#ifndef ACTIVE_STRESS_REGAZZONI_H
5#define ACTIVE_STRESS_REGAZZONI_H
6
7#include "ActiveStress.h"
8
9#include <array>
10
11/**
12 * @brief Mean-field active stress model (implements the RDQ20-MF formulation).
13 *
14 * This class implements the mean-field RDQ20-MF sarcomere model of
15 * cardiomyocyte force generation of Regazzoni, Dede', and Quarteroni (2020),
16 * described in [1] and validated against the authors' reference implementation
17 * [2]. The node-local state has 20 variables: 16 regulatory-unit (RU)
18 * probabilities (entries 0-15) describing the tropomyosin/troponin
19 * configuration of a triplet of neighbouring units, and 4 crossbridge (XB)
20 * moments (entries 16-19). The RU probabilities are advanced with an explicit
21 * forward-Euler substepping scheme — for every macro time step, a number of
22 * smaller sub-steps are taken to update the RU states — and the XB moments with
23 * one implicit-Euler step per time step; the active tension is then
24 * reconstructed from the XB first moments.
25 *
26 * The returned scalar active tension is
27 * @f[
28 * \Tact = a_\text{XB} \, (\mu_P^1 + \mu_N^1) \, \phi(SL)\;,
29 * @f]
30 * where @f$\mu_P^1@f$ and @f$\mu_N^1@f$ are the permissive and non-permissive
31 * first XB moments (state entries 17 and 19), @f$\phi(SL)@f$ is the
32 * single-overlap fraction of the sarcomere at sarcomere length @f$SL = SL_0 \,
33 * \fiberstretch@f$ (with @f$\fiberstretch@f$ the fiber stretch), and
34 * @f$a_\text{XB}@f$ is the tension upscaling factor. Because @f$\mu_P^1 +
35 * \mu_N^1@f$ and @f$\phi(SL)@f$ are dimensionless, @f$a_\text{XB}@f$ sets the
36 * units of the returned active tension.
37 *
38 * **References**:
39 * 1. [Regazzoni, Dede', Quarteroni
40 * (2020)](https://doi.org/10.1371/journal.pcbi.1008294)
41 * 2. [F. Regazzoni, cardiac-activation reference
42 * implementation](https://github.com/FrancescoRegazzoni/cardiac-activation)
43 *
44 * @note Although this model is governed by a system of ODEs, it inherits from
45 * @c ActiveStress rather than @c ActiveStressODE because it requires a
46 * customized time-stepping scheme to handle the stiffness of the model.
47 *
48 * @todo Force-strain-rate feedback requires a stabilization strategy for robust
49 * use in coupled electromechanics. This will be addressed in a follow-up PR.
50 */
52public:
53 /// Model label, used for factory registration and XML selection.
54 static inline const std::string label = "Regazzoni";
55
56 /// @name State vector layout
57 /// @{
58
59 /// Number of regulatory-unit (RU) probability states (entries 0-15).
60 static constexpr unsigned int n_ru_states = 16;
61
62 /// Number of crossbridge (XB) moment states (entries 16-19).
63 static constexpr unsigned int n_xb_states = 4;
64
65 /// Total number of state variables.
66 static constexpr unsigned int n_state_variables = n_ru_states + n_xb_states;
67
68 /**
69 * @brief Flat index of the RU probability state P(TL, TC, TR, CC).
70 *
71 * Each argument is 0 or 1 and denotes the state of, respectively, the left
72 * tropomyosin unit, the central tropomyosin unit, the right tropomyosin unit
73 * and the central troponin (calcium unbound/bound). The ordering matches the
74 * reference implementation's serialization (TL outermost, CC innermost) and
75 * spans [0, 15].
76 */
77 static constexpr unsigned int ru_index(unsigned int TL, unsigned int TC,
78 unsigned int TR, unsigned int CC) {
79 return 8 * TL + 4 * TC + 2 * TR + CC;
80 }
81
82 /// Flat index of the XB moment state @p i (in [0, 3]), spanning [16, 19].
83 static constexpr unsigned int xb_index(unsigned int i) {
84 return n_ru_states + i;
85 }
86
87 /// @}
88
89 /**
90 * @brief Model parameters class.
91 *
92 * Declares the parameters required by the model. All parameters are
93 * marked as required, and omitting a parameter will cause a parse error.
94 */
96 public:
98 constexpr bool required = true;
99
100 // Reference values: Regazzoni 2020 human body-temperature calibration,
101 // expressed consistently with the unit system used by this parameter set.
102 add_parameter("Kbasic", 0.013, required);
103 add_parameter("Koff", 0.1, required);
104 add_parameter("Q", 2.0, required);
105 add_parameter("mu", 10.0, required);
106 add_parameter("gamma", 12.0, required);
107 add_parameter("Kd0", 3.81e-4, required);
108 add_parameter("alphaKd", -5.71e-4, required);
109 add_parameter("SL0", 2.2, required);
110 add_parameter("ru_substep", 2.5e-2, required);
111 add_parameter("kd_reference_sarcomere_length", 2.15, required);
112
113 add_parameter("r0", 0.13431, required);
114 add_parameter("alpha", 25.184, required);
115 add_parameter("mu0_fP", 0.032653, required);
116 add_parameter("mu1_fP", 7.78e-4, required);
117
118 add_parameter("LA", 1.25, required);
119 add_parameter("LM", 1.65, required);
120 add_parameter("LB", 0.18, required);
121 add_parameter("a_XB", 22.894, required);
122
123 add_parameter("Disable_force_strain_rate_feedback", false, !required);
124 }
125 };
126
127 /**
128 * @brief Constructor.
129 */
131 : ActiveStress(/* n_state_variables = */ n_state_variables,
132 /* needs_fiber_stretch = */ true,
133 /* needs_fiber_stretch_rate = */ true) {}
134
135 /**
136 * @brief Construct an instance of model parameters.
137 */
138 virtual std::unique_ptr<ActiveStressModelParameters>
139 get_parameters() const override {
140 return std::make_unique<Parameters>();
141 }
142
143protected:
144 /**
145 * @brief Read model parameters from a parameter object.
146 */
148 const ActiveStressModelParameters &params) override;
149
150 /**
151 * @brief Distribute model parameters to all parallel processes.
152 */
153 virtual void distribute_model_specific_parameters(const CmMod &cm_mod,
154 const cmType &cm) override;
155
156 /**
157 * @brief Initialize the state vector for a single node.
158 *
159 * Sets the state to (1, 0, ..., 0), i.e. all probability mass in the RU state
160 * P(0, 0, 0, 0) and all crossbridge moments equal to zero.
161 *
162 * @param[out] state State vector for a single node, to be initialized by
163 * this function.
164 */
165 virtual void init_local(Vector<double> &state) const override;
166
167 /**
168 * @brief Advance in time for a single node.
169 *
170 * Advances the RU probabilities (entries 0-15) with the forward-Euler
171 * substepping scheme and then the XB moments (entries 16-19) with one
172 * implicit-Euler step, using the calcium, fiber stretch and fiber-stretch
173 * rate at the node.
174 */
175 virtual void advance_time_step_local(const double t, const double dt,
176 const double calcium,
177 const double fiber_stretch,
178 const double fiber_stretch_rate,
179 Vector<double> &state) const override;
180
181 /**
182 * @brief Compute the scalar active tension for a single node.
183 *
184 * Evaluates @f$\Tact@f$ as defined in the class description, using
185 * @p fiber_stretch to compute the sarcomere length
186 * @f$SL = SL_0 \, \fiberstretch@f$. The returned value has the stress
187 * units of @f$a_\text{XB}@f$.
188 */
189 virtual double
191 const double fiber_stretch) const override;
192
193private:
194 /// Array indexed over the four binary RU configuration variables (TL, TC, TR,
195 /// CC).
196 using RUArray =
197 std::array<std::array<std::array<std::array<double, 2>, 2>, 2>, 2>;
198
199 /// Array indexed over a pair of binary state variables.
200 using BinaryPairArray = std::array<std::array<double, 2>, 2>;
201
202 /// Array of the four crossbridge moment state variables.
203 using XBArray = std::array<double, 4>;
204
205 /// @name Regulatory-unit (RU) dynamics helpers
206 /// @{
207
208 /**
209 * @brief Compute the central-tropomyosin transition rate for each local RU
210 * configuration.
211 *
212 * Returns an @c RUArray where entry @c [TL][TC][TR][CC] is the rate at which
213 * the central tropomyosin changes state for that configuration. Because the
214 * rate depends on the neighbour states TL and TR, nearest-neighbour
215 * cooperativity is retained through the tracked TL-TC-TR configuration.
216 * These rates depend only on the model parameters, not on calcium or stretch.
217 *
218 * @return Central-tropomyosin transition rates, indexed @c [TL][TC][TR][CC].
219 */
220 RUArray ru_transition_rates_tropomyosin() const;
221
222 /**
223 * @brief Advance the 16 RU-state probabilities by one forward-Euler substep.
224 *
225 * Computes the probability fluxes caused by central-state transitions and the
226 * effective boundary-neighbour transitions from the mean-field closure, then
227 * updates @p state_RU in place.
228 *
229 * @param[in] dt Substep size [time].
230 * @param[in] rates_T Central-tropomyosin transition rates,
231 * indexed @c rates_T[TL][TC][TR][CC].
232 * @param[in] rates_C Troponin transition rates, indexed @c rates_C[CC][TC].
233 * @param[in,out] state_RU The 16 RU-state probabilities,
234 * indexed @c state_RU[TL][TC][TR][CC].
235 */
236 void ru_forward_euler_substep(double dt, const RUArray &rates_T,
237 const BinaryPairArray &rates_C,
238 RUArray &state_RU) const;
239
240 /**
241 * @brief Advance the four crossbridge moments by one implicit-Euler step.
242 *
243 * Computes the permissivity and the effective permissive/non-permissive
244 * transition rates from the updated RU probabilities, forms the 4x4 linear
245 * system for the implicit update, and returns the updated moments.
246 *
247 * @param[in] dt Outer time step [time].
248 * @param[in] velocity Shortening velocity @f$-\dot{SL}/SL_0@f$ [1/time].
249 * @param[in] rates_T Central-tropomyosin transition rates,
250 * indexed @c rates_T[TL][TC][TR][CC].
251 * @param[in] state_RU The updated 16 RU-state probabilities,
252 * indexed @c state_RU[TL][TC][TR][CC].
253 * @param[in] state_XB The four crossbridge moments (input), ordered
254 * @f$[\mu_P^0, \mu_P^1, \mu_N^0, \mu_N^1]@f$.
255 * @return Updated crossbridge moments, ordered
256 * @f$[\mu_P^0, \mu_P^1, \mu_N^0, \mu_N^1]@f$.
257 */
258 XBArray xb_implicit_update(double dt, double velocity, const RUArray &rates_T,
259 const RUArray &state_RU,
260 const XBArray &state_XB) const;
261
262 /**
263 * @brief Single-overlap fraction of the sarcomere at a given length.
264 *
265 * Returns the fraction @f$\phi(SL) \in [0, 1]@f$ of the sarcomere over which
266 * thin and thick filaments overlap exactly once, a piecewise-linear function
267 * of the sarcomere length built from the filament geometry (LA, LM, LB).
268 *
269 * @param[in] sarcomere_length Sarcomere length @f$SL@f$ [length].
270 */
271 double fraction_single_overlap(double sarcomere_length) const;
272
273 /// @}
274
275 /// @name RU model parameters
276 /// @{
277
278 double Kbasic; ///< Basic tropomyosin transition rate [1/time].
279 double Koff; ///< Troponin unbinding rate [1/time].
280 double Q; ///< Tropomyosin transition-rate asymmetry factor [-].
281 double mu; ///< Calcium-binding cooperativity factor [-].
282 double gamma; ///< Nearest-neighbour cooperativity factor [-].
283 double Kd0; ///< Calcium dissociation constant at reference length [calcium].
284 double alphaKd; ///< Length dependence of the dissociation constant
285 ///< [calcium/length].
286 double SL0; ///< Reference sarcomere length [length]; maps stretch to length.
287 double ru_substep; ///< RU forward-Euler substep size [time].
288
289 /// Reference sarcomere length [length] used in the length-dependent
290 /// dissociation constant (distinct from the parameter SL0).
291 double kd_reference_sarcomere_length;
292
293 double r0; ///< Combined attachment-detachment rate at zero velocity [1/time].
294 double alpha; ///< Coefficient of |v| in r(v) = r0 + alpha * |v| [-].
295 double mu0_fP; ///< Permissive influx into the zeroth-moment crossbridge state
296 ///< [1/time].
297 double mu1_fP; ///< Permissive influx into the first-moment crossbridge state
298 ///< [1/time].
299
300 double LA; ///< Thin-filament (actin) length [length].
301 double LM; ///< Thick-filament (myosin) length [length].
302 double LB; ///< Length of the myosin bare zone [length].
303
304 /// Tension upscaling factor [stress].
305 ///
306 /// Because the crossbridge moments and the overlap fraction are
307 /// dimensionless, a_XB sets the stress unit of the returned active tension.
308 /// It must be expressed in the same stress unit as the mechanical
309 /// configuration.
310 double a_XB;
311
312 /// Controls force–strain-rate feedback in the XB update.
313 /// - @c false (default): use @f$v = -\dot{\lambda}@f$ as shortening velocity.
314 /// - @c true: set shortening velocity to zero, disabling the feedback.
315 bool disable_force_strain_rate_feedback_ = false;
316
317 /// @}
318};
319
320#endif
Abstract active stress class.
Definition ActiveStress.h:100
Parameters for a generic active stress model.
Definition Parameters.h:1444
void add_parameter(const std::string &label, double default_value, bool required)
Add a new parameter to this object.
Definition Parameters.h:1490
Model parameters class.
Definition ActiveStressRegazzoni.h:95
Mean-field active stress model (implements the RDQ20-MF formulation).
Definition ActiveStressRegazzoni.h:51
static constexpr unsigned int n_xb_states
Number of crossbridge (XB) moment states (entries 16-19).
Definition ActiveStressRegazzoni.h:63
static constexpr unsigned int xb_index(unsigned int i)
Flat index of the XB moment state i (in [0, 3]), spanning [16, 19].
Definition ActiveStressRegazzoni.h:83
virtual void read_model_specific_parameters(const ActiveStressModelParameters &params) override
Read model parameters from a parameter object.
Definition ActiveStressRegazzoni.cpp:11
static constexpr unsigned int ru_index(unsigned int TL, unsigned int TC, unsigned int TR, unsigned int CC)
Flat index of the RU probability state P(TL, TC, TR, CC).
Definition ActiveStressRegazzoni.h:77
ActiveStressRegazzoni()
Constructor.
Definition ActiveStressRegazzoni.h:130
virtual void advance_time_step_local(const double t, const double dt, const double calcium, const double fiber_stretch, const double fiber_stretch_rate, Vector< double > &state) const override
Advance in time for a single node.
Definition ActiveStressRegazzoni.cpp:82
virtual double compute_active_tension_local(const Vector< double > &state, const double fiber_stretch) const override
Compute the scalar active tension for a single node.
Definition ActiveStressRegazzoni.cpp:144
virtual std::unique_ptr< ActiveStressModelParameters > get_parameters() const override
Construct an instance of model parameters.
Definition ActiveStressRegazzoni.h:139
static const std::string label
Model label, used for factory registration and XML selection.
Definition ActiveStressRegazzoni.h:54
static constexpr unsigned int n_state_variables
Total number of state variables.
Definition ActiveStressRegazzoni.h:66
virtual void init_local(Vector< double > &state) const override
Initialize the state vector for a single node.
Definition ActiveStressRegazzoni.cpp:75
virtual void distribute_model_specific_parameters(const CmMod &cm_mod, const cmType &cm) override
Distribute model parameters to all parallel processes.
Definition ActiveStressRegazzoni.cpp:49
static constexpr unsigned int n_ru_states
Number of regulatory-unit (RU) probability states (entries 0-15).
Definition ActiveStressRegazzoni.h:60
The CmMod class duplicates the data structures in the Fortran CMMOD module defined in COMU....
Definition CmMod.h:36
The Vector template class is used for storing int and double data.
Definition Vector.h:26
The cmType class stores data and defines methods used for mpi communication.
Definition CmMod.h:56