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