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