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