36 #include "NodeBasedCellPopulation.hpp" 38 #include "VtkMeshWriter.hpp" 40 template<
unsigned DIM>
42 std::vector<CellPtr>& rCells,
43 const std::vector<unsigned> locationIndices,
47 mDeleteMesh(deleteMesh),
48 mUseVariableRadii(false),
49 mLoadBalanceMesh(false),
50 mLoadBalanceFrequency(100)
60 template<
unsigned DIM>
71 template<
unsigned DIM>
81 template<
unsigned DIM>
87 template<
unsigned DIM>
93 template<
unsigned DIM>
99 std::vector<Node<DIM>*> temp_nodes;
106 temp_nodes.push_back(
new Node<DIM>(node_iter->GetIndex(), node_iter->rGetLocation(), node_iter->IsBoundaryNode()));
112 template<
unsigned DIM>
118 template<
unsigned DIM>
122 node_iter != this->
mrMesh.GetNodeIteratorEnd();
136 template<
unsigned DIM>
142 template<
unsigned DIM>
148 template<
unsigned DIM>
181 cell_iter != this->
End();
184 double cell_radius = cell_iter->GetCellData()->GetItem(
"Radius");
186 this->
GetNode(node_index)->SetRadius(cell_radius);
194 template<
unsigned DIM>
209 for (std::list<CellPtr>::iterator it = this->
mCells.begin();
213 unsigned old_node_index = old_map[(*it).get()];
218 unsigned new_node_index = map.
GetNewIndex(old_node_index);
226 template<
unsigned DIM>
229 unsigned num_removed = 0;
230 for (std::list<CellPtr>::iterator cell_iter = this->
mCells.begin();
231 cell_iter != this->
mCells.end();
234 if ((*cell_iter)->IsDead())
246 cell_iter = this->
mCells.erase(cell_iter);
257 template<
unsigned DIM>
263 template<
unsigned DIM>
269 template<
unsigned DIM>
283 template<
unsigned DIM>
288 template<
unsigned DIM>
294 template<
unsigned DIM>
298 *rParamsFile <<
"\t\t<UseVariableRadii>" <<
mUseVariableRadii <<
"</UseVariableRadii>\n";
304 template<
unsigned DIM>
307 pPopulationWriter->Visit(
this);
310 template<
unsigned DIM>
313 pPopulationCountWriter->Visit(
this);
316 template<
unsigned DIM>
319 pCellWriter->VisitCell(pCell,
this);
322 template<
unsigned DIM>
328 template<
unsigned DIM>
334 template<
unsigned DIM>
340 template<
unsigned DIM>
346 template<
unsigned DIM>
352 template<
unsigned DIM>
358 template<
unsigned DIM>
362 c_vector<double, DIM> global_size;
364 for (
unsigned i=0; i<DIM; i++)
372 template<
unsigned DIM>
378 EXCEPTION(
"neighbourhoodRadius should be less than or equal to the the maximum interaction radius defined on the NodesOnlyMesh");
381 std::set<unsigned> neighbouring_node_indices;
385 const c_vector<double, DIM>& r_node_i_location = p_node_i->
rGetLocation();
390 EXCEPTION(
"mNodeNeighbours not set up. Call Update() before GetNodesWithinNeighbourhoodRadius()");
397 for (std::vector<unsigned>::iterator iter = near_nodes.begin();
398 iter != near_nodes.end();
402 if ((*iter) != index)
407 const c_vector<double, DIM>& r_node_j_location = p_node_j->
rGetLocation();
413 double distance_between_nodes = norm_2(node_to_node_vector);
417 if (distance_between_nodes <= neighbourhoodRadius)
420 neighbouring_node_indices.insert((*iter));
425 return neighbouring_node_indices;
428 template<
unsigned DIM>
431 std::set<unsigned> neighbouring_node_indices;
435 const c_vector<double, DIM>& r_node_i_location = p_node_i->
rGetLocation();
436 double radius_of_cell_i = p_node_i->
GetRadius();
441 EXCEPTION(
"mNodeNeighbours not set up. Call Update() before GetNeighbouringNodeIndices()");
447 EXCEPTION(
"mpNodesOnlyMesh::mMaxInteractionDistance is smaller than twice the radius of cell " << index <<
" (" << radius_of_cell_i <<
") so interactions may be missed. Make the cut-off larger to avoid errors.");
454 for (std::vector<unsigned>::iterator iter = near_nodes.begin();
455 iter != near_nodes.end();
459 if ((*iter) != index)
464 const c_vector<double, DIM>& r_node_j_location = p_node_j->
rGetLocation();
470 double distance_between_nodes = norm_2(node_to_node_vector);
473 double radius_of_cell_j = p_node_j->
GetRadius();
476 double max_interaction_distance = radius_of_cell_i + radius_of_cell_j;
479 if (!(max_interaction_distance <= mpNodesOnlyMesh->GetMaximumInteractionDistance()))
481 EXCEPTION(
"mpNodesOnlyMesh::mMaxInteractionDistance is smaller than the sum of radius of cell " << index <<
" (" << radius_of_cell_i <<
") and cell " << (*iter) <<
" (" << radius_of_cell_j <<
"). Make the cut-off larger to avoid errors.");
483 if (distance_between_nodes <= max_interaction_distance)
486 neighbouring_node_indices.insert((*iter));
491 return neighbouring_node_indices;
494 template<
unsigned DIM>
498 assert(DIM==2 ||DIM==3);
505 double cell_radius = p_node->
GetRadius();
508 double averaged_cell_radius = 0.0;
509 unsigned num_cells = 0;
512 const c_vector<double, DIM>& r_node_i_location =
GetNode(node_index)->rGetLocation();
518 unsigned num_neighbours_equil;
521 num_neighbours_equil = 6;
526 num_neighbours_equil = 12;
530 for (std::set<unsigned>::iterator iter = neighbouring_node_indices.begin();
531 iter != neighbouring_node_indices.end();
537 const c_vector<double, DIM>& r_node_j_location = p_node_j->
rGetLocation();
539 double neighbouring_cell_radius = p_node_j->
GetRadius();
542 assert(cell_radius+neighbouring_cell_radius<mpNodesOnlyMesh->GetMaximumInteractionDistance());
547 if (separation < cell_radius+neighbouring_cell_radius)
550 averaged_cell_radius = averaged_cell_radius + cell_radius - (cell_radius+neighbouring_cell_radius-separation)/2.0;
554 if (num_cells < num_neighbours_equil)
556 averaged_cell_radius += (num_neighbours_equil-num_cells)*cell_radius;
558 averaged_cell_radius /= num_neighbours_equil;
562 averaged_cell_radius /= num_cells;
564 assert(averaged_cell_radius < mpNodesOnlyMesh->GetMaximumInteractionDistance()/2.0);
566 cell_radius = averaged_cell_radius;
571 double cell_volume = 0.0;
574 cell_volume = M_PI*cell_radius*cell_radius;
578 cell_volume = (4.0/3.0)*M_PI*cell_radius*cell_radius*cell_radius;
584 template<
unsigned DIM>
589 std::stringstream time;
603 std::vector<unsigned> node_indices_in_cell_order;
604 for (
auto cell_iter = this->
Begin(); cell_iter != this->
End(); ++cell_iter)
610 node_indices_in_cell_order.emplace_back(node_index);
618 if (p_cell_writer->GetOutputScalarData())
620 std::vector<double> vtk_cell_data(num_nodes);
622 unsigned loop_it = 0;
623 for (
auto cell_iter = this->
Begin(); cell_iter != this->
End(); ++cell_iter, ++loop_it)
625 unsigned node_idx = node_indices_in_cell_order[loop_it];
626 vtk_cell_data[node_idx] = p_cell_writer->GetCellDataForVtkOutput(*cell_iter,
this);
629 mesh_writer.AddPointData(p_cell_writer->GetVtkCellDataName(), vtk_cell_data);
633 if (p_cell_writer->GetOutputVectorData())
635 std::vector<c_vector<double, DIM>> vtk_cell_data(num_nodes);
637 unsigned loop_it = 0;
638 for (
auto cell_iter = this->
Begin(); cell_iter != this->
End(); ++cell_iter, ++loop_it)
640 unsigned node_idx = node_indices_in_cell_order[loop_it];
641 vtk_cell_data[node_idx] = p_cell_writer->GetVectorCellDataForVtkOutput(*cell_iter,
this);
644 mesh_writer.AddPointData(p_cell_writer->GetVtkVectorCellDataName(), vtk_cell_data);
652 auto num_cell_data_items = this->
Begin()->GetCellData()->GetNumItems();
653 std::vector<std::string> cell_data_names = this->
Begin()->GetCellData()->GetKeys();
654 std::vector<std::vector<double>> cell_data(num_cell_data_items, std::vector<double>(num_nodes));
656 std::vector<double> rank(num_nodes);
658 unsigned loop_it = 0;
659 for (
auto cell_iter = this->
Begin(); cell_iter != this->
End(); ++cell_iter, ++loop_it)
661 unsigned node_idx = node_indices_in_cell_order[loop_it];
663 for (
unsigned cell_data_idx = 0; cell_data_idx < num_cell_data_items; ++cell_data_idx)
665 cell_data[cell_data_idx][node_idx] = cell_iter->GetCellData()->GetItem(cell_data_names[cell_data_idx]);
672 mesh_writer.AddPointData(
"Process rank", rank);
673 for (
unsigned cell_data_idx = 0; cell_data_idx < num_cell_data_items; ++cell_data_idx)
675 mesh_writer.AddPointData(cell_data_names[cell_data_idx], cell_data[cell_data_idx]);
683 *(this->
mpVtkMetaFile) << R
"(" group="" part="0" file="results_)"; 697 template<
unsigned DIM>
704 assert(p_created_cell == pNewCell);
716 return p_created_cell;
719 template<
unsigned DIM>
726 this->
mCells.push_back(pCell);
732 template<
unsigned DIM>
738 for (std::list<CellPtr>::iterator cell_iter = this->
mCells.begin();
739 cell_iter != this->
mCells.end();
746 cell_iter = this->
mCells.erase(cell_iter);
753 template<
unsigned DIM>
770 template<
unsigned DIM>
798 template<
unsigned DIM>
811 template<
unsigned DIM>
818 std::pair<CellPtr, Node<DIM>* > new_pair(p_cell, p_node);
823 template<
unsigned DIM>
831 template<
unsigned DIM>
839 template<
unsigned DIM>
849 boost::shared_ptr<Node<DIM> > p_node(iter->second);
859 boost::shared_ptr<Node<DIM> > p_node(iter->second);
865 template<
unsigned DIM>
884 for (std::vector<unsigned>::iterator iter = nodes_to_send_right.begin();
885 iter != nodes_to_send_right.end();
891 for (std::vector<unsigned>::iterator iter = nodes_to_send_left.begin();
892 iter != nodes_to_send_left.end();
905 template<
unsigned DIM>
923 template<
unsigned DIM>
928 for (
unsigned i=0; i < cellLocationIndices.size(); i++)
934 template<
unsigned DIM>
939 for (
unsigned i=0; i < cellLocationIndices.size(); i++)
945 template<
unsigned DIM>
956 boost::shared_ptr<Node<DIM> > p_node(iter->second);
967 boost::shared_ptr<Node<DIM> > p_node(iter->second);
975 template<
unsigned DIM>
void AddCellsToSendRight(std::vector< unsigned > &cellLocationIndices)
double GetMechanicsCutOffLength()
void OutputCellPopulationParameters(out_stream &rParamsFile)
std::set< unsigned > GetNodesWithinNeighbourhoodRadius(unsigned index, double neighbourhoodRadius)
std::vector< unsigned > & rGetNodesToSendLeft()
NodesOnlyMesh< DIM > & rGetMesh()
virtual unsigned GetMaximumNodeIndex()
std::vector< unsigned > & rGetHaloNodesToSendLeft()
bool GetUseVariableRadii()
virtual ~NodeBasedCellPopulation()
void SetNode(unsigned nodeIndex, ChastePoint< SPACE_DIM > point, bool concreteMove=false)
boost::shared_ptr< std::vector< std::pair< CellPtr, Node< DIM > * > > > mpCellsRecvLeft
NodeBasedCellPopulation(NodesOnlyMesh< DIM > &rMesh, std::vector< CellPtr > &rCells, const std::vector< unsigned > locationIndices=std::vector< unsigned >(), bool deleteMesh=false, bool validate=true)
virtual CellPtr GetCellUsingLocationIndex(unsigned index)
unsigned GetLocationIndexUsingCell(CellPtr pCell)
std::vector< boost::shared_ptr< AbstractCellWriter< ELEMENT_DIM, SPACE_DIM > > > mCellWriters
virtual TetrahedralMesh< DIM, DIM > * GetTetrahedralMeshForPdeModifier()
double SmallPow(double x, unsigned exponent)
unsigned mLoadBalanceFrequency
c_vector< double, DIM > GetSizeOfCellPopulation()
void DeleteNodePriorToReMesh(unsigned index)
virtual void RemoveCellUsingLocationIndex(unsigned index, CellPtr pCell)
void SetRadius(double radius)
boost::shared_ptr< CLASS > SendRecvObject(boost::shared_ptr< CLASS > const pSendObject, unsigned destinationProcess, unsigned sendTag, unsigned sourceProcess, unsigned sourceTag, MPI_Status &status)
unsigned RemoveDeadCells()
#define EXCEPTION(message)
Node< DIM > * GetNode(unsigned index)
Node< SPACE_DIM > * GetNodeOrHaloNode(unsigned index) const
void AddCellsToSendLeft(std::vector< unsigned > &cellLocationIndices)
static const unsigned mCellCommunicationTag
static SimulationTime * Instance()
void SetParallelFiles(AbstractTetrahedralMesh< ELEMENT_DIM, SPACE_DIM > &rMesh)
std::map< CellPtr, unsigned > mHaloCellLocationMap
ObjectCommunicator< std::vector< std::pair< CellPtr, Node< DIM > * > > > mRightCommunicator
NodeIterator GetNodeIteratorEnd()
void SetNode(unsigned nodeIndex, ChastePoint< DIM > &rNewLocation)
std::vector< std::pair< Node< DIM > *, Node< DIM > * > > mNodePairs
void SetUseVariableRadii(bool useVariableRadii=true)
ObjectCommunicator< std::vector< std::pair< CellPtr, Node< DIM > * > > > mLeftCommunicator
unsigned GetTimeStepsElapsed() const
void ReMesh(NodeMap &rMap)
std::vector< CellPtr > mHaloCells
boost::shared_ptr< std::vector< std::pair< CellPtr, Node< DIM > * > > > mpCellsRecvRight
void AddMovedCell(CellPtr pCell, boost::shared_ptr< Node< DIM > > pNode)
void IRecvObject(unsigned sourceProcess, unsigned tag)
std::pair< CellPtr, Node< DIM > * > GetCellNodePair(unsigned nodeIndex)
void NonBlockingSendCellsToNeighbourProcesses()
double GetVolumeOfCell(CellPtr pCell)
virtual void AcceptPopulationWriter(boost::shared_ptr< AbstractCellPopulationWriter< DIM, DIM > > pPopulationWriter)
virtual void WriteVtkResultsToFile(const std::string &rDirectory)
virtual CellPtr AddCell(CellPtr pNewCell, CellPtr pParentCell)
virtual void OutputCellPopulationParameters(out_stream &rParamsFile)
std::vector< unsigned > & rGetHaloNodesToSendRight()
c_vector< double, SPACE_DIM > GetSizeOfCellPopulation()
void AddHaloNodesToBoxes()
std::vector< std::pair< CellPtr, Node< DIM > * > > mCellsToSendRight
void CalculateInteriorNodePairs(std::vector< std::pair< Node< SPACE_DIM > *, Node< SPACE_DIM > * > > &rNodePairs)
std::set< unsigned > GetNeighbouringNodeIndices(unsigned index)
void SendCellsToNeighbourProcesses()
#define EXPORT_TEMPLATE_CLASS_SAME_DIMS(CLASS)
std::map< unsigned, std::set< CellPtr > > mLocationCellMap
double GetWidth(const unsigned &rDimension) const
void SetCellUsingLocationIndex(unsigned index, CellPtr pCell)
void UpdateMapsAfterRemesh(NodeMap &map)
std::map< Cell *, unsigned > mCellLocationMap
double GetMaximumInteractionDistance()
void DeleteMovedNode(unsigned index)
boost::shared_ptr< CLASS > GetRecvObject()
void SetLoadBalanceMesh(bool loadBalanceMesh)
void ResizeBoxCollection()
unsigned SolveNodeMapping(unsigned index) const
CellPtr AddCell(CellPtr pNewCell, CellPtr pParentCell=CellPtr())
NodeIterator GetNodeIteratorBegin(bool skipDeletedNodes=true)
virtual void AcceptCellWriter(boost::shared_ptr< AbstractCellWriter< DIM, DIM > > pCellWriter, CellPtr pCell)
void UpdateBoxCollection()
void AddHaloNode(boost::shared_ptr< Node< SPACE_DIM > > pNewNode)
std::list< CellPtr > mCells
void CalculateNodesOutsideLocalDomain()
void AddHaloCell(CellPtr pCell, boost::shared_ptr< Node< DIM > > pNode)
double GetWidth(const unsigned &rDimension)
std::vector< unsigned > & rGetNeighbours()
unsigned AddNode(Node< DIM > *pNewNode)
const c_vector< double, SPACE_DIM > & rGetLocation() const
unsigned AddNode(Node< SPACE_DIM > *pNewNode)
std::vector< unsigned > & rGetNodesToSendRight()
bool IsDeleted(unsigned index)
unsigned GetNewIndex(unsigned oldIndex) const
bool GetNeighboursSetUp()
std::vector< std::pair< Node< DIM > *, Node< DIM > * > > & rGetNodePairs()
virtual CellPtr GetCellUsingLocationIndex(unsigned index)
void ISendObject(boost::shared_ptr< CLASS > const pObject, unsigned destinationProcess, unsigned tag)
virtual c_vector< double, SPACE_DIM > GetVectorFromAtoB(const c_vector< double, SPACE_DIM > &rLocationA, const c_vector< double, SPACE_DIM > &rLocationB)
void CalculateBoundaryNodePairs(std::vector< std::pair< Node< SPACE_DIM > *, Node< SPACE_DIM > * > > &rNodePairs)
NodesOnlyMesh< DIM > * mpNodesOnlyMesh
std::map< unsigned, CellPtr > mLocationHaloCellMap
std::vector< std::pair< CellPtr, Node< DIM > * > > mCellsToSendLeft
virtual void UpdateCellProcessLocation()
void AddMovedNode(boost::shared_ptr< Node< SPACE_DIM > > pMovedNode)
void DeleteMovedCell(unsigned index)
void Update(bool hasHadBirthsOrDeaths=true)
virtual void AddCellUsingLocationIndex(unsigned index, CellPtr pCell)
AbstractMesh< ELEMENT_DIM, SPACE_DIM > & mrMesh
virtual void AcceptPopulationCountWriter(boost::shared_ptr< AbstractCellPopulationCountWriter< DIM, DIM > > pPopulationCountWriter)
void SetLoadBalanceFrequency(unsigned loadBalanceFrequency)
void AddNodeAndCellToSendLeft(unsigned nodeIndex)
void AddReceivedHaloCells()
unsigned GetNumNodes() const
void AddNodeAndCellToSendRight(unsigned nodeIndex)
virtual void UpdateParticlesAfterReMesh(NodeMap &rMap)