36 #include "PottsBasedCellPopulation.hpp"
37 #include "RandomNumberGenerator.hpp"
38 #include "Warnings.hpp"
41 #include "VtkMeshWriter.hpp"
42 #include "NodesOnlyMesh.hpp"
46 #include "CellPopulationElementWriter.hpp"
47 #include "CellIdWriter.hpp"
49 template<
unsigned DIM>
53 std::vector<unsigned> validated_element = std::vector<unsigned>(this->GetNumElements(), 0);
56 cell_iter != this->End();
59 unsigned elem_index = this->GetLocationIndexUsingCell(*cell_iter);
60 validated_element[elem_index]++;
63 for (
unsigned i=0; i<validated_element.size(); i++)
65 if (validated_element[i] == 0)
70 if (validated_element[i] > 1)
72 EXCEPTION(
"At time " <<
SimulationTime::Instance()->GetTime() <<
", Element " << i <<
" appears to have " << validated_element[i] <<
" cells associated with it");
77 template<
unsigned DIM>
79 std::vector<CellPtr>& rCells,
82 const std::vector<unsigned> locationIndices)
84 mpElementTessellation(NULL),
87 mNumSweepsPerTimestep(1)
97 template<
unsigned DIM>
100 mpElementTessellation(NULL),
103 mNumSweepsPerTimestep(1)
108 template<
unsigned DIM>
111 delete mpElementTessellation;
113 delete mpMutableMesh;
115 if (this->mDeleteMesh)
117 delete &this->mrMesh;
121 template<
unsigned DIM>
127 template<
unsigned DIM>
133 template<
unsigned DIM>
136 return mpPottsMesh->GetElement(elementIndex);
139 template<
unsigned DIM>
142 return mpPottsMesh->GetNumElements();
145 template<
unsigned DIM>
148 return this->mrMesh.GetNode(index);
151 template<
unsigned DIM>
154 return this->mrMesh.GetNumNodes();
157 template<
unsigned DIM>
160 unsigned elem_index = this->GetLocationIndexUsingCell(pCell);
161 return mpPottsMesh->GetNeighbouringElementIndices(elem_index);
164 template<
unsigned DIM>
167 return mpPottsMesh->GetCentroidOfElement(this->GetLocationIndexUsingCell(pCell));
170 template<
unsigned DIM>
173 return mpPottsMesh->GetElement(this->GetLocationIndexUsingCell(pCell));
176 template<
unsigned DIM>
183 unsigned new_element_index = mpPottsMesh->DivideElement(p_element,
true);
186 this->mCells.push_back(pNewCell);
189 CellPtr p_created_cell = this->mCells.back();
190 this->SetCellUsingLocationIndex(new_element_index,p_created_cell);
191 return p_created_cell;
194 template<
unsigned DIM>
197 unsigned num_removed = 0;
199 for (std::list<CellPtr>::iterator it = this->mCells.begin();
200 it != this->mCells.end();
207 mpPottsMesh->DeleteElement(this->GetLocationIndexUsingCell((*it)));
208 it = this->mCells.erase(it);
217 template<
unsigned DIM>
233 unsigned num_nodes = this->mrMesh.GetNumNodes();
236 if (this->mIterateRandomlyOverUpdateRuleCollection)
239 p_gen->
Shuffle(mUpdateRuleCollection);
242 for (
unsigned i=0; i<num_nodes*mNumSweepsPerTimestep; i++)
246 if (this->mUpdateNodesInRandomOrder)
248 node_index = p_gen->
randMod(num_nodes);
253 node_index = i%num_nodes;
256 Node<DIM>* p_node = this->mrMesh.GetNode(node_index);
262 std::set<unsigned> neighbouring_node_indices = mpPottsMesh->GetMooreNeighbouringNodeIndices(node_index);
263 unsigned neighbour_location_index;
265 if (!neighbouring_node_indices.empty())
267 unsigned num_neighbours = neighbouring_node_indices.size();
268 unsigned chosen_neighbour = p_gen->
randMod(num_neighbours);
270 std::set<unsigned>::iterator neighbour_iter = neighbouring_node_indices.begin();
271 for (
unsigned j=0; j<chosen_neighbour; j++)
276 neighbour_location_index = *neighbour_iter;
279 std::set<unsigned> neighbour_containing_elements = GetNode(neighbour_location_index)->rGetContainingElementIndices();
281 if ( ( !containing_elements.empty() && neighbour_containing_elements.empty() )
282 || ( containing_elements.empty() && !neighbour_containing_elements.empty() )
283 || ( !containing_elements.empty() && !neighbour_containing_elements.empty() && *containing_elements.begin() != *neighbour_containing_elements.begin() ) )
285 double delta_H = 0.0;
289 iter != mUpdateRuleCollection.end();
292 delta_H += (*iter)->EvaluateHamiltonianContribution(neighbour_location_index, p_node->
GetIndex(), *
this);
296 double random_number = p_gen->
ranf();
298 double p = exp(-delta_H/mTemperature);
299 if (delta_H <= 0 || random_number < p)
304 for (std::set<unsigned>::iterator iter = containing_elements.begin();
305 iter != containing_elements.end();
308 GetElement(*iter)->DeleteNode(GetElement(*iter)->GetNodeLocalIndex(node_index));
314 for (std::set<unsigned>::iterator iter = neighbour_containing_elements.begin();
315 iter != neighbour_containing_elements.end();
318 GetElement(*iter)->AddNode(this->mrMesh.GetNode(node_index));
326 template<
unsigned DIM>
329 return GetElementCorrespondingToCell(pCell)->IsDeleted();
332 template<
unsigned DIM>
337 template<
unsigned DIM>
340 if (this->mOutputResultsForChasteVisualizer)
342 if (!this->
template HasWriter<CellPopulationElementWriter>())
344 this->
template AddPopulationWriter<CellPopulationElementWriter>();
348 this->
template AddCellWriter<CellIdWriter>();
353 template<
unsigned DIM>
356 CreateElementTessellation();
361 template<
unsigned DIM>
364 pPopulationWriter->Visit(
this);
367 template<
unsigned DIM>
370 pPopulationCountWriter->Visit(
this);
373 template<
unsigned DIM>
376 pCellWriter->VisitCell(pCell,
this);
379 template<
unsigned DIM>
383 unsigned elem_index = this->GetLocationIndexUsingCell(pCell);
386 double cell_volume = mpPottsMesh->GetVolumeOfElement(elem_index);
391 template<
unsigned DIM>
395 double width = this->mrMesh.GetWidth(rDimension);
400 template<
unsigned DIM>
403 mUpdateRuleCollection.push_back(pUpdateRule);
406 template<
unsigned DIM>
409 mUpdateRuleCollection.clear();
412 template<
unsigned DIM>
415 return mUpdateRuleCollection;
418 template<
unsigned DIM>
436 template<
unsigned DIM>
440 return mpElementTessellation;
443 template<
unsigned DIM>
446 delete mpMutableMesh;
449 std::vector<Node<DIM>*> nodes;
450 for (
unsigned node_index=0; node_index<this->mrMesh.GetNumNodes(); node_index++)
452 c_vector<double, DIM> location = this->mrMesh.GetNode(node_index)->rGetLocation();
453 nodes.push_back(
new Node<DIM>(node_index, location));
459 template<
unsigned DIM>
462 assert(mpMutableMesh);
463 return mpMutableMesh;
466 template<
unsigned DIM>
469 *rParamsFile <<
"\t\t<Temperature>" << mTemperature <<
"</Temperature>\n";
470 *rParamsFile <<
"\t\t<NumSweepsPerTimestep>" << mNumSweepsPerTimestep <<
"</NumSweepsPerTimestep>\n";
476 template<
unsigned DIM>
479 mTemperature = temperature;
482 template<
unsigned DIM>
488 template<
unsigned DIM>
491 mNumSweepsPerTimestep = numSweepsPerTimestep;
494 template<
unsigned DIM>
497 return mNumSweepsPerTimestep;
500 template<
unsigned DIM>
505 std::stringstream time;
506 time << num_timesteps;
512 unsigned num_nodes = GetNumNodes();
514 cell_writer_iter != this->mCellWriters.end();
518 std::vector<double> vtk_cell_data(num_nodes);
522 iter != mpPottsMesh->GetNodeIteratorEnd();
526 unsigned node_index = iter->GetIndex();
527 std::set<unsigned> element_indices = iter->rGetContainingElementIndices();
530 if (element_indices.empty())
533 vtk_cell_data[node_index] = -1.0;
538 assert(element_indices.size() == 1);
539 unsigned elem_index = *(element_indices.begin());
540 CellPtr p_cell = this->GetCellUsingLocationIndex(elem_index);
543 vtk_cell_data[node_index] = (*cell_writer_iter)->GetCellDataForVtkOutput(p_cell,
this);
547 mesh_writer.AddPointData((*cell_writer_iter)->GetVtkCellDataName(), vtk_cell_data);
551 unsigned num_cell_data_items = this->Begin()->GetCellData()->GetNumItems();
552 std::vector<std::string> cell_data_names = this->Begin()->GetCellData()->GetKeys();
554 std::vector<std::vector<double> > cell_data;
555 for (
unsigned var=0; var<num_cell_data_items; var++)
557 std::vector<double> cell_data_var(num_nodes);
558 cell_data.push_back(cell_data_var);
562 iter != mpPottsMesh->GetNodeIteratorEnd();
566 unsigned node_index = iter->GetIndex();
567 std::set<unsigned> element_indices = iter->rGetContainingElementIndices();
570 if (element_indices.empty())
572 for (
unsigned var=0; var<num_cell_data_items; var++)
574 cell_data[var][node_index] = -1.0;
580 assert(element_indices.size() == 1);
581 unsigned elem_index = *(element_indices.begin());
582 CellPtr p_cell = this->GetCellUsingLocationIndex(elem_index);
584 for (
unsigned var=0; var<num_cell_data_items; var++)
586 cell_data[var][node_index] = p_cell->GetCellData()->GetItem(cell_data_names[var]);
590 for (
unsigned var=0; var<cell_data.size(); var++)
592 mesh_writer.AddPointData(cell_data_names[var], cell_data[var]);
602 mesh_writer.WriteFilesUsingMesh(temp_mesh);
604 *(this->mpVtkMetaFile) <<
" <DataSet timestep=\"";
605 *(this->mpVtkMetaFile) << num_timesteps;
606 *(this->mpVtkMetaFile) <<
"\" group=\"\" part=\"0\" file=\"results_";
607 *(this->mpVtkMetaFile) << num_timesteps;
608 *(this->mpVtkMetaFile) <<
".vtu\"/>\n";
614 std::vector<Node<2>*> outline_nodes;
615 std::vector<VertexElement<2,2>*> outline_elements;
617 unsigned outline_node_index = 0;
618 unsigned outline_element_index = 0;
620 iter != mpPottsMesh->GetNodeIteratorEnd();
624 unsigned node_index = iter->GetIndex();
625 std::set<unsigned> element_indices = iter->rGetContainingElementIndices();
627 std::set<unsigned> target_neighbouring_node_indices = this->rGetMesh().GetVonNeumannNeighbouringNodeIndices(node_index);
629 for (std::set<unsigned>::iterator neighbour_iter = target_neighbouring_node_indices.begin();
630 neighbour_iter != target_neighbouring_node_indices.end();
633 std::set<unsigned> neighbouring_element_indices = this->rGetMesh().GetNode(*neighbour_iter)->rGetContainingElementIndices();
636 if ( element_indices != neighbouring_element_indices)
638 std::vector<Node<2>*> element_nodes;
640 c_vector<double, 2> node_location = this->mrMesh.GetNode(node_index)->rGetLocation();
641 c_vector<double, 2> neighbour_node_location = this->mrMesh.GetNode(*neighbour_iter)->rGetLocation();
643 c_vector<double, 2> unit_tangent = neighbour_node_location - node_location;
646 if (norm_2(unit_tangent) > 1.0)
648 c_vector<double, 2> mid_point = 0.5*(node_location + neighbour_node_location);
649 if (unit_tangent(0)==0)
651 if (node_location(1) < neighbour_node_location (1))
653 mid_point(1) = node_location(1) - 0.5;
657 mid_point(1) = node_location(1) + 0.5;
662 assert(unit_tangent(1)==0);
664 if (node_location(0) < neighbour_node_location (0))
666 mid_point(0) = node_location(0) - 0.5;
670 mid_point(0) = node_location(0) + 0.5;
673 assert(norm_2(unit_tangent)>0);
674 unit_tangent = unit_tangent/norm_2(unit_tangent);
676 c_vector<double, DIM> unit_normal;
677 unit_normal(0) = -unit_tangent(1);
678 unit_normal(1) = unit_tangent(0);
680 std::vector<Node<2>*> element_nodes;
683 Node<2>* p_node_1 =
new Node<2>(outline_node_index, mid_point - 0.5*unit_normal);
684 outline_nodes.push_back(p_node_1);
685 element_nodes.push_back(outline_nodes[outline_node_index]);
686 outline_node_index++;
689 outline_nodes.push_back(p_node_2);
690 element_nodes.push_back(outline_nodes[outline_node_index]);
691 outline_node_index++;
693 Node<2>* p_node_3 =
new Node<2>(outline_node_index, mid_point + 0.5*unit_normal);
694 outline_nodes.push_back(p_node_3);
695 element_nodes.push_back(outline_nodes[outline_node_index]);
696 outline_node_index++;
699 outline_elements.push_back(p_element);
700 outline_element_index++;
705 c_vector<double, 2> mid_point = 0.5*(node_location + neighbour_node_location);
707 assert(norm_2(unit_tangent)>0);
708 unit_tangent = unit_tangent/norm_2(unit_tangent);
710 c_vector<double, 2> unit_normal;
711 unit_normal(0) = -unit_tangent(1);
712 unit_normal(1) = unit_tangent(0);
714 std::vector<Node<2>*> element_nodes;
717 Node<2>* p_node_1 =
new Node<2>(outline_node_index, mid_point - 0.5*unit_normal);
718 outline_nodes.push_back(p_node_1);
719 element_nodes.push_back(outline_nodes[outline_node_index]);
720 outline_node_index++;
723 outline_nodes.push_back(p_node_2);
724 element_nodes.push_back(outline_nodes[outline_node_index]);
725 outline_node_index++;
727 Node<2>* p_node_3 =
new Node<2>(outline_node_index, mid_point + 0.5*unit_normal);
728 outline_nodes.push_back(p_node_3);
729 element_nodes.push_back(outline_nodes[outline_node_index]);
730 outline_node_index++;
733 outline_elements.push_back(p_element);
734 outline_element_index++;
unsigned randMod(unsigned base)
PottsMesh< DIM > * mpPottsMesh
Node< DIM > * GetNode(unsigned index)
void RemoveAllUpdateRules()
void WriteFilesUsingMesh(VertexMesh< ELEMENT_DIM, SPACE_DIM > &rMesh)
PottsMesh< DIM > & rGetMesh()
#define EXCEPTION(message)
VertexMesh< DIM, DIM > * GetElementTessellation()
static SimulationTime * Instance()
std::set< unsigned > GetNeighbouringLocationIndices(CellPtr pCell)
PottsElement< DIM > * GetElementCorrespondingToCell(CellPtr pCell)
unsigned GetNumElements()
const std::vector< boost::shared_ptr< AbstractPottsUpdateRule< DIM > > > & rGetUpdateRuleCollection() const
std::set< unsigned > & rGetContainingElementIndices()
unsigned GetTimeStepsElapsed() const
unsigned RemoveDeadCells()
virtual void OutputCellPopulationParameters(out_stream &rParamsFile)
virtual void AcceptPopulationCountWriter(boost::shared_ptr< AbstractCellPopulationCountWriter< DIM, DIM > > pPopulationCountWriter)
virtual void WriteResultsToFiles(const std::string &rDirectory)
void Shuffle(std::vector< boost::shared_ptr< T > > &rValues)
void CreateElementTessellation()
c_vector< double, DIM > GetLocationOfCellCentre(CellPtr pCell)
virtual void AcceptCellWriter(boost::shared_ptr< AbstractCellWriter< DIM, DIM > > pCellWriter, CellPtr pCell)
#define EXPORT_TEMPLATE_CLASS_SAME_DIMS(CLASS)
void OutputCellPopulationParameters(out_stream &rParamsFile)
void SetTemperature(double temperature)
virtual void WriteVtkResultsToFile(const std::string &rDirectory)
void AddUpdateRule(boost::shared_ptr< AbstractPottsUpdateRule< DIM > > pUpdateRule)
virtual void AcceptPopulationWriter(boost::shared_ptr< AbstractCellPopulationWriter< DIM, DIM > > pPopulationWriter)
void Update(bool hasHadBirthsOrDeaths=true)
void WriteVtkUsingMesh(VertexMesh< ELEMENT_DIM, SPACE_DIM > &rMesh, std::string stamp="")
CellPtr AddCell(CellPtr pNewCell, const c_vector< double, DIM > &rCellDivisionVector, CellPtr pParentCell=CellPtr())
static RandomNumberGenerator * Instance()
NodeIterator GetNodeIteratorBegin(bool skipDeletedNodes=true)
virtual void OpenWritersFiles(OutputFileHandler &rOutputFileHandler)
void ConstructNodesWithoutMesh(const std::vector< Node< SPACE_DIM > * > &rNodes, double maxInteractionDistance)
double GetVolumeOfCell(CellPtr pCell)
virtual void WriteResultsToFiles(const std::string &rDirectory)
MutableMesh< DIM, DIM > * GetMutableMesh()
void UpdateCellLocations(double dt)
unsigned GetNumContainingElements() const
unsigned GetIndex() const
PottsElement< DIM > * GetElement(unsigned elementIndex)
double GetWidth(const unsigned &rDimension)
virtual void OpenWritersFiles(OutputFileHandler &rOutputFileHandler)
unsigned GetNumSweepsPerTimestep()
AbstractMesh< ELEMENT_DIM, ELEMENT_DIM > & mrMesh
virtual ~PottsBasedCellPopulation()
void SetNumSweepsPerTimestep(unsigned numSweepsPerTimestep)
PottsBasedCellPopulation(PottsMesh< DIM > &rMesh, std::vector< CellPtr > &rCells, bool deleteMesh=false, bool validate=true, const std::vector< unsigned > locationIndices=std::vector< unsigned >())
bool IsCellAssociatedWithADeletedLocation(CellPtr pCell)