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 #include "MeshBasedTissue.hpp"
00031
00032 template<unsigned DIM>
00033 GeneralisedLinearSpringForce<DIM>::GeneralisedLinearSpringForce()
00034 : AbstractTwoBodyInteractionForce<DIM>()
00035 {
00036 }
00037
00038 template<unsigned DIM>
00039 double GeneralisedLinearSpringForce<DIM>::VariableSpringConstantMultiplicationFactor(unsigned nodeAGlobalIndex,
00040 unsigned nodeBGlobalIndex,
00041 AbstractTissue<DIM>& rTissue,
00042 bool isCloserThanRestLength)
00043 {
00044 return 1.0;
00045 }
00046
00047 template<unsigned DIM>
00048 GeneralisedLinearSpringForce<DIM>::~GeneralisedLinearSpringForce()
00049 {
00050 }
00051
00052 template<unsigned DIM>
00053 c_vector<double, DIM> GeneralisedLinearSpringForce<DIM>::CalculateForceBetweenNodes(unsigned nodeAGlobalIndex,
00054 unsigned nodeBGlobalIndex,
00055 AbstractTissue<DIM>& rTissue)
00056 {
00057
00058 assert(nodeAGlobalIndex!=nodeBGlobalIndex);
00059
00060
00061 c_vector<double, DIM> node_a_location = rTissue.GetNode(nodeAGlobalIndex)->rGetLocation();
00062 c_vector<double, DIM> node_b_location = rTissue.GetNode(nodeBGlobalIndex)->rGetLocation();
00063
00064
00065 c_vector<double, DIM> unit_difference;
00066 if (rTissue.HasMesh())
00067 {
00068
00069
00070
00071 unit_difference = (static_cast<MeshBasedTissue<DIM>*>(&rTissue))->rGetMesh().GetVectorFromAtoB(node_a_location, node_b_location);
00072 }
00073 else
00074 {
00075 unit_difference = node_b_location - node_a_location;
00076 }
00077
00078
00079 double distance_between_nodes = norm_2(unit_difference);
00080 assert(distance_between_nodes > 0);
00081 assert(!isnan(distance_between_nodes));
00082
00083 unit_difference /= distance_between_nodes;
00084
00085
00086
00087 if (this->mUseCutoffPoint)
00088 {
00089 if (distance_between_nodes >= this->mCutoffPoint)
00090 {
00091 return zero_vector<double>(DIM);
00092 }
00093 }
00094
00095
00096
00097 double rest_length = 1.0;
00098
00099 assert( !(rTissue.IsGhostNode(nodeAGlobalIndex)) && !(rTissue.IsGhostNode(nodeBGlobalIndex)) );
00100
00101 double ageA = rTissue.rGetCellUsingLocationIndex(nodeAGlobalIndex).GetAge();
00102 double ageB = rTissue.rGetCellUsingLocationIndex(nodeBGlobalIndex).GetAge();
00103
00104 assert(!isnan(ageA));
00105 assert(!isnan(ageB));
00106
00107 TissueCell& r_cell_A = rTissue.rGetCellUsingLocationIndex(nodeAGlobalIndex);
00108 TissueCell& r_cell_B = rTissue.rGetCellUsingLocationIndex(nodeBGlobalIndex);
00109
00110
00111
00112 if ( ageA<CancerParameters::Instance()->GetMDuration() && ageB<CancerParameters::Instance()->GetMDuration() )
00113 {
00114 if (rTissue.HasMesh())
00115 {
00116 if ( (static_cast<MeshBasedTissue<DIM>*>(&rTissue))->IsMarkedSpring(r_cell_A, r_cell_B) )
00117 {
00118
00119 double lambda = CancerParameters::Instance()->GetDivisionRestingSpringLength();
00120 rest_length = lambda + (1.0-lambda)*(ageA/(CancerParameters::Instance()->GetMDuration()));
00121 }
00122 if (ageA+SimulationTime::Instance()->GetTimeStep() >= CancerParameters::Instance()->GetMDuration())
00123 {
00124
00125 (static_cast<MeshBasedTissue<DIM>*>(&rTissue))->UnmarkSpring(r_cell_A, r_cell_B);
00126 }
00127 }
00128 else
00129 {
00130
00131 double lambda = CancerParameters::Instance()->GetDivisionRestingSpringLength();
00132 rest_length = lambda + (1.0-lambda)*(ageA/(CancerParameters::Instance()->GetMDuration()));
00133 }
00134 }
00135
00136 double a_rest_length = rest_length*0.5;
00137 double b_rest_length = a_rest_length;
00138
00139
00140
00141 if (rTissue.rGetCellUsingLocationIndex(nodeAGlobalIndex).HasApoptosisBegun())
00142 {
00143 double time_until_death_a = rTissue.rGetCellUsingLocationIndex(nodeAGlobalIndex).TimeUntilDeath();
00144 a_rest_length = a_rest_length*(time_until_death_a)/(CancerParameters::Instance()->GetApoptosisTime());
00145 }
00146 if (rTissue.rGetCellUsingLocationIndex(nodeBGlobalIndex).HasApoptosisBegun())
00147 {
00148 double time_until_death_b = rTissue.rGetCellUsingLocationIndex(nodeBGlobalIndex).TimeUntilDeath();
00149 b_rest_length = b_rest_length*(time_until_death_b)/(CancerParameters::Instance()->GetApoptosisTime());
00150 }
00151
00152 rest_length = a_rest_length + b_rest_length;
00153
00154 assert(rest_length<=1.0+1e-12);
00155
00156 bool is_closer_than_rest_length = true;
00157
00158 if (distance_between_nodes - rest_length >0)
00159 {
00160 is_closer_than_rest_length = false;
00161 }
00162
00163
00164
00165 double multiplication_factor = 1.0;
00166 multiplication_factor *= VariableSpringConstantMultiplicationFactor(nodeAGlobalIndex, nodeBGlobalIndex, rTissue, is_closer_than_rest_length);
00167
00168 if (rTissue.HasMesh())
00169 {
00170 return multiplication_factor * CancerParameters::Instance()->GetSpringStiffness() * unit_difference * (distance_between_nodes - rest_length);
00171 }
00172 else
00173 {
00174
00175 if (distance_between_nodes > rest_length)
00176 {
00177 double alpha = 5;
00178 c_vector<double, DIM> temp = CancerParameters::Instance()->GetSpringStiffness() * unit_difference * (distance_between_nodes - rest_length)*exp(-alpha*(distance_between_nodes-rest_length));
00179 for (unsigned i=0; i<DIM; i++)
00180 {
00181 assert(!isnan(temp[i]));
00182 }
00183 return temp;
00184 }
00185 else
00186 {
00187 c_vector<double, DIM> temp = CancerParameters::Instance()->GetSpringStiffness() * unit_difference * log(1 + distance_between_nodes - rest_length);
00188 for (unsigned i=0; i<DIM; i++)
00189 {
00190 assert(!isnan(temp[i]));
00191 }
00192 return temp;
00193 }
00194 }
00195 }
00196
00197 template<unsigned DIM>
00198 void GeneralisedLinearSpringForce<DIM>::AddForceContribution(std::vector<c_vector<double, DIM> >& rForces,
00199 AbstractTissue<DIM>& rTissue)
00200 {
00201 if (rTissue.HasMesh())
00202 {
00203
00204 for (typename MeshBasedTissue<DIM>::SpringIterator spring_iterator=(static_cast<MeshBasedTissue<DIM>*>(&rTissue))->SpringsBegin();
00205 spring_iterator!=(static_cast<MeshBasedTissue<DIM>*>(&rTissue))->SpringsEnd();
00206 ++spring_iterator)
00207 {
00208 unsigned nodeA_global_index = spring_iterator.GetNodeA()->GetIndex();
00209 unsigned nodeB_global_index = spring_iterator.GetNodeB()->GetIndex();
00210
00211
00212 c_vector<double, DIM> force = CalculateForceBetweenNodes(nodeA_global_index, nodeB_global_index, rTissue);
00213
00214
00215 rForces[nodeB_global_index] -= force;
00216 rForces[nodeA_global_index] += force;
00217 }
00218 }
00219 else
00220 {
00221
00222 for (unsigned node_a_index=0; node_a_index<rTissue.GetNumNodes(); node_a_index++)
00223 {
00224
00225 for (unsigned node_b_index=node_a_index+1; node_b_index<rTissue.GetNumNodes(); node_b_index++)
00226 {
00227
00228 c_vector<double, DIM> force = CalculateForceBetweenNodes(node_a_index, node_b_index, rTissue);
00229 for (unsigned j=0; j<DIM; j++)
00230 {
00231 assert(!isnan(force[j]));
00232 }
00233
00234
00235 rForces[node_a_index] += force;
00236 rForces[node_b_index] -= force;
00237 }
00238 }
00239 }
00240 }
00241
00242
00244
00246
00247 template class GeneralisedLinearSpringForce<1>;
00248 template class GeneralisedLinearSpringForce<2>;
00249 template class GeneralisedLinearSpringForce<3>;