36 #include <boost/scoped_array.hpp>
38 #include "CaBasedCellPopulation.hpp"
39 #include "MutableMesh.hpp"
40 #include "AbstractCaUpdateRule.hpp"
41 #include "AbstractCaSwitchingUpdateRule.hpp"
42 #include "RandomNumberGenerator.hpp"
43 #include "CellLocationIndexWriter.hpp"
44 #include "ExclusionCaBasedDivisionRule.hpp"
45 #include "NodesOnlyMesh.hpp"
46 #include "ApoptoticCellProperty.hpp"
49 #include "VtkMeshWriter.hpp"
52 template<
unsigned DIM>
59 template<
unsigned DIM>
61 std::vector<CellPtr>& rCells,
62 const std::vector<unsigned> locationIndices,
63 unsigned latticeCarryingCapacity,
67 mLatticeCarryingCapacity(latticeCarryingCapacity)
75 if (locationIndices.empty())
77 EXCEPTION(
"No location indices being passed. Specify where cells lie before creating the cell population.");
83 std::list<CellPtr>::iterator it = this->
mCells.begin();
84 for (
unsigned i=0; it != this->
mCells.end(); ++it, ++i)
86 assert(i < locationIndices.size());
89 EXCEPTION(
"One of the lattice sites has more cells than the carrying capacity. Check the initial cell locations.");
96 EXCEPTION(
"There is no validation for CaBasedCellPopulation.");
100 template<
unsigned DIM>
106 template<
unsigned DIM>
109 if (this->mDeleteMesh)
111 delete &this->mrMesh;
115 template<
unsigned DIM>
118 return mAvailableSpaces;
121 template<
unsigned DIM>
125 return (mAvailableSpaces[index] != 0);
128 template<
unsigned DIM>
134 template<
unsigned DIM>
140 template<
unsigned DIM>
143 std::vector<Node<DIM>*> temp_nodes;
146 unsigned cell_index = 0;
148 cell_iter != this->End();
151 temp_nodes.push_back(
new Node<DIM>(cell_index, this->GetLocationOfCellCentre(*cell_iter)));
158 template<
unsigned DIM>
161 return this->mrMesh.GetNode(index);
164 template<
unsigned DIM>
167 return this->mrMesh.GetNumNodes();
170 template<
unsigned DIM>
173 unsigned index = this->GetLocationIndexUsingCell(pCell);
176 std::set<unsigned> neighbour_indices;
177 for (std::set<unsigned>::iterator iter = candidates.begin();
178 iter != candidates.end();
181 if (!IsSiteAvailable(*iter, pCell))
183 neighbour_indices.insert(*iter);
187 return neighbour_indices;
190 template<
unsigned DIM>
193 return this->mrMesh.GetNode(this->GetLocationIndexUsingCell(pCell))->rGetLocation();
196 template<
unsigned DIM>
199 return this->mrMesh.GetNode(this->GetLocationIndexUsingCell(pCell));
202 template<
unsigned DIM>
205 if (!IsSiteAvailable(index, pCell))
207 EXCEPTION(
"No available spaces at location index " << index <<
".");
210 mAvailableSpaces[index]--;
214 template<
unsigned DIM>
219 mAvailableSpaces[index]++;
221 assert(mAvailableSpaces[index] <= mLatticeCarryingCapacity);
224 template<
unsigned DIM>
227 return mpCaBasedDivisionRule->IsRoomToDivide(pCell, *
this);
230 template<
unsigned DIM>
233 unsigned daughter_node_index = mpCaBasedDivisionRule->CalculateDaughterNodeIndex(pNewCell,pParentCell,*
this);
236 this->mCells.push_back(pNewCell);
239 CellPtr p_created_cell = this->mCells.back();
240 AddCellUsingLocationIndex(daughter_node_index,p_created_cell);
242 return p_created_cell;
245 template<
unsigned DIM>
247 unsigned targetNodeIndex,
253 template<
unsigned DIM>
256 unsigned num_removed = 0;
258 for (std::list<CellPtr>::iterator cell_iter = this->mCells.begin();
259 cell_iter != this->mCells.end();
262 if ((*cell_iter)->IsDead())
265 unsigned location_index = this->GetLocationIndexUsingCell(*cell_iter);
268 RemoveCellUsingLocationIndex(location_index, (*cell_iter));
271 cell_iter = this->mCells.erase(cell_iter);
282 template<
unsigned DIM>
289 if (!(this->mUpdateRuleCollection.empty()))
293 for (std::list<CellPtr>::iterator cell_iter = this->mCells.begin();
294 cell_iter != this->mCells.end();
298 unsigned node_index = this->GetLocationIndexUsingCell(*cell_iter);
302 std::vector<double> neighbouring_node_propensities;
303 std::vector<unsigned> neighbouring_node_indices_vector;
305 if (!neighbouring_node_indices.empty())
307 unsigned num_neighbours = neighbouring_node_indices.size();
308 double probability_of_not_moving = 1.0;
310 for (std::set<unsigned>::iterator iter = neighbouring_node_indices.begin();
311 iter != neighbouring_node_indices.end();
314 double probability_of_moving = 0.0;
316 neighbouring_node_indices_vector.push_back(*iter);
318 if (IsSiteAvailable(*iter, *cell_iter))
321 for (
typename std::vector<boost::shared_ptr<
AbstractUpdateRule<DIM> > >::iterator iter_rule = this->mUpdateRuleCollection.begin();
322 iter_rule != this->mUpdateRuleCollection.end();
326 double p = (boost::static_pointer_cast<
AbstractCaUpdateRule<DIM> >(*iter_rule))->EvaluateProbability(node_index, *iter, *
this, dt, 1, *cell_iter);
327 probability_of_moving += p;
328 if (probability_of_moving < 0)
330 EXCEPTION(
"The probability of cellular movement is smaller than zero. In order to prevent it from happening you should change your time step and parameters");
333 if (probability_of_moving > 1)
335 EXCEPTION(
"The probability of the cellular movement is bigger than one. In order to prevent it from happening you should change your time step and parameters");
339 probability_of_not_moving -= probability_of_moving;
340 neighbouring_node_propensities.push_back(probability_of_moving);
344 neighbouring_node_propensities.push_back(0.0);
347 if (probability_of_not_moving < 0)
349 EXCEPTION(
"The probability of the cell not moving is smaller than zero. In order to prevent it from happening you should change your time step and parameters");
354 double random_number = p_gen->
ranf();
356 double total_probability = 0.0;
357 for (
unsigned counter=0; counter<num_neighbours; counter++)
359 total_probability += neighbouring_node_propensities[counter];
360 if (total_probability >= random_number)
363 unsigned chosen_neighbour_location_index = neighbouring_node_indices_vector[counter];
364 this->MoveCellInLocationMap((*cell_iter), node_index, chosen_neighbour_location_index);
384 if (!(mSwitchingUpdateRuleCollection.empty()))
386 assert(mLatticeCarryingCapacity == 1);
389 unsigned num_nodes = this->mrMesh.GetNumNodes();
392 if (this->mIterateRandomlyOverUpdateRuleCollection)
395 p_gen->
Shuffle(mSwitchingUpdateRuleCollection);
398 for (
unsigned i=0; i<num_nodes; i++)
402 if (this->mUpdateNodesInRandomOrder)
404 node_index = p_gen->
randMod(num_nodes);
409 node_index = i%num_nodes;
415 unsigned neighbour_location_index;
417 if (!neighbouring_node_indices.empty())
419 unsigned num_neighbours = neighbouring_node_indices.size();
420 unsigned chosen_neighbour = p_gen->
randMod(num_neighbours);
422 std::set<unsigned>::iterator neighbour_iter = neighbouring_node_indices.begin();
423 for (
unsigned j=0; j<chosen_neighbour; j++)
427 neighbour_location_index = *neighbour_iter;
429 bool is_cell_on_node_index = mAvailableSpaces[node_index] == 0 ?
true :
false;
430 bool is_cell_on_neighbour_location_index = mAvailableSpaces[neighbour_location_index] == 0 ?
true :
false;
432 if (is_cell_on_node_index || is_cell_on_neighbour_location_index)
434 double probability_of_switch = 0.0;
437 for (
typename std::vector<boost::shared_ptr<
AbstractUpdateRule<DIM> > >::iterator iter_rule = mSwitchingUpdateRuleCollection.begin();
438 iter_rule != mSwitchingUpdateRuleCollection.end();
442 double p = (boost::static_pointer_cast<
AbstractCaSwitchingUpdateRule<DIM> >(*iter_rule))->EvaluateSwitchingProbability(node_index, neighbour_location_index, *
this, dt, 1);
443 probability_of_switch += p;
446 assert(probability_of_switch >= 0);
447 assert(probability_of_switch <= 1);
450 double random_number = p_gen->
ranf();
452 if (random_number < probability_of_switch)
454 if (is_cell_on_node_index && is_cell_on_neighbour_location_index)
457 CellPtr p_cell = this->GetCellUsingLocationIndex(node_index);
458 CellPtr p_neighbour_cell = this->GetCellUsingLocationIndex(neighbour_location_index);
461 RemoveCellUsingLocationIndex(node_index, p_cell);
462 RemoveCellUsingLocationIndex(neighbour_location_index, p_neighbour_cell);
465 AddCellUsingLocationIndex(node_index, p_neighbour_cell);
466 AddCellUsingLocationIndex(neighbour_location_index, p_cell);
468 else if (is_cell_on_node_index && !is_cell_on_neighbour_location_index)
471 CellPtr p_cell = this->GetCellUsingLocationIndex(node_index);
472 RemoveCellUsingLocationIndex(node_index, p_cell);
473 AddCellUsingLocationIndex(neighbour_location_index, p_cell);
475 else if (!is_cell_on_node_index && is_cell_on_neighbour_location_index)
478 CellPtr p_neighbour_cell = this->GetCellUsingLocationIndex(neighbour_location_index);
479 RemoveCellUsingLocationIndex(neighbour_location_index, p_neighbour_cell);
480 AddCellUsingLocationIndex(node_index, p_neighbour_cell);
493 template<
unsigned DIM>
499 template<
unsigned DIM>
504 template<
unsigned DIM>
507 pPopulationWriter->Visit(
this);
510 template<
unsigned DIM>
513 pPopulationCountWriter->Visit(
this);
516 template<
unsigned DIM>
519 pCellWriter->VisitCell(pCell,
this);
522 template<
unsigned DIM>
525 if (this->mOutputResultsForChasteVisualizer)
527 if (!this->
template HasWriter<CellLocationIndexWriter>())
529 this->
template AddCellWriter<CellLocationIndexWriter>();
536 template<
unsigned DIM>
539 double cell_volume = 1.0;
543 template<
unsigned DIM>
546 double width = this->mrMesh.GetWidth(rDimension);
550 template<
unsigned DIM>
559 this->mUpdateRuleCollection.push_back(pUpdateRule);
563 mSwitchingUpdateRuleCollection.push_back(pUpdateRule);
567 template<
unsigned DIM>
571 mSwitchingUpdateRuleCollection.clear();
577 template<
unsigned DIM>
580 std::vector<boost::shared_ptr<AbstractUpdateRule<DIM> > > update_rules;
582 for (
unsigned i=0; i<this->mUpdateRuleCollection.size(); i++)
584 update_rules.push_back(this->mUpdateRuleCollection[i]);
586 for (
unsigned i=0; i<mSwitchingUpdateRuleCollection.size(); i++)
588 update_rules.push_back(mSwitchingUpdateRuleCollection[i]);
594 template<
unsigned DIM>
597 return mpCaBasedDivisionRule;
600 template<
unsigned DIM>
603 mpCaBasedDivisionRule = pCaBasedDivisionRule;
606 template<
unsigned DIM>
610 *rParamsFile <<
"\t\t<CaBasedDivisionRule>\n";
611 mpCaBasedDivisionRule->OutputCellCaBasedDivisionRuleInfo(rParamsFile);
612 *rParamsFile <<
"\t\t</CaBasedDivisionRule>\n";
618 template<
unsigned DIM>
624 std::stringstream time;
625 time << num_timesteps;
628 unsigned num_cells = this->GetNumRealCells();
631 unsigned num_cell_data_items = 0u;
632 std::vector<std::string> cell_data_names;
635 num_cell_data_items = this->Begin()->GetCellData()->GetNumItems();
636 cell_data_names = this->Begin()->GetCellData()->GetKeys();
638 std::vector<std::vector<double> > cell_data;
639 for (
unsigned var=0; var<num_cell_data_items; var++)
641 std::vector<double> cell_data_var(num_cells);
642 cell_data.push_back(cell_data_var);
650 boost::scoped_array<unsigned> number_of_cells_at_site(
new unsigned[num_sites]);
651 for (
unsigned i=0; i<num_sites; i++)
653 number_of_cells_at_site[i] = 0;
657 std::vector<Node<DIM>*> nodes;
658 unsigned node_index = 0;
660 cell_iter != this->End();
664 unsigned location_index = this->GetLocationIndexUsingCell(*cell_iter);
665 number_of_cells_at_site[location_index]++;
666 assert(number_of_cells_at_site[location_index] <= mLatticeCarryingCapacity);
669 c_vector<double, DIM> coords;
670 coords = this->mrMesh.GetNode(location_index)->rGetLocation();
673 if (mLatticeCarryingCapacity > 1)
675 c_vector<double, DIM> offset;
679 double angle = (
double)number_of_cells_at_site[location_index]*2.0*M_PI/(
double)mLatticeCarryingCapacity;
680 offset[0] = 0.2*sin(angle);
681 offset[1] = 0.2*cos(angle);
686 for (
unsigned i=0; i<DIM; i++)
688 offset[i] = p_gen->
ranf();
692 for (
unsigned i=0; i<DIM; i++)
694 coords[i] += offset[i];
698 nodes.push_back(
new Node<DIM>(node_index, coords,
false));
704 cell_writer_iter != this->mCellWriters.end();
709 std::vector<double> vtk_cell_data(num_cells, -1.0);
712 unsigned cell_index = 0;
714 cell_iter != this->End();
718 vtk_cell_data[cell_index] = (*cell_writer_iter)->GetCellDataForVtkOutput(*cell_iter,
this);
722 mesh_writer.AddPointData((*cell_writer_iter)->GetVtkCellDataName(), vtk_cell_data);
726 unsigned cell_index = 0;
728 cell_iter != this->End();
731 for (
unsigned var=0; var<num_cell_data_items; var++)
733 cell_data[var][cell_index] = cell_iter->GetCellData()->GetItem(cell_data_names[var]);
737 for (
unsigned var=0; var<num_cell_data_items; var++)
739 mesh_writer.AddPointData(cell_data_names[var], cell_data[var]);
751 double volume = this->mrMesh.
GetWidth(0);
752 for (
unsigned idx=1; idx<DIM; idx++)
754 volume *= this->mrMesh.GetWidth(idx);
758 if (this->mrMesh.GetNumNodes() >0 && volume > 0.0)
760 spacing = std::pow(volume /
double(this->mrMesh.GetNumNodes()), 1.0/
double(DIM));
768 mesh_writer.WriteFilesUsingMesh(temp_mesh);
770 *(this->mpVtkMetaFile) <<
" <DataSet timestep=\"";
771 *(this->mpVtkMetaFile) << num_timesteps;
772 *(this->mpVtkMetaFile) <<
"\" group=\"\" part=\"0\" file=\"results_";
773 *(this->mpVtkMetaFile) << num_timesteps;
774 *(this->mpVtkMetaFile) <<
".vtu\"/>\n";
777 for (
unsigned i=0; i<nodes.size(); i++)
784 template<
unsigned DIM>
786 unsigned pdeNodeIndex,
787 std::string& rVariableName,
788 bool dirichletBoundaryConditionApplies,
789 double dirichletBoundaryValue)
791 unsigned counter = 0;
793 while (counter != pdeNodeIndex)
799 double value = cell_iter->GetCellData()->GetItem(rVariableName);
804 template<
unsigned DIM>
810 assert(pdeNodeIndex < this->GetNumRealCells());
811 for (
unsigned i=0; i<pdeNodeIndex; i++)
815 bool is_cell_apoptotic = cell_iter->template HasCellProperty<ApoptoticCellProperty>();
817 return !is_cell_apoptotic;
bool IsCellAssociatedWithADeletedLocation(CellPtr pCell)
boost::shared_ptr< AbstractCaBasedDivisionRule< DIM > > GetCaBasedDivisionRule()
std::vector< unsigned > mAvailableSpaces
unsigned randMod(unsigned base)
std::vector< unsigned > & rGetAvailableSpaces()
void AddCellUsingLocationIndex(unsigned index, CellPtr pCell)
virtual double EvaluateDivisionPropensity(unsigned currentNodeIndex, unsigned targetNodeIndex, CellPtr pCell)
PottsMesh< DIM > & rGetMesh()
void OutputCellPopulationParameters(out_stream &rParamsFile)
virtual bool IsPdeNodeAssociatedWithNonApoptoticCell(unsigned pdeNodeIndex)
virtual void RemoveCellUsingLocationIndex(unsigned index, CellPtr pCell)
Node< DIM > * GetNode(unsigned index)
#define EXCEPTION(message)
virtual void AcceptPopulationCountWriter(boost::shared_ptr< AbstractCellPopulationCountWriter< DIM, DIM > > pPopulationCountWriter)
static SimulationTime * Instance()
virtual bool IsSiteAvailable(unsigned index, CellPtr pCell)
virtual unsigned GetNumNodes()
boost::shared_ptr< AbstractCaBasedDivisionRule< DIM > > mpCaBasedDivisionRule
virtual unsigned GetNumNodes() const
unsigned GetTimeStepsElapsed() const
std::set< unsigned > GetMooreNeighbouringNodeIndices(unsigned nodeIndex)
virtual void OutputCellPopulationParameters(out_stream &rParamsFile)
void RemoveCellUsingLocationIndex(unsigned index, CellPtr pCell)
virtual void WriteVtkResultsToFile(const std::string &rDirectory)
virtual ~CaBasedCellPopulation()
CaBasedCellPopulation(PottsMesh< DIM > &rMesh, std::vector< CellPtr > &rCells, const std::vector< unsigned > locationIndices, unsigned latticeCarryingCapacity=1u, bool deleteMesh=false, bool validate=false)
virtual void RemoveAllUpdateRules()
void Shuffle(std::vector< boost::shared_ptr< T > > &rValues)
bool IsRoomToDivide(CellPtr pCell)
virtual TetrahedralMesh< DIM, DIM > * GetTetrahedralMeshForPdeModifier()
void SetCaBasedDivisionRule(boost::shared_ptr< AbstractCaBasedDivisionRule< DIM > > pCaBasedDivisionRule)
#define EXPORT_TEMPLATE_CLASS_SAME_DIMS(CLASS)
double GetWidth(const unsigned &rDimension) const
std::set< unsigned > GetNeighbouringLocationIndices(CellPtr pCell)
void UpdateCellLocations(double dt)
void Update(bool hasHadBirthsOrDeaths=true)
static RandomNumberGenerator * Instance()
virtual void OpenWritersFiles(OutputFileHandler &rOutputFileHandler)
std::list< CellPtr > mCells
virtual double GetCellDataItemAtPdeNode(unsigned pdeNodeIndex, std::string &rVariableName, bool dirichletBoundaryConditionApplies=false, double dirichletBoundaryValue=0.0)
void RemoveAllUpdateRules()
void ConstructNodesWithoutMesh(const std::vector< Node< SPACE_DIM > * > &rNodes, double maxInteractionDistance)
Node< DIM > * GetNodeCorrespondingToCell(CellPtr pCell)
c_vector< double, DIM > GetLocationOfCellCentre(CellPtr pCell)
double GetWidth(const unsigned &rDimension)
unsigned RemoveDeadCells()
virtual void AcceptPopulationWriter(boost::shared_ptr< AbstractCellPopulationWriter< DIM, DIM > > pPopulationWriter)
double GetVolumeOfCell(CellPtr pCell)
virtual void AddCellUsingLocationIndex(unsigned index, CellPtr pCell)
CellPtr AddCell(CellPtr pNewCell, CellPtr pParentCell=CellPtr())
AbstractMesh< ELEMENT_DIM, ELEMENT_DIM > & mrMesh
virtual void AddUpdateRule(boost::shared_ptr< AbstractUpdateRule< DIM > > pUpdateRule)
virtual void AcceptCellWriter(boost::shared_ptr< AbstractCellWriter< DIM, DIM > > pCellWriter, CellPtr pCell)
virtual void OpenWritersFiles(OutputFileHandler &rOutputFileHandler)
virtual const std::vector< boost::shared_ptr< AbstractUpdateRule< DIM > > > GetUpdateRuleCollection() const