CryptProjectionForce.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
00030
00031
00032
00033
00034
00035
00036 #include "CryptProjectionForce.hpp"
00037 #include "MeshBasedCellPopulation.hpp"
00038 #include "WntConcentration.hpp"
00039 #include "IsNan.hpp"
00040
00041 CryptProjectionForce::CryptProjectionForce()
00042 : GeneralisedLinearSpringForce<2>(),
00043 mIncludeWntChemotaxis(false),
00044 mWntChemotaxisStrength(100.0)
00045 {
00046 mA = WntConcentration<2>::Instance()->GetCryptProjectionParameterA();
00047 mB = WntConcentration<2>::Instance()->GetCryptProjectionParameterB();
00048 }
00049
00050 CryptProjectionForce::~CryptProjectionForce()
00051 {
00052 }
00053
00054 void CryptProjectionForce::UpdateNode3dLocationMap(AbstractCellPopulation<2>& rCellPopulation)
00055 {
00056 mNode3dLocationMap.clear();
00057
00058 c_vector<double, 2> node_location_2d;
00059 c_vector<double, 3> node_location_3d;
00060
00061
00062 for (AbstractCellPopulation<2>::Iterator cell_iter = rCellPopulation.Begin();
00063 cell_iter != rCellPopulation.End();
00064 ++cell_iter)
00065 {
00066
00067 unsigned node_index = rCellPopulation.GetLocationIndexUsingCell(*cell_iter);
00068
00069
00070 node_location_2d = rCellPopulation.GetLocationOfCellCentre(*cell_iter);
00071
00072 node_location_3d[0] = node_location_2d[0];
00073 node_location_3d[1] = node_location_2d[1];
00074 node_location_3d[2] = CalculateCryptSurfaceHeightAtPoint(node_location_2d);
00075
00076
00077 mNode3dLocationMap[node_index] = node_location_3d;
00078 }
00079 }
00080
00081 double CryptProjectionForce::GetA() const
00082 {
00083 return mA;
00084 }
00085
00086 double CryptProjectionForce::GetB() const
00087 {
00088 return mB;
00089 }
00090
00091 void CryptProjectionForce::SetWntChemotaxisStrength(double wntChemotaxisStrength)
00092 {
00093 assert(wntChemotaxisStrength >= 0.0);
00094 mWntChemotaxisStrength = wntChemotaxisStrength;
00095 }
00096 double CryptProjectionForce::GetWntChemotaxisStrength()
00097 {
00098 return mWntChemotaxisStrength;
00099 }
00100
00101 void CryptProjectionForce::SetWntChemotaxis(bool includeWntChemotaxis)
00102 {
00103 mIncludeWntChemotaxis = includeWntChemotaxis;
00104 }
00105
00106 double CryptProjectionForce::CalculateCryptSurfaceHeightAtPoint(const c_vector<double,2>& rNodeLocation)
00107 {
00108 return mA*pow(norm_2(rNodeLocation), mB);
00109 }
00110
00111 double CryptProjectionForce::CalculateCryptSurfaceDerivativeAtPoint(const c_vector<double,2>& rNodeLocation)
00112 {
00113 return mA*mB*pow(norm_2(rNodeLocation), (mB - 1.0));
00114 }
00115
00116 c_vector<double,2> CryptProjectionForce::CalculateForceBetweenNodes(unsigned nodeAGlobalIndex, unsigned nodeBGlobalIndex, AbstractCellPopulation<2>& rCellPopulation)
00117 {
00118 MeshBasedCellPopulation<2>* p_static_cast_cell_population = static_cast<MeshBasedCellPopulation<2>*>(&rCellPopulation);
00119
00120
00121 assert(nodeAGlobalIndex != nodeBGlobalIndex);
00122
00123
00124 c_vector<double,2> node_a_location_2d = rCellPopulation.GetNode(nodeAGlobalIndex)->rGetLocation();
00125 c_vector<double,2> node_b_location_2d = rCellPopulation.GetNode(nodeBGlobalIndex)->rGetLocation();
00126
00127
00128
00129
00130 c_vector<double,3> unit_difference = mNode3dLocationMap[nodeBGlobalIndex] - mNode3dLocationMap[nodeAGlobalIndex];
00131
00132
00133 double distance_between_nodes = norm_2(unit_difference);
00134 assert(distance_between_nodes > 0);
00135 assert(!std::isnan(distance_between_nodes));
00136
00137 unit_difference /= distance_between_nodes;
00138
00139
00140
00141 if (this->mUseCutOffLength)
00142 {
00143 if (distance_between_nodes >= mMechanicsCutOffLength)
00144 {
00145
00146 return zero_vector<double>(2);
00147 }
00148 }
00149
00150
00151
00152 double rest_length = 1.0;
00153
00154 CellPtr p_cell_A = rCellPopulation.GetCellUsingLocationIndex(nodeAGlobalIndex);
00155 CellPtr p_cell_B = rCellPopulation.GetCellUsingLocationIndex(nodeBGlobalIndex);
00156
00157 double ageA = p_cell_A->GetAge();
00158 double ageB = p_cell_B->GetAge();
00159
00160 assert(!std::isnan(ageA));
00161 assert(!std::isnan(ageB));
00162
00163
00164
00165
00166
00167 if (ageA < mMeinekeSpringGrowthDuration && ageB < mMeinekeSpringGrowthDuration)
00168 {
00169
00170
00171
00172
00173 std::pair<CellPtr,CellPtr> cell_pair = p_static_cast_cell_population->CreateCellPair(p_cell_A, p_cell_B);
00174 if (p_static_cast_cell_population->IsMarkedSpring(cell_pair))
00175 {
00176 double lambda = mMeinekeDivisionRestingSpringLength;
00177 rest_length = lambda + (1.0 - lambda) * ageA/mMeinekeSpringGrowthDuration;
00178 }
00179 if (ageA+SimulationTime::Instance()->GetTimeStep() >= mMeinekeSpringGrowthDuration)
00180 {
00181
00182 p_static_cast_cell_population->UnmarkSpring(cell_pair);
00183 }
00184 }
00185
00186 double a_rest_length = rest_length*0.5;
00187 double b_rest_length = a_rest_length;
00188
00189
00190
00191
00192
00193 if (p_cell_A->HasApoptosisBegun())
00194 {
00195 double time_until_death_a = p_cell_A->GetTimeUntilDeath();
00196 a_rest_length = a_rest_length * time_until_death_a / p_cell_A->GetApoptosisTime();
00197 }
00198 if (p_cell_B->HasApoptosisBegun())
00199 {
00200 double time_until_death_b = p_cell_B->GetTimeUntilDeath();
00201 b_rest_length = b_rest_length * time_until_death_b / p_cell_B->GetApoptosisTime();
00202 }
00203
00204 rest_length = a_rest_length + b_rest_length;
00205
00206
00207 assert(rest_length <= 1.0+1e-12);
00208
00209 bool is_closer_than_rest_length = true;
00210
00211 if (distance_between_nodes - rest_length > 0)
00212 {
00213 is_closer_than_rest_length = false;
00214 }
00215
00216
00217
00218
00219
00220 double multiplication_factor = 1.0;
00221 multiplication_factor *= VariableSpringConstantMultiplicationFactor(nodeAGlobalIndex, nodeBGlobalIndex, rCellPopulation, is_closer_than_rest_length);
00222
00223
00224 c_vector<double,3> force_between_nodes = multiplication_factor * this->GetMeinekeSpringStiffness() * unit_difference * (distance_between_nodes - rest_length);
00225
00226
00227 c_vector<double,3> outward_normal_unit_vector;
00228
00229 double dfdr = CalculateCryptSurfaceDerivativeAtPoint(node_b_location_2d);
00230 double theta_B = atan2(node_b_location_2d[1], node_b_location_2d[0]);
00231 double normalization_factor = sqrt(1 + dfdr*dfdr);
00232
00233 outward_normal_unit_vector[0] = dfdr*cos(theta_B)/normalization_factor;
00234 outward_normal_unit_vector[1] = dfdr*sin(theta_B)/normalization_factor;
00235 outward_normal_unit_vector[2] = -1.0/normalization_factor;
00236
00237
00238 c_vector<double,2> projected_force_between_nodes_2d;
00239 double force_dot_normal = inner_prod(force_between_nodes, outward_normal_unit_vector);
00240
00241 for (unsigned i=0; i<2; i++)
00242 {
00243 projected_force_between_nodes_2d[i] = force_between_nodes[i]
00244 - force_dot_normal*outward_normal_unit_vector[i]
00245 + force_dot_normal*outward_normal_unit_vector[2];
00246 }
00247
00248 return projected_force_between_nodes_2d;
00249 }
00250
00251 void CryptProjectionForce::AddForceContribution(AbstractCellPopulation<2>& rCellPopulation)
00252 {
00253
00254 UpdateNode3dLocationMap(rCellPopulation);
00255
00256
00257 if (dynamic_cast<MeshBasedCellPopulation<2>*>(&rCellPopulation) == NULL)
00258 {
00259 EXCEPTION("CryptProjectionForce is to be used with a subclass of MeshBasedCellPopulation only");
00260 }
00261
00262 MeshBasedCellPopulation<2>* p_static_cast_cell_population = static_cast<MeshBasedCellPopulation<2>*>(&rCellPopulation);
00263
00264 for (MeshBasedCellPopulation<2>::SpringIterator spring_iterator = p_static_cast_cell_population->SpringsBegin();
00265 spring_iterator != p_static_cast_cell_population->SpringsEnd();
00266 ++spring_iterator)
00267 {
00268 unsigned nodeA_global_index = spring_iterator.GetNodeA()->GetIndex();
00269 unsigned nodeB_global_index = spring_iterator.GetNodeB()->GetIndex();
00270
00271 c_vector<double, 2> force = CalculateForceBetweenNodes(nodeA_global_index, nodeB_global_index, rCellPopulation);
00272 c_vector<double, 2> negative_force = -1.0 * force;
00273 spring_iterator.GetNodeB()->AddAppliedForceContribution(negative_force);
00274 spring_iterator.GetNodeA()->AddAppliedForceContribution(force);
00275 }
00276
00277 if (mIncludeWntChemotaxis)
00278 {
00279 assert(WntConcentration<2>::Instance()->IsWntSetUp());
00280
00281 for (AbstractCellPopulation<2>::Iterator cell_iter = rCellPopulation.Begin();
00282 cell_iter != rCellPopulation.End();
00283 ++cell_iter)
00284 {
00285 if (cell_iter->GetCellProliferativeType()->IsType<StemCellProliferativeType>())
00286 {
00287 c_vector<double, 2> wnt_chemotactic_force = mWntChemotaxisStrength*WntConcentration<2>::Instance()->GetWntGradient(*cell_iter);
00288 unsigned index = rCellPopulation.GetLocationIndexUsingCell(*cell_iter);
00289
00290 rCellPopulation.GetNode(index)->AddAppliedForceContribution(wnt_chemotactic_force);
00291 }
00292 }
00293 }
00294 }
00295
00296 void CryptProjectionForce::OutputForceParameters(out_stream& rParamsFile)
00297 {
00298 *rParamsFile << "\t\t\t<A>" << mA << "</A>\n";
00299 *rParamsFile << "\t\t\t<B>" << mB << "</B>\n";
00300 *rParamsFile << "\t\t\t<IncludeWntChemotaxis>" << mIncludeWntChemotaxis << "</IncludeWntChemotaxis>\n";
00301 *rParamsFile << "\t\t\t<WntChemotaxisStrength>" << mWntChemotaxisStrength << "</WntChemotaxisStrength>\n";
00302
00303
00304 GeneralisedLinearSpringForce<2>::OutputForceParameters(rParamsFile);
00305 }
00306
00307
00308 #include "SerializationExportWrapperForCpp.hpp"
00309 CHASTE_CLASS_EXPORT(CryptProjectionForce)