GeneralisedLinearSpringForce.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "GeneralisedLinearSpringForce.hpp"
00030
00031 template<unsigned DIM>
00032 GeneralisedLinearSpringForce<DIM>::GeneralisedLinearSpringForce()
00033 : AbstractTwoBodyInteractionForce<DIM>(),
00034 mMeinekeSpringStiffness(15.0),
00035 mMeinekeDivisionRestingSpringLength(0.5),
00036 mMeinekeSpringGrowthDuration(1.0)
00037 {
00038 if (DIM == 1)
00039 {
00040 mMeinekeSpringStiffness = 30.0;
00041 }
00042 }
00043
00044 template<unsigned DIM>
00045 double GeneralisedLinearSpringForce<DIM>::VariableSpringConstantMultiplicationFactor(unsigned nodeAGlobalIndex,
00046 unsigned nodeBGlobalIndex,
00047 AbstractCellPopulation<DIM>& rCellPopulation,
00048 bool isCloserThanRestLength)
00049 {
00050 return 1.0;
00051 }
00052
00053 template<unsigned DIM>
00054 GeneralisedLinearSpringForce<DIM>::~GeneralisedLinearSpringForce()
00055 {
00056 }
00057
00058 template<unsigned DIM>
00059 c_vector<double, DIM> GeneralisedLinearSpringForce<DIM>::CalculateForceBetweenNodes(unsigned nodeAGlobalIndex,
00060 unsigned nodeBGlobalIndex,
00061 AbstractCellPopulation<DIM>& rCellPopulation)
00062 {
00063
00064 assert(nodeAGlobalIndex != nodeBGlobalIndex);
00065
00066
00067 c_vector<double, DIM> node_a_location = rCellPopulation.GetNode(nodeAGlobalIndex)->rGetLocation();
00068 c_vector<double, DIM> node_b_location = rCellPopulation.GetNode(nodeBGlobalIndex)->rGetLocation();
00069
00070
00071 c_vector<double, DIM> unit_difference;
00072 if (dynamic_cast<MeshBasedCellPopulation<DIM>*>(&rCellPopulation))
00073 {
00074
00075
00076
00077
00078
00079
00080 unit_difference = (static_cast<MeshBasedCellPopulation<DIM>*>(&rCellPopulation))->rGetMesh().GetVectorFromAtoB(node_a_location, node_b_location);
00081 }
00082 else
00083 {
00084 unit_difference = node_b_location - node_a_location;
00085 }
00086
00087
00088 double distance_between_nodes = norm_2(unit_difference);
00089 assert(distance_between_nodes > 0);
00090 assert(!std::isnan(distance_between_nodes));
00091
00092 unit_difference /= distance_between_nodes;
00093
00094
00095
00096
00097
00098 if (this->mUseCutOffLength)
00099 {
00100 if (distance_between_nodes >= this->GetCutOffLength())
00101 {
00102 return zero_vector<double>(DIM);
00103 }
00104 }
00105
00106
00107
00108 double rest_length = 1.0;
00109
00110 CellPtr p_cell_A = rCellPopulation.GetCellUsingLocationIndex(nodeAGlobalIndex);
00111 CellPtr p_cell_B = rCellPopulation.GetCellUsingLocationIndex(nodeBGlobalIndex);
00112
00113 double ageA = p_cell_A->GetAge();
00114 double ageB = p_cell_B->GetAge();
00115
00116 assert(!std::isnan(ageA));
00117 assert(!std::isnan(ageB));
00118
00119
00120
00121
00122
00123 if (ageA < mMeinekeSpringGrowthDuration && ageB < mMeinekeSpringGrowthDuration)
00124 {
00125 if (dynamic_cast<MeshBasedCellPopulation<DIM>*>(&rCellPopulation))
00126 {
00127 MeshBasedCellPopulation<DIM>* p_static_cast_cell_population = static_cast<MeshBasedCellPopulation<DIM>*>(&rCellPopulation);
00128
00129 std::pair<CellPtr,CellPtr> cell_pair = p_static_cast_cell_population->CreateCellPair(p_cell_A, p_cell_B);
00130
00131 if (p_static_cast_cell_population->IsMarkedSpring(cell_pair))
00132 {
00133
00134 double lambda = mMeinekeDivisionRestingSpringLength;
00135 rest_length = lambda + (1.0 - lambda) * ageA/mMeinekeSpringGrowthDuration;
00136 }
00137 if (ageA + SimulationTime::Instance()->GetTimeStep() >= mMeinekeSpringGrowthDuration)
00138 {
00139
00140 p_static_cast_cell_population->UnmarkSpring(cell_pair);
00141 }
00142 }
00143 else
00144 {
00145
00146 double lambda = mMeinekeDivisionRestingSpringLength;
00147 rest_length = lambda + (1.0 - lambda) * ageA/mMeinekeSpringGrowthDuration;
00148 }
00149 }
00150
00151 double a_rest_length = rest_length*0.5;
00152 double b_rest_length = a_rest_length;
00153
00154
00155
00156
00157
00158 if (p_cell_A->HasApoptosisBegun())
00159 {
00160 double time_until_death_a = p_cell_A->GetTimeUntilDeath();
00161 a_rest_length = a_rest_length * time_until_death_a / p_cell_A->GetApoptosisTime();
00162 }
00163 if (p_cell_B->HasApoptosisBegun())
00164 {
00165 double time_until_death_b = p_cell_B->GetTimeUntilDeath();
00166 b_rest_length = b_rest_length * time_until_death_b / p_cell_B->GetApoptosisTime();
00167 }
00168
00169 rest_length = a_rest_length + b_rest_length;
00170 assert(rest_length <= 1.0+1e-12);
00171
00172
00173
00174
00175 double overlap = distance_between_nodes - rest_length;
00176 bool is_closer_than_rest_length = (overlap <= 0);
00177 double multiplication_factor = VariableSpringConstantMultiplicationFactor(nodeAGlobalIndex, nodeBGlobalIndex, rCellPopulation, is_closer_than_rest_length);
00178 double spring_stiffness = mMeinekeSpringStiffness;
00179
00180 if (dynamic_cast<MeshBasedCellPopulation<DIM>*>(&rCellPopulation))
00181 {
00182 return multiplication_factor * spring_stiffness * unit_difference * overlap;
00183 }
00184 else
00185 {
00186
00187 if (is_closer_than_rest_length)
00188 {
00189
00190 assert(overlap > -1);
00191 c_vector<double, DIM> temp = spring_stiffness * unit_difference * log(1 + overlap);
00192 return temp;
00193 }
00194 else
00195 {
00196 double alpha = 5;
00197 c_vector<double, DIM> temp = spring_stiffness * unit_difference * overlap * exp(-alpha * overlap);
00198 return temp;
00199 }
00200 }
00201 }
00202
00203 template<unsigned DIM>
00204 double GeneralisedLinearSpringForce<DIM>::GetMeinekeSpringStiffness()
00205 {
00206 return mMeinekeSpringStiffness;
00207 }
00208 template<unsigned DIM>
00209 double GeneralisedLinearSpringForce<DIM>::GetMeinekeDivisionRestingSpringLength()
00210 {
00211 return mMeinekeDivisionRestingSpringLength;
00212 }
00213 template<unsigned DIM>
00214 double GeneralisedLinearSpringForce<DIM>::GetMeinekeSpringGrowthDuration()
00215 {
00216 return mMeinekeSpringGrowthDuration;
00217 }
00218
00219 template<unsigned DIM>
00220 void GeneralisedLinearSpringForce<DIM>::SetMeinekeSpringStiffness(double springStiffness)
00221 {
00222 assert(springStiffness > 0.0);
00223 mMeinekeSpringStiffness = springStiffness;
00224 }
00225
00226 template<unsigned DIM>
00227 void GeneralisedLinearSpringForce<DIM>::SetMeinekeDivisionRestingSpringLength(double divisionRestingSpringLength)
00228 {
00229 assert(divisionRestingSpringLength <= 1.0);
00230 assert(divisionRestingSpringLength >= 0.0);
00231
00232 mMeinekeDivisionRestingSpringLength = divisionRestingSpringLength;
00233 }
00234
00235 template<unsigned DIM>
00236 void GeneralisedLinearSpringForce<DIM>::SetMeinekeSpringGrowthDuration(double springGrowthDuration)
00237 {
00238 assert(springGrowthDuration >= 0.0);
00239
00240 mMeinekeSpringGrowthDuration = springGrowthDuration;
00241 }
00242
00243 template<unsigned DIM>
00244 void GeneralisedLinearSpringForce<DIM>::OutputForceParameters(out_stream& rParamsFile)
00245 {
00246 *rParamsFile << "\t\t\t<MeinekeSpringStiffness>" << mMeinekeSpringStiffness << "</MeinekeSpringStiffness>\n";
00247 *rParamsFile << "\t\t\t<MeinekeDivisionRestingSpringLength>" << mMeinekeDivisionRestingSpringLength << "</MeinekeDivisionRestingSpringLength>\n";
00248 *rParamsFile << "\t\t\t<MeinekeSpringGrowthDuration>" << mMeinekeSpringGrowthDuration << "</MeinekeSpringGrowthDuration>\n";
00249
00250
00251 AbstractTwoBodyInteractionForce<DIM>::OutputForceParameters(rParamsFile);
00252 }
00253
00255
00257
00258 template class GeneralisedLinearSpringForce<1>;
00259 template class GeneralisedLinearSpringForce<2>;
00260 template class GeneralisedLinearSpringForce<3>;
00261
00262
00263 #include "SerializationExportWrapperForCpp.hpp"
00264 EXPORT_TEMPLATE_CLASS_SAME_DIMS(GeneralisedLinearSpringForce)