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