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>
64 mUseVariableRadii(false),
65 mLoadBalanceMesh(false),
66 mLoadBalanceFrequency(100)
71 template<
unsigned DIM>
81 template<
unsigned DIM>
84 return *mpNodesOnlyMesh;
87 template<
unsigned DIM>
90 return *mpNodesOnlyMesh;
93 template<
unsigned DIM>
99 std::vector<Node<DIM>*> temp_nodes;
103 node_iter != mpNodesOnlyMesh->GetNodeIteratorEnd();
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();
127 this->GetCellUsingLocationIndex(node_iter->GetIndex());
136 template<
unsigned DIM>
139 return mpNodesOnlyMesh->GetNodeOrHaloNode(index);
142 template<
unsigned DIM>
145 mpNodesOnlyMesh->SetNode(nodeIndex, rNewLocation,
false);
148 template<
unsigned DIM>
151 UpdateCellProcessLocation();
153 mpNodesOnlyMesh->UpdateBoxCollection();
155 if (mLoadBalanceMesh)
159 mpNodesOnlyMesh->LoadBalanceMesh();
161 UpdateCellProcessLocation();
163 mpNodesOnlyMesh->UpdateBoxCollection();
169 mpNodesOnlyMesh->CalculateInteriorNodePairs(mNodePairs);
171 AddReceivedHaloCells();
173 mpNodesOnlyMesh->CalculateBoundaryNodePairs(mNodePairs);
178 if (mUseVariableRadii)
181 cell_iter != this->End();
184 double cell_radius = cell_iter->GetCellData()->GetItem(
"Radius");
185 unsigned node_index = this->GetLocationIndexUsingCell(*cell_iter);
186 this->GetNode(node_index)->SetRadius(cell_radius);
194 template<
unsigned DIM>
199 UpdateParticlesAfterReMesh(map);
203 std::map<Cell*, unsigned> old_map = this->mCellLocationMap;
206 this->mLocationCellMap.clear();
207 this->mCellLocationMap.clear();
209 for (std::list<CellPtr>::iterator it = this->mCells.begin();
210 it != this->mCells.end();
213 unsigned old_node_index = old_map[(*it).get()];
218 unsigned new_node_index = map.
GetNewIndex(old_node_index);
219 this->SetCellUsingLocationIndex(new_node_index,*it);
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())
238 unsigned location_index = mpNodesOnlyMesh->SolveNodeMapping(this->GetLocationIndexUsingCell((*cell_iter)));
239 mpNodesOnlyMesh->DeleteNodePriorToReMesh(location_index);
242 unsigned location_index_of_removed_node = this->GetLocationIndexUsingCell((*cell_iter));
243 this->RemoveCellUsingLocationIndex(location_index_of_removed_node, (*cell_iter));
246 cell_iter = this->mCells.erase(cell_iter);
257 template<
unsigned DIM>
260 return mpNodesOnlyMesh->AddNode(pNewNode);
263 template<
unsigned DIM>
266 return mpNodesOnlyMesh->GetNumNodes();
269 template<
unsigned DIM>
272 std::map<unsigned, CellPtr>::iterator iter = mLocationHaloCellMap.find(index);
273 if (iter != mLocationHaloCellMap.end())
283 template<
unsigned DIM>
288 template<
unsigned DIM>
294 template<
unsigned DIM>
297 *rParamsFile <<
"\t\t<MechanicsCutOffLength>" << mpNodesOnlyMesh->GetMaximumInteractionDistance() <<
"</MechanicsCutOffLength>\n";
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>
325 return mpNodesOnlyMesh->GetMaximumInteractionDistance();
328 template<
unsigned DIM>
331 return mUseVariableRadii;
334 template<
unsigned DIM>
337 mUseVariableRadii = useVariableRadii;
340 template<
unsigned DIM>
343 mLoadBalanceMesh = loadBalanceMesh;
346 template<
unsigned DIM>
349 mLoadBalanceFrequency = loadBalanceFrequency;
352 template<
unsigned DIM>
355 return mpNodesOnlyMesh->GetWidth(rDimension);
358 template<
unsigned DIM>
362 c_vector<double, DIM> global_size;
364 for (
unsigned i=0; i<DIM; i++)
372 template<
unsigned DIM>
376 if (neighbourhoodRadius > mpNodesOnlyMesh->GetMaximumInteractionDistance())
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;
384 Node<DIM>* p_node_i = this->GetNode(index);
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)
404 Node<DIM>* p_node_j = this->GetNode((*iter));
407 const c_vector<double, DIM>& r_node_j_location = p_node_j->
rGetLocation();
410 c_vector<double, DIM> node_to_node_vector = mpNodesOnlyMesh->GetVectorFromAtoB(r_node_j_location, r_node_i_location);
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;
434 Node<DIM>* p_node_i = this->GetNode(index);
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()");
445 if (!(radius_of_cell_i * 2.0 <= mpNodesOnlyMesh->GetMaximumInteractionDistance()))
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)
461 Node<DIM>* p_node_j = this->GetNode((*iter));
464 const c_vector<double, DIM>& r_node_j_location = p_node_j->
rGetLocation();
467 c_vector<double, DIM> node_to_node_vector = mpNodesOnlyMesh->GetVectorFromAtoB(r_node_j_location, r_node_i_location);
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);
501 unsigned node_index = this->GetLocationIndexUsingCell(pCell);
502 Node<DIM>* p_node = this->GetNode(node_index);
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();
515 std::set<unsigned> neighbouring_node_indices = GetNeighbouringNodeIndices(node_index);
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();
534 Node<DIM>* p_node_j = this->GetNode(*iter);
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());
545 double separation = norm_2(mpNodesOnlyMesh->GetVectorFromAtoB(r_node_j_location, r_node_i_location));
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;
593 NodeMap map(1 + this->mpNodesOnlyMesh->GetMaximumNodeIndex());
594 this->mpNodesOnlyMesh->ReMesh(map);
600 auto num_nodes = GetNumNodes();
603 std::vector<unsigned> node_indices_in_cell_order;
604 for (
auto cell_iter = this->Begin(); cell_iter != this->End(); ++cell_iter)
607 unsigned global_index = this->GetLocationIndexUsingCell(*cell_iter);
608 unsigned node_index = this->rGetMesh().SolveNodeMapping(global_index);
610 node_indices_in_cell_order.emplace_back(node_index);
615 for (
auto&& p_cell_writer : this->mCellWriters)
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);
650 if (this->Begin() != this->End())
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]);
679 mesh_writer.WriteFilesUsingMesh(*mpNodesOnlyMesh);
681 *(this->mpVtkMetaFile) <<
" <DataSet timestep=\"";
683 *(this->mpVtkMetaFile) << R
"(" group="" part="0" file="results_)";
687 *(this->mpVtkMetaFile) <<
".vtu\"/>\n";
692 *(this->mpVtkMetaFile) <<
".pvtu\"/>\n";
697 template<
unsigned DIM>
704 assert(p_created_cell == pNewCell);
707 unsigned parent_node_index = this->GetLocationIndexUsingCell(pParentCell);
708 Node<DIM>* p_parent_node = this->GetNode(parent_node_index);
710 unsigned new_node_index = this->GetLocationIndexUsingCell(p_created_cell);
711 Node<DIM>* p_new_node = this->GetNode(new_node_index);
716 return p_created_cell;
719 template<
unsigned DIM>
723 mpNodesOnlyMesh->AddMovedNode(pNode);
726 this->mCells.push_back(pCell);
729 this->AddCellUsingLocationIndex(pNode->GetIndex(), pCell);
732 template<
unsigned DIM>
735 mpNodesOnlyMesh->DeleteMovedNode(index);
738 for (std::list<CellPtr>::iterator cell_iter = this->mCells.begin();
739 cell_iter != this->mCells.end();
742 if (this->GetLocationIndexUsingCell(*cell_iter) == index)
745 this->RemoveCellUsingLocationIndex(index, (*cell_iter));
746 cell_iter = this->mCells.erase(cell_iter);
753 template<
unsigned DIM>
760 boost::shared_ptr<std::vector<std::pair<CellPtr, Node<DIM>* > > > p_cells_right(&mCellsToSendRight,
null_deleter());
765 boost::shared_ptr<std::vector<std::pair<CellPtr, Node<DIM>* > > > p_cells_left(&mCellsToSendLeft,
null_deleter());
770 template<
unsigned DIM>
775 boost::shared_ptr<std::vector<std::pair<CellPtr, Node<DIM>* > > > p_cells_right(&mCellsToSendRight,
null_deleter());
782 boost::shared_ptr<std::vector<std::pair<CellPtr, Node<DIM>* > > > p_cells_left(&mCellsToSendLeft,
null_deleter());
798 template<
unsigned DIM>
803 mpCellsRecvRight = mRightCommunicator.GetRecvObject();
807 mpCellsRecvLeft = mLeftCommunicator.GetRecvObject();
811 template<
unsigned DIM>
814 Node<DIM>* p_node = this->GetNode(nodeIndex);
816 CellPtr p_cell = this->GetCellUsingLocationIndex(nodeIndex);
818 std::pair<CellPtr, Node<DIM>* > new_pair(p_cell, p_node);
823 template<
unsigned DIM>
826 std::pair<CellPtr, Node<DIM>* > pair = GetCellNodePair(nodeIndex);
828 mCellsToSendRight.push_back(pair);
831 template<
unsigned DIM>
834 std::pair<CellPtr, Node<DIM>* > pair = GetCellNodePair(nodeIndex);
836 mCellsToSendLeft.push_back(pair);
839 template<
unsigned DIM>
844 for (
typename std::vector<std::pair<CellPtr,
Node<DIM>* > >::iterator iter = mpCellsRecvLeft->begin();
845 iter != mpCellsRecvLeft->end();
849 boost::shared_ptr<Node<DIM> > p_node(iter->second);
850 AddMovedCell(iter->first, p_node);
855 for (
typename std::vector<std::pair<CellPtr,
Node<DIM>* > >::iterator iter = mpCellsRecvRight->begin();
856 iter != mpCellsRecvRight->end();
859 boost::shared_ptr<Node<DIM> > p_node(iter->second);
860 AddMovedCell(iter->first, p_node);
865 template<
unsigned DIM>
868 mpNodesOnlyMesh->ResizeBoxCollection();
870 mpNodesOnlyMesh->CalculateNodesOutsideLocalDomain();
872 std::vector<unsigned> nodes_to_send_right = mpNodesOnlyMesh->rGetNodesToSendRight();
873 AddCellsToSendRight(nodes_to_send_right);
875 std::vector<unsigned> nodes_to_send_left = mpNodesOnlyMesh->rGetNodesToSendLeft();
876 AddCellsToSendLeft(nodes_to_send_left);
879 SendCellsToNeighbourProcesses();
884 for (std::vector<unsigned>::iterator iter = nodes_to_send_right.begin();
885 iter != nodes_to_send_right.end();
888 DeleteMovedCell(*iter);
891 for (std::vector<unsigned>::iterator iter = nodes_to_send_left.begin();
892 iter != nodes_to_send_left.end();
895 DeleteMovedCell(*iter);
900 NodeMap map(1 + mpNodesOnlyMesh->GetMaximumNodeIndex());
901 mpNodesOnlyMesh->ReMesh(map);
902 UpdateMapsAfterRemesh(map);
905 template<
unsigned DIM>
908 mpNodesOnlyMesh->ClearHaloNodes();
911 mHaloCellLocationMap.clear();
912 mLocationHaloCellMap.clear();
914 std::vector<unsigned> halos_to_send_right = mpNodesOnlyMesh->rGetHaloNodesToSendRight();
915 AddCellsToSendRight(halos_to_send_right);
917 std::vector<unsigned> halos_to_send_left = mpNodesOnlyMesh->rGetHaloNodesToSendLeft();
918 AddCellsToSendLeft(halos_to_send_left);
920 NonBlockingSendCellsToNeighbourProcesses();
923 template<
unsigned DIM>
926 mCellsToSendRight.clear();
928 for (
unsigned i=0; i < cellLocationIndices.size(); i++)
930 AddNodeAndCellToSendRight(cellLocationIndices[i]);
934 template<
unsigned DIM>
937 mCellsToSendLeft.clear();
939 for (
unsigned i=0; i < cellLocationIndices.size(); i++)
941 AddNodeAndCellToSendLeft(cellLocationIndices[i]);
945 template<
unsigned DIM>
952 for (
typename std::vector<std::pair<CellPtr,
Node<DIM>* > >::iterator iter = mpCellsRecvLeft->begin();
953 iter != mpCellsRecvLeft->end();
956 boost::shared_ptr<Node<DIM> > p_node(iter->second);
957 AddHaloCell(iter->first, p_node);
963 for (
typename std::vector<std::pair<CellPtr,
Node<DIM>* > >::iterator iter = mpCellsRecvRight->begin();
964 iter != mpCellsRecvRight->end();
967 boost::shared_ptr<Node<DIM> > p_node(iter->second);
968 AddHaloCell(iter->first, p_node);
972 mpNodesOnlyMesh->AddHaloNodesToBoxes();
975 template<
unsigned DIM>
978 mHaloCells.push_back(pCell);
980 mpNodesOnlyMesh->AddHaloNode(pNode);
982 mHaloCellLocationMap[pCell] = pNode->GetIndex();
984 mLocationHaloCellMap[pNode->GetIndex()] = pCell;
void AddCellsToSendRight(std::vector< unsigned > &cellLocationIndices)
double GetMechanicsCutOffLength()
void OutputCellPopulationParameters(out_stream &rParamsFile)
std::set< unsigned > GetNodesWithinNeighbourhoodRadius(unsigned index, double neighbourhoodRadius)
NodesOnlyMesh< DIM > & rGetMesh()
bool GetUseVariableRadii()
virtual ~NodeBasedCellPopulation()
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)
virtual TetrahedralMesh< DIM, DIM > * GetTetrahedralMeshForPdeModifier()
double SmallPow(double x, unsigned exponent)
c_vector< double, DIM > GetSizeOfCellPopulation()
void SetRadius(double radius)
unsigned RemoveDeadCells()
#define EXCEPTION(message)
Node< DIM > * GetNode(unsigned index)
void AddCellsToSendLeft(std::vector< unsigned > &cellLocationIndices)
static SimulationTime * Instance()
void SetParallelFiles(AbstractTetrahedralMesh< ELEMENT_DIM, SPACE_DIM > &rMesh)
void SetNode(unsigned nodeIndex, ChastePoint< DIM > &rNewLocation)
void SetUseVariableRadii(bool useVariableRadii=true)
unsigned GetTimeStepsElapsed() const
void AddMovedCell(CellPtr pCell, boost::shared_ptr< Node< DIM > > pNode)
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)
c_vector< double, SPACE_DIM > GetSizeOfCellPopulation()
std::set< unsigned > GetNeighbouringNodeIndices(unsigned index)
void SendCellsToNeighbourProcesses()
#define EXPORT_TEMPLATE_CLASS_SAME_DIMS(CLASS)
void UpdateMapsAfterRemesh(NodeMap &map)
void SetLoadBalanceMesh(bool loadBalanceMesh)
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 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
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)
NodesOnlyMesh< DIM > * mpNodesOnlyMesh
virtual void UpdateCellProcessLocation()
void DeleteMovedCell(unsigned index)
void Update(bool hasHadBirthsOrDeaths=true)
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()
void AddNodeAndCellToSendRight(unsigned nodeIndex)
virtual void UpdateParticlesAfterReMesh(NodeMap &rMap)