PottsBasedCellPopulation.cpp
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 "PottsBasedCellPopulation.hpp"
00037 #include "RandomNumberGenerator.hpp"
00038 #include "Warnings.hpp"
00039
00040
00041 #include "VtkMeshWriter.hpp"
00042 #include "NodesOnlyMesh.hpp"
00043 #include "Exception.hpp"
00044
00045
00046 #include "CellPopulationElementWriter.hpp"
00047
00048 template<unsigned DIM>
00049 void PottsBasedCellPopulation<DIM>::Validate()
00050 {
00051
00052 std::vector<unsigned> validated_element = std::vector<unsigned>(this->GetNumElements(), 0);
00053
00054 for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->Begin();
00055 cell_iter != this->End();
00056 ++cell_iter)
00057 {
00058 unsigned elem_index = this->GetLocationIndexUsingCell(*cell_iter);
00059 validated_element[elem_index]++;
00060 }
00061
00062 for (unsigned i=0; i<validated_element.size(); i++)
00063 {
00064 if (validated_element[i] == 0)
00065 {
00066 EXCEPTION("Element " << i << " does not appear to have a cell associated with it");
00067 }
00068
00069 if (validated_element[i] > 1)
00070 {
00071 EXCEPTION("Element " << i << " appears to have " << validated_element[i] << " cells associated with it");
00072 }
00073 }
00074 }
00075
00076 template<unsigned DIM>
00077 PottsBasedCellPopulation<DIM>::PottsBasedCellPopulation(PottsMesh<DIM>& rMesh,
00078 std::vector<CellPtr>& rCells,
00079 bool deleteMesh,
00080 bool validate,
00081 const std::vector<unsigned> locationIndices)
00082 : AbstractOnLatticeCellPopulation<DIM>(rMesh, rCells, locationIndices, deleteMesh),
00083 mpElementTessellation(NULL),
00084 mpMutableMesh(NULL),
00085 mTemperature(0.1),
00086 mNumSweepsPerTimestep(1)
00087 {
00088 mpPottsMesh = static_cast<PottsMesh<DIM>* >(&(this->mrMesh));
00089
00090 if (validate)
00091 {
00092 Validate();
00093 }
00094 }
00095
00096 template<unsigned DIM>
00097 PottsBasedCellPopulation<DIM>::PottsBasedCellPopulation(PottsMesh<DIM>& rMesh)
00098 : AbstractOnLatticeCellPopulation<DIM>(rMesh),
00099 mpElementTessellation(NULL),
00100 mpMutableMesh(NULL),
00101 mTemperature(0.1),
00102 mNumSweepsPerTimestep(1)
00103 {
00104 mpPottsMesh = static_cast<PottsMesh<DIM>* >(&(this->mrMesh));
00105 }
00106
00107 template<unsigned DIM>
00108 PottsBasedCellPopulation<DIM>::~PottsBasedCellPopulation()
00109 {
00110 delete mpElementTessellation;
00111
00112 delete mpMutableMesh;
00113
00114 if (this->mDeleteMesh)
00115 {
00116 delete &this->mrMesh;
00117 }
00118 }
00119
00120 template<unsigned DIM>
00121 PottsMesh<DIM>& PottsBasedCellPopulation<DIM>::rGetMesh()
00122 {
00123 return *mpPottsMesh;
00124 }
00125
00126 template<unsigned DIM>
00127 const PottsMesh<DIM>& PottsBasedCellPopulation<DIM>::rGetMesh() const
00128 {
00129 return *mpPottsMesh;
00130 }
00131
00132 template<unsigned DIM>
00133 PottsElement<DIM>* PottsBasedCellPopulation<DIM>::GetElement(unsigned elementIndex)
00134 {
00135 return mpPottsMesh->GetElement(elementIndex);
00136 }
00137
00138 template<unsigned DIM>
00139 unsigned PottsBasedCellPopulation<DIM>::GetNumElements()
00140 {
00141 return mpPottsMesh->GetNumElements();
00142 }
00143
00144 template<unsigned DIM>
00145 Node<DIM>* PottsBasedCellPopulation<DIM>::GetNode(unsigned index)
00146 {
00147 return this->mrMesh.GetNode(index);
00148 }
00149
00150 template<unsigned DIM>
00151 unsigned PottsBasedCellPopulation<DIM>::GetNumNodes()
00152 {
00153 return this->mrMesh.GetNumNodes();
00154 }
00155
00156 template<unsigned DIM>
00157 c_vector<double, DIM> PottsBasedCellPopulation<DIM>::GetLocationOfCellCentre(CellPtr pCell)
00158 {
00159 return mpPottsMesh->GetCentroidOfElement(this->GetLocationIndexUsingCell(pCell));
00160 }
00161
00162 template<unsigned DIM>
00163 PottsElement<DIM>* PottsBasedCellPopulation<DIM>::GetElementCorrespondingToCell(CellPtr pCell)
00164 {
00165 return mpPottsMesh->GetElement(this->GetLocationIndexUsingCell(pCell));
00166 }
00167
00168 template<unsigned DIM>
00169 CellPtr PottsBasedCellPopulation<DIM>::AddCell(CellPtr pNewCell, const c_vector<double,DIM>& rCellDivisionVector, CellPtr pParentCell)
00170 {
00171
00172 PottsElement<DIM>* p_element = GetElementCorrespondingToCell(pParentCell);
00173
00174
00175 unsigned new_element_index = mpPottsMesh->DivideElement(p_element, true);
00176
00177
00178 this->mCells.push_back(pNewCell);
00179
00180
00181 CellPtr p_created_cell = this->mCells.back();
00182 this->SetCellUsingLocationIndex(new_element_index,p_created_cell);
00183 return p_created_cell;
00184 }
00185
00186 template<unsigned DIM>
00187 unsigned PottsBasedCellPopulation<DIM>::RemoveDeadCells()
00188 {
00189 unsigned num_removed = 0;
00190
00191 for (std::list<CellPtr>::iterator it = this->mCells.begin();
00192 it != this->mCells.end();
00193 )
00194 {
00195 if ((*it)->IsDead())
00196 {
00197
00198 num_removed++;
00199 mpPottsMesh->DeleteElement(this->GetLocationIndexUsingCell((*it)));
00200 it = this->mCells.erase(it);
00201 }
00202 else
00203 {
00204 ++it;
00205 }
00206 }
00207 return num_removed;
00208 }
00209 template<unsigned DIM>
00210 void PottsBasedCellPopulation<DIM>::UpdateCellLocations(double dt)
00211 {
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224 RandomNumberGenerator* p_gen = RandomNumberGenerator::Instance();
00225 unsigned num_nodes = this->mrMesh.GetNumNodes();
00226
00227
00228 if (this->mIterateRandomlyOverUpdateRuleCollection)
00229 {
00230
00231 p_gen->Shuffle(mUpdateRuleCollection);
00232 }
00233
00234 for (unsigned i=0; i<num_nodes*mNumSweepsPerTimestep; i++)
00235 {
00236 unsigned node_index;
00237
00238 if (this->mUpdateNodesInRandomOrder)
00239 {
00240 node_index = p_gen->randMod(num_nodes);
00241 }
00242 else
00243 {
00244
00245 node_index = i%num_nodes;
00246 }
00247
00248 Node<DIM>* p_node = this->mrMesh.GetNode(node_index);
00249
00250
00251 assert(p_node->GetNumContainingElements() <= 1);
00252
00253
00254 std::set<unsigned> neighbouring_node_indices = mpPottsMesh->GetMooreNeighbouringNodeIndices(node_index);
00255 unsigned neighbour_location_index;
00256
00257 if (!neighbouring_node_indices.empty())
00258 {
00259 unsigned num_neighbours = neighbouring_node_indices.size();
00260 unsigned chosen_neighbour = p_gen->randMod(num_neighbours);
00261
00262 std::set<unsigned>::iterator neighbour_iter = neighbouring_node_indices.begin();
00263 for (unsigned j=0; j<chosen_neighbour; j++)
00264 {
00265 neighbour_iter++;
00266 }
00267
00268 neighbour_location_index = *neighbour_iter;
00269
00270 std::set<unsigned> containing_elements = p_node->rGetContainingElementIndices();
00271 std::set<unsigned> neighbour_containing_elements = GetNode(neighbour_location_index)->rGetContainingElementIndices();
00272
00273 if ( ( !containing_elements.empty() && neighbour_containing_elements.empty() )
00274 || ( containing_elements.empty() && !neighbour_containing_elements.empty() )
00275 || ( !containing_elements.empty() && !neighbour_containing_elements.empty() && *containing_elements.begin() != *neighbour_containing_elements.begin() ) )
00276 {
00277 double delta_H = 0.0;
00278
00279
00280 for (typename std::vector<boost::shared_ptr<AbstractPottsUpdateRule<DIM> > >::iterator iter = mUpdateRuleCollection.begin();
00281 iter != mUpdateRuleCollection.end();
00282 ++iter)
00283 {
00284 delta_H += (*iter)->EvaluateHamiltonianContribution(neighbour_location_index, p_node->GetIndex(), *this);
00285 }
00286
00287
00288 double random_number = p_gen->ranf();
00289
00290 double p = exp(-delta_H/mTemperature);
00291 if (delta_H <= 0 || random_number < p)
00292 {
00293
00294
00295
00296 for (std::set<unsigned>::iterator iter = containing_elements.begin();
00297 iter != containing_elements.end();
00298 ++iter)
00299 {
00300 GetElement(*iter)->DeleteNode(GetElement(*iter)->GetNodeLocalIndex(node_index));
00301
00303 }
00304
00305
00306 for (std::set<unsigned>::iterator iter = neighbour_containing_elements.begin();
00307 iter != neighbour_containing_elements.end();
00308 ++iter)
00309 {
00310 GetElement(*iter)->AddNode(this->mrMesh.GetNode(node_index));
00311 }
00312 }
00313 }
00314 }
00315 }
00316 }
00317
00318 template<unsigned DIM>
00319 bool PottsBasedCellPopulation<DIM>::IsCellAssociatedWithADeletedLocation(CellPtr pCell)
00320 {
00321 return GetElementCorrespondingToCell(pCell)->IsDeleted();
00322 }
00323
00324 template<unsigned DIM>
00325 void PottsBasedCellPopulation<DIM>::Update(bool hasHadBirthsOrDeaths)
00326 {
00327 }
00328
00329 template<unsigned DIM>
00330 void PottsBasedCellPopulation<DIM>::OpenWritersFiles(const std::string& rDirectory)
00331 {
00332 if (this->mOutputResultsForChasteVisualizer)
00333 {
00334 if (!this-> template HasWriter<CellPopulationElementWriter>())
00335 {
00336 this-> template AddPopulationWriter<CellPopulationElementWriter>();
00337 }
00338 }
00339
00340 AbstractCellPopulation<DIM>::OpenWritersFiles(rDirectory);
00341 }
00342
00343 template<unsigned DIM>
00344 void PottsBasedCellPopulation<DIM>::WriteResultsToFiles(const std::string& rDirectory)
00345 {
00346 CreateElementTessellation();
00347
00348 AbstractCellPopulation<DIM>::WriteResultsToFiles(rDirectory);
00349 }
00350
00351 template<unsigned DIM>
00352 void PottsBasedCellPopulation<DIM>::AcceptPopulationWriter(boost::shared_ptr<AbstractCellPopulationWriter<DIM, DIM> > pPopulationWriter)
00353 {
00354 pPopulationWriter->Visit(this);
00355 }
00356
00357 template<unsigned DIM>
00358 void PottsBasedCellPopulation<DIM>::AcceptCellWriter(boost::shared_ptr<AbstractCellWriter<DIM, DIM> > pCellWriter, CellPtr pCell)
00359 {
00360 pCellWriter->VisitCell(pCell, this);
00361 }
00362
00363 template<unsigned DIM>
00364 double PottsBasedCellPopulation<DIM>::GetVolumeOfCell(CellPtr pCell)
00365 {
00366
00367 unsigned elem_index = this->GetLocationIndexUsingCell(pCell);
00368
00369
00370 double cell_volume = mpPottsMesh->GetVolumeOfElement(elem_index);
00371
00372 return cell_volume;
00373 }
00374
00375 template<unsigned DIM>
00376 double PottsBasedCellPopulation<DIM>::GetWidth(const unsigned& rDimension)
00377 {
00378
00379 double width = this->mrMesh.GetWidth(rDimension);
00380
00381 return width;
00382 }
00383
00384 template<unsigned DIM>
00385 void PottsBasedCellPopulation<DIM>::AddUpdateRule(boost::shared_ptr<AbstractPottsUpdateRule<DIM> > pUpdateRule)
00386 {
00387 mUpdateRuleCollection.push_back(pUpdateRule);
00388 }
00389
00390 template<unsigned DIM>
00391 void PottsBasedCellPopulation<DIM>::RemoveAllUpdateRules()
00392 {
00393 mUpdateRuleCollection.clear();
00394 }
00395
00396 template<unsigned DIM>
00397 const std::vector<boost::shared_ptr<AbstractPottsUpdateRule<DIM> > >& PottsBasedCellPopulation<DIM>::rGetUpdateRuleCollection() const
00398 {
00399 return mUpdateRuleCollection;
00400 }
00401
00402 template<unsigned DIM>
00403 void PottsBasedCellPopulation<DIM>::CreateElementTessellation()
00404 {
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418 }
00419
00420 template<unsigned DIM>
00421 VertexMesh<DIM,DIM>* PottsBasedCellPopulation<DIM>::GetElementTessellation()
00422 {
00423
00424 return mpElementTessellation;
00425 }
00426
00427 template<unsigned DIM>
00428 void PottsBasedCellPopulation<DIM>::CreateMutableMesh()
00429 {
00430 delete mpMutableMesh;
00431
00432
00433 std::vector<Node<DIM>*> nodes;
00434 for (unsigned node_index=0; node_index<this->mrMesh.GetNumNodes(); node_index++)
00435 {
00436 c_vector<double, DIM> location = this->mrMesh.GetNode(node_index)->rGetLocation();
00437 nodes.push_back(new Node<DIM>(node_index, location));
00438 }
00439
00440 mpMutableMesh = new MutableMesh<DIM,DIM>(nodes);
00441 }
00442
00443 template<unsigned DIM>
00444 MutableMesh<DIM,DIM>* PottsBasedCellPopulation<DIM>::GetMutableMesh()
00445 {
00446 assert(mpMutableMesh);
00447 return mpMutableMesh;
00448 }
00449
00450 template<unsigned DIM>
00451 void PottsBasedCellPopulation<DIM>::OutputCellPopulationParameters(out_stream& rParamsFile)
00452 {
00453 *rParamsFile << "\t\t<Temperature>" << mTemperature << "</Temperature>\n";
00454 *rParamsFile << "\t\t<NumSweepsPerTimestep>" << mNumSweepsPerTimestep << "</NumSweepsPerTimestep>\n";
00455
00456
00457 AbstractOnLatticeCellPopulation<DIM>::OutputCellPopulationParameters(rParamsFile);
00458 }
00459
00460 template<unsigned DIM>
00461 void PottsBasedCellPopulation<DIM>::SetTemperature(double temperature)
00462 {
00463 mTemperature = temperature;
00464 }
00465
00466 template<unsigned DIM>
00467 double PottsBasedCellPopulation<DIM>::GetTemperature()
00468 {
00469 return mTemperature;
00470 }
00471
00472 template<unsigned DIM>
00473 void PottsBasedCellPopulation<DIM>::SetNumSweepsPerTimestep(unsigned numSweepsPerTimestep)
00474 {
00475 mNumSweepsPerTimestep = numSweepsPerTimestep;
00476 }
00477
00478 template<unsigned DIM>
00479 unsigned PottsBasedCellPopulation<DIM>::GetNumSweepsPerTimestep()
00480 {
00481 return mNumSweepsPerTimestep;
00482 }
00483
00484 template<unsigned DIM>
00485 void PottsBasedCellPopulation<DIM>::WriteVtkResultsToFile(const std::string& rDirectory)
00486 {
00487 #ifdef CHASTE_VTK
00488 unsigned num_timesteps = SimulationTime::Instance()->GetTimeStepsElapsed();
00489 std::stringstream time;
00490 time << num_timesteps;
00491
00492
00493 VtkMeshWriter<DIM, DIM> mesh_writer(rDirectory, "results_"+time.str(), false);
00494
00495
00496 unsigned num_nodes = GetNumNodes();
00497 for (typename std::set<boost::shared_ptr<AbstractCellWriter<DIM, DIM> > >::iterator cell_writer_iter = this->mCellWriters.begin();
00498 cell_writer_iter != this->mCellWriters.end();
00499 ++cell_writer_iter)
00500 {
00501
00502 std::vector<double> vtk_cell_data(num_nodes);
00503
00504
00505 for (typename AbstractMesh<DIM,DIM>::NodeIterator iter = mpPottsMesh->GetNodeIteratorBegin();
00506 iter != mpPottsMesh->GetNodeIteratorEnd();
00507 ++iter)
00508 {
00509
00510 unsigned node_index = iter->GetIndex();
00511 std::set<unsigned> element_indices = iter->rGetContainingElementIndices();
00512
00513
00514 if (element_indices.empty())
00515 {
00516
00517 vtk_cell_data[node_index] = -1.0;
00518 }
00519 else
00520 {
00521
00522 assert(element_indices.size() == 1);
00523 unsigned elem_index = *(element_indices.begin());
00524 CellPtr p_cell = this->GetCellUsingLocationIndex(elem_index);
00525
00526
00527 vtk_cell_data[node_index] = (*cell_writer_iter)->GetCellDataForVtkOutput(p_cell, this);
00528 }
00529 }
00530
00531 mesh_writer.AddPointData((*cell_writer_iter)->GetVtkCellDataName(), vtk_cell_data);
00532 }
00533
00534
00535
00536 unsigned num_cell_data_items = this->Begin()->GetCellData()->GetNumItems();
00537 std::vector<std::string> cell_data_names = this->Begin()->GetCellData()->GetKeys();
00538
00539 std::vector<std::vector<double> > cell_data;
00540 for (unsigned var=0; var<num_cell_data_items; var++)
00541 {
00542 std::vector<double> cell_data_var(num_nodes);
00543 cell_data.push_back(cell_data_var);
00544 }
00545
00546 for (typename AbstractMesh<DIM,DIM>::NodeIterator iter = mpPottsMesh->GetNodeIteratorBegin();
00547 iter != mpPottsMesh->GetNodeIteratorEnd();
00548 ++iter)
00549 {
00550
00551 unsigned node_index = iter->GetIndex();
00552 std::set<unsigned> element_indices = iter->rGetContainingElementIndices();
00553
00554
00555 if (element_indices.empty())
00556 {
00557 for (unsigned var=0; var<num_cell_data_items; var++)
00558 {
00559 cell_data[var][node_index] = -1.0;
00560 }
00561 }
00562 else
00563 {
00564
00565 assert(element_indices.size() == 1);
00566 unsigned elem_index = *(element_indices.begin());
00567 CellPtr p_cell = this->GetCellUsingLocationIndex(elem_index);
00568
00569 for (unsigned var=0; var<num_cell_data_items; var++)
00570 {
00571 cell_data[var][node_index] = p_cell->GetCellData()->GetItem(cell_data_names[var]);
00572 }
00573 }
00574 }
00575 for (unsigned var=0; var<cell_data.size(); var++)
00576 {
00577 mesh_writer.AddPointData(cell_data_names[var], cell_data[var]);
00578 }
00579
00580
00581
00582
00583
00584 NodesOnlyMesh<DIM> temp_mesh;
00585 temp_mesh.ConstructNodesWithoutMesh(*mpPottsMesh, 1.5);
00586 mesh_writer.WriteFilesUsingMesh(temp_mesh);
00587
00588 *(this->mpVtkMetaFile) << " <DataSet timestep=\"";
00589 *(this->mpVtkMetaFile) << num_timesteps;
00590 *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_";
00591 *(this->mpVtkMetaFile) << num_timesteps;
00592 *(this->mpVtkMetaFile) << ".vtu\"/>\n";
00593 #endif //CHASTE_VTK
00594 }
00595
00596
00597 template class PottsBasedCellPopulation<1>;
00598 template class PottsBasedCellPopulation<2>;
00599 template class PottsBasedCellPopulation<3>;
00600
00601
00602 #include "SerializationExportWrapperForCpp.hpp"
00603 EXPORT_TEMPLATE_CLASS_SAME_DIMS(PottsBasedCellPopulation)