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 #include "MeshBasedCellPopulation.hpp"
00030 #include "CellwiseData.hpp"
00031 #include "TrianglesMeshWriter.hpp"
00032 #include "VtkMeshWriter.hpp"
00033 #include "CellBasedEventHandler.hpp"
00034 #include "ApoptoticCellProperty.hpp"
00035 #include "Cylindrical2dMesh.hpp"
00036 #include "NodesOnlyMesh.hpp"
00037 #include "Exception.hpp"
00038
00039 template<unsigned DIM>
00040 MeshBasedCellPopulation<DIM>::MeshBasedCellPopulation(MutableMesh<DIM, DIM>& rMesh,
00041 std::vector<CellPtr>& rCells,
00042 const std::vector<unsigned> locationIndices,
00043 bool deleteMesh,
00044 bool validate)
00045 : AbstractCentreBasedCellPopulation<DIM>(rCells, locationIndices),
00046 mrMesh(rMesh),
00047 mpVoronoiTessellation(NULL),
00048 mDeleteMesh(deleteMesh),
00049 mUseAreaBasedDampingConstant(false),
00050 mAreaBasedDampingConstantParameter(0.1),
00051 mOutputVoronoiData(false),
00052 mOutputCellPopulationVolumes(false),
00053 mWriteVtkAsPoints(false)
00054 {
00055
00056 assert(this->mCells.size() <= mrMesh.GetNumNodes());
00057
00058 if (validate)
00059 {
00060 Validate();
00061 }
00062 }
00063
00064 template<unsigned DIM>
00065 MeshBasedCellPopulation<DIM>::MeshBasedCellPopulation(MutableMesh<DIM, DIM>& rMesh)
00066 : mrMesh(rMesh)
00067 {
00068 mpVoronoiTessellation = NULL;
00069 mDeleteMesh = true;
00070 }
00071
00072 template<unsigned DIM>
00073 MeshBasedCellPopulation<DIM>::~MeshBasedCellPopulation()
00074 {
00075 delete mpVoronoiTessellation;
00076
00077 if (mDeleteMesh)
00078 {
00079 delete &mrMesh;
00080 }
00081 }
00082
00083 template<unsigned DIM>
00084 bool MeshBasedCellPopulation<DIM>::UseAreaBasedDampingConstant()
00085 {
00086 return mUseAreaBasedDampingConstant;
00087 }
00088
00089 template<unsigned DIM>
00090 void MeshBasedCellPopulation<DIM>::SetAreaBasedDampingConstant(bool useAreaBasedDampingConstant)
00091 {
00092 assert(DIM==2);
00093 mUseAreaBasedDampingConstant = useAreaBasedDampingConstant;
00094 }
00095
00096 template<unsigned DIM>
00097 unsigned MeshBasedCellPopulation<DIM>::AddNode(Node<DIM>* pNewNode)
00098 {
00099 return mrMesh.AddNode(pNewNode);
00100 }
00101
00102 template<unsigned DIM>
00103 void MeshBasedCellPopulation<DIM>::SetNode(unsigned nodeIndex, ChastePoint<DIM>& rNewLocation)
00104 {
00105 mrMesh.SetNode(nodeIndex, rNewLocation, false);
00106 }
00107
00108 template<unsigned DIM>
00109 double MeshBasedCellPopulation<DIM>::GetDampingConstant(unsigned nodeIndex)
00110 {
00111 double damping_multiplier = AbstractCentreBasedCellPopulation<DIM>::GetDampingConstant(nodeIndex);
00112
00113 if (mUseAreaBasedDampingConstant)
00114 {
00124 assert(DIM==2);
00125
00126 double rest_length = 1.0;
00127 double d0 = mAreaBasedDampingConstantParameter;
00128
00134 double d1 = 2.0*(1.0 - d0)/(sqrt(3)*rest_length*rest_length);
00135
00136 double area_cell = GetVolumeOfVoronoiElement(nodeIndex);
00137
00143 assert(area_cell < 1000);
00144
00145 damping_multiplier = d0 + area_cell*d1;
00146 }
00147
00148 return damping_multiplier;
00149 }
00150
00151 template<unsigned DIM>
00152 void MeshBasedCellPopulation<DIM>::Validate()
00153 {
00154 std::vector<bool> validated_node = std::vector<bool>(this->GetNumNodes(), false);
00155
00156 for (typename AbstractCellPopulation<DIM>::Iterator cell_iter=this->Begin(); cell_iter!=this->End(); ++cell_iter)
00157 {
00158 unsigned node_index = GetLocationIndexUsingCell(*cell_iter);
00159 validated_node[node_index] = true;
00160 }
00161
00162 for (unsigned i=0; i<validated_node.size(); i++)
00163 {
00164 if (!validated_node[i])
00165 {
00166 EXCEPTION("Node " << i << " does not appear to have a cell associated with it");
00167 }
00168 }
00169 }
00170
00171 template<unsigned DIM>
00172 MutableMesh<DIM, DIM>& MeshBasedCellPopulation<DIM>::rGetMesh()
00173 {
00174 return mrMesh;
00175 }
00176
00177 template<unsigned DIM>
00178 const MutableMesh<DIM, DIM>& MeshBasedCellPopulation<DIM>::rGetMesh() const
00179 {
00180 return mrMesh;
00181 }
00182
00183 template<unsigned DIM>
00184 unsigned MeshBasedCellPopulation<DIM>::RemoveDeadCells()
00185 {
00186 unsigned num_removed = 0;
00187 for (std::list<CellPtr>::iterator it = this->mCells.begin();
00188 it != this->mCells.end();
00189 ++it)
00190 {
00191 if ((*it)->IsDead())
00192 {
00193
00194 std::vector<const std::pair<CellPtr,CellPtr>*> pairs_to_remove;
00195 for (std::set<std::pair<CellPtr,CellPtr> >::iterator it1 = mMarkedSprings.begin();
00196 it1 != mMarkedSprings.end();
00197 ++it1)
00198 {
00199 const std::pair<CellPtr,CellPtr>& r_pair = *it1;
00200
00201 for (unsigned i=0; i<2; i++)
00202 {
00203 CellPtr p_cell = (i==0 ? r_pair.first : r_pair.second);
00204
00205 if (p_cell == *it)
00206 {
00207
00208 pairs_to_remove.push_back(&r_pair);
00209 break;
00210 }
00211 }
00212 }
00213
00214
00215 for (std::vector<const std::pair<CellPtr,CellPtr>* >::iterator pair_it = pairs_to_remove.begin();
00216 pair_it != pairs_to_remove.end();
00217 ++pair_it)
00218 {
00219 mMarkedSprings.erase(**pair_it);
00220 }
00221
00222
00223 num_removed++;
00224 mrMesh.DeleteNodePriorToReMesh(this->mCellLocationMap[(*it).get()]);
00225
00226
00227 unsigned location_index_of_removed_node = this->mCellLocationMap[(*it).get()];
00228 this->mCellLocationMap.erase((*it).get());
00229 this->mLocationCellMap.erase(location_index_of_removed_node);
00230
00231
00232 it = this->mCells.erase(it);
00233 --it;
00234 }
00235 }
00236
00237 return num_removed;
00238 }
00239
00240 template<unsigned DIM>
00241 void MeshBasedCellPopulation<DIM>::Update(bool hasHadBirthsOrDeaths)
00242 {
00243 NodeMap map(mrMesh.GetNumAllNodes());
00244 try
00245 {
00246 mrMesh.ReMesh(map);
00247 }
00248 catch (Exception &e)
00249 {
00250 EXCEPTION("Simulation has produced an element with zero area. Please re-run with a cutoff on your forces");
00251 }
00252 if (!map.IsIdentityMap())
00253 {
00254 UpdateGhostNodesAfterReMesh(map);
00255
00256
00257 std::map<Cell*, unsigned> old_map = this->mCellLocationMap;
00258
00259
00260 this->mLocationCellMap.clear();
00261 this->mCellLocationMap.clear();
00262
00263 for (std::list<CellPtr>::iterator it = this->mCells.begin();
00264 it != this->mCells.end();
00265 ++it)
00266 {
00267 unsigned old_node_index = old_map[(*it).get()];
00268
00269
00270 assert(!map.IsDeleted(old_node_index));
00271
00272 unsigned new_node_index = map.GetNewIndex(old_node_index);
00273 this->mLocationCellMap[new_node_index] = *it;
00274 this->mCellLocationMap[(*it).get()] = new_node_index;
00275 }
00276
00277 this->Validate();
00278 }
00279
00280
00281 std::vector<const std::pair<CellPtr,CellPtr>*> springs_to_remove;
00282 for (std::set<std::pair<CellPtr,CellPtr> >::iterator spring_it = mMarkedSprings.begin();
00283 spring_it != mMarkedSprings.end();
00284 ++spring_it)
00285 {
00286 CellPtr p_cell_1 = spring_it->first;
00287 CellPtr p_cell_2 = spring_it->second;
00288 Node<DIM>* p_node_1 = this->GetNodeCorrespondingToCell(p_cell_1);
00289 Node<DIM>* p_node_2 = this->GetNodeCorrespondingToCell(p_cell_2);
00290
00291 bool joined = false;
00292
00293
00294 std::set<unsigned> node2_elements = p_node_2->rGetContainingElementIndices();
00295 for (typename Node<DIM>::ContainingElementIterator elem_iter = p_node_1->ContainingElementsBegin();
00296 elem_iter != p_node_1->ContainingElementsEnd();
00297 ++elem_iter)
00298 {
00299 if (node2_elements.find(*elem_iter) != node2_elements.end())
00300 {
00301 joined = true;
00302 break;
00303 }
00304 }
00305
00306
00307 if (!joined)
00308 {
00309 springs_to_remove.push_back(&(*spring_it));
00310 }
00311 }
00312
00313
00314 for (std::vector<const std::pair<CellPtr,CellPtr>* >::iterator spring_it = springs_to_remove.begin();
00315 spring_it != springs_to_remove.end();
00316 ++spring_it)
00317 {
00318 mMarkedSprings.erase(**spring_it);
00319 }
00320
00321
00322 TessellateIfNeeded();
00323
00324 mrMesh.SetMeshHasChangedSinceLoading();
00325 }
00326
00327 template<unsigned DIM>
00328 void MeshBasedCellPopulation<DIM>::TessellateIfNeeded()
00329 {
00330 if (DIM==2 || DIM==3)
00331 {
00332 CellBasedEventHandler::BeginEvent(CellBasedEventHandler::TESSELLATION);
00333 if (mUseAreaBasedDampingConstant || mOutputVoronoiData || mOutputCellPopulationVolumes || this->mOutputCellVolumes)
00334 {
00335 CreateVoronoiTessellation();
00336 }
00337 CellBasedEventHandler::EndEvent(CellBasedEventHandler::TESSELLATION);
00338 }
00339 }
00340
00341 template<unsigned DIM>
00342 Node<DIM>* MeshBasedCellPopulation<DIM>::GetNode(unsigned index)
00343 {
00344 return mrMesh.GetNode(index);
00345 }
00346
00347 template<unsigned DIM>
00348 unsigned MeshBasedCellPopulation<DIM>::GetNumNodes()
00349 {
00350 return mrMesh.GetNumAllNodes();
00351 }
00352
00353 template<unsigned DIM>
00354 void MeshBasedCellPopulation<DIM>::UpdateGhostNodesAfterReMesh(NodeMap& rMap)
00355 {
00356 }
00357
00358 template<unsigned DIM>
00359 CellPtr MeshBasedCellPopulation<DIM>::AddCell(CellPtr pNewCell, const c_vector<double,DIM>& rCellDivisionVector, CellPtr pParentCell)
00360 {
00361 assert(pNewCell);
00362 assert(pParentCell);
00363
00364
00365 CellPtr p_created_cell = AbstractCentreBasedCellPopulation<DIM>::AddCell(pNewCell, rCellDivisionVector, pParentCell);
00366 assert(p_created_cell == pNewCell);
00367
00368
00369 std::pair<CellPtr,CellPtr> cell_pair = CreateCellPair(pParentCell, p_created_cell);
00370 MarkSpring(cell_pair);
00371
00372
00373 return p_created_cell;
00374 }
00375
00377
00379
00380 template<unsigned DIM>
00381 void MeshBasedCellPopulation<DIM>::CreateOutputFiles(const std::string& rDirectory, bool cleanOutputDirectory)
00382 {
00383 AbstractCentreBasedCellPopulation<DIM>::CreateOutputFiles(rDirectory, cleanOutputDirectory);
00384
00385 OutputFileHandler output_file_handler(rDirectory, cleanOutputDirectory);
00386 mpVizElementsFile = output_file_handler.OpenOutputFile("results.vizelements");
00387
00388 if (mOutputVoronoiData)
00389 {
00390 mpVoronoiFile = output_file_handler.OpenOutputFile("voronoi.dat");
00391 }
00392 if (mOutputCellPopulationVolumes)
00393 {
00394 mpCellPopulationVolumesFile = output_file_handler.OpenOutputFile("cellpopulationareas.dat");
00395 }
00396 }
00397
00398 template<unsigned DIM>
00399 void MeshBasedCellPopulation<DIM>::CloseOutputFiles()
00400 {
00401 AbstractCentreBasedCellPopulation<DIM>::CloseOutputFiles();
00402
00403 mpVizElementsFile->close();
00404
00405 if (mOutputVoronoiData)
00406 {
00407 mpVoronoiFile->close();
00408 }
00409 if (mOutputCellPopulationVolumes)
00410 {
00411 mpCellPopulationVolumesFile->close();
00412 }
00413 }
00414
00415 template<unsigned DIM>
00416 void MeshBasedCellPopulation<DIM>::WriteResultsToFiles()
00417 {
00418 if (SimulationTime::Instance()->GetTimeStepsElapsed() == 0 && this->mpVoronoiTessellation == NULL)
00419 {
00420 TessellateIfNeeded();
00421 }
00422
00423 AbstractCentreBasedCellPopulation<DIM>::WriteResultsToFiles();
00424
00425
00426 *mpVizElementsFile << SimulationTime::Instance()->GetTime() << "\t";
00427
00428 for (typename MutableMesh<DIM,DIM>::ElementIterator elem_iter = mrMesh.GetElementIteratorBegin();
00429 elem_iter != mrMesh.GetElementIteratorEnd();
00430 ++elem_iter)
00431 {
00432 bool element_contains_dead_cells_or_deleted_nodes = false;
00433
00434
00435 for (unsigned i=0; i<DIM+1; i++)
00436 {
00437 unsigned node_index = elem_iter->GetNodeGlobalIndex(i);
00438
00439 if (this->GetNode(node_index)->IsDeleted())
00440 {
00441 element_contains_dead_cells_or_deleted_nodes = true;
00442 break;
00443 }
00444 else if (this->mLocationCellMap[node_index])
00445 {
00446 if (this->mLocationCellMap[node_index]->IsDead())
00447 {
00448 element_contains_dead_cells_or_deleted_nodes = true;
00449 break;
00450 }
00451 }
00452 }
00453 if (!element_contains_dead_cells_or_deleted_nodes)
00454 {
00455 for (unsigned i=0; i<DIM+1; i++)
00456 {
00457 *mpVizElementsFile << elem_iter->GetNodeGlobalIndex(i) << " ";
00458 }
00459 }
00460 }
00461 *mpVizElementsFile << "\n";
00462
00463
00464 if (mOutputVoronoiData)
00465 {
00466 WriteVoronoiResultsToFile();
00467 }
00468 if (mOutputCellPopulationVolumes)
00469 {
00470 WriteCellPopulationVolumeResultsToFile();
00471 }
00472
00473 }
00474
00475 template<unsigned DIM>
00476 void MeshBasedCellPopulation<DIM>::WriteVtkResultsToFile()
00477 {
00478 #ifdef CHASTE_VTK
00479
00480 std::stringstream time;
00481 time << SimulationTime::Instance()->GetTimeStepsElapsed();
00482
00483 unsigned num_points = GetNumNodes();
00484 if (!mWriteVtkAsPoints && (mpVoronoiTessellation != NULL))
00485 {
00486 num_points = mpVoronoiTessellation->GetNumElements();
00487 }
00488
00489 std::vector<double> cell_types(num_points);
00490 std::vector<double> cell_ancestors(num_points);
00491 std::vector<double> cell_mutation_states(num_points);
00492 std::vector<double> cell_ages(num_points);
00493 std::vector<double> cell_cycle_phases(num_points);
00494 std::vector<std::vector<double> > cellwise_data;
00495
00496 if (CellwiseData<DIM>::Instance()->IsSetUp())
00497 {
00498 CellwiseData<DIM>* p_data = CellwiseData<DIM>::Instance();
00499 for (unsigned var=0; var<p_data->GetNumVariables(); var++)
00500 {
00501 std::vector<double> cellwise_data_var(num_points);
00502 cellwise_data.push_back(cellwise_data_var);
00503 }
00504 }
00505
00506 if (mWriteVtkAsPoints)
00507 {
00508 VtkMeshWriter<DIM, DIM> mesh_writer(this->mDirPath, "results_"+time.str(), false);
00509
00510
00511 for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->Begin();
00512 cell_iter != this->End();
00513 ++cell_iter)
00514 {
00515
00516 unsigned node_index = this->GetLocationIndexUsingCell(*cell_iter);
00517
00518
00519 AbstractCellCycleModel* p_model = cell_iter->GetCellCycleModel();
00520
00521 if (this->mOutputCellAncestors)
00522 {
00523 double ancestor_index = (cell_iter->GetAncestor() == UNSIGNED_UNSET) ? (-1.0) : (double)cell_iter->GetAncestor();
00524 cell_ancestors[node_index] = ancestor_index;
00525 }
00526 if (this->mOutputCellProliferativeTypes)
00527 {
00528 cell_types[node_index] = p_model->GetCellProliferativeType();
00529 }
00530 if (this->mOutputCellMutationStates)
00531 {
00532 cell_mutation_states[node_index] = cell_iter->GetMutationState()->GetColour();
00533 }
00534 if (this->mOutputCellAges)
00535 {
00536 cell_ages[node_index] = cell_iter->GetAge();
00537 }
00538 if (this->mOutputCellCyclePhases)
00539 {
00540 cell_cycle_phases[node_index] = p_model->GetCurrentCellCyclePhase();
00541 }
00542 if (CellwiseData<DIM>::Instance()->IsSetUp())
00543 {
00544 CellwiseData<DIM>* p_data = CellwiseData<DIM>::Instance();
00545 for (unsigned var=0; var<p_data->GetNumVariables(); var++)
00546 {
00547 cellwise_data[var][node_index] = p_data->GetValue(*cell_iter, var);
00548 }
00549 }
00550 }
00551
00552 if (this->mOutputCellProliferativeTypes)
00553 {
00554 mesh_writer.AddPointData("Cell types", cell_types);
00555 }
00556 if (this->mOutputCellAncestors)
00557 {
00558 mesh_writer.AddPointData("Ancestors", cell_ancestors);
00559 }
00560 if (this->mOutputCellMutationStates)
00561 {
00562 mesh_writer.AddPointData("Mutation states", cell_mutation_states);
00563 }
00564 if (this->mOutputCellAges)
00565 {
00566 mesh_writer.AddPointData("Ages", cell_ages);
00567 }
00568 if (this->mOutputCellCyclePhases)
00569 {
00570 mesh_writer.AddPointData("Cycle phases", cell_cycle_phases);
00571 }
00572 if (CellwiseData<DIM>::Instance()->IsSetUp())
00573 {
00574 for (unsigned var=0; var<cellwise_data.size(); var++)
00575 {
00576 std::stringstream data_name;
00577 data_name << "Cellwise data " << var;
00578 std::vector<double> cellwise_data_var = cellwise_data[var];
00579 mesh_writer.AddPointData(data_name.str(), cellwise_data_var);
00580 }
00581 }
00582
00583 {
00584
00585 std::vector<Node<DIM>* > nodes;
00586 for (unsigned index=0; index<mrMesh.GetNumNodes(); index++)
00587 {
00588 Node<DIM>* p_node = mrMesh.GetNode(index);
00589 nodes.push_back(p_node);
00590 }
00591
00592 NodesOnlyMesh<DIM> mesh;
00593 mesh.ConstructNodesWithoutMesh(nodes);
00594 mesh_writer.WriteFilesUsingMesh(mesh);
00595 }
00596
00597 *(this->mpVtkMetaFile) << " <DataSet timestep=\"";
00598 *(this->mpVtkMetaFile) << SimulationTime::Instance()->GetTimeStepsElapsed();
00599 *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_";
00600 *(this->mpVtkMetaFile) << SimulationTime::Instance()->GetTimeStepsElapsed();
00601 *(this->mpVtkMetaFile) << ".vtu\"/>\n";
00602 }
00603 else if (mpVoronoiTessellation != NULL)
00604 {
00605 VertexMeshWriter<DIM, DIM> mesh_writer(this->mDirPath, "results", false);
00606 std::vector<double> cell_volumes(num_points);
00607
00608
00609 for (typename VertexMesh<DIM,DIM>::VertexElementIterator elem_iter = mpVoronoiTessellation->GetElementIteratorBegin();
00610 elem_iter != mpVoronoiTessellation->GetElementIteratorEnd();
00611 ++elem_iter)
00612 {
00613
00614 unsigned elem_index = elem_iter->GetIndex();
00615
00616
00617 unsigned node_index = mpVoronoiTessellation->GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(elem_index);
00618
00619
00620 assert(!this->IsGhostNode(node_index));
00621
00622
00623 CellPtr p_cell = this->mLocationCellMap[node_index];
00624
00625
00626 AbstractCellCycleModel* p_model = p_cell->GetCellCycleModel();
00627
00628 if (this->mOutputCellAncestors)
00629 {
00630 double ancestor_index = (p_cell->GetAncestor() == UNSIGNED_UNSET) ? (-1.0) : (double)p_cell->GetAncestor();
00631 cell_ancestors[elem_index] = ancestor_index;
00632 }
00633 if (this->mOutputCellProliferativeTypes)
00634 {
00635 cell_types[elem_index] = p_model->GetCellProliferativeType();
00636 }
00637 if (this->mOutputCellMutationStates)
00638 {
00639 cell_mutation_states[elem_index] = p_cell->GetMutationState()->GetColour();
00640 }
00641 if (this->mOutputCellAges)
00642 {
00643 cell_ages[elem_index] = p_cell->GetAge();
00644 }
00645 if (this->mOutputCellCyclePhases)
00646 {
00647 cell_cycle_phases[elem_index] = p_model->GetCurrentCellCyclePhase();
00648 }
00649 if (this->mOutputCellVolumes)
00650 {
00651 cell_volumes[elem_index] = mpVoronoiTessellation->GetVolumeOfElement(elem_index);
00652 }
00653 if (CellwiseData<DIM>::Instance()->IsSetUp())
00654 {
00655 CellwiseData<DIM>* p_data = CellwiseData<DIM>::Instance();
00656 for (unsigned var=0; var<p_data->GetNumVariables(); var++)
00657 {
00658 cellwise_data[var][elem_index] = p_data->GetValue(p_cell, var);
00659 }
00660 }
00661 }
00662
00663 if (this->mOutputCellProliferativeTypes)
00664 {
00665 mesh_writer.AddCellData("Cell types", cell_types);
00666 }
00667 if (this->mOutputCellAncestors)
00668 {
00669 mesh_writer.AddCellData("Ancestors", cell_ancestors);
00670 }
00671 if (this->mOutputCellMutationStates)
00672 {
00673 mesh_writer.AddCellData("Mutation states", cell_mutation_states);
00674 }
00675 if (this->mOutputCellAges)
00676 {
00677 mesh_writer.AddCellData("Ages", cell_ages);
00678 }
00679 if (this->mOutputCellCyclePhases)
00680 {
00681 mesh_writer.AddCellData("Cycle phases", cell_cycle_phases);
00682 }
00683 if (this->mOutputCellVolumes)
00684 {
00685 mesh_writer.AddCellData("Cell volumes", cell_volumes);
00686 }
00687 if (CellwiseData<DIM>::Instance()->IsSetUp())
00688 {
00689 for (unsigned var=0; var<cellwise_data.size(); var++)
00690 {
00691 std::stringstream data_name;
00692 data_name << "Cellwise data " << var;
00693 std::vector<double> cellwise_data_var = cellwise_data[var];
00694 mesh_writer.AddCellData(data_name.str(), cellwise_data_var);
00695 }
00696 }
00697
00698 mesh_writer.WriteVtkUsingMesh(*mpVoronoiTessellation, time.str());
00699 *(this->mpVtkMetaFile) << " <DataSet timestep=\"";
00700 *(this->mpVtkMetaFile) << SimulationTime::Instance()->GetTimeStepsElapsed();
00701 *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_";
00702 *(this->mpVtkMetaFile) << SimulationTime::Instance()->GetTimeStepsElapsed();
00703 *(this->mpVtkMetaFile) << ".vtu\"/>\n";
00704 }
00705 #endif //CHASTE_VTK
00706 }
00707
00708 template<unsigned DIM>
00709 void MeshBasedCellPopulation<DIM>::WriteVoronoiResultsToFile()
00710 {
00711 assert(DIM==2 || DIM==3);
00712 assert(mpVoronoiTessellation != NULL);
00713
00714 *mpVoronoiFile << SimulationTime::Instance()->GetTime() << " ";
00715
00716
00717 for (typename VertexMesh<DIM,DIM>::VertexElementIterator elem_iter = mpVoronoiTessellation->GetElementIteratorBegin();
00718 elem_iter != mpVoronoiTessellation->GetElementIteratorEnd();
00719 ++elem_iter)
00720 {
00721
00722 unsigned elem_index = elem_iter->GetIndex();
00723
00724
00725 unsigned node_index = mpVoronoiTessellation->GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(elem_index);
00726
00727
00728 *mpVoronoiFile << node_index << " ";
00729 c_vector<double, DIM> node_location = this->GetNode(node_index)->rGetLocation();
00730 for (unsigned i=0; i<DIM; i++)
00731 {
00732 *mpVoronoiFile << node_location[i] << " ";
00733 }
00734
00735 double cell_volume = mpVoronoiTessellation->GetVolumeOfElement(elem_index);
00736 double cell_surface_area = mpVoronoiTessellation->GetSurfaceAreaOfElement(elem_index);
00737 *mpVoronoiFile << cell_volume << " " << cell_surface_area << " ";
00738 }
00739 *mpVoronoiFile << "\n";
00740 }
00741
00742 template<unsigned DIM>
00743 void MeshBasedCellPopulation<DIM>::WriteCellPopulationVolumeResultsToFile()
00744 {
00745 assert(DIM==2 || DIM==3);
00746
00747
00748 *mpCellPopulationVolumesFile << SimulationTime::Instance()->GetTime() << " ";
00749 assert (this->mpVoronoiTessellation != NULL);
00750
00751
00752 double total_area = mrMesh.GetVolume();
00753 double apoptotic_area = 0.0;
00754
00755
00756 for (typename VertexMesh<DIM,DIM>::VertexElementIterator elem_iter = mpVoronoiTessellation->GetElementIteratorBegin();
00757 elem_iter != mpVoronoiTessellation->GetElementIteratorEnd();
00758 ++elem_iter)
00759 {
00760
00761 unsigned elem_index = elem_iter->GetIndex();
00762
00763
00764 unsigned node_index = mpVoronoiTessellation->GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(elem_index);
00765
00766
00767 if (!this->IsGhostNode(node_index))
00768 {
00769
00770 CellPtr p_cell = this->mLocationCellMap[node_index];
00771
00772
00773 bool cell_is_apoptotic = p_cell->HasCellProperty<ApoptoticCellProperty>();
00774 if (cell_is_apoptotic)
00775 {
00776 double cell_volume = mpVoronoiTessellation->GetVolumeOfElement(elem_index);
00777 apoptotic_area += cell_volume;
00778 }
00779 }
00780 }
00781 *mpCellPopulationVolumesFile << total_area << " " << apoptotic_area << "\n";
00782 }
00783
00784 template<unsigned DIM>
00785 void MeshBasedCellPopulation<DIM>::WriteCellVolumeResultsToFile()
00786 {
00787 assert (mpVoronoiTessellation != NULL);
00788 assert(DIM==2 || DIM==3);
00789
00790
00791 *(this->mpCellVolumesFile) << SimulationTime::Instance()->GetTime() << " ";
00792
00793
00794 for (typename VertexMesh<DIM,DIM>::VertexElementIterator elem_iter = mpVoronoiTessellation->GetElementIteratorBegin();
00795 elem_iter != mpVoronoiTessellation->GetElementIteratorEnd();
00796 ++elem_iter)
00797 {
00798
00799 unsigned elem_index = elem_iter->GetIndex();
00800
00801
00802 unsigned node_index = mpVoronoiTessellation->GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(elem_index);
00803
00804
00805 if (!this->IsGhostNode(node_index))
00806 {
00807
00808 *(this->mpCellVolumesFile) << node_index << " ";
00809
00810
00811 CellPtr p_cell = this->mLocationCellMap[node_index];
00812
00813
00814 unsigned cell_index = p_cell->GetCellId();
00815 *(this->mpCellVolumesFile) << cell_index << " ";
00816
00817
00818 c_vector<double, DIM> node_location = this->GetNode(node_index)->rGetLocation();
00819 for (unsigned i=0; i<DIM; i++)
00820 {
00821 *(this->mpCellVolumesFile) << node_location[i] << " ";
00822 }
00823
00824
00825 double cell_volume = mpVoronoiTessellation->GetVolumeOfElement(elem_index);
00826 *(this->mpCellVolumesFile) << cell_volume << " ";
00827 }
00828 }
00829 *(this->mpCellVolumesFile) << "\n";
00830
00831 }
00832
00833 template<unsigned DIM>
00834 void MeshBasedCellPopulation<DIM>::SetWriteVtkAsPoints(bool writeVtkAsPoints)
00835 {
00836 mWriteVtkAsPoints = writeVtkAsPoints;
00837 }
00838
00839 template<unsigned DIM>
00840 bool MeshBasedCellPopulation<DIM>::GetWriteVtkAsPoints()
00841 {
00842 return mWriteVtkAsPoints;
00843 }
00844
00846
00848
00849 template<unsigned DIM>
00850 Node<DIM>* MeshBasedCellPopulation<DIM>::SpringIterator::GetNodeA()
00851 {
00852 return mEdgeIter.GetNodeA();
00853 }
00854
00855 template<unsigned DIM>
00856 Node<DIM>* MeshBasedCellPopulation<DIM>::SpringIterator::GetNodeB()
00857 {
00858 return mEdgeIter.GetNodeB();
00859 }
00860
00861 template<unsigned DIM>
00862 CellPtr MeshBasedCellPopulation<DIM>::SpringIterator::GetCellA()
00863 {
00864 assert((*this) != mrCellPopulation.SpringsEnd());
00865 return mrCellPopulation.GetCellUsingLocationIndex(mEdgeIter.GetNodeA()->GetIndex());
00866 }
00867
00868 template<unsigned DIM>
00869 CellPtr MeshBasedCellPopulation<DIM>::SpringIterator::GetCellB()
00870 {
00871 assert((*this) != mrCellPopulation.SpringsEnd());
00872 return mrCellPopulation.GetCellUsingLocationIndex(mEdgeIter.GetNodeB()->GetIndex());
00873 }
00874
00875 template<unsigned DIM>
00876 bool MeshBasedCellPopulation<DIM>::SpringIterator::operator!=(const MeshBasedCellPopulation<DIM>::SpringIterator& rOther)
00877 {
00878 return (mEdgeIter != rOther.mEdgeIter);
00879 }
00880
00881 template<unsigned DIM>
00882 typename MeshBasedCellPopulation<DIM>::SpringIterator& MeshBasedCellPopulation<DIM>::SpringIterator::operator++()
00883 {
00884 bool edge_is_ghost = false;
00885
00886 do
00887 {
00888 ++mEdgeIter;
00889 if (*this != mrCellPopulation.SpringsEnd())
00890 {
00891 bool a_is_ghost = mrCellPopulation.IsGhostNode(mEdgeIter.GetNodeA()->GetIndex());
00892 bool b_is_ghost = mrCellPopulation.IsGhostNode(mEdgeIter.GetNodeB()->GetIndex());
00893
00894 edge_is_ghost = (a_is_ghost || b_is_ghost);
00895 }
00896 }
00897 while (*this!=mrCellPopulation.SpringsEnd() && edge_is_ghost);
00898
00899 return (*this);
00900 }
00901
00902 template<unsigned DIM>
00903 MeshBasedCellPopulation<DIM>::SpringIterator::SpringIterator(
00904 MeshBasedCellPopulation<DIM>& rCellPopulation,
00905 typename MutableMesh<DIM,DIM>::EdgeIterator edgeIter)
00906 : mrCellPopulation(rCellPopulation),
00907 mEdgeIter(edgeIter)
00908 {
00909 if (mEdgeIter!=mrCellPopulation.mrMesh.EdgesEnd())
00910 {
00911 bool a_is_ghost = mrCellPopulation.IsGhostNode(mEdgeIter.GetNodeA()->GetIndex());
00912 bool b_is_ghost = mrCellPopulation.IsGhostNode(mEdgeIter.GetNodeB()->GetIndex());
00913
00914 if (a_is_ghost || b_is_ghost)
00915 {
00916 ++(*this);
00917 }
00918 }
00919 }
00920
00921 template<unsigned DIM>
00922 typename MeshBasedCellPopulation<DIM>::SpringIterator MeshBasedCellPopulation<DIM>::SpringsBegin()
00923 {
00924 return SpringIterator(*this, mrMesh.EdgesBegin());
00925 }
00926
00927 template<unsigned DIM>
00928 typename MeshBasedCellPopulation<DIM>::SpringIterator MeshBasedCellPopulation<DIM>::SpringsEnd()
00929 {
00930 return SpringIterator(*this, mrMesh.EdgesEnd());
00931 }
00932
00936 template<>
00937 void MeshBasedCellPopulation<2>::CreateVoronoiTessellation()
00938 {
00939 delete mpVoronoiTessellation;
00940
00941
00942 bool is_mesh_periodic = false;
00943 if (dynamic_cast<Cylindrical2dMesh*>(&mrMesh))
00944 {
00945 is_mesh_periodic = true;
00946 }
00947
00948 mpVoronoiTessellation = new VertexMesh<2, 2>(mrMesh, is_mesh_periodic);
00949 }
00950
00956 template<>
00957 void MeshBasedCellPopulation<3>::CreateVoronoiTessellation()
00958 {
00959 delete mpVoronoiTessellation;
00960 mpVoronoiTessellation = new VertexMesh<3, 3>(mrMesh);
00961 }
00962
00967 template<>
00968 void MeshBasedCellPopulation<1>::CreateVoronoiTessellation()
00969 {
00970
00971 NEVER_REACHED;
00972 }
00973
00974 template<unsigned DIM>
00975 VertexMesh<DIM, DIM>* MeshBasedCellPopulation<DIM>::GetVoronoiTessellation()
00976 {
00977 assert(mpVoronoiTessellation!=NULL);
00978 return mpVoronoiTessellation;
00979 }
00980
00981 template<unsigned DIM>
00982 double MeshBasedCellPopulation<DIM>::GetVolumeOfVoronoiElement(unsigned index)
00983 {
00984 unsigned element_index = mpVoronoiTessellation->GetVoronoiElementIndexCorrespondingToDelaunayNodeIndex(index);
00985 double volume = mpVoronoiTessellation->GetVolumeOfElement(element_index);
00986 return volume;
00987 }
00988
00989 template<unsigned DIM>
00990 double MeshBasedCellPopulation<DIM>::GetSurfaceAreaOfVoronoiElement(unsigned index)
00991 {
00992 unsigned element_index = mpVoronoiTessellation->GetVoronoiElementIndexCorrespondingToDelaunayNodeIndex(index);
00993 double surface_area = mpVoronoiTessellation->GetSurfaceAreaOfElement(element_index);
00994 return surface_area;
00995 }
00996
00997 template<unsigned DIM>
00998 double MeshBasedCellPopulation<DIM>::GetVoronoiEdgeLength(unsigned index1, unsigned index2)
00999 {
01000 unsigned element_index1 = mpVoronoiTessellation->GetVoronoiElementIndexCorrespondingToDelaunayNodeIndex(index1);
01001 unsigned element_index2 = mpVoronoiTessellation->GetVoronoiElementIndexCorrespondingToDelaunayNodeIndex(index2);
01002 try
01003 {
01004 double edge_length = mpVoronoiTessellation->GetEdgeLength(element_index1, element_index2);
01005 return edge_length;
01006 }
01007 catch (Exception& e)
01008 {
01009
01010 EXCEPTION("Spring iterator tried to calculate interaction between degenerate cells on the boundary of the mesh. Have you set ghost layers correctly?");
01011 }
01012 }
01013
01014 template<unsigned DIM>
01015 void MeshBasedCellPopulation<DIM>::CheckCellPointers()
01016 {
01017 bool res = true;
01018 for (std::list<CellPtr>::iterator it=this->mCells.begin();
01019 it!=this->mCells.end();
01020 ++it)
01021 {
01022 CellPtr p_cell = *it;
01023 assert(p_cell);
01024 AbstractCellCycleModel* p_model = p_cell->GetCellCycleModel();
01025 assert(p_model);
01026
01027
01028 unsigned node_index = this->mCellLocationMap[p_cell.get()];
01029 std::cout << "Cell at node " << node_index << " addr " << p_cell << std::endl << std::flush;
01030 CellPtr p_cell_in_cell_population = this->GetCellUsingLocationIndex(node_index);
01031 #define COVERAGE_IGNORE //Debugging code. Shouldn't fail under normal conditions
01032 if (p_cell_in_cell_population != p_cell)
01033 {
01034 std::cout << " Mismatch with cell population" << std::endl << std::flush;
01035 res = false;
01036 }
01037
01038
01039 if (p_model->GetCell() != p_cell)
01040 {
01041 std::cout << " Mismatch with cycle model" << std::endl << std::flush;
01042 res = false;
01043 }
01044 }
01045 assert(res);
01046 #undef COVERAGE_IGNORE
01047
01048 res = true;
01049 for (std::set<std::pair<CellPtr,CellPtr> >::iterator it1 = mMarkedSprings.begin();
01050 it1 != mMarkedSprings.end();
01051 ++it1)
01052 {
01053 const std::pair<CellPtr,CellPtr>& r_pair = *it1;
01054
01055 for (unsigned i=0; i<2; i++)
01056 {
01057 CellPtr p_cell = (i==0 ? r_pair.first : r_pair.second);
01058
01059 assert(p_cell);
01060 AbstractCellCycleModel* p_model = p_cell->GetCellCycleModel();
01061 assert(p_model);
01062 unsigned node_index = this->mCellLocationMap[p_cell.get()];
01063 std::cout << "Cell at node " << node_index << " addr " << p_cell << std::endl << std::flush;
01064
01065 #define COVERAGE_IGNORE //Debugging code. Shouldn't fail under normal conditions
01066
01067 if (p_cell->IsDead())
01068 {
01069 std::cout << " Cell is dead" << std::endl << std::flush;
01070 res = false;
01071 }
01072
01073
01074 CellPtr p_cell_in_cell_population = this->GetCellUsingLocationIndex(node_index);
01075 if (p_cell_in_cell_population != p_cell)
01076 {
01077 std::cout << " Mismatch with cell population" << std::endl << std::flush;
01078 res = false;
01079 }
01080
01081
01082 if (p_model->GetCell() != p_cell)
01083 {
01084 std::cout << " Mismatch with cycle model" << std::endl << std::flush;
01085 res = false;
01086 }
01087 }
01088 #undef COVERAGE_IGNORE
01089 }
01090 assert(res);
01091 }
01092
01093 template<unsigned DIM>
01094 std::pair<CellPtr,CellPtr> MeshBasedCellPopulation<DIM>::CreateCellPair(CellPtr pCell1, CellPtr pCell2)
01095 {
01096 assert(pCell1);
01097 assert(pCell2);
01098
01099 std::pair<CellPtr,CellPtr> cell_pair;
01100
01101 if (pCell1->GetCellId() < pCell2->GetCellId())
01102 {
01103 cell_pair.first = pCell1;
01104 cell_pair.second = pCell2;
01105 }
01106 else
01107 {
01108 cell_pair.first = pCell2;
01109 cell_pair.second = pCell1;
01110 }
01111 return cell_pair;
01112 }
01113
01114 template<unsigned DIM>
01115 bool MeshBasedCellPopulation<DIM>::IsMarkedSpring(const std::pair<CellPtr,CellPtr>& rCellPair)
01116 {
01117
01118 assert(rCellPair.first->GetCellId() < rCellPair.second->GetCellId());
01119
01120 return mMarkedSprings.find(rCellPair) != mMarkedSprings.end();
01121 }
01122
01123 template<unsigned DIM>
01124 void MeshBasedCellPopulation<DIM>::MarkSpring(std::pair<CellPtr,CellPtr>& rCellPair)
01125 {
01126
01127 assert(rCellPair.first->GetCellId() < rCellPair.second->GetCellId());
01128
01129 mMarkedSprings.insert(rCellPair);
01130 }
01131
01132 template<unsigned DIM>
01133 void MeshBasedCellPopulation<DIM>::UnmarkSpring(std::pair<CellPtr,CellPtr>& rCellPair)
01134 {
01135
01136 assert(rCellPair.first->GetCellId() < rCellPair.second->GetCellId());
01137
01138 mMarkedSprings.erase(rCellPair);
01139 }
01140
01141 template<unsigned DIM>
01142 double MeshBasedCellPopulation<DIM>::GetAreaBasedDampingConstantParameter()
01143 {
01144 return mAreaBasedDampingConstantParameter;
01145 }
01146
01147 template<unsigned DIM>
01148 void MeshBasedCellPopulation<DIM>::SetAreaBasedDampingConstantParameter(double areaBasedDampingConstantParameter)
01149 {
01150 assert(areaBasedDampingConstantParameter >= 0.0);
01151 mAreaBasedDampingConstantParameter = areaBasedDampingConstantParameter;
01152 }
01153
01154 template<unsigned DIM>
01155 bool MeshBasedCellPopulation<DIM>::GetOutputVoronoiData()
01156 {
01157 return mOutputVoronoiData;
01158 }
01159
01160 template<unsigned DIM>
01161 void MeshBasedCellPopulation<DIM>::SetOutputVoronoiData(bool outputVoronoiData)
01162 {
01163 mOutputVoronoiData = outputVoronoiData;
01164 }
01165
01166 template<unsigned DIM>
01167 bool MeshBasedCellPopulation<DIM>::GetOutputCellPopulationVolumes()
01168 {
01169 return mOutputCellPopulationVolumes;
01170 }
01171
01172 template<unsigned DIM>
01173 void MeshBasedCellPopulation<DIM>::SetOutputCellPopulationVolumes(bool outputCellPopulationVolumes)
01174 {
01175 mOutputCellPopulationVolumes = outputCellPopulationVolumes;
01176 }
01177
01178 template<unsigned DIM>
01179 void MeshBasedCellPopulation<DIM>::OutputCellPopulationParameters(out_stream& rParamsFile)
01180 {
01181 *rParamsFile << "\t\t<UseAreaBasedDampingConstant>" << mUseAreaBasedDampingConstant << "</UseAreaBasedDampingConstant>\n";
01182 *rParamsFile << "\t\t<AreaBasedDampingConstantParameter>" << mAreaBasedDampingConstantParameter << "</AreaBasedDampingConstantParameter>\n";
01183 *rParamsFile << "\t\t<OutputVoronoiData>" << mOutputVoronoiData << "</OutputVoronoiData>\n";
01184 *rParamsFile << "\t\t<OutputCellPopulationVolumes>" << mOutputCellPopulationVolumes << "</OutputCellPopulationVolumes>\n";
01185
01186
01187 AbstractCentreBasedCellPopulation<DIM>::OutputCellPopulationParameters(rParamsFile);
01188 }
01189
01190 template<unsigned DIM>
01191 double MeshBasedCellPopulation<DIM>::GetWidth(const unsigned& rDimension)
01192 {
01193
01194 double width = mrMesh.GetWidth(rDimension);
01195 return width;
01196 }
01197
01198 template<unsigned DIM>
01199 std::set<unsigned> MeshBasedCellPopulation<DIM>::GetNeighbouringNodeIndices(unsigned index)
01200 {
01201
01202 Node<DIM>* p_node = mrMesh.GetNode(index);
01203
01204
01205 std::set<unsigned> neighbouring_node_indices;
01206 for (typename Node<DIM>::ContainingElementIterator elem_iter = p_node->ContainingElementsBegin();
01207 elem_iter != p_node->ContainingElementsEnd();
01208 ++elem_iter)
01209 {
01210
01211 Element<DIM,DIM>* p_element = mrMesh.GetElement(*elem_iter);
01212
01213
01214 for (unsigned i=0; i<p_element->GetNumNodes(); i++)
01215 {
01216
01217 unsigned node_index = p_element->GetNodeGlobalIndex(i);
01218 if (node_index != index)
01219 {
01220 neighbouring_node_indices.insert(node_index);
01221 }
01222 }
01223 }
01224 return neighbouring_node_indices;
01225 }
01226
01228
01230
01231 template class MeshBasedCellPopulation<1>;
01232 template class MeshBasedCellPopulation<2>;
01233 template class MeshBasedCellPopulation<3>;
01234
01235
01236 #include "SerializationExportWrapperForCpp.hpp"
01237 EXPORT_TEMPLATE_CLASS_SAME_DIMS(MeshBasedCellPopulation)