Chaste Commit::f2ff7ee04e70ac9d06c57344df8d017dbb12b97b
AbstractCentreBasedCellPopulation.cpp
1/*
2
3Copyright (c) 2005-2024, University of Oxford.
4All rights reserved.
5
6University of Oxford means the Chancellor, Masters and Scholars of the
7University of Oxford, having an administrative office at Wellington
8Square, Oxford OX1 2JD, UK.
9
10This file is part of Chaste.
11
12Redistribution and use in source and binary forms, with or without
13modification, 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
23THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
29GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
34*/
35
36#include "AbstractCentreBasedCellPopulation.hpp"
37
38#include "RandomDirectionCentreBasedDivisionRule.hpp"
39#include "RandomNumberGenerator.hpp"
40#include "StepSizeException.hpp"
41#include "WildTypeCellMutationState.hpp"
42
43template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
45 std::vector<CellPtr>& rCells,
46 const std::vector<unsigned> locationIndices)
47 : AbstractOffLatticeCellPopulation<ELEMENT_DIM, SPACE_DIM>(rMesh, rCells, locationIndices),
48 mMeinekeDivisionSeparation(0.3) // educated guess
49{
50 // If no location indices are specified, associate with nodes from the mesh.
51 std::list<CellPtr>::iterator it = this->mCells.begin();
53
54 for (unsigned i = 0; it != this->mCells.end(); ++it, ++i, ++node_iter)
55 {
56 unsigned index = locationIndices.empty() ? node_iter->GetIndex() : locationIndices[i]; // assume that the ordering matches
58 }
59
61}
62
63template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
65 : AbstractOffLatticeCellPopulation<ELEMENT_DIM, SPACE_DIM>(rMesh),
66 mMeinekeDivisionSeparation(0.3) // educated guess
67{
68}
69
70template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
72{
73 return GetNodeCorrespondingToCell(pCell)->rGetLocation();
74}
75
76template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
78{
79 unsigned index = this->GetLocationIndexUsingCell(pCell);
80 return this->GetNode(index);
81}
82
83template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
85 unsigned pdeNodeIndex,
86 std::string& rVariableName,
87 bool dirichletBoundaryConditionApplies,
88 double dirichletBoundaryValue)
89{
90 CellPtr p_cell = this->GetCellUsingLocationIndex(pdeNodeIndex);
91 double value = p_cell->GetCellData()->GetItem(rVariableName);
92
93 return value;
94}
95
96template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
97CellPtr AbstractCentreBasedCellPopulation<ELEMENT_DIM, SPACE_DIM>::AddCell(CellPtr pNewCell, CellPtr pParentCell)
98{
99 // Calculate the locations of the two daughter cells
100 std::pair<c_vector<double, SPACE_DIM>, c_vector<double, SPACE_DIM> > positions = mpCentreBasedDivisionRule->CalculateCellDivisionVector(pParentCell, *this);
101
102 c_vector<double, SPACE_DIM> parent_position = positions.first;
103 c_vector<double, SPACE_DIM> daughter_position = positions.second;
104
105 // Set the parent cell to use this location
106 ChastePoint<SPACE_DIM> parent_point(parent_position);
107 unsigned node_index = this->GetLocationIndexUsingCell(pParentCell);
108 this->SetNode(node_index, parent_point);
109
110 // Create a new node
111 Node<SPACE_DIM>* p_new_node = new Node<SPACE_DIM>(this->GetNumNodes(), daughter_position, false); // never on boundary
112
113 // Clear the applied force on the new node, in case velocity is ouptut on the same timestep as this cell's division
114 p_new_node->ClearAppliedForce();
115
116 // Copy any node attributes from the parent node
117 if (this->GetNode(node_index)->HasNodeAttributes())
118 {
119 p_new_node->rGetNodeAttributes() = this->GetNode(node_index)->rGetNodeAttributes();
120 }
121
122 unsigned new_node_index = this->AddNode(p_new_node); // use copy constructor so it doesn't matter that new_node goes out of scope
123
124 // Update cells vector
125 this->mCells.push_back(pNewCell);
126
127 // Update mappings between cells and location indices
128 this->SetCellUsingLocationIndex(new_node_index, pNewCell);
129 this->mCellLocationMap[pNewCell.get()] = new_node_index;
130
131 return pNewCell;
132}
134template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
135std::pair<CellPtr,CellPtr> AbstractCentreBasedCellPopulation<ELEMENT_DIM, SPACE_DIM>::CreateCellPair(CellPtr pCell1, CellPtr pCell2)
136{
137 assert(pCell1);
138 assert(pCell2);
139
140 std::pair<CellPtr,CellPtr> cell_pair;
141
142 if (pCell1->GetCellId() < pCell2->GetCellId())
143 {
144 cell_pair.first = pCell1;
145 cell_pair.second = pCell2;
146 }
147 else
148 {
149 cell_pair.first = pCell2;
150 cell_pair.second = pCell1;
151 }
152 return cell_pair;
153}
155template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
157{
158 // the pair should be ordered like this (CreateCellPair will ensure this)
159 assert(rCellPair.first->GetCellId() < rCellPair.second->GetCellId());
160
161 return mMarkedSprings.find(rCellPair) != mMarkedSprings.end();
162}
163
164template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
166{
167 // the pair should be ordered like this (CreateCellPair will ensure this)
168 assert(rCellPair.first->GetCellId() < rCellPair.second->GetCellId());
169
170 mMarkedSprings.insert(rCellPair);
172
173template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
175{
176 // the pair should be ordered like this (CreateCellPair will ensure this)
177 assert(rCellPair.first->GetCellId() < rCellPair.second->GetCellId());
178
179 mMarkedSprings.erase(rCellPair);
180}
181
182template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
185 return GetNodeCorrespondingToCell(pCell)->IsDeleted();
186}
187
188template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
190{
191 unsigned node_index = this->GetLocationIndexUsingCell(pCell);
192 return this->GetNeighbouringNodeIndices(node_index);
193}
194
195template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
196void AbstractCentreBasedCellPopulation<ELEMENT_DIM, SPACE_DIM>::CheckForStepSizeException(unsigned nodeIndex, c_vector<double,SPACE_DIM>& rDisplacement, double dt)
197{
198 double length = norm_2(rDisplacement);
199
200 if ((length > this->mAbsoluteMovementThreshold) && (!this->IsGhostNode(nodeIndex)) && (!this->IsParticle(nodeIndex)))
201 {
202 std::ostringstream message;
203 message << "Cells are moving by " << length;
204 message << ", which is more than the AbsoluteMovementThreshold: use a smaller timestep to avoid this exception.";
205
206 // Suggest a net time step that will give a movement smaller than the movement threshold
207 double new_step = 0.95*dt*(this->mAbsoluteMovementThreshold/length);
208
209 throw StepSizeException(new_step, message.str(), true); // terminate
210 }
211}
212
213template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
215{
216 if (this->IsGhostNode(nodeIndex) || this->IsParticle(nodeIndex))
217 {
218 return this->GetDampingConstantNormal();
219 }
220 else
221 {
222 CellPtr p_cell = this->GetCellUsingLocationIndex(nodeIndex);
223 if (p_cell->GetMutationState()->IsType<WildTypeCellMutationState>())
224 {
225 return this->GetDampingConstantNormal();
226 }
227 else
228 {
229 return this->GetDampingConstantMutant();
230 }
231 }
232}
233
234template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
236{
237 return false;
238}
239
240template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
242{
243 return false;
244}
245
246template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
251
252template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
254{
255 assert(divisionSeparation <= 1.0);
256 assert(divisionSeparation >= 0.0);
257 mMeinekeDivisionSeparation = divisionSeparation;
258}
259
260template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
262{
263 for (typename AbstractMesh<ELEMENT_DIM, SPACE_DIM>::NodeIterator node_iter = this->rGetMesh().GetNodeIteratorBegin();
264 node_iter != this->rGetMesh().GetNodeIteratorEnd();
265 ++node_iter)
266 {
267 for (typename std::vector<boost::shared_ptr<AbstractCellWriter<ELEMENT_DIM, SPACE_DIM> > >::iterator cell_writer_iter = this->mCellWriters.begin();
268 cell_writer_iter != this->mCellWriters.end();
269 ++cell_writer_iter)
270 {
271 CellPtr cell_from_node = this->GetCellUsingLocationIndex(node_iter->GetIndex());
272 this->AcceptCellWriter(*cell_writer_iter, cell_from_node);
273 }
275}
276
277template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
278boost::shared_ptr<AbstractCentreBasedDivisionRule<ELEMENT_DIM, SPACE_DIM> > AbstractCentreBasedCellPopulation<ELEMENT_DIM, SPACE_DIM>::GetCentreBasedDivisionRule()
279{
280 return mpCentreBasedDivisionRule;
281}
282
283template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
285{
286 mpCentreBasedDivisionRule = pCentreBasedDivisionRule;
287}
288
289template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
291{
292 *rParamsFile << "\t\t<MeinekeDivisionSeparation>" << mMeinekeDivisionSeparation << "</MeinekeDivisionSeparation>\n";
293
294 // Add the division rule parameters
295 *rParamsFile << "\t\t<CentreBasedDivisionRule>\n";
296 mpCentreBasedDivisionRule->OutputCellCentreBasedDivisionRuleInfo(rParamsFile);
297 *rParamsFile << "\t\t</CentreBasedDivisionRule>\n";
298
299 // Call method on direct parent class
301}
302
303template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
virtual void AddCellUsingLocationIndex(unsigned index, CellPtr pCell)
void MarkSpring(std::pair< CellPtr, CellPtr > &rCellPair)
void UnmarkSpring(std::pair< CellPtr, CellPtr > &rCellPair)
virtual void OutputCellPopulationParameters(out_stream &rParamsFile)
AbstractCentreBasedCellPopulation(AbstractMesh< ELEMENT_DIM, SPACE_DIM > &rMesh)
virtual void CheckForStepSizeException(unsigned nodeIndex, c_vector< double, SPACE_DIM > &rDisplacement, double dt)
std::pair< CellPtr, CellPtr > CreateCellPair(CellPtr pCell1, CellPtr pCell2)
void SetCentreBasedDivisionRule(boost::shared_ptr< AbstractCentreBasedDivisionRule< ELEMENT_DIM, SPACE_DIM > > pCentreBasedDivisionRule)
void SetMeinekeDivisionSeparation(double divisionSeparation)
virtual double GetDampingConstant(unsigned nodeIndex)
bool IsMarkedSpring(const std::pair< CellPtr, CellPtr > &rCellPair)
boost::shared_ptr< AbstractCentreBasedDivisionRule< ELEMENT_DIM, SPACE_DIM > > mpCentreBasedDivisionRule
c_vector< double, SPACE_DIM > GetLocationOfCellCentre(CellPtr pCell)
virtual double GetCellDataItemAtPdeNode(unsigned pdeNodeIndex, std::string &rVariableName, bool dirichletBoundaryConditionApplies=false, double dirichletBoundaryValue=0.0)
virtual std::set< unsigned > GetNeighbouringLocationIndices(CellPtr pCell)
Node< SPACE_DIM > * GetNodeCorrespondingToCell(CellPtr pCell)
CellPtr AddCell(CellPtr pNewCell, CellPtr pParentCell=CellPtr())
boost::shared_ptr< AbstractCentreBasedDivisionRule< ELEMENT_DIM, SPACE_DIM > > GetCentreBasedDivisionRule()
NodeIterator GetNodeIteratorBegin(bool skipDeletedNodes=true)
virtual void OutputCellPopulationParameters(out_stream &rParamsFile)
Definition Node.hpp:59
void ClearAppliedForce()
Definition Node.cpp:216
std::vector< double > & rGetNodeAttributes()
Definition Node.cpp:178