00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include "NodeBasedCellPopulation.hpp"
00037 #include "MathsCustomFunctions.hpp"
00038 #include "VtkMeshWriter.hpp"
00039
00040
00041 #include "CellAgesWriter.hpp"
00042 #include "CellAncestorWriter.hpp"
00043 #include "CellProliferativePhasesWriter.hpp"
00044 #include "CellProliferativeTypesWriter.hpp"
00045 #include "CellVolumesWriter.hpp"
00046 #include "CellMutationStatesWriter.hpp"
00047
00048 template<unsigned DIM>
00049 NodeBasedCellPopulation<DIM>::NodeBasedCellPopulation(NodesOnlyMesh<DIM>& rMesh,
00050 std::vector<CellPtr>& rCells,
00051 const std::vector<unsigned> locationIndices,
00052 bool deleteMesh,
00053 bool validate)
00054 : AbstractCentreBasedCellPopulation<DIM>(rMesh, rCells, locationIndices),
00055 mDeleteMesh(deleteMesh),
00056 mUseVariableRadii(false),
00057 mLoadBalanceMesh(false),
00058 mLoadBalanceFrequency(100)
00059 {
00060 mpNodesOnlyMesh = static_cast<NodesOnlyMesh<DIM>* >(&(this->mrMesh));
00061
00062 if (validate)
00063 {
00064 Validate();
00065 }
00066 }
00067
00068 template<unsigned DIM>
00069 NodeBasedCellPopulation<DIM>::NodeBasedCellPopulation(NodesOnlyMesh<DIM>& rMesh)
00070 : AbstractCentreBasedCellPopulation<DIM>(rMesh),
00071 mDeleteMesh(true),
00072 mUseVariableRadii(false),
00073 mLoadBalanceMesh(false),
00074 mLoadBalanceFrequency(100)
00075 {
00076 mpNodesOnlyMesh = static_cast<NodesOnlyMesh<DIM>* >(&(this->mrMesh));
00077 }
00078
00079 template<unsigned DIM>
00080 NodeBasedCellPopulation<DIM>::~NodeBasedCellPopulation()
00081 {
00082 Clear();
00083 if (mDeleteMesh)
00084 {
00085 delete &this->mrMesh;
00086 }
00087 }
00088
00089 template<unsigned DIM>
00090 NodesOnlyMesh<DIM>& NodeBasedCellPopulation<DIM>::rGetMesh()
00091 {
00092 return *mpNodesOnlyMesh;
00093 }
00094
00095 template<unsigned DIM>
00096 const NodesOnlyMesh<DIM>& NodeBasedCellPopulation<DIM>::rGetMesh() const
00097 {
00098 return *mpNodesOnlyMesh;
00099 }
00100
00101 template<unsigned DIM>
00102 void NodeBasedCellPopulation<DIM>::Clear()
00103 {
00104 mNodePairs.clear();
00105 }
00106
00107 template<unsigned DIM>
00108 void NodeBasedCellPopulation<DIM>::Validate()
00109 {
00110 for (typename AbstractMesh<DIM,DIM>::NodeIterator node_iter = this->mrMesh.GetNodeIteratorBegin();
00111 node_iter != this->mrMesh.GetNodeIteratorEnd();
00112 ++node_iter)
00113 {
00114 try
00115 {
00116 this->GetCellUsingLocationIndex(node_iter->GetIndex());
00117 }
00118 catch (Exception&)
00119 {
00120 EXCEPTION("At time " << SimulationTime::Instance()->GetTime() << ", Node " << node_iter->GetIndex() << " does not appear to have a cell associated with it");
00121 }
00122 }
00123 }
00124
00125 template<unsigned DIM>
00126 Node<DIM>* NodeBasedCellPopulation<DIM>::GetNode(unsigned index)
00127 {
00128 return mpNodesOnlyMesh->GetNodeOrHaloNode(index);
00129 }
00130
00131 template<unsigned DIM>
00132 void NodeBasedCellPopulation<DIM>::SetNode(unsigned nodeIndex, ChastePoint<DIM>& rNewLocation)
00133 {
00134 mpNodesOnlyMesh->GetNode(nodeIndex)->SetPoint(rNewLocation);
00135 }
00136
00137 template<unsigned DIM>
00138 void NodeBasedCellPopulation<DIM>::Update(bool hasHadBirthsOrDeaths)
00139 {
00140 UpdateCellProcessLocation();
00141
00142 mpNodesOnlyMesh->UpdateBoxCollection();
00143
00144 if (mLoadBalanceMesh)
00145 {
00146 if ((SimulationTime::Instance()->GetTimeStepsElapsed() % mLoadBalanceFrequency) == 0)
00147 {
00148 mpNodesOnlyMesh->LoadBalanceMesh();
00149
00150 UpdateCellProcessLocation();
00151
00152 mpNodesOnlyMesh->UpdateBoxCollection();
00153 }
00154 }
00155
00156 RefreshHaloCells();
00157
00158 mpNodesOnlyMesh->CalculateInteriorNodePairs(mNodePairs, mNodeNeighbours);
00159
00160 AddReceivedHaloCells();
00161
00162 mpNodesOnlyMesh->CalculateBoundaryNodePairs(mNodePairs, mNodeNeighbours);
00163
00164
00165
00166
00167 if (mUseVariableRadii)
00168 {
00169 for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->Begin();
00170 cell_iter != this->End();
00171 ++cell_iter)
00172 {
00173 double cell_radius = cell_iter->GetCellData()->GetItem("Radius");
00174 unsigned node_index = this->GetLocationIndexUsingCell(*cell_iter);
00175 this->GetNode(node_index)->SetRadius(cell_radius);
00176 }
00177 }
00178
00179
00180 PetscTools::Barrier("Update");
00181 }
00182
00183 template<unsigned DIM>
00184 void NodeBasedCellPopulation<DIM>::UpdateMapsAfterRemesh(NodeMap& map)
00185 {
00186 if (!map.IsIdentityMap())
00187 {
00188 UpdateParticlesAfterReMesh(map);
00189
00190
00192 std::map<Cell*, unsigned> old_map = this->mCellLocationMap;
00193
00194
00195 this->mLocationCellMap.clear();
00196 this->mCellLocationMap.clear();
00197
00198 for (std::list<CellPtr>::iterator it = this->mCells.begin();
00199 it != this->mCells.end();
00200 ++it)
00201 {
00202 unsigned old_node_index = old_map[(*it).get()];
00203
00204
00205 assert(!map.IsDeleted(old_node_index));
00206
00207 unsigned new_node_index = map.GetNewIndex(old_node_index);
00208 this->SetCellUsingLocationIndex(new_node_index,*it);
00209 }
00210
00211 this->Validate();
00212 }
00213 }
00214
00215 template<unsigned DIM>
00216 unsigned NodeBasedCellPopulation<DIM>::RemoveDeadCells()
00217 {
00218 unsigned num_removed = 0;
00219 for (std::list<CellPtr>::iterator cell_iter = this->mCells.begin();
00220 cell_iter != this->mCells.end();
00221 )
00222 {
00223 if ((*cell_iter)->IsDead())
00224 {
00225
00226 num_removed++;
00227 unsigned location_index = mpNodesOnlyMesh->SolveNodeMapping(this->GetLocationIndexUsingCell((*cell_iter)));
00228 mpNodesOnlyMesh->DeleteNodePriorToReMesh(location_index);
00229
00230
00231 unsigned location_index_of_removed_node = this->GetLocationIndexUsingCell((*cell_iter));
00232 this->RemoveCellUsingLocationIndex(location_index_of_removed_node, (*cell_iter));
00233
00234
00235 cell_iter = this->mCells.erase(cell_iter);
00236 }
00237 else
00238 {
00239 ++cell_iter;
00240 }
00241 }
00242
00243 return num_removed;
00244 }
00245
00246 template<unsigned DIM>
00247 unsigned NodeBasedCellPopulation<DIM>::AddNode(Node<DIM>* pNewNode)
00248 {
00249 return mpNodesOnlyMesh->AddNode(pNewNode);
00250 }
00251
00252 template<unsigned DIM>
00253 unsigned NodeBasedCellPopulation<DIM>::GetNumNodes()
00254 {
00255 return mpNodesOnlyMesh->GetNumNodes();
00256 }
00257
00258 template<unsigned DIM>
00259 CellPtr NodeBasedCellPopulation<DIM>::GetCellUsingLocationIndex(unsigned index)
00260 {
00261 std::map<unsigned, CellPtr>::iterator iter = mLocationHaloCellMap.find(index);
00262 if (iter != mLocationHaloCellMap.end())
00263 {
00264 return iter->second;
00265 }
00266 else
00267 {
00268 return AbstractCellPopulation<DIM, DIM>::GetCellUsingLocationIndex(index);
00269 }
00270 }
00271
00272 template<unsigned DIM>
00273 void NodeBasedCellPopulation<DIM>::UpdateParticlesAfterReMesh(NodeMap& rMap)
00274 {
00275 }
00276
00277 template<unsigned DIM>
00278 std::vector< std::pair<Node<DIM>*, Node<DIM>* > >& NodeBasedCellPopulation<DIM>::rGetNodePairs()
00279 {
00280 return mNodePairs;
00281 }
00282
00283 template<unsigned DIM>
00284 void NodeBasedCellPopulation<DIM>::OutputCellPopulationParameters(out_stream& rParamsFile)
00285 {
00286 *rParamsFile << "\t\t<MechanicsCutOffLength>" << mpNodesOnlyMesh->GetMaximumInteractionDistance() << "</MechanicsCutOffLength>\n";
00287 *rParamsFile << "\t\t<UseVariableRadii>" << mUseVariableRadii <<
00288 "</UseVariableRadii>\n";
00289
00290
00291 AbstractCentreBasedCellPopulation<DIM>::OutputCellPopulationParameters(rParamsFile);
00292 }
00293
00294 template<unsigned DIM>
00295 void NodeBasedCellPopulation<DIM>::AcceptPopulationWriter(boost::shared_ptr<AbstractCellPopulationWriter<DIM, DIM> > pPopulationWriter)
00296 {
00297 pPopulationWriter->Visit(this);
00298 }
00299
00300 template<unsigned DIM>
00301 void NodeBasedCellPopulation<DIM>::AcceptPopulationCountWriter(boost::shared_ptr<AbstractCellPopulationCountWriter<DIM, DIM> > pPopulationCountWriter)
00302 {
00303 pPopulationCountWriter->Visit(this);
00304 }
00305
00306 template<unsigned DIM>
00307 void NodeBasedCellPopulation<DIM>::AcceptCellWriter(boost::shared_ptr<AbstractCellWriter<DIM, DIM> > pCellWriter, CellPtr pCell)
00308 {
00309 pCellWriter->VisitCell(pCell, this);
00310 }
00311
00312 template<unsigned DIM>
00313 double NodeBasedCellPopulation<DIM>::GetMechanicsCutOffLength()
00314 {
00315 return mpNodesOnlyMesh->GetMaximumInteractionDistance();
00316 }
00317
00318 template<unsigned DIM>
00319 bool NodeBasedCellPopulation<DIM>::GetUseVariableRadii()
00320 {
00321 return mUseVariableRadii;
00322 }
00323
00324 template<unsigned DIM>
00325 void NodeBasedCellPopulation<DIM>::SetUseVariableRadii(bool useVariableRadii)
00326 {
00327 mUseVariableRadii = useVariableRadii;
00328 }
00329
00330 template<unsigned DIM>
00331 void NodeBasedCellPopulation<DIM>::SetLoadBalanceMesh(bool loadBalanceMesh)
00332 {
00333 mLoadBalanceMesh = loadBalanceMesh;
00334 }
00335
00336 template<unsigned DIM>
00337 void NodeBasedCellPopulation<DIM>::SetLoadBalanceFrequency(unsigned loadBalanceFrequency)
00338 {
00339 mLoadBalanceFrequency = loadBalanceFrequency;
00340 }
00341
00342 template<unsigned DIM>
00343 double NodeBasedCellPopulation<DIM>::GetWidth(const unsigned& rDimension)
00344 {
00345 return mpNodesOnlyMesh->GetWidth(rDimension);
00346 }
00347
00348 template<unsigned DIM>
00349 c_vector<double, DIM> NodeBasedCellPopulation<DIM>::GetSizeOfCellPopulation()
00350 {
00351 c_vector<double, DIM> local_size = AbstractCellPopulation<DIM, DIM>::GetSizeOfCellPopulation();
00352 c_vector<double, DIM> global_size;
00353
00354 for (unsigned i=0; i<DIM; i++)
00355 {
00356 MPI_Allreduce(&local_size[i], &global_size[i], 1, MPI_DOUBLE, MPI_MAX, PetscTools::GetWorld());
00357 }
00358
00359 return global_size;
00360 }
00361
00362 template<unsigned DIM>
00363 std::set<unsigned> NodeBasedCellPopulation<DIM>::GetNeighbouringNodeIndices(unsigned index)
00364 {
00365
00366 if (mNodeNeighbours.empty())
00367 {
00368 EXCEPTION("mNodeNeighbours not set up. Call Update() before GetNeighbouringNodeIndices()");
00369 }
00370
00371 std::set<unsigned> neighbouring_node_indices;
00372
00373
00374 Node<DIM>* p_node_i = this->GetNode(index);
00375 c_vector<double, DIM> node_i_location = p_node_i->rGetLocation();
00376 double radius_of_cell_i = p_node_i->GetRadius();
00377
00378
00379 if (!(radius_of_cell_i * 2.0 < mpNodesOnlyMesh->GetMaximumInteractionDistance()))
00380 {
00381 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.");
00382 }
00383
00384
00385 std::set<unsigned> near_nodes = mNodeNeighbours.find(index)->second;
00386
00387
00388 for (std::set<unsigned>::iterator iter = near_nodes.begin();
00389 iter != near_nodes.end();
00390 ++iter)
00391 {
00392
00393 if ((*iter) != index)
00394 {
00395 Node<DIM>* p_node_j = this->GetNode((*iter));
00396
00397
00398 c_vector<double, DIM> node_j_location = p_node_j->rGetLocation();
00399
00400
00401 c_vector<double, DIM> node_to_node_vector = mpNodesOnlyMesh->GetVectorFromAtoB(node_j_location,node_i_location);
00402
00403
00404 double distance_between_nodes = norm_2(node_to_node_vector);
00405
00406
00407 double radius_of_cell_j = p_node_j->GetRadius();
00408
00409
00410 double max_interaction_distance = radius_of_cell_i + radius_of_cell_j;
00411
00412
00413 if (!(max_interaction_distance < mpNodesOnlyMesh->GetMaximumInteractionDistance()))
00414 {
00415 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.");
00416 }
00417 if (distance_between_nodes <= max_interaction_distance)
00418 {
00419
00420 neighbouring_node_indices.insert((*iter));
00421 }
00422 }
00423 }
00424
00425 return neighbouring_node_indices;
00426 }
00427
00428 template<unsigned DIM>
00429 double NodeBasedCellPopulation<DIM>::GetVolumeOfCell(CellPtr pCell)
00430 {
00431
00432 assert(DIM==2 ||DIM==3);
00433
00434
00435 unsigned node_index = this->GetLocationIndexUsingCell(pCell);
00436 Node<DIM>* p_node = this->GetNode(node_index);
00437
00438
00439 double cell_radius = p_node->GetRadius();
00440
00441
00442 double averaged_cell_radius = 0.0;
00443 unsigned num_cells = 0;
00444
00445
00446 c_vector<double, DIM> node_i_location = GetNode(node_index)->rGetLocation();
00447
00448
00449 std::set<unsigned> neighbouring_node_indices = GetNeighbouringNodeIndices(node_index);
00450
00451
00452 unsigned num_neighbours_equil;
00453 if (DIM==2)
00454 {
00455 num_neighbours_equil = 6;
00456 }
00457 else
00458 {
00459 assert(DIM==3);
00460 num_neighbours_equil = 12;
00461 }
00462
00463
00464 for (std::set<unsigned>::iterator iter = neighbouring_node_indices.begin();
00465 iter != neighbouring_node_indices.end();
00466 ++iter)
00467 {
00468 Node<DIM>* p_node_j = this->GetNode(*iter);
00469
00470
00471 c_vector<double, DIM> node_j_location = p_node_j->rGetLocation();
00472
00473 double neighbouring_cell_radius = p_node_j->GetRadius();
00474
00475
00476 assert(cell_radius+neighbouring_cell_radius<mpNodesOnlyMesh->GetMaximumInteractionDistance());
00477
00478
00479 double separation = norm_2(mpNodesOnlyMesh->GetVectorFromAtoB(node_j_location,node_i_location));
00480
00481 if (separation < cell_radius+neighbouring_cell_radius)
00482 {
00483
00484 averaged_cell_radius = averaged_cell_radius + cell_radius - (cell_radius+neighbouring_cell_radius-separation)/2.0;
00485 num_cells++;
00486 }
00487 }
00488 if (num_cells < num_neighbours_equil)
00489 {
00490 averaged_cell_radius += (num_neighbours_equil-num_cells)*cell_radius;
00491
00492 averaged_cell_radius /= num_neighbours_equil;
00493 }
00494 else
00495 {
00496 averaged_cell_radius /= num_cells;
00497 }
00498 assert(averaged_cell_radius < mpNodesOnlyMesh->GetMaximumInteractionDistance()/2.0);
00499
00500 cell_radius = averaged_cell_radius;
00501
00502
00503
00504
00505 double cell_volume = 0.0;
00506 if (DIM == 2)
00507 {
00508 cell_volume = M_PI*cell_radius*cell_radius;
00509 }
00510 else if (DIM == 3)
00511 {
00512 cell_volume = (4.0/3.0)*M_PI*cell_radius*cell_radius*cell_radius;
00513 }
00514
00515 return cell_volume;
00516 }
00517
00518 template<unsigned DIM>
00519 void NodeBasedCellPopulation<DIM>::WriteVtkResultsToFile(const std::string& rDirectory)
00520 {
00521 #ifdef CHASTE_VTK
00522
00523 std::stringstream time;
00524 time << SimulationTime::Instance()->GetTimeStepsElapsed();
00525
00526
00527 NodeMap map(1 + this->mpNodesOnlyMesh->GetMaximumNodeIndex());
00528 this->mpNodesOnlyMesh->ReMesh(map);
00529
00530
00531 unsigned num_nodes = GetNumNodes();
00532 std::vector<double> rank(num_nodes);
00533
00534 unsigned num_cell_data_items = 0;
00535 std::vector<std::string> cell_data_names;
00536
00537
00538 if (num_nodes > 0)
00539 {
00540 num_cell_data_items = this->Begin()->GetCellData()->GetNumItems();
00541 cell_data_names = this->Begin()->GetCellData()->GetKeys();
00542 }
00543
00544 std::vector<std::vector<double> > cell_data;
00545 for (unsigned var=0; var<num_cell_data_items; var++)
00546 {
00547 std::vector<double> cell_data_var(num_nodes);
00548 cell_data.push_back(cell_data_var);
00549 }
00550
00551
00552 VtkMeshWriter<DIM, DIM> mesh_writer(rDirectory, "results_"+time.str(), false);
00553 mesh_writer.SetParallelFiles(*mpNodesOnlyMesh);
00554
00555
00556 for (typename std::vector<boost::shared_ptr<AbstractCellWriter<DIM, DIM> > >::iterator cell_writer_iter = this->mCellWriters.begin();
00557 cell_writer_iter != this->mCellWriters.end();
00558 ++cell_writer_iter)
00559 {
00560
00561 std::vector<double> vtk_cell_data(num_nodes);
00562
00563
00564 for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->Begin();
00565 cell_iter != this->End();
00566 ++cell_iter)
00567 {
00568
00569 unsigned global_index = this->GetLocationIndexUsingCell(*cell_iter);
00570 unsigned node_index = this->rGetMesh().SolveNodeMapping(global_index);
00571
00572
00573 vtk_cell_data[node_index] = (*cell_writer_iter)->GetCellDataForVtkOutput(*cell_iter, this);
00574 }
00575
00576 mesh_writer.AddPointData((*cell_writer_iter)->GetVtkCellDataName(), vtk_cell_data);
00577 }
00578
00579
00580 for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->Begin();
00581 cell_iter != this->End();
00582 ++cell_iter)
00583 {
00584
00585 unsigned global_index = this->GetLocationIndexUsingCell(*cell_iter);
00586 unsigned node_index = this->rGetMesh().SolveNodeMapping(global_index);
00587
00588 for (unsigned var=0; var<num_cell_data_items; var++)
00589 {
00590 cell_data[var][node_index] = cell_iter->GetCellData()->GetItem(cell_data_names[var]);
00591 }
00592
00593 rank[node_index] = (PetscTools::GetMyRank());
00594 }
00595
00596 mesh_writer.AddPointData("Process rank", rank);
00597
00598 if (num_cell_data_items > 0)
00599 {
00600 for (unsigned var=0; var<cell_data.size(); var++)
00601 {
00602 mesh_writer.AddPointData(cell_data_names[var], cell_data[var]);
00603 }
00604 }
00605
00606 mesh_writer.WriteFilesUsingMesh(*mpNodesOnlyMesh);
00607
00608 *(this->mpVtkMetaFile) << " <DataSet timestep=\"";
00609 *(this->mpVtkMetaFile) << SimulationTime::Instance()->GetTimeStepsElapsed();
00610 *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_";
00611 *(this->mpVtkMetaFile) << SimulationTime::Instance()->GetTimeStepsElapsed();
00612 if (PetscTools::IsSequential())
00613 {
00614 *(this->mpVtkMetaFile) << ".vtu\"/>\n";
00615 }
00616 else
00617 {
00618
00619 *(this->mpVtkMetaFile) << ".pvtu\"/>\n";
00620 }
00621 #endif //CHASTE_VTK
00622 }
00623
00624 template<unsigned DIM>
00625 CellPtr NodeBasedCellPopulation<DIM>::AddCell(CellPtr pNewCell, const c_vector<double,DIM>& rCellDivisionVector, CellPtr pParentCell)
00626 {
00627 assert(pNewCell);
00628
00629
00630 CellPtr p_created_cell = AbstractCentreBasedCellPopulation<DIM>::AddCell(pNewCell, rCellDivisionVector, pParentCell);
00631 assert(p_created_cell == pNewCell);
00632
00633
00634 unsigned parent_node_index = this->GetLocationIndexUsingCell(pParentCell);
00635 Node<DIM>* p_parent_node = this->GetNode(parent_node_index);
00636
00637 unsigned new_node_index = this->GetLocationIndexUsingCell(p_created_cell);
00638 Node<DIM>* p_new_node = this->GetNode(new_node_index);
00639
00640 p_new_node->SetRadius(p_parent_node->GetRadius());
00641
00642
00643 return p_created_cell;
00644 }
00645
00646 template<unsigned DIM>
00647 void NodeBasedCellPopulation<DIM>::AddMovedCell(CellPtr pCell, boost::shared_ptr<Node<DIM> > pNode)
00648 {
00649
00650 mpNodesOnlyMesh->AddMovedNode(pNode);
00651
00652
00653 this->mCells.push_back(pCell);
00654
00655
00656 this->AddCellUsingLocationIndex(pNode->GetIndex(), pCell);
00657 }
00658
00659 template<unsigned DIM>
00660 void NodeBasedCellPopulation<DIM>::DeleteMovedCell(unsigned index)
00661 {
00662 mpNodesOnlyMesh->DeleteMovedNode(index);
00663
00664
00665 for (std::list<CellPtr>::iterator cell_iter = this->mCells.begin();
00666 cell_iter != this->mCells.end();
00667 ++cell_iter)
00668 {
00669 if (this->GetLocationIndexUsingCell(*cell_iter) == index)
00670 {
00671
00672 this->RemoveCellUsingLocationIndex(index, (*cell_iter));
00673 cell_iter = this->mCells.erase(cell_iter);
00674
00675 break;
00676 }
00677 }
00678 }
00679
00686 struct null_deleter
00687 {
00691 void operator()(void const *) const
00692 {
00693 }
00694 };
00695
00696 template<unsigned DIM>
00697 void NodeBasedCellPopulation<DIM>::SendCellsToNeighbourProcesses()
00698 {
00699 #if BOOST_VERSION < 103700
00700 EXCEPTION("Parallel cell-based Chaste requires Boost >= 1.37");
00701 #else // BOOST_VERSION >= 103700
00702 MPI_Status status;
00703
00704 if (!PetscTools::AmTopMost())
00705 {
00706 boost::shared_ptr<std::vector<std::pair<CellPtr, Node<DIM>* > > > p_cells_right(&mCellsToSendRight, null_deleter());
00707 mpCellsRecvRight = mRightCommunicator.SendRecvObject(p_cells_right, PetscTools::GetMyRank() + 1, mCellCommunicationTag, PetscTools::GetMyRank() + 1, mCellCommunicationTag, status);
00708 }
00709 if (!PetscTools::AmMaster())
00710 {
00711 boost::shared_ptr<std::vector<std::pair<CellPtr, Node<DIM>* > > > p_cells_left(&mCellsToSendLeft, null_deleter());
00712 mpCellsRecvLeft = mLeftCommunicator.SendRecvObject(p_cells_left, PetscTools::GetMyRank() - 1, mCellCommunicationTag, PetscTools::GetMyRank() - 1, mCellCommunicationTag, status);
00713 }
00714 #endif
00715 }
00716
00717 template<unsigned DIM>
00718 void NodeBasedCellPopulation<DIM>::NonBlockingSendCellsToNeighbourProcesses()
00719 {
00720 #if BOOST_VERSION < 103700
00721 EXCEPTION("Parallel cell-based Chaste requires Boost >= 1.37");
00722 #else // BOOST_VERSION >= 103700
00723
00724 if (!PetscTools::AmTopMost())
00725 {
00726 boost::shared_ptr<std::vector<std::pair<CellPtr, Node<DIM>* > > > p_cells_right(&mCellsToSendRight, null_deleter());
00727 int tag = SmallPow(2u, 1+ PetscTools::GetMyRank() ) * SmallPow (3u, 1 + PetscTools::GetMyRank() + 1);
00728 mRightCommunicator.ISendObject(p_cells_right, PetscTools::GetMyRank() + 1, tag);
00729 }
00730 if (!PetscTools::AmMaster())
00731 {
00732 int tag = SmallPow (2u, 1 + PetscTools::GetMyRank() ) * SmallPow (3u, 1 + PetscTools::GetMyRank() - 1);
00733 boost::shared_ptr<std::vector<std::pair<CellPtr, Node<DIM>* > > > p_cells_left(&mCellsToSendLeft, null_deleter());
00734 mLeftCommunicator.ISendObject(p_cells_left, PetscTools::GetMyRank() - 1, tag);
00735 }
00736
00737 if (!PetscTools::AmTopMost())
00738 {
00739 int tag = SmallPow (3u, 1 + PetscTools::GetMyRank() ) * SmallPow (2u, 1+ PetscTools::GetMyRank() + 1);
00740 mRightCommunicator.IRecvObject(PetscTools::GetMyRank() + 1, tag);
00741 }
00742 if (!PetscTools::AmMaster())
00743 {
00744 int tag = SmallPow (3u, 1 + PetscTools::GetMyRank() ) * SmallPow (2u, 1+ PetscTools::GetMyRank() - 1);
00745 mLeftCommunicator.IRecvObject(PetscTools::GetMyRank() - 1, tag);
00746 }
00747 #endif
00748 }
00749
00750 template<unsigned DIM>
00751 void NodeBasedCellPopulation<DIM>::GetReceivedCells()
00752 {
00753 #if BOOST_VERSION < 103700
00754 EXCEPTION("Parallel cell-based Chaste requires Boost >= 1.37");
00755 #else // BOOST_VERSION >= 103700
00756
00757 if (!PetscTools::AmTopMost())
00758 {
00759 mpCellsRecvRight = mRightCommunicator.GetRecvObject();
00760 }
00761 if (!PetscTools::AmMaster())
00762 {
00763 mpCellsRecvLeft = mLeftCommunicator.GetRecvObject();
00764 }
00765 #endif
00766 }
00767 template<unsigned DIM>
00768 std::pair<CellPtr, Node<DIM>* > NodeBasedCellPopulation<DIM>::GetCellNodePair(unsigned nodeIndex)
00769 {
00770 Node<DIM>* p_node = this->GetNode(nodeIndex);
00771
00772 CellPtr p_cell = this->GetCellUsingLocationIndex(nodeIndex);
00773
00774 std::pair<CellPtr, Node<DIM>* > new_pair(p_cell, p_node);
00775
00776 return new_pair;
00777 }
00778
00779 template<unsigned DIM>
00780 void NodeBasedCellPopulation<DIM>::AddNodeAndCellToSendRight(unsigned nodeIndex)
00781 {
00782 std::pair<CellPtr, Node<DIM>* > pair = GetCellNodePair(nodeIndex);
00783
00784 mCellsToSendRight.push_back(pair);
00785 }
00786
00787 template<unsigned DIM>
00788 void NodeBasedCellPopulation<DIM>::AddNodeAndCellToSendLeft(unsigned nodeIndex)
00789 {
00790 std::pair<CellPtr, Node<DIM>* > pair = GetCellNodePair(nodeIndex);
00791
00792 mCellsToSendLeft.push_back(pair);
00793 }
00794
00795 template<unsigned DIM>
00796 void NodeBasedCellPopulation<DIM>::AddReceivedCells()
00797 {
00798 if (!PetscTools::AmMaster())
00799 {
00800 for (typename std::vector<std::pair<CellPtr, Node<DIM>* > >::iterator iter = mpCellsRecvLeft->begin();
00801 iter != mpCellsRecvLeft->end();
00802 ++iter)
00803 {
00804
00805 boost::shared_ptr<Node<DIM> > p_node(iter->second);
00806 AddMovedCell(iter->first, p_node);
00807 }
00808 }
00809 if (!PetscTools::AmTopMost())
00810 {
00811 for (typename std::vector<std::pair<CellPtr, Node<DIM>* > >::iterator iter = mpCellsRecvRight->begin();
00812 iter != mpCellsRecvRight->end();
00813 ++iter)
00814 {
00815 boost::shared_ptr<Node<DIM> > p_node(iter->second);
00816 AddMovedCell(iter->first, p_node);
00817 }
00818 }
00819 }
00820
00821 template<unsigned DIM>
00822 void NodeBasedCellPopulation<DIM>::UpdateCellProcessLocation()
00823 {
00824 mpNodesOnlyMesh->ResizeBoxCollection();
00825
00826 mpNodesOnlyMesh->CalculateNodesOutsideLocalDomain();
00827
00828 std::vector<unsigned> nodes_to_send_right = mpNodesOnlyMesh->rGetNodesToSendRight();
00829 AddCellsToSendRight(nodes_to_send_right);
00830
00831 std::vector<unsigned> nodes_to_send_left = mpNodesOnlyMesh->rGetNodesToSendLeft();
00832 AddCellsToSendLeft(nodes_to_send_left);
00833
00834
00835 SendCellsToNeighbourProcesses();
00836
00837
00838
00839
00840 for (std::vector<unsigned>::iterator iter = nodes_to_send_right.begin();
00841 iter != nodes_to_send_right.end();
00842 ++iter)
00843 {
00844 DeleteMovedCell(*iter);
00845 }
00846
00847 for (std::vector<unsigned>::iterator iter = nodes_to_send_left.begin();
00848 iter != nodes_to_send_left.end();
00849 ++iter)
00850 {
00851 DeleteMovedCell(*iter);
00852 }
00853
00854 AddReceivedCells();
00855
00856 NodeMap map(1 + mpNodesOnlyMesh->GetMaximumNodeIndex());
00857 mpNodesOnlyMesh->ReMesh(map);
00858 UpdateMapsAfterRemesh(map);
00859 }
00860
00861 template<unsigned DIM>
00862 void NodeBasedCellPopulation<DIM>::RefreshHaloCells()
00863 {
00864 mpNodesOnlyMesh->ClearHaloNodes();
00865
00866 mHaloCells.clear();
00867 mHaloCellLocationMap.clear();
00868 mLocationHaloCellMap.clear();
00869
00870 std::vector<unsigned> halos_to_send_right = mpNodesOnlyMesh->rGetHaloNodesToSendRight();
00871 AddCellsToSendRight(halos_to_send_right);
00872
00873 std::vector<unsigned> halos_to_send_left = mpNodesOnlyMesh->rGetHaloNodesToSendLeft();
00874 AddCellsToSendLeft(halos_to_send_left);
00875
00876 NonBlockingSendCellsToNeighbourProcesses();
00877 }
00878
00879 template<unsigned DIM>
00880 void NodeBasedCellPopulation<DIM>::AddCellsToSendRight(std::vector<unsigned>& cellLocationIndices)
00881 {
00882 mCellsToSendRight.clear();
00883
00884 for (unsigned i=0; i < cellLocationIndices.size(); i++)
00885 {
00886 AddNodeAndCellToSendRight(cellLocationIndices[i]);
00887 }
00888 }
00889
00890 template<unsigned DIM>
00891 void NodeBasedCellPopulation<DIM>::AddCellsToSendLeft(std::vector<unsigned>& cellLocationIndices)
00892 {
00893 mCellsToSendLeft.clear();
00894
00895 for (unsigned i=0; i < cellLocationIndices.size(); i++)
00896 {
00897 AddNodeAndCellToSendLeft(cellLocationIndices[i]);
00898 }
00899 }
00900
00901 template<unsigned DIM>
00902 void NodeBasedCellPopulation<DIM>::AddReceivedHaloCells()
00903 {
00904 GetReceivedCells();
00905
00906 if (!PetscTools::AmMaster())
00907 {
00908 for (typename std::vector<std::pair<CellPtr, Node<DIM>* > >::iterator iter = mpCellsRecvLeft->begin();
00909 iter != mpCellsRecvLeft->end();
00910 ++iter)
00911 {
00912 boost::shared_ptr<Node<DIM> > p_node(iter->second);
00913 AddHaloCell(iter->first, p_node);
00914
00915 }
00916 }
00917 if (!PetscTools::AmTopMost())
00918 {
00919 for (typename std::vector<std::pair<CellPtr, Node<DIM>* > >::iterator iter = mpCellsRecvRight->begin();
00920 iter != mpCellsRecvRight->end();
00921 ++iter)
00922 {
00923 boost::shared_ptr<Node<DIM> > p_node(iter->second);
00924 AddHaloCell(iter->first, p_node);
00925 }
00926 }
00927
00928 mpNodesOnlyMesh->AddHaloNodesToBoxes();
00929 }
00930
00931 template<unsigned DIM>
00932 void NodeBasedCellPopulation<DIM>::AddHaloCell(CellPtr pCell, boost::shared_ptr<Node<DIM> > pNode)
00933 {
00934 mHaloCells.push_back(pCell);
00935
00936 mpNodesOnlyMesh->AddHaloNode(pNode);
00937
00938 mHaloCellLocationMap[pCell] = pNode->GetIndex();
00939
00940 mLocationHaloCellMap[pNode->GetIndex()] = pCell;
00941 }
00942
00943
00944 template class NodeBasedCellPopulation<1>;
00945 template class NodeBasedCellPopulation<2>;
00946 template class NodeBasedCellPopulation<3>;
00947
00948
00949 #include "SerializationExportWrapperForCpp.hpp"
00950 EXPORT_TEMPLATE_CLASS_SAME_DIMS(NodeBasedCellPopulation)