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("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>::AcceptCellWriter(boost::shared_ptr<AbstractCellWriter<DIM, DIM> > pCellWriter, CellPtr pCell)
00302 {
00303 pCellWriter->VisitCell(pCell, this);
00304 }
00305
00306 template<unsigned DIM>
00307 double NodeBasedCellPopulation<DIM>::GetMechanicsCutOffLength()
00308 {
00309 return mpNodesOnlyMesh->GetMaximumInteractionDistance();
00310 }
00311
00312 template<unsigned DIM>
00313 bool NodeBasedCellPopulation<DIM>::GetUseVariableRadii()
00314 {
00315 return mUseVariableRadii;
00316 }
00317
00318 template<unsigned DIM>
00319 void NodeBasedCellPopulation<DIM>::SetUseVariableRadii(bool useVariableRadii)
00320 {
00321 mUseVariableRadii = useVariableRadii;
00322 }
00323
00324 template<unsigned DIM>
00325 void NodeBasedCellPopulation<DIM>::SetLoadBalanceMesh(bool loadBalanceMesh)
00326 {
00327 mLoadBalanceMesh = loadBalanceMesh;
00328 }
00329
00330 template<unsigned DIM>
00331 void NodeBasedCellPopulation<DIM>::SetLoadBalanceFrequency(unsigned loadBalanceFrequency)
00332 {
00333 mLoadBalanceFrequency = loadBalanceFrequency;
00334 }
00335
00336 template<unsigned DIM>
00337 double NodeBasedCellPopulation<DIM>::GetWidth(const unsigned& rDimension)
00338 {
00339 return mpNodesOnlyMesh->GetWidth(rDimension);
00340 }
00341
00342 template<unsigned DIM>
00343 c_vector<double, DIM> NodeBasedCellPopulation<DIM>::GetSizeOfCellPopulation()
00344 {
00345 c_vector<double, DIM> local_size = AbstractCellPopulation<DIM, DIM>::GetSizeOfCellPopulation();
00346 c_vector<double, DIM> global_size;
00347
00348 for (unsigned i=0; i<DIM; i++)
00349 {
00350 MPI_Allreduce(&local_size[i], &global_size[i], 1, MPI_DOUBLE, MPI_MAX, PetscTools::GetWorld());
00351 }
00352
00353 return global_size;
00354 }
00355
00356 template<unsigned DIM>
00357 std::set<unsigned> NodeBasedCellPopulation<DIM>::GetNeighbouringNodeIndices(unsigned index)
00358 {
00359
00360 if (mNodeNeighbours.empty())
00361 {
00362 EXCEPTION("mNodeNeighbours not set up. Call Update() before GetNeighbouringNodeIndices()");
00363 }
00364
00365 std::set<unsigned> neighbouring_node_indices;
00366
00367
00368 Node<DIM>* p_node_i = this->GetNode(index);
00369 c_vector<double, DIM> node_i_location = p_node_i->rGetLocation();
00370 double radius_of_cell_i = p_node_i->GetRadius();
00371
00372
00373 if (!(radius_of_cell_i * 2.0 < mpNodesOnlyMesh->GetMaximumInteractionDistance()))
00374 {
00375 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.");
00376 }
00377
00378
00379
00380 std::set<unsigned> near_nodes = mNodeNeighbours.find(index)->second;
00381
00382
00383 for (std::set<unsigned>::iterator iter = near_nodes.begin();
00384 iter != near_nodes.end();
00385 ++iter)
00386 {
00387
00388 if ((*iter) != index)
00389 {
00390 Node<DIM>* p_node_j = this->GetNode((*iter));
00391
00392
00393 c_vector<double, DIM> node_j_location = p_node_j->rGetLocation();
00394
00395
00396 c_vector<double, DIM> node_to_node_vector = mpNodesOnlyMesh->GetVectorFromAtoB(node_j_location,node_i_location);
00397
00398
00399 double distance_between_nodes = norm_2(node_to_node_vector);
00400
00401
00402 double radius_of_cell_j = p_node_j->GetRadius();
00403
00404
00405 double max_interaction_distance = radius_of_cell_i + radius_of_cell_j;
00406
00407
00408 if (!(max_interaction_distance < mpNodesOnlyMesh->GetMaximumInteractionDistance()))
00409 {
00410 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.");
00411 }
00412 if (distance_between_nodes <= max_interaction_distance)
00413 {
00414
00415 neighbouring_node_indices.insert((*iter));
00416 }
00417 }
00418 }
00419
00420 return neighbouring_node_indices;
00421 }
00422
00423 template<unsigned DIM>
00424 double NodeBasedCellPopulation<DIM>::GetVolumeOfCell(CellPtr pCell)
00425 {
00426
00427 assert(DIM==2 ||DIM==3);
00428
00429
00430 unsigned node_index = this->GetLocationIndexUsingCell(pCell);
00431 Node<DIM>* p_node = this->GetNode(node_index);
00432
00433
00434 double cell_radius = p_node->GetRadius();
00435
00436
00437 double averaged_cell_radius = 0.0;
00438 unsigned num_cells = 0;
00439
00440
00441 c_vector<double, DIM> node_i_location = GetNode(node_index)->rGetLocation();
00442
00443
00444 std::set<unsigned> neighbouring_node_indices = GetNeighbouringNodeIndices(node_index);
00445
00446
00447 unsigned num_neighbours_equil;
00448 if (DIM==2)
00449 {
00450 num_neighbours_equil = 6;
00451 }
00452 else
00453 {
00454 assert(DIM==3);
00455 num_neighbours_equil = 12;
00456 }
00457
00458
00459 for (std::set<unsigned>::iterator iter = neighbouring_node_indices.begin();
00460 iter != neighbouring_node_indices.end();
00461 ++iter)
00462 {
00463 Node<DIM>* p_node_j = this->GetNode(*iter);
00464
00465
00466 c_vector<double, DIM> node_j_location = p_node_j->rGetLocation();
00467
00468 double neighbouring_cell_radius = p_node_j->GetRadius();
00469
00470
00471 assert(cell_radius+neighbouring_cell_radius<mpNodesOnlyMesh->GetMaximumInteractionDistance());
00472
00473
00474 double separation = norm_2(mpNodesOnlyMesh->GetVectorFromAtoB(node_j_location,node_i_location));
00475
00476 if (separation < cell_radius+neighbouring_cell_radius)
00477 {
00478
00479 averaged_cell_radius = averaged_cell_radius + cell_radius - (cell_radius+neighbouring_cell_radius-separation)/2.0;
00480 num_cells++;
00481 }
00482 }
00483 if (num_cells < num_neighbours_equil)
00484 {
00485 averaged_cell_radius += (num_neighbours_equil-num_cells)*cell_radius;
00486
00487 averaged_cell_radius /=num_neighbours_equil;
00488 }
00489 else
00490 {
00491 averaged_cell_radius /= num_cells;
00492 }
00493 assert(averaged_cell_radius < mpNodesOnlyMesh->GetMaximumInteractionDistance()/2.0);
00494
00495 cell_radius = averaged_cell_radius;
00496
00497
00498
00499
00500 double cell_volume = 0.0;
00501 if (DIM == 2)
00502 {
00503 cell_volume = M_PI*cell_radius*cell_radius;
00504 }
00505 else if (DIM == 3)
00506 {
00507 cell_volume = (4.0/3.0)*M_PI*cell_radius*cell_radius*cell_radius;
00508 }
00509
00510 return cell_volume;
00511 }
00512
00513 template<unsigned DIM>
00514 void NodeBasedCellPopulation<DIM>::WriteVtkResultsToFile(const std::string& rDirectory)
00515 {
00516 #ifdef CHASTE_VTK
00517 std::stringstream time;
00518 time << SimulationTime::Instance()->GetTimeStepsElapsed();
00519 VtkMeshWriter<DIM, DIM> mesh_writer(rDirectory, "results_"+time.str(), false);
00520
00521
00522 NodeMap map(1 + this->mpNodesOnlyMesh->GetMaximumNodeIndex());
00523 this->mpNodesOnlyMesh->ReMesh(map);
00524
00525 mesh_writer.SetParallelFiles(*mpNodesOnlyMesh);
00526
00527 unsigned num_nodes = GetNumNodes();
00528 std::vector<double> cell_types(num_nodes);
00529 std::vector<double> cell_ancestors(num_nodes);
00530 std::vector<double> cell_mutation_states(num_nodes);
00531 std::vector<double> cell_ages(num_nodes);
00532 std::vector<double> cell_cycle_phases(num_nodes);
00533 std::vector<double> cell_radii(num_nodes);
00534 std::vector<std::vector<double> > cellwise_data;
00535 std::vector<double> rank(num_nodes);
00536
00537 unsigned num_cell_data_items = 0;
00538 std::vector<std::string> cell_data_names;
00539
00540
00541 if (num_nodes > 0)
00542 {
00543 num_cell_data_items = this->Begin()->GetCellData()->GetNumItems();
00544 cell_data_names = this->Begin()->GetCellData()->GetKeys();
00545 }
00546
00547 for (unsigned var=0; var<num_cell_data_items; var++)
00548 {
00549 std::vector<double> cellwise_data_var(num_nodes);
00550 cellwise_data.push_back(cellwise_data_var);
00551 }
00552
00553
00554 for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->Begin();
00555 cell_iter != this->End();
00556 ++cell_iter)
00557 {
00558
00559 unsigned global_index = this->GetLocationIndexUsingCell(*cell_iter);
00560
00561 Node<DIM>* p_node = this->GetNode(global_index);
00562
00563 unsigned node_index = this->rGetMesh().SolveNodeMapping(global_index);
00564
00565 if (this-> template HasWriter<CellAncestorWriter>())
00566 {
00567 double ancestor_index = (cell_iter->GetAncestor() == UNSIGNED_UNSET) ? (-1.0) : (double)cell_iter->GetAncestor();
00568 cell_ancestors[node_index] = ancestor_index;
00569 }
00570 if (this-> template HasWriter<CellProliferativeTypesWriter>())
00571 {
00572 double cell_type = cell_iter->GetCellProliferativeType()->GetColour();
00573 cell_types[node_index] = cell_type;
00574 }
00575 if (this-> template HasWriter<CellMutationStatesWriter>())
00576 {
00577 double mutation_state = cell_iter->GetMutationState()->GetColour();
00578
00580 CellPropertyCollection collection = cell_iter->rGetCellPropertyCollection();
00581 CellPropertyCollection label_collection = collection.GetProperties<CellLabel>();
00582
00583 if (label_collection.GetSize() == 1)
00584 {
00585 boost::shared_ptr<CellLabel> p_label = boost::static_pointer_cast<CellLabel>(label_collection.GetProperty());
00586 mutation_state = p_label->GetColour();
00587 }
00588
00589 cell_mutation_states[node_index] = mutation_state;
00590 }
00591 if (this-> template HasWriter<CellAgesWriter>())
00592 {
00593 double age = cell_iter->GetAge();
00594 cell_ages[node_index] = age;
00595 }
00596 if (this-> template HasWriter<CellProliferativePhasesWriter>())
00597 {
00598 double cycle_phase = cell_iter->GetCellCycleModel()->GetCurrentCellCyclePhase();
00599 cell_cycle_phases[node_index] = cycle_phase;
00600 }
00601 if (this-> template HasWriter<CellVolumesWriter>())
00602 {
00603 double cell_radius = p_node->GetRadius();
00604 cell_radii[node_index] = cell_radius;
00605 }
00606
00607 for (unsigned var=0; var<num_cell_data_items; var++)
00608 {
00609 cellwise_data[var][node_index] = cell_iter->GetCellData()->GetItem(cell_data_names[var]);
00610 }
00611
00612 rank[node_index] = (PetscTools::GetMyRank());
00613 }
00614
00615 mesh_writer.AddPointData("Process rank", rank);
00616
00617 if (this-> template HasWriter<CellProliferativeTypesWriter>())
00618 {
00619 mesh_writer.AddPointData("Cell types", cell_types);
00620 }
00621 if (this-> template HasWriter<CellAncestorWriter>())
00622 {
00623 mesh_writer.AddPointData("Ancestors", cell_ancestors);
00624 }
00625 if (this-> template HasWriter<CellMutationStatesWriter>())
00626 {
00627 mesh_writer.AddPointData("Mutation states", cell_mutation_states);
00628 }
00629 if (this-> template HasWriter<CellAgesWriter>())
00630 {
00631 mesh_writer.AddPointData("Ages", cell_ages);
00632 }
00633 if (this-> template HasWriter<CellProliferativePhasesWriter>())
00634 {
00635 mesh_writer.AddPointData("Cycle phases", cell_cycle_phases);
00636 }
00637 if (this-> template HasWriter<CellVolumesWriter>())
00638 {
00639 mesh_writer.AddPointData("Cell radii", cell_radii);
00640 }
00641 if (num_cell_data_items > 0)
00642 {
00643 for (unsigned var=0; var<cellwise_data.size(); var++)
00644 {
00645 mesh_writer.AddPointData(cell_data_names[var], cellwise_data[var]);
00646 }
00647 }
00648
00649 mesh_writer.WriteFilesUsingMesh(*mpNodesOnlyMesh);
00650
00651 *(this->mpVtkMetaFile) << " <DataSet timestep=\"";
00652 *(this->mpVtkMetaFile) << SimulationTime::Instance()->GetTimeStepsElapsed();
00653 *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_";
00654 *(this->mpVtkMetaFile) << SimulationTime::Instance()->GetTimeStepsElapsed();
00655 *(this->mpVtkMetaFile) << ".vtu\"/>\n";
00656 #endif //CHASTE_VTK
00657 }
00658
00659 template<unsigned DIM>
00660 CellPtr NodeBasedCellPopulation<DIM>::AddCell(CellPtr pNewCell, const c_vector<double,DIM>& rCellDivisionVector, CellPtr pParentCell)
00661 {
00662 assert(pNewCell);
00663
00664
00665 CellPtr p_created_cell = AbstractCentreBasedCellPopulation<DIM>::AddCell(pNewCell, rCellDivisionVector, pParentCell);
00666 assert(p_created_cell == pNewCell);
00667
00668
00669 unsigned parent_node_index = this->GetLocationIndexUsingCell(pParentCell);
00670 Node<DIM>* p_parent_node = this->GetNode(parent_node_index);
00671
00672 unsigned new_node_index = this->GetLocationIndexUsingCell(p_created_cell);
00673 Node<DIM>* p_new_node = this->GetNode(new_node_index);
00674
00675 p_new_node->SetRadius(p_parent_node->GetRadius());
00676
00677
00678 return p_created_cell;
00679 }
00680
00681 template<unsigned DIM>
00682 void NodeBasedCellPopulation<DIM>::AddMovedCell(CellPtr pCell, boost::shared_ptr<Node<DIM> > pNode)
00683 {
00684
00685 mpNodesOnlyMesh->AddMovedNode(pNode);
00686
00687
00688 this->mCells.push_back(pCell);
00689
00690
00691 this->AddCellUsingLocationIndex(pNode->GetIndex(), pCell);
00692 }
00693
00694 template<unsigned DIM>
00695 void NodeBasedCellPopulation<DIM>::DeleteMovedCell(unsigned index)
00696 {
00697 mpNodesOnlyMesh->DeleteMovedNode(index);
00698
00699
00700 for (std::list<CellPtr>::iterator cell_iter = this->mCells.begin();
00701 cell_iter != this->mCells.end();
00702 ++cell_iter)
00703 {
00704 if (this->GetLocationIndexUsingCell(*cell_iter) == index)
00705 {
00706
00707 this->RemoveCellUsingLocationIndex(index, (*cell_iter));
00708 cell_iter = this->mCells.erase(cell_iter);
00709
00710 break;
00711 }
00712 }
00713 }
00714
00721 struct null_deleter
00722 {
00726 void operator()(void const *) const
00727 {
00728 }
00729 };
00730
00731 template<unsigned DIM>
00732 void NodeBasedCellPopulation<DIM>::SendCellsToNeighbourProcesses()
00733 {
00734 #if BOOST_VERSION < 103700
00735 EXCEPTION("Parallel cell-based Chaste requires Boost >= 1.37");
00736 #else // BOOST_VERSION >= 103700
00737 MPI_Status status;
00738
00739 if (!PetscTools::AmTopMost())
00740 {
00741 boost::shared_ptr<std::vector<std::pair<CellPtr, Node<DIM>* > > > p_cells_right(&mCellsToSendRight, null_deleter());
00742 mpCellsRecvRight = mRightCommunicator.SendRecvObject(p_cells_right, PetscTools::GetMyRank() + 1, mCellCommunicationTag, PetscTools::GetMyRank() + 1, mCellCommunicationTag, status);
00743 }
00744 if (!PetscTools::AmMaster())
00745 {
00746 boost::shared_ptr<std::vector<std::pair<CellPtr, Node<DIM>* > > > p_cells_left(&mCellsToSendLeft, null_deleter());
00747 mpCellsRecvLeft = mLeftCommunicator.SendRecvObject(p_cells_left, PetscTools::GetMyRank() - 1, mCellCommunicationTag, PetscTools::GetMyRank() - 1, mCellCommunicationTag, status);
00748 }
00749 #endif
00750 }
00751
00752 template<unsigned DIM>
00753 void NodeBasedCellPopulation<DIM>::NonBlockingSendCellsToNeighbourProcesses()
00754 {
00755 #if BOOST_VERSION < 103700
00756 EXCEPTION("Parallel cell-based Chaste requires Boost >= 1.37");
00757 #else // BOOST_VERSION >= 103700
00758
00759 if (!PetscTools::AmTopMost())
00760 {
00761 boost::shared_ptr<std::vector<std::pair<CellPtr, Node<DIM>* > > > p_cells_right(&mCellsToSendRight, null_deleter());
00762 int tag = SmallPow(2u, 1+ PetscTools::GetMyRank() ) * SmallPow (3u, 1 + PetscTools::GetMyRank() + 1);
00763 mRightCommunicator.ISendObject(p_cells_right, PetscTools::GetMyRank() + 1, tag);
00764 }
00765 if (!PetscTools::AmMaster())
00766 {
00767 int tag = SmallPow (2u, 1 + PetscTools::GetMyRank() ) * SmallPow (3u, 1 + PetscTools::GetMyRank() - 1);
00768 boost::shared_ptr<std::vector<std::pair<CellPtr, Node<DIM>* > > > p_cells_left(&mCellsToSendLeft, null_deleter());
00769 mLeftCommunicator.ISendObject(p_cells_left, PetscTools::GetMyRank() - 1, tag);
00770 }
00771
00772 if (!PetscTools::AmTopMost())
00773 {
00774 int tag = SmallPow (3u, 1 + PetscTools::GetMyRank() ) * SmallPow (2u, 1+ PetscTools::GetMyRank() + 1);
00775 mRightCommunicator.IRecvObject(PetscTools::GetMyRank() + 1, tag);
00776 }
00777 if (!PetscTools::AmMaster())
00778 {
00779 int tag = SmallPow (3u, 1 + PetscTools::GetMyRank() ) * SmallPow (2u, 1+ PetscTools::GetMyRank() - 1);
00780 mLeftCommunicator.IRecvObject(PetscTools::GetMyRank() - 1, tag);
00781 }
00782 #endif
00783 }
00784
00785 template<unsigned DIM>
00786 void NodeBasedCellPopulation<DIM>::GetReceivedCells()
00787 {
00788 #if BOOST_VERSION < 103700
00789 EXCEPTION("Parallel cell-based Chaste requires Boost >= 1.37");
00790 #else // BOOST_VERSION >= 103700
00791
00792 if (!PetscTools::AmTopMost())
00793 {
00794 mpCellsRecvRight = mRightCommunicator.GetRecvObject();
00795 }
00796 if (!PetscTools::AmMaster())
00797 {
00798 mpCellsRecvLeft = mLeftCommunicator.GetRecvObject();
00799 }
00800 #endif
00801 }
00802 template<unsigned DIM>
00803 std::pair<CellPtr, Node<DIM>* > NodeBasedCellPopulation<DIM>::GetCellNodePair(unsigned nodeIndex)
00804 {
00805 Node<DIM>* p_node = this->GetNode(nodeIndex);
00806
00807 CellPtr p_cell = this->GetCellUsingLocationIndex(nodeIndex);
00808
00809 std::pair<CellPtr, Node<DIM>* > new_pair(p_cell, p_node);
00810
00811 return new_pair;
00812 }
00813
00814 template<unsigned DIM>
00815 void NodeBasedCellPopulation<DIM>::AddNodeAndCellToSendRight(unsigned nodeIndex)
00816 {
00817 std::pair<CellPtr, Node<DIM>* > pair = GetCellNodePair(nodeIndex);
00818
00819 mCellsToSendRight.push_back(pair);
00820 }
00821
00822 template<unsigned DIM>
00823 void NodeBasedCellPopulation<DIM>::AddNodeAndCellToSendLeft(unsigned nodeIndex)
00824 {
00825 std::pair<CellPtr, Node<DIM>* > pair = GetCellNodePair(nodeIndex);
00826
00827 mCellsToSendLeft.push_back(pair);
00828 }
00829
00830 template<unsigned DIM>
00831 void NodeBasedCellPopulation<DIM>::AddReceivedCells()
00832 {
00833 if (!PetscTools::AmMaster())
00834 {
00835 for (typename std::vector<std::pair<CellPtr, Node<DIM>* > >::iterator iter = mpCellsRecvLeft->begin();
00836 iter != mpCellsRecvLeft->end();
00837 ++iter)
00838 {
00839
00840 boost::shared_ptr<Node<DIM> > p_node(iter->second);
00841 AddMovedCell(iter->first, p_node);
00842 }
00843 }
00844 if (!PetscTools::AmTopMost())
00845 {
00846 for (typename std::vector<std::pair<CellPtr, Node<DIM>* > >::iterator iter = mpCellsRecvRight->begin();
00847 iter != mpCellsRecvRight->end();
00848 ++iter)
00849 {
00850 boost::shared_ptr<Node<DIM> > p_node(iter->second);
00851 AddMovedCell(iter->first, p_node);
00852 }
00853 }
00854 }
00855
00856 template<unsigned DIM>
00857 void NodeBasedCellPopulation<DIM>::UpdateCellProcessLocation()
00858 {
00859 mpNodesOnlyMesh->ResizeBoxCollection();
00860
00861 mpNodesOnlyMesh->CalculateNodesOutsideLocalDomain();
00862
00863 std::vector<unsigned> nodes_to_send_right = mpNodesOnlyMesh->rGetNodesToSendRight();
00864 AddCellsToSendRight(nodes_to_send_right);
00865
00866 std::vector<unsigned> nodes_to_send_left = mpNodesOnlyMesh->rGetNodesToSendLeft();
00867 AddCellsToSendLeft(nodes_to_send_left);
00868
00869
00870 SendCellsToNeighbourProcesses();
00871
00872
00873
00874
00875 for (std::vector<unsigned>::iterator iter = nodes_to_send_right.begin();
00876 iter != nodes_to_send_right.end();
00877 ++iter)
00878 {
00879 DeleteMovedCell(*iter);
00880 }
00881
00882 for (std::vector<unsigned>::iterator iter = nodes_to_send_left.begin();
00883 iter != nodes_to_send_left.end();
00884 ++iter)
00885 {
00886 DeleteMovedCell(*iter);
00887 }
00888
00889 AddReceivedCells();
00890
00891 NodeMap map(1 + mpNodesOnlyMesh->GetMaximumNodeIndex());
00892 mpNodesOnlyMesh->ReMesh(map);
00893 UpdateMapsAfterRemesh(map);
00894 }
00895
00896 template<unsigned DIM>
00897 void NodeBasedCellPopulation<DIM>::RefreshHaloCells()
00898 {
00899 mpNodesOnlyMesh->ClearHaloNodes();
00900
00901 mHaloCells.clear();
00902 mHaloCellLocationMap.clear();
00903 mLocationHaloCellMap.clear();
00904
00905 std::vector<unsigned> halos_to_send_right = mpNodesOnlyMesh->rGetHaloNodesToSendRight();
00906 AddCellsToSendRight(halos_to_send_right);
00907
00908 std::vector<unsigned> halos_to_send_left = mpNodesOnlyMesh->rGetHaloNodesToSendLeft();
00909 AddCellsToSendLeft(halos_to_send_left);
00910
00911 NonBlockingSendCellsToNeighbourProcesses();
00912 }
00913
00914 template<unsigned DIM>
00915 void NodeBasedCellPopulation<DIM>::AddCellsToSendRight(std::vector<unsigned>& cellLocationIndices)
00916 {
00917 mCellsToSendRight.clear();
00918
00919 for (unsigned i=0; i < cellLocationIndices.size(); i++)
00920 {
00921 AddNodeAndCellToSendRight(cellLocationIndices[i]);
00922 }
00923 }
00924
00925 template<unsigned DIM>
00926 void NodeBasedCellPopulation<DIM>::AddCellsToSendLeft(std::vector<unsigned>& cellLocationIndices)
00927 {
00928 mCellsToSendLeft.clear();
00929
00930 for (unsigned i=0; i < cellLocationIndices.size(); i++)
00931 {
00932 AddNodeAndCellToSendLeft(cellLocationIndices[i]);
00933 }
00934 }
00935
00936 template<unsigned DIM>
00937 void NodeBasedCellPopulation<DIM>::AddReceivedHaloCells()
00938 {
00939 GetReceivedCells();
00940
00941 if (!PetscTools::AmMaster())
00942 {
00943 for (typename std::vector<std::pair<CellPtr, Node<DIM>* > >::iterator iter = mpCellsRecvLeft->begin();
00944 iter != mpCellsRecvLeft->end();
00945 ++iter)
00946 {
00947 boost::shared_ptr<Node<DIM> > p_node(iter->second);
00948 AddHaloCell(iter->first, p_node);
00949
00950 }
00951 }
00952 if (!PetscTools::AmTopMost())
00953 {
00954 for (typename std::vector<std::pair<CellPtr, Node<DIM>* > >::iterator iter = mpCellsRecvRight->begin();
00955 iter != mpCellsRecvRight->end();
00956 ++iter)
00957 {
00958 boost::shared_ptr<Node<DIM> > p_node(iter->second);
00959 AddHaloCell(iter->first, p_node);
00960 }
00961 }
00962
00963 mpNodesOnlyMesh->AddHaloNodesToBoxes();
00964 }
00965
00966 template<unsigned DIM>
00967 void NodeBasedCellPopulation<DIM>::AddHaloCell(CellPtr pCell, boost::shared_ptr<Node<DIM> > pNode)
00968 {
00969 mHaloCells.push_back(pCell);
00970
00971 mpNodesOnlyMesh->AddHaloNode(pNode);
00972
00973 mHaloCellLocationMap[pCell] = pNode->GetIndex();
00974
00975 mLocationHaloCellMap[pNode->GetIndex()] = pCell;
00976 }
00977
00978
00979 template class NodeBasedCellPopulation<1>;
00980 template class NodeBasedCellPopulation<2>;
00981 template class NodeBasedCellPopulation<3>;
00982
00983
00984 #include "SerializationExportWrapperForCpp.hpp"
00985 EXPORT_TEMPLATE_CLASS_SAME_DIMS(NodeBasedCellPopulation)