From 698186aa3ff0cf8da72ecacfd9af8b95d03bde8a Mon Sep 17 00:00:00 2001 From: dseyler Date: Tue, 18 Aug 2026 15:32:19 -0700 Subject: [PATCH 1/4] Added boolean flag indicating whether active stress classes require fiber stretch/rate. Integrator:predictor() now skips fiber kinematics when not required (~5% of total runtime) --- Code/Source/solver/Integrator.cpp | 77 +++++++++++-------- Code/Source/solver/active_stress.h | 15 ++++ .../solver/active_stress_nash_panfilov.h | 7 ++ .../solver/active_stress_uniform_steady.h | 7 ++ .../solver/active_stress_uniform_unsteady.h | 7 ++ 5 files changed, 80 insertions(+), 33 deletions(-) diff --git a/Code/Source/solver/Integrator.cpp b/Code/Source/solver/Integrator.cpp index 75b9b5447..6274f4989 100644 --- a/Code/Source/solver/Integrator.cpp +++ b/Code/Source/solver/Integrator.cpp @@ -466,6 +466,17 @@ void Integrator::predictor() // Determine if we need to compute fiber stretch and stretch rate, by going // through all domains of all equations until we find one for which active // stress is enabled. + // + // Two separate questions are being answered here: + // have_active_stress - is an active stress model present at all? If so the + // stretch vectors are indexed for every node by + // ActiveStress::advance_time_step and must be allocated, whether or not + // the model reads the values. + // need_fiber_stretch{,_rate} - does anything actually consume the values? + // Only then is the per-element Gauss-point loop in post::fib_stretch + // worth running; otherwise the defaults below (no stretch, no movement) + // are handed to the model unchanged. + bool have_active_stress = false; bool need_fiber_stretch = false; bool need_fiber_stretch_rate = false; int fiber_stretch_eq_index = -1; @@ -477,8 +488,10 @@ void Integrator::predictor() for (const auto &dmn : eq.dmn) { if (dmn.active_stress != nullptr) { - need_fiber_stretch = true; - need_fiber_stretch_rate = true; + have_active_stress = true; + need_fiber_stretch |= dmn.active_stress->needs_fiber_stretch(); + need_fiber_stretch_rate |= + dmn.active_stress->needs_fiber_stretch_rate(); } } } @@ -488,44 +501,42 @@ void Integrator::predictor() } } - // If we need to compute fiber stretch, we iterate through all meshes, compute - // the stretch for each mesh, and then copy the mesh-local resulting vector - // into the global vector. - if (need_fiber_stretch) { + // Allocate whenever the vectors will be read, and default them to no stretch + // and no movement. That covers both the case where no domain solves for the + // displacement and the case where the active stress models present do not + // read these values at all. + if (have_active_stress || need_fiber_stretch) { fiber_stretch.resize(com_mod.tnNo); + fiber_stretch = 1.0; + } - if (fiber_stretch_eq_index >= 0) { - for (const auto &mesh : com_mod.msh) { - Vector tmp(mesh.nNo); + if (have_active_stress || need_fiber_stretch_rate) { + fiber_stretch_rate.resize(com_mod.tnNo); + fiber_stretch_rate = 0.0; + } - post::fib_stretch(com_mod, fiber_stretch_eq_index, mesh, Dn, tmp); - for (int a = 0; a < mesh.nNo; ++a) - fiber_stretch[mesh.gN[a]] = tmp[a]; - } - } else { - // If we didn't find any domain solving for the displacement, then we set - // the fiber stretch to 1, corresponding to no stretch. - fiber_stretch = 1.0; + // If something consumes the fiber stretch, we iterate through all meshes, + // compute the stretch for each mesh, and then copy the mesh-local resulting + // vector into the global vector. + if (need_fiber_stretch && fiber_stretch_eq_index >= 0) { + for (const auto &mesh : com_mod.msh) { + Vector tmp(mesh.nNo); + + post::fib_stretch(com_mod, fiber_stretch_eq_index, mesh, Dn, tmp); + for (int a = 0; a < mesh.nNo; ++a) + fiber_stretch[mesh.gN[a]] = tmp[a]; } } // Same for fiber stretch rate. - if (need_fiber_stretch_rate) { - fiber_stretch_rate.resize(com_mod.tnNo); - - if (fiber_stretch_eq_index >= 0) { - for (const auto &mesh : com_mod.msh) { - Vector tmp(mesh.nNo); - - post::fib_stretch_rate(com_mod, fiber_stretch_eq_index, mesh, - solutions_, tmp); - for (int a = 0; a < mesh.nNo; ++a) - fiber_stretch_rate[mesh.gN[a]] = tmp[a]; - } - } else { - // If we didn't find any domain solving for the displacement, then we set - // the fiber stretch rate to 0, corresponding to no movement. - fiber_stretch_rate = 0.0; + if (need_fiber_stretch_rate && fiber_stretch_eq_index >= 0) { + for (const auto &mesh : com_mod.msh) { + Vector tmp(mesh.nNo); + + post::fib_stretch_rate(com_mod, fiber_stretch_eq_index, mesh, + solutions_, tmp); + for (int a = 0; a < mesh.nNo; ++a) + fiber_stretch_rate[mesh.gN[a]] = tmp[a]; } } diff --git a/Code/Source/solver/active_stress.h b/Code/Source/solver/active_stress.h index da5f38c26..555cc0a0e 100644 --- a/Code/Source/solver/active_stress.h +++ b/Code/Source/solver/active_stress.h @@ -175,6 +175,21 @@ class ActiveStress { const Vector &fiber_stretch, const Vector &fiber_stretch_rate); + /** + * @brief Whether this model uses the fiber stretch passed to + * @ref advance_time_step. + * + * Defaults to true so that a model which forgets to override it is merely + * slower, rather than silently receiving values it expected to be meaningful. + */ + virtual bool needs_fiber_stretch() const { return true; } + + /** + * @brief Whether this model uses the fiber stretch rate passed to + * @ref advance_time_step. + */ + virtual bool needs_fiber_stretch_rate() const { return true; } + /// Number of state variables for this model. const unsigned int n_states; diff --git a/Code/Source/solver/active_stress_nash_panfilov.h b/Code/Source/solver/active_stress_nash_panfilov.h index a164be7c6..ef9a8124d 100644 --- a/Code/Source/solver/active_stress_nash_panfilov.h +++ b/Code/Source/solver/active_stress_nash_panfilov.h @@ -69,6 +69,13 @@ class NashPanfilov : public ActiveStressODE { return std::make_unique(); } + /** + * @brief This model's state evolves with the calcium concentration alone + * (see @ref getf), so it uses neither the fiber stretch nor its rate. + */ + virtual bool needs_fiber_stretch() const override { return false; } + virtual bool needs_fiber_stretch_rate() const override { return false; } + protected: /** * @brief Read model parameters from a parameter object. diff --git a/Code/Source/solver/active_stress_uniform_steady.h b/Code/Source/solver/active_stress_uniform_steady.h index 93676f9b0..33d303b16 100644 --- a/Code/Source/solver/active_stress_uniform_steady.h +++ b/Code/Source/solver/active_stress_uniform_steady.h @@ -63,6 +63,13 @@ class UniformSteadyActiveStress : public ActiveStress { */ virtual void init_local(Vector &state) const override {} + /** + * @brief This model's active tension is a constant, so it uses neither the fiber + * stretch nor its rate. + */ + virtual bool needs_fiber_stretch() const override { return false; } + virtual bool needs_fiber_stretch_rate() const override { return false; } + /** * @brief Advance in time for a single node. * diff --git a/Code/Source/solver/active_stress_uniform_unsteady.h b/Code/Source/solver/active_stress_uniform_unsteady.h index 696be51ab..6543a2f99 100644 --- a/Code/Source/solver/active_stress_uniform_unsteady.h +++ b/Code/Source/solver/active_stress_uniform_unsteady.h @@ -75,6 +75,13 @@ class UniformUnsteadyActiveStress : public ActiveStress { */ virtual void init_local(Vector &state) const override {} + /** + * @brief This model's active tension is a function of time alone, so it uses + * neither the fiber stretch nor its rate. + */ + virtual bool needs_fiber_stretch() const override { return false; } + virtual bool needs_fiber_stretch_rate() const override { return false; } + /** * @brief Advance in time for a single node. * From 4a265d8b6dd4a4d43409933029f6e8183d635285 Mon Sep 17 00:00:00 2001 From: dseyler Date: Thu, 20 Aug 2026 10:32:52 -0700 Subject: [PATCH 2/4] Changed fiber stretch flags to const. Reverted predictor logic to more closely resemble main branch --- Code/Source/solver/Integrator.cpp | 76 +++++++++---------- Code/Source/solver/active_stress.h | 30 ++++---- .../solver/active_stress_nash_panfilov.h | 10 +-- Code/Source/solver/active_stress_ode.h | 6 +- Code/Source/solver/active_stress_regazzoni.h | 5 +- .../solver/active_stress_uniform_steady.h | 10 +-- .../solver/active_stress_uniform_unsteady.h | 10 +-- 7 files changed, 68 insertions(+), 79 deletions(-) diff --git a/Code/Source/solver/Integrator.cpp b/Code/Source/solver/Integrator.cpp index 6274f4989..54268d7a5 100644 --- a/Code/Source/solver/Integrator.cpp +++ b/Code/Source/solver/Integrator.cpp @@ -465,17 +465,11 @@ void Integrator::predictor() // Determine if we need to compute fiber stretch and stretch rate, by going // through all domains of all equations until we find one for which active - // stress is enabled. + // stress is enabled and the active stres model needs the stretch or stretch rate. // - // Two separate questions are being answered here: - // have_active_stress - is an active stress model present at all? If so the - // stretch vectors are indexed for every node by - // ActiveStress::advance_time_step and must be allocated, whether or not - // the model reads the values. - // need_fiber_stretch{,_rate} - does anything actually consume the values? - // Only then is the per-element Gauss-point loop in post::fib_stretch - // worth running; otherwise the defaults below (no stretch, no movement) - // are handed to the model unchanged. + // have_active_stress is tracked separately from need_fiber_stretch because + // advance_time_step() indexes both vectors for every node whether or not the + // model reads the values, so they must be allocated either way. bool have_active_stress = false; bool need_fiber_stretch = false; bool need_fiber_stretch_rate = false; @@ -489,9 +483,9 @@ void Integrator::predictor() for (const auto &dmn : eq.dmn) { if (dmn.active_stress != nullptr) { have_active_stress = true; - need_fiber_stretch |= dmn.active_stress->needs_fiber_stretch(); + need_fiber_stretch |= dmn.active_stress->needs_fiber_stretch; need_fiber_stretch_rate |= - dmn.active_stress->needs_fiber_stretch_rate(); + dmn.active_stress->needs_fiber_stretch_rate; } } } @@ -501,42 +495,44 @@ void Integrator::predictor() } } - // Allocate whenever the vectors will be read, and default them to no stretch - // and no movement. That covers both the case where no domain solves for the - // displacement and the case where the active stress models present do not - // read these values at all. + // If we need to compute fiber stretch, we iterate through all meshes, compute + // the stretch for each mesh, and then copy the mesh-local resulting vector + // into the global vector. if (have_active_stress || need_fiber_stretch) { fiber_stretch.resize(com_mod.tnNo); - fiber_stretch = 1.0; - } - - if (have_active_stress || need_fiber_stretch_rate) { - fiber_stretch_rate.resize(com_mod.tnNo); - fiber_stretch_rate = 0.0; - } - // If something consumes the fiber stretch, we iterate through all meshes, - // compute the stretch for each mesh, and then copy the mesh-local resulting - // vector into the global vector. - if (need_fiber_stretch && fiber_stretch_eq_index >= 0) { - for (const auto &mesh : com_mod.msh) { - Vector tmp(mesh.nNo); + if (need_fiber_stretch && fiber_stretch_eq_index >= 0) { + for (const auto &mesh : com_mod.msh) { + Vector tmp(mesh.nNo); - post::fib_stretch(com_mod, fiber_stretch_eq_index, mesh, Dn, tmp); - for (int a = 0; a < mesh.nNo; ++a) - fiber_stretch[mesh.gN[a]] = tmp[a]; + post::fib_stretch(com_mod, fiber_stretch_eq_index, mesh, Dn, tmp); + for (int a = 0; a < mesh.nNo; ++a) + fiber_stretch[mesh.gN[a]] = tmp[a]; + } + } else { + // No domain solves for the displacement, or no model reads the stretch: + // set the fiber stretch to 1, corresponding to no stretch. + fiber_stretch = 1.0; } } // Same for fiber stretch rate. - if (need_fiber_stretch_rate && fiber_stretch_eq_index >= 0) { - for (const auto &mesh : com_mod.msh) { - Vector tmp(mesh.nNo); - - post::fib_stretch_rate(com_mod, fiber_stretch_eq_index, mesh, - solutions_, tmp); - for (int a = 0; a < mesh.nNo; ++a) - fiber_stretch_rate[mesh.gN[a]] = tmp[a]; + if (have_active_stress) { + fiber_stretch_rate.resize(com_mod.tnNo); + + if (need_fiber_stretch_rate && fiber_stretch_eq_index >= 0) { + for (const auto &mesh : com_mod.msh) { + Vector tmp(mesh.nNo); + + post::fib_stretch_rate(com_mod, fiber_stretch_eq_index, mesh, + solutions_, tmp); + for (int a = 0; a < mesh.nNo; ++a) + fiber_stretch_rate[mesh.gN[a]] = tmp[a]; + } + } else { + // If we didn't find any domain solving for the displacement, then we set + // the fiber stretch rate to 0, corresponding to no movement. + fiber_stretch_rate = 0.0; } } diff --git a/Code/Source/solver/active_stress.h b/Code/Source/solver/active_stress.h index b28c40e4b..b374db223 100644 --- a/Code/Source/solver/active_stress.h +++ b/Code/Source/solver/active_stress.h @@ -103,8 +103,15 @@ class ActiveStress { * @brief Constructor. * * @param n_states_ Number of state variables for this model. + * @param needs_fiber_stretch_ Whether this model uses the fiber stretch + * passed to @ref advance_time_step. + * @param needs_fiber_stretch_rate_ Whether this model uses the fiber stretch + * rate passed to @ref advance_time_step. */ - ActiveStress(const unsigned int n_states_) : n_states(n_states_) {} + ActiveStress(const unsigned int n_states_, const bool needs_fiber_stretch_, + const bool needs_fiber_stretch_rate_) + : n_states(n_states_), needs_fiber_stretch(needs_fiber_stretch_), + needs_fiber_stretch_rate(needs_fiber_stretch_rate_) {} /** * @brief Virtual destructor. @@ -175,24 +182,15 @@ class ActiveStress { const Vector &fiber_stretch, const Vector &fiber_stretch_rate); - /** - * @brief Whether this model uses the fiber stretch passed to - * @ref advance_time_step. - * - * Defaults to true so that a model which forgets to override it is merely - * slower, rather than silently receiving values it expected to be meaningful. - */ - virtual bool needs_fiber_stretch() const { return true; } - - /** - * @brief Whether this model uses the fiber stretch rate passed to - * @ref advance_time_step. - */ - virtual bool needs_fiber_stretch_rate() const { return true; } - /// Number of state variables for this model. const unsigned int n_states; + /// Whether this model uses the fiber stretch passed to + const bool needs_fiber_stretch; + + /// Whether this model uses the fiber stretch rate passed to + const bool needs_fiber_stretch_rate; + protected: /** * @brief Read model parameters from a parameter object. diff --git a/Code/Source/solver/active_stress_nash_panfilov.h b/Code/Source/solver/active_stress_nash_panfilov.h index ea392aca9..80353c859 100644 --- a/Code/Source/solver/active_stress_nash_panfilov.h +++ b/Code/Source/solver/active_stress_nash_panfilov.h @@ -59,7 +59,9 @@ class NashPanfilov : public ActiveStressODE { /** * @brief Constructor. */ - NashPanfilov() : ActiveStressODE(1) {} + NashPanfilov() : ActiveStressODE(/* n_state_variables = */ 1, + /* needs_fiber_stretch = */ false, + /* needs_fiber_stretch_rate = */ false) {} /** * @brief Construct an instance of model parameters. @@ -69,12 +71,6 @@ class NashPanfilov : public ActiveStressODE { return std::make_unique(); } - /** - * @brief This model's state evolves with the calcium concentration alone - * (see @ref getf), so it uses neither the fiber stretch nor its rate. - */ - virtual bool needs_fiber_stretch() const override { return false; } - virtual bool needs_fiber_stretch_rate() const override { return false; } protected: /** diff --git a/Code/Source/solver/active_stress_ode.h b/Code/Source/solver/active_stress_ode.h index 6ebfa7d09..5ab70ca73 100644 --- a/Code/Source/solver/active_stress_ode.h +++ b/Code/Source/solver/active_stress_ode.h @@ -92,8 +92,12 @@ class ActiveStressODE : public ActiveStress { * @brief Constructor. * * @param n_states Number of state variables for this model. + * @param needs_fiber_stretch See @ref ActiveStress::ActiveStress. + * @param needs_fiber_stretch_rate See @ref ActiveStress::ActiveStress. */ - ActiveStressODE(const unsigned int n_states) : ActiveStress(n_states) {} + ActiveStressODE(const unsigned int n_states, const bool needs_fiber_stretch, + const bool needs_fiber_stretch_rate) + : ActiveStress(n_states, needs_fiber_stretch, needs_fiber_stretch_rate) {} protected: /** diff --git a/Code/Source/solver/active_stress_regazzoni.h b/Code/Source/solver/active_stress_regazzoni.h index 27f7427ff..80e42fd14 100644 --- a/Code/Source/solver/active_stress_regazzoni.h +++ b/Code/Source/solver/active_stress_regazzoni.h @@ -123,7 +123,9 @@ class RegazzoniActiveStress : public ActiveStress { /** * @brief Constructor. */ - RegazzoniActiveStress() : ActiveStress(n_state_variables) {} + RegazzoniActiveStress() : ActiveStress(/* n_state_variables = */ n_state_variables, + /* needs_fiber_stretch = */ true, + /* needs_fiber_stretch_rate = */ true) {} /** * @brief Construct an instance of model parameters. @@ -133,6 +135,7 @@ class RegazzoniActiveStress : public ActiveStress { return std::make_unique(); } + protected: /** * @brief Read model parameters from a parameter object. diff --git a/Code/Source/solver/active_stress_uniform_steady.h b/Code/Source/solver/active_stress_uniform_steady.h index 7afbe2c10..039c23d36 100644 --- a/Code/Source/solver/active_stress_uniform_steady.h +++ b/Code/Source/solver/active_stress_uniform_steady.h @@ -33,7 +33,9 @@ class UniformSteadyActiveStress : public ActiveStress { /** * @brief Constructor. */ - UniformSteadyActiveStress() : ActiveStress(/* n_states = */ 0) {} + UniformSteadyActiveStress() : ActiveStress(/* n_states = */ 0, + /* needs_fiber_stretch = */ false, + /* needs_fiber_stretch_rate = */ false) {} /** * @brief Construct an instance of model parameters. @@ -63,12 +65,6 @@ class UniformSteadyActiveStress : public ActiveStress { */ virtual void init_local(Vector &state) const override {} - /** - * @brief This model's active tension is a constant, so it uses neither the fiber - * stretch nor its rate. - */ - virtual bool needs_fiber_stretch() const override { return false; } - virtual bool needs_fiber_stretch_rate() const override { return false; } /** * @brief Advance in time for a single node. diff --git a/Code/Source/solver/active_stress_uniform_unsteady.h b/Code/Source/solver/active_stress_uniform_unsteady.h index a478b99e0..fb8fa4d53 100644 --- a/Code/Source/solver/active_stress_uniform_unsteady.h +++ b/Code/Source/solver/active_stress_uniform_unsteady.h @@ -37,7 +37,9 @@ class UniformUnsteadyActiveStress : public ActiveStress { /** * @brief Constructor. */ - UniformUnsteadyActiveStress() : ActiveStress(/* n_states = */ 0) {} + UniformUnsteadyActiveStress() : ActiveStress(/* n_states = */ 0, + /* needs_fiber_stretch = */ false, + /* needs_fiber_stretch_rate = */ false) {} /** * @brief Construct an instance of model parameters. @@ -75,12 +77,6 @@ class UniformUnsteadyActiveStress : public ActiveStress { */ virtual void init_local(Vector &state) const override {} - /** - * @brief This model's active tension is a function of time alone, so it uses - * neither the fiber stretch nor its rate. - */ - virtual bool needs_fiber_stretch() const override { return false; } - virtual bool needs_fiber_stretch_rate() const override { return false; } /** * @brief Advance in time for a single node. From 5296009a0c1e75158c8f7bb226373accd722ca2c Mon Sep 17 00:00:00 2001 From: dseyler Date: Thu, 20 Aug 2026 10:42:17 -0700 Subject: [PATCH 3/4] cleaned up commenting --- Code/Source/solver/active_stress.h | 4 ++-- Code/Source/solver/active_stress_nash_panfilov.h | 1 - Code/Source/solver/active_stress_regazzoni.h | 1 - Code/Source/solver/active_stress_uniform_steady.h | 1 - Code/Source/solver/active_stress_uniform_unsteady.h | 1 - 5 files changed, 2 insertions(+), 6 deletions(-) diff --git a/Code/Source/solver/active_stress.h b/Code/Source/solver/active_stress.h index b374db223..b28b97642 100644 --- a/Code/Source/solver/active_stress.h +++ b/Code/Source/solver/active_stress.h @@ -185,10 +185,10 @@ class ActiveStress { /// Number of state variables for this model. const unsigned int n_states; - /// Whether this model uses the fiber stretch passed to + /// Whether this model uses fiber stretch. const bool needs_fiber_stretch; - /// Whether this model uses the fiber stretch rate passed to + /// Whether this model uses fiber stretch rate. const bool needs_fiber_stretch_rate; protected: diff --git a/Code/Source/solver/active_stress_nash_panfilov.h b/Code/Source/solver/active_stress_nash_panfilov.h index 80353c859..37ba4e362 100644 --- a/Code/Source/solver/active_stress_nash_panfilov.h +++ b/Code/Source/solver/active_stress_nash_panfilov.h @@ -71,7 +71,6 @@ class NashPanfilov : public ActiveStressODE { return std::make_unique(); } - protected: /** * @brief Read model parameters from a parameter object. diff --git a/Code/Source/solver/active_stress_regazzoni.h b/Code/Source/solver/active_stress_regazzoni.h index 80e42fd14..419effa1f 100644 --- a/Code/Source/solver/active_stress_regazzoni.h +++ b/Code/Source/solver/active_stress_regazzoni.h @@ -135,7 +135,6 @@ class RegazzoniActiveStress : public ActiveStress { return std::make_unique(); } - protected: /** * @brief Read model parameters from a parameter object. diff --git a/Code/Source/solver/active_stress_uniform_steady.h b/Code/Source/solver/active_stress_uniform_steady.h index 039c23d36..fc5cf41fb 100644 --- a/Code/Source/solver/active_stress_uniform_steady.h +++ b/Code/Source/solver/active_stress_uniform_steady.h @@ -65,7 +65,6 @@ class UniformSteadyActiveStress : public ActiveStress { */ virtual void init_local(Vector &state) const override {} - /** * @brief Advance in time for a single node. * diff --git a/Code/Source/solver/active_stress_uniform_unsteady.h b/Code/Source/solver/active_stress_uniform_unsteady.h index fb8fa4d53..7f9dfa1cc 100644 --- a/Code/Source/solver/active_stress_uniform_unsteady.h +++ b/Code/Source/solver/active_stress_uniform_unsteady.h @@ -77,7 +77,6 @@ class UniformUnsteadyActiveStress : public ActiveStress { */ virtual void init_local(Vector &state) const override {} - /** * @brief Advance in time for a single node. * From 0e51c7f4c0c715f3d5c77d689efb9554489445ac Mon Sep 17 00:00:00 2001 From: dseyler <43078283+dseyler@users.noreply.github.com> Date: Thu, 20 Aug 2026 12:45:08 -0700 Subject: [PATCH 4/4] Copilot suggestion: remove trailing whitespace Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- Code/Source/solver/active_stress_uniform_steady.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Source/solver/active_stress_uniform_steady.h b/Code/Source/solver/active_stress_uniform_steady.h index fc5cf41fb..a209c5b11 100644 --- a/Code/Source/solver/active_stress_uniform_steady.h +++ b/Code/Source/solver/active_stress_uniform_steady.h @@ -33,7 +33,7 @@ class UniformSteadyActiveStress : public ActiveStress { /** * @brief Constructor. */ - UniformSteadyActiveStress() : ActiveStress(/* n_states = */ 0, + UniformSteadyActiveStress() : ActiveStress(/* n_states = */ 0, /* needs_fiber_stretch = */ false, /* needs_fiber_stretch_rate = */ false) {}