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