Chaste Commit::6e4f5fe395bca70eb7641cf6e0e87f450383ca5a
LinearSpringWithVariableSpringConstantsForce.cpp
1/*
2
3Copyright (c) 2005-2026, University of Oxford.
4All rights reserved.
5
6University of Oxford means the Chancellor, Masters and Scholars of the
7University of Oxford, having an administrative office at Wellington
8Square, Oxford OX1 2JD, UK.
9
10This file is part of Chaste.
11
12Redistribution and use in source and binary forms, with or without
13modification, are permitted provided that the following conditions are met:
14 * Redistributions of source code must retain the above copyright notice,
15 this list of conditions and the following disclaimer.
16 * Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19 * Neither the name of the University of Oxford nor the names of its
20 contributors may be used to endorse or promote products derived from this
21 software without specific prior written permission.
22
23THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
29GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
34*/
35
36#include "LinearSpringWithVariableSpringConstantsForce.hpp"
37#include "MeshBasedCellPopulation.hpp"
38#include "AbstractVanLeeuwen2009WntSwatCellCycleModel.hpp"
39#include "ApoptoticCellProperty.hpp"
40#include "BetaCateninOneHitCellMutationState.hpp"
41#include "ApcTwoHitCellMutationState.hpp"
42
43template<unsigned DIM>
45 : LinearSpringForce<DIM>(),
46 mUseEdgeBasedSpringConstant(false),
47 mUseMutantSprings(false),
48 mMutantMutantMultiplier(DOUBLE_UNSET),
49 mNormalMutantMultiplier(DOUBLE_UNSET),
50 mUseBCatSprings(false),
51 mUseApoptoticSprings(false),
52 mBetaCatSpringScaler(18.14/6.0), // scale spring constant with beta-catenin level (divided by 6 for heaxagonal cells)
53 mApoptoticSpringTensionStiffness(15.0*0.25),
54 mApoptoticSpringCompressionStiffness(15.0*0.75)
55{
56}
57
58template<unsigned DIM>
62
63template<unsigned DIM>
65{
66 assert(DIM == 2); // LCOV_EXCL_LINE
67 mUseEdgeBasedSpringConstant = useEdgeBasedSpringConstant;
68}
69
70template<unsigned DIM>
71void LinearSpringWithVariableSpringConstantsForce<DIM>::SetMutantSprings(bool useMutantSprings, double mutantMutantMultiplier, double normalMutantMultiplier)
72{
73 mUseMutantSprings = useMutantSprings;
74 mMutantMutantMultiplier = mutantMutantMultiplier;
75 mNormalMutantMultiplier = normalMutantMultiplier;
76}
77
78template<unsigned DIM>
80{
81 mUseBCatSprings = useBCatSprings;
82}
83
84template<unsigned DIM>
86{
87 mUseApoptoticSprings = useApoptoticSprings;
88}
89
90template<unsigned DIM>
92 unsigned nodeAGlobalIndex,
93 unsigned nodeBGlobalIndex,
94 AbstractCellPopulation<DIM>& rCellPopulation,
95 bool isCloserThanRestLength)
96{
97
98 double multiplication_factor = LinearSpringForce<DIM>::VariableSpringConstantMultiplicationFactor(nodeAGlobalIndex,
99 nodeBGlobalIndex,
100 rCellPopulation,
101 isCloserThanRestLength);
102
103 CellPtr p_cell_A = rCellPopulation.GetCellUsingLocationIndex(nodeAGlobalIndex);
104 CellPtr p_cell_B = rCellPopulation.GetCellUsingLocationIndex(nodeBGlobalIndex);
105
106 /*
107 * The next code block computes the edge-dependent spring constant as given by equation
108 * (3) in the following reference: van Leeuwen et al. 2009. An integrative computational model
109 * for intestinal tissue renewal. Cell Prolif. 42(5):617-636. doi:10.1111/j.1365-2184.2009.00627.x
110 */
111 if (mUseEdgeBasedSpringConstant)
112 {
113 assert(bool(dynamic_cast<MeshBasedCellPopulation<DIM>*>(&rCellPopulation)));
114 assert(!mUseBCatSprings); // don't want to do both (both account for edge length)
115
116 multiplication_factor = (static_cast<MeshBasedCellPopulation<DIM>*>(&rCellPopulation))->GetVoronoiEdgeLength(nodeAGlobalIndex, nodeBGlobalIndex)*sqrt(3.0);
117 }
118
119 if (mUseMutantSprings)
120 {
121 unsigned number_of_mutants = 0;
122
123 if (p_cell_A->GetMutationState()->IsType<ApcTwoHitCellMutationState>() || p_cell_A->GetMutationState()->IsType<BetaCateninOneHitCellMutationState>())
124 {
125 // If cell A is mutant
126 number_of_mutants++;
127 }
128
129 if (p_cell_B->GetMutationState()->IsType<ApcTwoHitCellMutationState>() || p_cell_B->GetMutationState()->IsType<BetaCateninOneHitCellMutationState>())
130 {
131 // If cell B is mutant
132 number_of_mutants++;
133 }
134
135 switch (number_of_mutants)
136 {
137 case 1u:
138 {
139 multiplication_factor *= mNormalMutantMultiplier;
140 break;
141 }
142 case 2u:
143 {
144 multiplication_factor *= mMutantMutantMultiplier;
145 break;
146 }
147 }
148 }
149
150 /*
151 * The next code block computes the beta-catenin dependent spring constant as given by equation
152 * (4) in the following reference: van Leeuwen et al. 2009. An integrative computational model
153 * for intestinal tissue renewal. Cell Prolif. 42(5):617-636. doi:10.1111/j.1365-2184.2009.00627.x
154 */
155 if (mUseBCatSprings)
156 {
157 assert(bool(dynamic_cast<MeshBasedCellPopulation<DIM>*>(&rCellPopulation)));
158
159 // If using beta-cat dependent springs, both cell-cycle models had better be VanLeeuwen2009WntSwatCellCycleModel
160 AbstractVanLeeuwen2009WntSwatCellCycleModel* p_model_A = dynamic_cast<AbstractVanLeeuwen2009WntSwatCellCycleModel*>(p_cell_A->GetCellCycleModel());
161 AbstractVanLeeuwen2009WntSwatCellCycleModel* p_model_B = dynamic_cast<AbstractVanLeeuwen2009WntSwatCellCycleModel*>(p_cell_B->GetCellCycleModel());
162
163 assert(!mUseEdgeBasedSpringConstant); // This already adapts for edge lengths - don't want to do it twice.
164 double beta_cat_cell_1 = p_model_A->GetMembraneBoundBetaCateninLevel();
165 double beta_cat_cell_2 = p_model_B->GetMembraneBoundBetaCateninLevel();
166
167 MeshBasedCellPopulation<DIM>* p_static_cast_cell_population = (static_cast<MeshBasedCellPopulation<DIM>*>(&rCellPopulation));
168
169 double perim_cell_1 = p_static_cast_cell_population->GetSurfaceAreaOfVoronoiElement(nodeAGlobalIndex);
170 double perim_cell_2 = p_static_cast_cell_population->GetSurfaceAreaOfVoronoiElement(nodeBGlobalIndex);
171 double edge_length_between_1_and_2 = p_static_cast_cell_population->GetVoronoiEdgeLength(nodeAGlobalIndex, nodeBGlobalIndex);
172
173 double beta_cat_on_cell_1_edge = beta_cat_cell_1 * edge_length_between_1_and_2 / perim_cell_1;
174 double beta_cat_on_cell_2_edge = beta_cat_cell_2 * edge_length_between_1_and_2 / perim_cell_2;
175
176 double min_beta_Cat_of_two_cells = std::min(beta_cat_on_cell_1_edge, beta_cat_on_cell_2_edge);
177
178 multiplication_factor *= min_beta_Cat_of_two_cells / mBetaCatSpringScaler;
179 }
180
181 if (mUseApoptoticSprings)
182 {
183 bool cell_A_is_apoptotic = p_cell_A->HasCellProperty<ApoptoticCellProperty>();
184 bool cell_B_is_apoptotic = p_cell_B->HasCellProperty<ApoptoticCellProperty>();
185
186 if (cell_A_is_apoptotic || cell_B_is_apoptotic)
187 {
188 double spring_a_stiffness = 2.0 * this->GetSpringStiffness();
189 double spring_b_stiffness = 2.0 * this->GetSpringStiffness();
190
191 if (cell_A_is_apoptotic)
192 {
193 if (!isCloserThanRestLength) // if under tension
194 {
195 spring_a_stiffness = mApoptoticSpringTensionStiffness;
196 }
197 else // if under compression
198 {
199 spring_a_stiffness = mApoptoticSpringCompressionStiffness;
200 }
201 }
202 if (cell_B_is_apoptotic)
203 {
204 if (!isCloserThanRestLength) // if under tension
205 {
206 spring_b_stiffness = mApoptoticSpringTensionStiffness;
207 }
208 else // if under compression
209 {
210 spring_b_stiffness = mApoptoticSpringCompressionStiffness;
211 }
212 }
213
214 multiplication_factor /= (1.0/spring_a_stiffness + 1.0/spring_b_stiffness)*this->GetSpringStiffness();
215 }
216 }
217
218 return multiplication_factor;
219}
220
221template<unsigned DIM>
223{
224 // Throw an exception message if not using a MeshBasedCellPopulation
225 if (dynamic_cast<MeshBasedCellPopulation<DIM>*>(&rCellPopulation) == nullptr)
226 {
227 EXCEPTION("LinearSpringWithVariableSpringConstantsForce is to be used with a subclass of MeshBasedCellPopulation only");
228 }
229
230 MeshBasedCellPopulation<DIM>* p_static_cast_cell_population = static_cast<MeshBasedCellPopulation<DIM>*>(&rCellPopulation);
231
232 for (typename MeshBasedCellPopulation<DIM>::SpringIterator spring_iterator = p_static_cast_cell_population->SpringsBegin();
233 spring_iterator != p_static_cast_cell_population->SpringsEnd();
234 ++spring_iterator)
235 {
236 unsigned nodeA_global_index = spring_iterator.GetNodeA()->GetIndex();
237 unsigned nodeB_global_index = spring_iterator.GetNodeB()->GetIndex();
238
239 c_vector<double, DIM> force = this->CalculateForceBetweenNodes(nodeA_global_index, nodeB_global_index, rCellPopulation);
240 c_vector<double, DIM> negative_force = -1.0*force;
241
242 spring_iterator.GetNodeB()->AddAppliedForceContribution(negative_force);
243 spring_iterator.GetNodeA()->AddAppliedForceContribution(force);
244 }
245}
246
247template<unsigned DIM>
249{
250 return mBetaCatSpringScaler;
251}
252
253template<unsigned DIM>
255{
256 assert(betaCatSpringScaler > 0.0);
257 mBetaCatSpringScaler = betaCatSpringScaler;
258}
259
260template<unsigned DIM>
262{
263 return mApoptoticSpringTensionStiffness;
264}
265
266template<unsigned DIM>
268{
269 assert(apoptoticSpringTensionStiffness >= 0.0);
270 mApoptoticSpringTensionStiffness = apoptoticSpringTensionStiffness;
271}
272
273template<unsigned DIM>
275{
276 return mApoptoticSpringCompressionStiffness;
277}
278
279template<unsigned DIM>
281{
282 assert(apoptoticSpringCompressionStiffness >= 0.0);
283 mApoptoticSpringCompressionStiffness = apoptoticSpringCompressionStiffness;
284}
285
286template<unsigned DIM>
288{
289 *rParamsFile << "\t\t\t<UseEdgeBasedSpringConstant>" << mUseEdgeBasedSpringConstant << "</UseEdgeBasedSpringConstant>\n";
290 *rParamsFile << "\t\t\t<UseMutantSprings>" << mUseMutantSprings << "</UseMutantSprings>\n";
291 *rParamsFile << "\t\t\t<MutantMutantMultiplier>" << mMutantMutantMultiplier << "</MutantMutantMultiplier>\n";
292 *rParamsFile << "\t\t\t<NormalMutantMultiplier>" << mNormalMutantMultiplier << "</NormalMutantMultiplier>\n";
293 *rParamsFile << "\t\t\t<UseBCatSprings>" << mUseBCatSprings << "</UseBCatSprings>\n";
294 *rParamsFile << "\t\t\t<UseApoptoticSprings>" << mUseApoptoticSprings << "</UseApoptoticSprings>\n";
295 *rParamsFile << "\t\t\t<BetaCatSpringScaler>" << mBetaCatSpringScaler << "</BetaCatSpringScaler>\n";
296 *rParamsFile << "\t\t\t<ApoptoticSpringTensionStiffness>" << mApoptoticSpringTensionStiffness << "</ApoptoticSpringTensionStiffness>\n";
297 *rParamsFile << "\t\t\t<ApoptoticSpringCompressionStiffness>" << mApoptoticSpringCompressionStiffness << "</ApoptoticSpringCompressionStiffness>\n";
298
299 // Call method on direct parent class
301}
302
303// Explicit instantiation
307
308// Serialization for Boost >= 1.36
const double DOUBLE_UNSET
Definition Exception.hpp:57
#define EXCEPTION(message)
#define EXPORT_TEMPLATE_CLASS_SAME_DIMS(CLASS)
virtual CellPtr GetCellUsingLocationIndex(unsigned index)
virtual double VariableSpringConstantMultiplicationFactor(unsigned nodeAGlobalIndex, unsigned nodeBGlobalIndex, AbstractCellPopulation< ELEMENT_DIM, SPACE_DIM > &rCellPopulation, bool isCloserThanRestLength)
virtual void OutputForceParameters(out_stream &rParamsFile)
void AddForceContribution(AbstractCellPopulation< DIM > &rCellPopulation)
void SetMutantSprings(bool useMutantSprings, double mutantMutantMultiplier=2, double normalMutantMultiplier=1.5)
double VariableSpringConstantMultiplicationFactor(unsigned nodeAGlobalIndex, unsigned nodeBGlobalIndex, AbstractCellPopulation< DIM > &rCellPopulation, bool isCloserThanRestLength)
void SetApoptoticSpringCompressionStiffness(double apoptoticSpringCompressionStiffness)
void SetApoptoticSpringTensionStiffness(double apoptoticSpringTensionStiffness)
double GetVoronoiEdgeLength(unsigned index1, unsigned index2)
double GetSurfaceAreaOfVoronoiElement(unsigned index)