Chaste  Release::3.4
CryptProjectionForce.cpp
1 /*
2 
3 Copyright (c) 2005-2016, University of Oxford.
4 All rights reserved.
5 
6 University of Oxford means the Chancellor, Masters and Scholars of the
7 University of Oxford, having an administrative office at Wellington
8 Square, Oxford OX1 2JD, UK.
9 
10 This file is part of Chaste.
11 
12 Redistribution and use in source and binary forms, with or without
13 modification, are permitted provided that the following conditions are met:
14  * Redistributions of source code must retain the above copyright notice,
15  this list of conditions and the following disclaimer.
16  * Redistributions in binary form must reproduce the above copyright notice,
17  this list of conditions and the following disclaimer in the documentation
18  and/or other materials provided with the distribution.
19  * Neither the name of the University of Oxford nor the names of its
20  contributors may be used to endorse or promote products derived from this
21  software without specific prior written permission.
22 
23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
29 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 
34 */
35 
36 #include "CryptProjectionForce.hpp"
37 #include "MeshBasedCellPopulation.hpp"
38 #include "WntConcentration.hpp"
39 #include "IsNan.hpp"
40 
43  mIncludeWntChemotaxis(false),
44  mWntChemotaxisStrength(100.0)
45 {
48 }
49 
51 {
52 }
53 
55 {
56  mNode3dLocationMap.clear();
57 
58  c_vector<double, 2> node_location_2d;
59  c_vector<double, 3> node_location_3d;
60 
61  // Only consider nodes corresponding to real cells
62  for (AbstractCellPopulation<2>::Iterator cell_iter = rCellPopulation.Begin();
63  cell_iter != rCellPopulation.End();
64  ++cell_iter)
65  {
66  // Get node index
67  unsigned node_index = rCellPopulation.GetLocationIndexUsingCell(*cell_iter);
68 
69  // Get 3D location
70  node_location_2d = rCellPopulation.GetLocationOfCellCentre(*cell_iter);
71 
72  node_location_3d[0] = node_location_2d[0];
73  node_location_3d[1] = node_location_2d[1];
74  node_location_3d[2] = CalculateCryptSurfaceHeightAtPoint(node_location_2d);
75 
76  // Add to map
77  mNode3dLocationMap[node_index] = node_location_3d;
78  }
79 }
80 
82 {
83  return mA;
84 }
85 
87 {
88  return mB;
89 }
90 
91 void CryptProjectionForce::SetWntChemotaxisStrength(double wntChemotaxisStrength)
92 {
93  assert(wntChemotaxisStrength >= 0.0);
94  mWntChemotaxisStrength = wntChemotaxisStrength;
95 }
97 {
99 }
100 
101 void CryptProjectionForce::SetWntChemotaxis(bool includeWntChemotaxis)
102 {
103  mIncludeWntChemotaxis = includeWntChemotaxis;
104 }
105 
106 double CryptProjectionForce::CalculateCryptSurfaceHeightAtPoint(const c_vector<double,2>& rNodeLocation)
107 {
108  return mA*pow(norm_2(rNodeLocation), mB); // =z_coord;
109 }
110 
111 double CryptProjectionForce::CalculateCryptSurfaceDerivativeAtPoint(const c_vector<double,2>& rNodeLocation)
112 {
113  return mA*mB*pow(norm_2(rNodeLocation), (mB - 1.0));
114 }
115 
116 c_vector<double,2> CryptProjectionForce::CalculateForceBetweenNodes(unsigned nodeAGlobalIndex, unsigned nodeBGlobalIndex, AbstractCellPopulation<2>& rCellPopulation)
117 {
118  MeshBasedCellPopulation<2>* p_static_cast_cell_population = static_cast<MeshBasedCellPopulation<2>*>(&rCellPopulation);
119 
120  // We should only ever calculate the force between two distinct nodes
121  assert(nodeAGlobalIndex != nodeBGlobalIndex);
122 
123  // Get the node locations in 2D
124  c_vector<double,2> node_a_location_2d = rCellPopulation.GetNode(nodeAGlobalIndex)->rGetLocation();
125  c_vector<double,2> node_b_location_2d = rCellPopulation.GetNode(nodeBGlobalIndex)->rGetLocation();
126 
127  // "Get the unit vector parallel to the line joining the two nodes" [GeneralisedLinearSpringForce]
128 
129  // Create a unit vector in the direction of the 3D spring
130  c_vector<double,3> unit_difference = mNode3dLocationMap[nodeBGlobalIndex] - mNode3dLocationMap[nodeAGlobalIndex];
131 
132  // Calculate the distance between the two nodes
133  double distance_between_nodes = norm_2(unit_difference);
134  assert(distance_between_nodes > 0);
135  assert(!std::isnan(distance_between_nodes));
136 
137  unit_difference /= distance_between_nodes;
138 
139  // If mUseCutOffLength has been set, then there is zero force between
140  // two nodes located a distance apart greater than mUseCutOffLength
141  if (this->mUseCutOffLength)
142  {
143  if (distance_between_nodes >= mMechanicsCutOffLength)
144  {
145  // Return zero (2D projected) force
146  return zero_vector<double>(2);
147  }
148  }
149 
150  // Calculate the rest length of the spring connecting the two nodes
151 
152  double rest_length = 1.0;
153 
154  CellPtr p_cell_A = rCellPopulation.GetCellUsingLocationIndex(nodeAGlobalIndex);
155  CellPtr p_cell_B = rCellPopulation.GetCellUsingLocationIndex(nodeBGlobalIndex);
156 
157  double ageA = p_cell_A->GetAge();
158  double ageB = p_cell_B->GetAge();
159 
160  assert(!std::isnan(ageA));
161  assert(!std::isnan(ageB));
162 
163  /*
164  * If the cells are both newly divided, then the rest length of the spring
165  * connecting them grows linearly with time, until mMeinekeSpringGrowthDuration hour after division.
166  */
168  {
169  /*
170  * The spring rest length increases from a predefined small parameter
171  * to a normal rest length of 1.0, over a period of one hour.
172  */
173  std::pair<CellPtr,CellPtr> cell_pair = p_static_cast_cell_population->CreateCellPair(p_cell_A, p_cell_B);
174  if (p_static_cast_cell_population->IsMarkedSpring(cell_pair))
175  {
176  double lambda = mMeinekeDivisionRestingSpringLength;
177  rest_length = lambda + (1.0 - lambda) * ageA/mMeinekeSpringGrowthDuration;
178  }
180  {
181  // This spring is about to go out of scope
182  p_static_cast_cell_population->UnmarkSpring(cell_pair);
183  }
184  }
185 
186  double a_rest_length = rest_length*0.5;
187  double b_rest_length = a_rest_length;
188 
189  /*
190  * If either of the cells has begun apoptosis, then the length of the spring
191  * connecting them decreases linearly with time.
192  */
193  if (p_cell_A->HasApoptosisBegun())
194  {
195  double time_until_death_a = p_cell_A->GetTimeUntilDeath();
196  a_rest_length = a_rest_length * time_until_death_a / p_cell_A->GetApoptosisTime();
197  }
198  if (p_cell_B->HasApoptosisBegun())
199  {
200  double time_until_death_b = p_cell_B->GetTimeUntilDeath();
201  b_rest_length = b_rest_length * time_until_death_b / p_cell_B->GetApoptosisTime();
202  }
203 
204  rest_length = a_rest_length + b_rest_length;
205 
206  // Assert that the rest length does not exceed 1
207  assert(rest_length <= 1.0+1e-12);
208 
209  bool is_closer_than_rest_length = true;
210 
211  if (distance_between_nodes - rest_length > 0)
212  {
213  is_closer_than_rest_length = false;
214  }
215 
216  /*
217  * Although in this class the 'spring constant' is a constant parameter, in
218  * subclasses it can depend on properties of each of the cells.
219  */
220  double multiplication_factor = 1.0;
221  multiplication_factor *= VariableSpringConstantMultiplicationFactor(nodeAGlobalIndex, nodeBGlobalIndex, rCellPopulation, is_closer_than_rest_length);
222 
223  // Calculate the 3D force between the two points
224  c_vector<double,3> force_between_nodes = multiplication_factor * this->GetMeinekeSpringStiffness() * unit_difference * (distance_between_nodes - rest_length);
225 
226  // Calculate an outward normal unit vector to the tangent plane of the crypt surface at the 3D point corresponding to node B
227  c_vector<double,3> outward_normal_unit_vector;
228 
229  double dfdr = CalculateCryptSurfaceDerivativeAtPoint(node_b_location_2d);
230  double theta_B = atan2(node_b_location_2d[1], node_b_location_2d[0]); // use atan2 to determine the quadrant
231  double normalization_factor = sqrt(1 + dfdr*dfdr);
232 
233  outward_normal_unit_vector[0] = dfdr*cos(theta_B)/normalization_factor;
234  outward_normal_unit_vector[1] = dfdr*sin(theta_B)/normalization_factor;
235  outward_normal_unit_vector[2] = -1.0/normalization_factor;
236 
237  // Calculate the projection of the force onto the plane z=0
238  c_vector<double,2> projected_force_between_nodes_2d;
239  double force_dot_normal = inner_prod(force_between_nodes, outward_normal_unit_vector);
240 
241  for (unsigned i=0; i<2; i++)
242  {
243  projected_force_between_nodes_2d[i] = force_between_nodes[i]
244  - force_dot_normal*outward_normal_unit_vector[i]
245  + force_dot_normal*outward_normal_unit_vector[2];
246  }
247 
248  return projected_force_between_nodes_2d;
249 }
250 
252 {
253  // First work out the 3D location of each cell
254  UpdateNode3dLocationMap(rCellPopulation);
255 
256  // Throw an exception message if not using a MeshBasedCellPopulation
257  if (dynamic_cast<MeshBasedCellPopulation<2>*>(&rCellPopulation) == NULL)
258  {
259  EXCEPTION("CryptProjectionForce is to be used with a subclass of MeshBasedCellPopulation only");
260  }
261 
262  MeshBasedCellPopulation<2>* p_static_cast_cell_population = static_cast<MeshBasedCellPopulation<2>*>(&rCellPopulation);
263 
264  for (MeshBasedCellPopulation<2>::SpringIterator spring_iterator = p_static_cast_cell_population->SpringsBegin();
265  spring_iterator != p_static_cast_cell_population->SpringsEnd();
266  ++spring_iterator)
267  {
268  unsigned nodeA_global_index = spring_iterator.GetNodeA()->GetIndex();
269  unsigned nodeB_global_index = spring_iterator.GetNodeB()->GetIndex();
270 
271  c_vector<double, 2> force = CalculateForceBetweenNodes(nodeA_global_index, nodeB_global_index, rCellPopulation);
272  c_vector<double, 2> negative_force = -1.0 * force;
273  spring_iterator.GetNodeB()->AddAppliedForceContribution(negative_force);
274  spring_iterator.GetNodeA()->AddAppliedForceContribution(force);
275  }
276 
278  {
279  assert(WntConcentration<2>::Instance()->IsWntSetUp());
280 
281  for (AbstractCellPopulation<2>::Iterator cell_iter = rCellPopulation.Begin();
282  cell_iter != rCellPopulation.End();
283  ++cell_iter)
284  {
285  if (cell_iter->GetCellProliferativeType()->IsType<StemCellProliferativeType>())
286  {
287  c_vector<double, 2> wnt_chemotactic_force = mWntChemotaxisStrength*WntConcentration<2>::Instance()->GetWntGradient(*cell_iter);
288  unsigned index = rCellPopulation.GetLocationIndexUsingCell(*cell_iter);
289 
290  rCellPopulation.GetNode(index)->AddAppliedForceContribution(wnt_chemotactic_force);
291  }
292  }
293  }
294 }
295 
296 void CryptProjectionForce::OutputForceParameters(out_stream& rParamsFile)
297 {
298  *rParamsFile << "\t\t\t<A>" << mA << "</A>\n";
299  *rParamsFile << "\t\t\t<B>" << mB << "</B>\n";
300  *rParamsFile << "\t\t\t<IncludeWntChemotaxis>" << mIncludeWntChemotaxis << "</IncludeWntChemotaxis>\n";
301  *rParamsFile << "\t\t\t<WntChemotaxisStrength>" << mWntChemotaxisStrength << "</WntChemotaxisStrength>\n";
302 
303  // Call method on direct parent class
305 }
306 
307 // Serialization for Boost >= 1.36
virtual Node< SPACE_DIM > * GetNode(unsigned index)=0
void UnmarkSpring(std::pair< CellPtr, CellPtr > &rCellPair)
virtual CellPtr GetCellUsingLocationIndex(unsigned index)
void SetWntChemotaxis(bool includeWntChemotaxis)
unsigned GetLocationIndexUsingCell(CellPtr pCell)
#define EXCEPTION(message)
Definition: Exception.hpp:143
static SimulationTime * Instance()
double CalculateCryptSurfaceDerivativeAtPoint(const c_vector< double, 2 > &rNodeLocation)
double GetCryptProjectionParameterB()
double GetTimeStep() const
std::pair< CellPtr, CellPtr > CreateCellPair(CellPtr pCell1, CellPtr pCell2)
double CalculateCryptSurfaceHeightAtPoint(const c_vector< double, 2 > &rNodeLocation)
void UpdateNode3dLocationMap(AbstractCellPopulation< 2 > &rCellPopulation)
static WntConcentration * Instance()
c_vector< double, 2 > CalculateForceBetweenNodes(unsigned nodeAGlobalIndex, unsigned nodeBGlobalIndex, AbstractCellPopulation< 2 > &rCellPopulation)
c_vector< double, DIM > GetWntGradient(c_vector< double, DIM > &rLocation)
bool IsMarkedSpring(const std::pair< CellPtr, CellPtr > &rCellPair)
virtual c_vector< double, SPACE_DIM > GetLocationOfCellCentre(CellPtr pCell)=0
std::map< unsigned, c_vector< double, 3 > > mNode3dLocationMap
void OutputForceParameters(out_stream &rParamsFile)
virtual double VariableSpringConstantMultiplicationFactor(unsigned nodeAGlobalIndex, unsigned nodeBGlobalIndex, AbstractCellPopulation< ELEMENT_DIM, ELEMENT_DIM > &rCellPopulation, bool isCloserThanRestLength)
virtual void OutputForceParameters(out_stream &rParamsFile)
void AddForceContribution(AbstractCellPopulation< 2 > &rCellPopulation)
void SetWntChemotaxisStrength(double wntChemotaxisStrength)
#define CHASTE_CLASS_EXPORT(T)
double GetCryptProjectionParameterA()