MeshBasedCellPopulation.cpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2011
00004 
00005 University of Oxford means the Chancellor, Masters and Scholars of the
00006 University of Oxford, having an administrative office at Wellington
00007 Square, Oxford OX1 2JD, UK.
00008 
00009 This file is part of Chaste.
00010 
00011 Chaste is free software: you can redistribute it and/or modify it
00012 under the terms of the GNU Lesser General Public License as published
00013 by the Free Software Foundation, either version 2.1 of the License, or
00014 (at your option) any later version.
00015 
00016 Chaste is distributed in the hope that it will be useful, but WITHOUT
00017 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
00019 License for more details. The offer of Chaste under the terms of the
00020 License is subject to the License being interpreted in accordance with
00021 English Law and subject to any action against the University of Oxford
00022 being under the jurisdiction of the English Courts.
00023 
00024 You should have received a copy of the GNU Lesser General Public License
00025 along with Chaste. If not, see <http://www.gnu.org/licenses/>.
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 
00037 template<unsigned DIM>
00038 MeshBasedCellPopulation<DIM>::MeshBasedCellPopulation(MutableMesh<DIM, DIM>& rMesh,
00039                                       std::vector<CellPtr>& rCells,
00040                                       const std::vector<unsigned> locationIndices,
00041                                       bool deleteMesh,
00042                                       bool validate)
00043     : AbstractCentreBasedCellPopulation<DIM>(rCells, locationIndices),
00044       mrMesh(rMesh),
00045       mpVoronoiTessellation(NULL),
00046       mDeleteMesh(deleteMesh),
00047       mUseAreaBasedDampingConstant(false),
00048       mAreaBasedDampingConstantParameter(0.1),
00049       mOutputVoronoiData(false),
00050       mOutputCellPopulationVolumes(false),
00051       mWriteVtkAsPoints(false)
00052 {
00053     // This must always be true
00054     assert(this->mCells.size() <= mrMesh.GetNumNodes());
00055 
00056     this->mCellPopulationContainsMesh = true;
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     this->mCellPopulationContainsMesh = true;
00069     mpVoronoiTessellation = NULL;
00070     mDeleteMesh = true;
00071 }
00072 
00073 template<unsigned DIM>
00074 MeshBasedCellPopulation<DIM>::~MeshBasedCellPopulation()
00075 {
00076     delete mpVoronoiTessellation;
00077 
00078     if (mDeleteMesh)
00079     {
00080         delete &mrMesh;
00081     }
00082 }
00083 
00084 template<unsigned DIM>
00085 bool MeshBasedCellPopulation<DIM>::UseAreaBasedDampingConstant()
00086 {
00087     return mUseAreaBasedDampingConstant;
00088 }
00089 
00090 template<unsigned DIM>
00091 void MeshBasedCellPopulation<DIM>::SetAreaBasedDampingConstant(bool useAreaBasedDampingConstant)
00092 {
00093     assert(DIM==2);
00094     mUseAreaBasedDampingConstant = useAreaBasedDampingConstant;
00095 }
00096 
00097 template<unsigned DIM>
00098 unsigned MeshBasedCellPopulation<DIM>::AddNode(Node<DIM>* pNewNode)
00099 {
00100     return mrMesh.AddNode(pNewNode);
00101 }
00102 
00103 template<unsigned DIM>
00104 void MeshBasedCellPopulation<DIM>::SetNode(unsigned nodeIndex, ChastePoint<DIM>& rNewLocation)
00105 {
00106     mrMesh.SetNode(nodeIndex, rNewLocation, false);
00107 }
00108 
00109 template<unsigned DIM>
00110 double MeshBasedCellPopulation<DIM>::GetDampingConstant(unsigned nodeIndex)
00111 {
00112     double damping_multiplier = AbstractCentreBasedCellPopulation<DIM>::GetDampingConstant(nodeIndex);
00113 
00114     if (mUseAreaBasedDampingConstant)
00115     {
00125         assert(DIM==2);
00126 
00127         double rest_length = 1.0;
00128         double d0 = mAreaBasedDampingConstantParameter;
00129 
00135         double d1 = 2.0*(1.0 - d0)/(sqrt(3)*rest_length*rest_length);
00136 
00137         double area_cell = GetVolumeOfVoronoiElement(nodeIndex);
00138 
00144         assert(area_cell < 1000);
00145 
00146         damping_multiplier = d0 + area_cell*d1;
00147     }
00148 
00149     return damping_multiplier;
00150 }
00151 
00152 template<unsigned DIM>
00153 void MeshBasedCellPopulation<DIM>::Validate()
00154 {
00155     std::vector<bool> validated_node = std::vector<bool>(this->GetNumNodes(), false);
00156 
00157     for (typename AbstractCellPopulation<DIM>::Iterator cell_iter=this->Begin(); cell_iter!=this->End(); ++cell_iter)
00158     {
00159         unsigned node_index = GetLocationIndexUsingCell(*cell_iter);
00160         validated_node[node_index] = true;
00161     }
00162 
00163     for (unsigned i=0; i<validated_node.size(); i++)
00164     {
00165         if (!validated_node[i])
00166         {
00167             std::stringstream ss;
00168             ss << "Node " << i << " does not appear to have a cell associated with it";
00169             EXCEPTION(ss.str());
00170         }
00171     }
00172 }
00173 
00174 template<unsigned DIM>
00175 MutableMesh<DIM, DIM>& MeshBasedCellPopulation<DIM>::rGetMesh()
00176 {
00177     return mrMesh;
00178 }
00179 
00180 template<unsigned DIM>
00181 const MutableMesh<DIM, DIM>& MeshBasedCellPopulation<DIM>::rGetMesh() const
00182 {
00183     return mrMesh;
00184 }
00185 
00186 template<unsigned DIM>
00187 unsigned MeshBasedCellPopulation<DIM>::RemoveDeadCells()
00188 {
00189     unsigned num_removed = 0;
00190     for (std::list<CellPtr>::iterator it = this->mCells.begin();
00191          it != this->mCells.end();
00192          ++it)
00193     {
00194         if ((*it)->IsDead())
00195         {
00196             // Check if this cell is in a marked spring
00197             std::vector<const std::pair<CellPtr,CellPtr>*> pairs_to_remove; // Pairs that must be purged
00198             for (std::set<std::pair<CellPtr,CellPtr> >::iterator it1 = mMarkedSprings.begin();
00199                  it1 != mMarkedSprings.end();
00200                  ++it1)
00201             {
00202                 const std::pair<CellPtr,CellPtr>& r_pair = *it1;
00203 
00204                 for (unsigned i=0; i<2; i++)
00205                 {
00206                     CellPtr p_cell = (i==0 ? r_pair.first : r_pair.second);
00207 
00208                     if (p_cell == *it)
00209                     {
00210                         // Remember to purge this spring
00211                         pairs_to_remove.push_back(&r_pair);
00212                         break;
00213                     }
00214                 }
00215             }
00216 
00217             // Purge any marked springs that contained this cell
00218             for (std::vector<const std::pair<CellPtr,CellPtr>* >::iterator pair_it = pairs_to_remove.begin();
00219                  pair_it != pairs_to_remove.end();
00220                  ++pair_it)
00221             {
00222                 mMarkedSprings.erase(**pair_it);
00223             }
00224 
00225             // Remove the node from the mesh
00226             num_removed++;
00227             mrMesh.DeleteNodePriorToReMesh(this->mCellLocationMap[(*it).get()]);
00228 
00229             // Update mappings between cells and location indices
00230             unsigned location_index_of_removed_node = this->mCellLocationMap[(*it).get()];
00231             this->mCellLocationMap.erase((*it).get());
00232             this->mLocationCellMap.erase(location_index_of_removed_node);
00233 
00234             // Update vector of cells
00235             it = this->mCells.erase(it);
00236             --it;
00237         }
00238     }
00239 
00240     return num_removed;
00241 }
00242 
00243 
00244 template<unsigned DIM>
00245 void MeshBasedCellPopulation<DIM>::Update(bool hasHadBirthsOrDeaths)
00246 {
00247     NodeMap map(mrMesh.GetNumAllNodes());
00248     mrMesh.ReMesh(map);
00249 
00250     if (!map.IsIdentityMap())
00251     {
00252         UpdateGhostNodesAfterReMesh(map);
00253 
00254         // Update the mappings between cells and location indices
00255         std::map<Cell*, unsigned> old_map = this->mCellLocationMap;
00256 
00257         // Remove any dead pointers from the maps (needed to avoid archiving errors)
00258         this->mLocationCellMap.clear();
00259         this->mCellLocationMap.clear();
00260 
00261         for (std::list<CellPtr>::iterator it = this->mCells.begin();
00262              it != this->mCells.end();
00263              ++it)
00264         {
00265             unsigned old_node_index = old_map[(*it).get()];
00266 
00267             // This shouldn't ever happen, as the cell vector only contains living cells
00268             assert(!map.IsDeleted(old_node_index));
00269 
00270             unsigned new_node_index = map.GetNewIndex(old_node_index);
00271             this->mLocationCellMap[new_node_index] = *it;
00272             this->mCellLocationMap[(*it).get()] = new_node_index;
00273         }
00274 
00275         this->Validate();
00276     }
00277 
00278     // Purge any marked springs that are no longer springs
00279     std::vector<const std::pair<CellPtr,CellPtr>*> springs_to_remove;
00280     for (std::set<std::pair<CellPtr,CellPtr> >::iterator spring_it = mMarkedSprings.begin();
00281          spring_it != mMarkedSprings.end();
00282          ++spring_it)
00283     {
00284         CellPtr p_cell_1 = spring_it->first;
00285         CellPtr p_cell_2 = spring_it->second;
00286         Node<DIM>* p_node_1 = this->GetNodeCorrespondingToCell(p_cell_1);
00287         Node<DIM>* p_node_2 = this->GetNodeCorrespondingToCell(p_cell_2);
00288 
00289         bool joined = false;
00290 
00291         // For each element containing node1, if it also contains node2 then the cells are joined
00292         std::set<unsigned> node2_elements = p_node_2->rGetContainingElementIndices();
00293         for (typename Node<DIM>::ContainingElementIterator elem_iter = p_node_1->ContainingElementsBegin();
00294              elem_iter != p_node_1->ContainingElementsEnd();
00295              ++elem_iter)
00296         {
00297             if (node2_elements.find(*elem_iter) != node2_elements.end())
00298             {
00299                 joined = true;
00300                 break;
00301             }
00302         }
00303 
00304         // If no longer joined, remove this spring from the set
00305         if (!joined)
00306         {
00307             springs_to_remove.push_back(&(*spring_it));
00308         }
00309     }
00310 
00311     // Remove any springs necessary
00312     for (std::vector<const std::pair<CellPtr,CellPtr>* >::iterator spring_it = springs_to_remove.begin();
00313          spring_it != springs_to_remove.end();
00314          ++spring_it)
00315     {
00316         mMarkedSprings.erase(**spring_it);
00317     }
00318 
00319     // Tessellate if needed
00320     if (DIM==2 || DIM==3)
00321     {
00322         CellBasedEventHandler::BeginEvent(CellBasedEventHandler::TESSELLATION);
00323         if (mUseAreaBasedDampingConstant || mOutputVoronoiData || mOutputCellPopulationVolumes || this->mOutputCellVolumes)
00324         {
00325             CreateVoronoiTessellation();
00326         }
00327         CellBasedEventHandler::EndEvent(CellBasedEventHandler::TESSELLATION);
00328     }
00329 
00330     mrMesh.SetMeshHasChangedSinceLoading();
00331 }
00332 
00333 template<unsigned DIM>
00334 Node<DIM>* MeshBasedCellPopulation<DIM>::GetNode(unsigned index)
00335 {
00336     return mrMesh.GetNode(index);
00337 }
00338 
00339 template<unsigned DIM>
00340 unsigned MeshBasedCellPopulation<DIM>::GetNumNodes()
00341 {
00342     return mrMesh.GetNumAllNodes();
00343 }
00344 
00345 template<unsigned DIM>
00346 void MeshBasedCellPopulation<DIM>::UpdateGhostNodesAfterReMesh(NodeMap& rMap)
00347 {
00348 }
00349 
00350 template<unsigned DIM>
00351 CellPtr MeshBasedCellPopulation<DIM>::AddCell(CellPtr pNewCell, const c_vector<double,DIM>& rCellDivisionVector, CellPtr pParentCell)
00352 {
00353     assert(pNewCell);
00354     assert(pParentCell);
00355 
00356     // Add new cell to cell population
00357     CellPtr p_created_cell = AbstractCentreBasedCellPopulation<DIM>::AddCell(pNewCell, rCellDivisionVector, pParentCell);
00358     assert(p_created_cell == pNewCell);
00359 
00360     // Mark spring between parent cell and new cell
00361     std::pair<CellPtr,CellPtr> cell_pair = CreateCellPair(pParentCell, p_created_cell);
00362     MarkSpring(cell_pair);
00363 
00364     // Return pointer to new cell
00365     return p_created_cell;
00366 }
00367 
00369 //                             Output methods                               //
00371 
00372 template<unsigned DIM>
00373 void MeshBasedCellPopulation<DIM>::CreateOutputFiles(const std::string& rDirectory, bool cleanOutputDirectory)
00374 {
00375     AbstractCentreBasedCellPopulation<DIM>::CreateOutputFiles(rDirectory, cleanOutputDirectory);
00376 
00377     OutputFileHandler output_file_handler(rDirectory, cleanOutputDirectory);
00378     mpVizElementsFile = output_file_handler.OpenOutputFile("results.vizelements");
00379 
00380     if (mOutputVoronoiData)
00381     {
00382         mpVoronoiFile = output_file_handler.OpenOutputFile("voronoi.dat");
00383     }
00384     if (mOutputCellPopulationVolumes)
00385     {
00386         mpCellPopulationVolumesFile = output_file_handler.OpenOutputFile("cellpopulationareas.dat");
00387     }
00388     if (this->mOutputCellVolumes)
00389     {
00390         mpCellVolumesFile = output_file_handler.OpenOutputFile("cellareas.dat");
00391     }
00392 }
00393 
00394 template<unsigned DIM>
00395 void MeshBasedCellPopulation<DIM>::CloseOutputFiles()
00396 {
00397     AbstractCentreBasedCellPopulation<DIM>::CloseOutputFiles();
00398 
00399     mpVizElementsFile->close();
00400 
00401     if (mOutputVoronoiData)
00402     {
00403         mpVoronoiFile->close();
00404     }
00405     if (mOutputCellPopulationVolumes)
00406     {
00407         mpCellPopulationVolumesFile->close();
00408     }
00409     if (this->mOutputCellVolumes)
00410     {
00411         mpCellVolumesFile->close();
00412     }
00413 }
00414 
00415 template<unsigned DIM>
00416 void MeshBasedCellPopulation<DIM>::WriteResultsToFiles()
00417 {
00418     AbstractCentreBasedCellPopulation<DIM>::WriteResultsToFiles();
00419 
00420     // Write element data to file
00421     *mpVizElementsFile << SimulationTime::Instance()->GetTime() << "\t";
00422 
00423     for (typename MutableMesh<DIM,DIM>::ElementIterator elem_iter = mrMesh.GetElementIteratorBegin();
00424          elem_iter != mrMesh.GetElementIteratorEnd();
00425          ++elem_iter)
00426     {
00427         bool element_contains_dead_cells_or_deleted_nodes = false;
00428 
00429         // Hack that covers the case where the element contains a node that is associated with a cell that has just been killed (#1129)
00430         for (unsigned i=0; i<DIM+1; i++)
00431         {
00432             unsigned node_index = elem_iter->GetNodeGlobalIndex(i);
00433 
00434             if (this->GetNode(node_index)->IsDeleted())
00435             {
00436                 element_contains_dead_cells_or_deleted_nodes = true;
00437                 break;
00438             }
00439             else if (this->mLocationCellMap[node_index])
00440             {
00441                 if (this->mLocationCellMap[node_index]->IsDead())
00442                 {
00443                     element_contains_dead_cells_or_deleted_nodes = true;
00444                     break;
00445                 }
00446             }
00447         }
00448         if (!element_contains_dead_cells_or_deleted_nodes)
00449         {
00450             for (unsigned i=0; i<DIM+1; i++)
00451             {
00452                 *mpVizElementsFile << elem_iter->GetNodeGlobalIndex(i) << " ";
00453             }
00454         }
00455     }
00456     *mpVizElementsFile << "\n";
00457 
00458     if (mpVoronoiTessellation != NULL)
00459     {
00460         if (mOutputVoronoiData)
00461         {
00462             WriteVoronoiResultsToFile();
00463         }
00464         if (mOutputCellPopulationVolumes)
00465         {
00466             WriteCellPopulationVolumeResultsToFile();
00467         }
00468         if (this->mOutputCellVolumes)
00469         {
00470             WriteCellVolumeResultsToFile();
00471         }
00472     }
00473 }
00474 
00475 template<unsigned DIM>
00476 void MeshBasedCellPopulation<DIM>::WriteVtkResultsToFile()
00477 {
00478 #ifdef CHASTE_VTK
00479     // Write time to file
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         // Loop over cells
00511         for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->Begin();
00512              cell_iter != this->End();
00513              ++cell_iter)
00514         {
00515             // Get the node index corresponding to this cell
00516             unsigned node_index = this->GetLocationIndexUsingCell(*cell_iter);
00517     
00518             // Get this cell-cycle model
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             // Make a copy of the nodes in a disposable mesh for writing
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             TetrahedralMesh<DIM,DIM> mesh;
00592             mesh.ConstructNodesWithoutMesh(nodes);
00593             mesh_writer.WriteFilesUsingMesh(mesh);
00594         }
00595 
00596         *(this->mpVtkMetaFile) << "        <DataSet timestep=\"";
00597         *(this->mpVtkMetaFile) << SimulationTime::Instance()->GetTimeStepsElapsed();
00598         *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_";
00599         *(this->mpVtkMetaFile) << SimulationTime::Instance()->GetTimeStepsElapsed();
00600         *(this->mpVtkMetaFile) << ".vtu\"/>\n";
00601     }
00602     else if (mpVoronoiTessellation != NULL)
00603     {
00604         VertexMeshWriter<DIM, DIM> mesh_writer(this->mDirPath, "results", false);
00605         std::vector<double> cell_volumes(num_points);
00606     
00607         // Loop over elements of mpVoronoiTessellation
00608         for (typename VertexMesh<DIM,DIM>::VertexElementIterator elem_iter = mpVoronoiTessellation->GetElementIteratorBegin();
00609              elem_iter != mpVoronoiTessellation->GetElementIteratorEnd();
00610              ++elem_iter)
00611         {
00612             // Get index of this element in mpVoronoiTessellation
00613             unsigned elem_index = elem_iter->GetIndex();
00614     
00615             // Get the index of the corresponding node in mrMesh
00616             unsigned node_index = mpVoronoiTessellation->GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(elem_index);
00617     
00618             // There should be no ghost nodes
00619             assert(!this->IsGhostNode(node_index));
00620     
00621             // Get the cell corresponding to this element
00622             CellPtr p_cell = this->mLocationCellMap[node_index];
00623 
00624             // Get this cell-cycle model
00625             AbstractCellCycleModel* p_model = p_cell->GetCellCycleModel();
00626     
00627             if (this->mOutputCellAncestors)
00628             {
00629                 double ancestor_index = (p_cell->GetAncestor() == UNSIGNED_UNSET) ? (-1.0) : (double)p_cell->GetAncestor();
00630                 cell_ancestors[elem_index] = ancestor_index;
00631             }
00632             if (this->mOutputCellProliferativeTypes)
00633             {
00634                 cell_types[elem_index] = p_model->GetCellProliferativeType();
00635             }
00636             if (this->mOutputCellMutationStates)
00637             {
00638                 cell_mutation_states[elem_index] = p_cell->GetMutationState()->GetColour();
00639             }
00640             if (this->mOutputCellAges)
00641             {
00642                 cell_ages[elem_index] = p_cell->GetAge();
00643             }
00644             if (this->mOutputCellCyclePhases)
00645             {
00646                 cell_cycle_phases[elem_index] = p_model->GetCurrentCellCyclePhase();
00647             }
00648             if (this->mOutputCellVolumes)
00649             {
00650                 cell_volumes[elem_index] = mpVoronoiTessellation->GetVolumeOfElement(elem_index);
00651             }
00652             if (CellwiseData<DIM>::Instance()->IsSetUp())
00653             {
00654                 CellwiseData<DIM>* p_data = CellwiseData<DIM>::Instance();
00655                 for (unsigned var=0; var<p_data->GetNumVariables(); var++)
00656                 {
00657                     cellwise_data[var][elem_index] = p_data->GetValue(p_cell, var);
00658                 }
00659             }
00660         }
00661     
00662         if (this->mOutputCellProliferativeTypes)
00663         {
00664             mesh_writer.AddCellData("Cell types", cell_types);
00665         }
00666         if (this->mOutputCellAncestors)
00667         {
00668             mesh_writer.AddCellData("Ancestors", cell_ancestors);
00669         }
00670         if (this->mOutputCellMutationStates)
00671         {
00672             mesh_writer.AddCellData("Mutation states", cell_mutation_states);
00673         }
00674         if (this->mOutputCellAges)
00675         {
00676             mesh_writer.AddCellData("Ages", cell_ages);
00677         }
00678         if (this->mOutputCellCyclePhases)
00679         {
00680             mesh_writer.AddCellData("Cycle phases", cell_cycle_phases);
00681         }
00682         if (this->mOutputCellVolumes)
00683         {
00684             mesh_writer.AddCellData("Cell volumes", cell_volumes);
00685         }
00686         if (CellwiseData<DIM>::Instance()->IsSetUp())
00687         {
00688             for (unsigned var=0; var<cellwise_data.size(); var++)
00689             {
00690                 std::stringstream data_name;
00691                 data_name << "Cellwise data " << var;
00692                 std::vector<double> cellwise_data_var = cellwise_data[var];
00693                 mesh_writer.AddCellData(data_name.str(), cellwise_data_var);
00694             }
00695         }
00696     
00697         mesh_writer.WriteVtkUsingMesh(*mpVoronoiTessellation, time.str());
00698         *(this->mpVtkMetaFile) << "        <DataSet timestep=\"";
00699         *(this->mpVtkMetaFile) << SimulationTime::Instance()->GetTimeStepsElapsed();
00700         *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_";
00701         *(this->mpVtkMetaFile) << SimulationTime::Instance()->GetTimeStepsElapsed();
00702         *(this->mpVtkMetaFile) << ".vtu\"/>\n";
00703     }
00704 #endif //CHASTE_VTK
00705 }
00706 
00707 template<unsigned DIM>
00708 void MeshBasedCellPopulation<DIM>::WriteVoronoiResultsToFile()
00709 {
00710     assert(DIM==2 || DIM==3);
00711 
00712     // Write time to file
00713     *mpVoronoiFile << SimulationTime::Instance()->GetTime() << " ";
00714 
00715     // Loop over elements of mpVoronoiTessellation
00716     for (typename VertexMesh<DIM,DIM>::VertexElementIterator elem_iter = mpVoronoiTessellation->GetElementIteratorBegin();
00717          elem_iter != mpVoronoiTessellation->GetElementIteratorEnd();
00718          ++elem_iter)
00719     {
00720         // Get index of this element in mpVoronoiTessellation
00721         unsigned elem_index = elem_iter->GetIndex();
00722 
00723         // Get the index of the corresponding node in mrMesh
00724         unsigned node_index = mpVoronoiTessellation->GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(elem_index);
00725 
00726         // Write node index and location to file
00727         *mpVoronoiFile << node_index << " ";
00728         c_vector<double, DIM> node_location = this->GetNode(node_index)->rGetLocation();
00729         for (unsigned i=0; i<DIM; i++)
00730         {
00731             *mpVoronoiFile << node_location[i] << " ";
00732         }
00733 
00734         double cell_volume = mpVoronoiTessellation->GetVolumeOfElement(elem_index);
00735         double cell_surface_area = mpVoronoiTessellation->GetSurfaceAreaOfElement(elem_index);
00736         *mpVoronoiFile << cell_volume << " " << cell_surface_area << " ";
00737     }
00738     *mpVoronoiFile << "\n";
00739 }
00740 
00741 template<unsigned DIM>
00742 void MeshBasedCellPopulation<DIM>::WriteCellPopulationVolumeResultsToFile()
00743 {
00744     assert(DIM==2 || DIM==3);
00745 
00746     // Write time to file
00747     *mpCellPopulationVolumesFile << SimulationTime::Instance()->GetTime() << " ";
00748 
00749     // Don't use the Voronoi tessellation to calculate the total area of the mesh because it gives huge areas for boundary cells
00750     double total_area = mrMesh.GetVolume();
00751     double apoptotic_area = 0.0;
00752 
00753     // Loop over elements of mpVoronoiTessellation
00754     for (typename VertexMesh<DIM,DIM>::VertexElementIterator elem_iter = mpVoronoiTessellation->GetElementIteratorBegin();
00755          elem_iter != mpVoronoiTessellation->GetElementIteratorEnd();
00756          ++elem_iter)
00757     {
00758         // Get index of this element in mpVoronoiTessellation
00759         unsigned elem_index = elem_iter->GetIndex();
00760 
00761         // Get the index of the corresponding node in mrMesh
00762         unsigned node_index = mpVoronoiTessellation->GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(elem_index);
00763 
00764         // Discount ghost nodes
00765         if (!this->IsGhostNode(node_index))
00766         {
00767             // Get the cell corresponding to this node
00768             CellPtr p_cell =  this->mLocationCellMap[node_index];
00769 
00770             // Only bother calculating the area/volume of apoptotic cells
00771             bool cell_is_apoptotic = p_cell->HasCellProperty<ApoptoticCellProperty>();
00772             if (cell_is_apoptotic)
00773             {
00774                 double cell_volume = mpVoronoiTessellation->GetVolumeOfElement(elem_index);
00775                 apoptotic_area += cell_volume;
00776             }
00777         }
00778     }
00779     *mpCellPopulationVolumesFile << total_area << " " << apoptotic_area << "\n";
00780 }
00781 
00782 template<unsigned DIM>
00783 void MeshBasedCellPopulation<DIM>::WriteCellVolumeResultsToFile()
00784 {
00785     assert(DIM==2 || DIM==3);
00786 
00787      // Write time to file
00788     *mpCellVolumesFile << SimulationTime::Instance()->GetTime() << " ";
00789 
00790     // Loop over elements of mpVoronoiTessellation
00791     for (typename VertexMesh<DIM,DIM>::VertexElementIterator elem_iter = mpVoronoiTessellation->GetElementIteratorBegin();
00792          elem_iter != mpVoronoiTessellation->GetElementIteratorEnd();
00793          ++elem_iter)
00794     {
00795         // Get index of this element in mpVoronoiTessellation
00796         unsigned elem_index = elem_iter->GetIndex();
00797 
00798         // Get the index of the corresponding node in mrMesh
00799         unsigned node_index = mpVoronoiTessellation->GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(elem_index);
00800 
00801         // Discount ghost nodes
00802         if (!this->IsGhostNode(node_index))
00803         {
00804             // Write node index to file
00805             *mpCellVolumesFile << node_index << " ";
00806 
00807             // Get the cell corresponding to this node
00808             CellPtr p_cell =  this->mLocationCellMap[node_index];
00809 
00810             // Write cell ID to file
00811             unsigned cell_index = p_cell->GetCellId();
00812             *mpCellVolumesFile << cell_index << " ";
00813 
00814             // Write node location to file
00815             c_vector<double, DIM> node_location = this->GetNode(node_index)->rGetLocation();
00816             for (unsigned i=0; i<DIM; i++)
00817             {
00818                 *mpCellVolumesFile << node_location[i] << " ";
00819             }
00820 
00821             // Write cell volume (in 3D) or area (in 2D) to file
00822             double cell_volume = mpVoronoiTessellation->GetVolumeOfElement(elem_index);
00823             *mpCellVolumesFile << cell_volume << " ";
00824         }
00825     }
00826     *mpCellVolumesFile << "\n";
00827 }
00828 
00829 template<unsigned DIM>
00830 void MeshBasedCellPopulation<DIM>::SetWriteVtkAsPoints(bool writeVtkAsPoints)
00831 {
00832     mWriteVtkAsPoints = writeVtkAsPoints;
00833 }
00834 
00835 template<unsigned DIM>
00836 bool MeshBasedCellPopulation<DIM>::GetWriteVtkAsPoints()
00837 {
00838     return mWriteVtkAsPoints;
00839 }
00840 
00842 //                          Spring iterator class                           //
00844 
00845 template<unsigned DIM>
00846 Node<DIM>* MeshBasedCellPopulation<DIM>::SpringIterator::GetNodeA()
00847 {
00848     return mEdgeIter.GetNodeA();
00849 }
00850 
00851 template<unsigned DIM>
00852 Node<DIM>* MeshBasedCellPopulation<DIM>::SpringIterator::GetNodeB()
00853 {
00854     return mEdgeIter.GetNodeB();
00855 }
00856 
00857 template<unsigned DIM>
00858 CellPtr MeshBasedCellPopulation<DIM>::SpringIterator::GetCellA()
00859 {
00860     assert((*this) != mrCellPopulation.SpringsEnd());
00861     return mrCellPopulation.GetCellUsingLocationIndex(mEdgeIter.GetNodeA()->GetIndex());
00862 }
00863 
00864 template<unsigned DIM>
00865 CellPtr MeshBasedCellPopulation<DIM>::SpringIterator::GetCellB()
00866 {
00867     assert((*this) != mrCellPopulation.SpringsEnd());
00868     return mrCellPopulation.GetCellUsingLocationIndex(mEdgeIter.GetNodeB()->GetIndex());
00869 }
00870 
00871 template<unsigned DIM>
00872 bool MeshBasedCellPopulation<DIM>::SpringIterator::operator!=(const MeshBasedCellPopulation<DIM>::SpringIterator& rOther)
00873 {
00874     return (mEdgeIter != rOther.mEdgeIter);
00875 }
00876 
00877 template<unsigned DIM>
00878 typename MeshBasedCellPopulation<DIM>::SpringIterator& MeshBasedCellPopulation<DIM>::SpringIterator::operator++()
00879 {
00880     bool edge_is_ghost = false;
00881 
00882     do
00883     {
00884         ++mEdgeIter;
00885         if (*this != mrCellPopulation.SpringsEnd())
00886         {
00887             bool a_is_ghost = mrCellPopulation.IsGhostNode(mEdgeIter.GetNodeA()->GetIndex());
00888             bool b_is_ghost = mrCellPopulation.IsGhostNode(mEdgeIter.GetNodeB()->GetIndex());
00889 
00890             edge_is_ghost = (a_is_ghost || b_is_ghost);
00891         }
00892     }
00893     while (*this!=mrCellPopulation.SpringsEnd() && edge_is_ghost);
00894 
00895     return (*this);
00896 }
00897 
00898 template<unsigned DIM>
00899 MeshBasedCellPopulation<DIM>::SpringIterator::SpringIterator(
00900             MeshBasedCellPopulation<DIM>& rCellPopulation,
00901             typename MutableMesh<DIM,DIM>::EdgeIterator edgeIter)
00902     : mrCellPopulation(rCellPopulation),
00903       mEdgeIter(edgeIter)
00904 {
00905     if (mEdgeIter!=mrCellPopulation.mrMesh.EdgesEnd())
00906     {
00907         bool a_is_ghost = mrCellPopulation.IsGhostNode(mEdgeIter.GetNodeA()->GetIndex());
00908         bool b_is_ghost = mrCellPopulation.IsGhostNode(mEdgeIter.GetNodeB()->GetIndex());
00909 
00910         if (a_is_ghost || b_is_ghost)
00911         {
00912             ++(*this);
00913         }
00914     }
00915 }
00916 
00917 template<unsigned DIM>
00918 typename MeshBasedCellPopulation<DIM>::SpringIterator MeshBasedCellPopulation<DIM>::SpringsBegin()
00919 {
00920     return SpringIterator(*this, mrMesh.EdgesBegin());
00921 }
00922 
00923 template<unsigned DIM>
00924 typename MeshBasedCellPopulation<DIM>::SpringIterator MeshBasedCellPopulation<DIM>::SpringsEnd()
00925 {
00926     return SpringIterator(*this, mrMesh.EdgesEnd());
00927 }
00928 
00932 template<>
00933 void MeshBasedCellPopulation<2>::CreateVoronoiTessellation()
00934 {
00935     delete mpVoronoiTessellation;
00936 
00937     // Check if the mesh associated with this cell population is periodic
00938     bool is_mesh_periodic = false;
00939     if (dynamic_cast<Cylindrical2dMesh*>(&mrMesh))
00940     {
00941         is_mesh_periodic = true;
00942     }
00943 
00944     mpVoronoiTessellation = new VertexMesh<2, 2>(mrMesh, is_mesh_periodic);
00945 }
00946 
00952 template<>
00953 void MeshBasedCellPopulation<3>::CreateVoronoiTessellation()
00954 {
00955     delete mpVoronoiTessellation;
00956     mpVoronoiTessellation = new VertexMesh<3, 3>(mrMesh);
00957 }
00958 
00963 template<>
00964 void MeshBasedCellPopulation<1>::CreateVoronoiTessellation()
00965 {
00966     // No 1D Voronoi tessellation
00967     NEVER_REACHED;
00968 }
00969 
00970 template<unsigned DIM>
00971 VertexMesh<DIM, DIM>* MeshBasedCellPopulation<DIM>::GetVoronoiTessellation()
00972 {
00973     assert(mpVoronoiTessellation!=NULL);
00974     return mpVoronoiTessellation;
00975 }
00976 
00977 template<unsigned DIM>
00978 double MeshBasedCellPopulation<DIM>::GetVolumeOfVoronoiElement(unsigned index)
00979 {
00980     unsigned element_index = mpVoronoiTessellation->GetVoronoiElementIndexCorrespondingToDelaunayNodeIndex(index);
00981     double volume = mpVoronoiTessellation->GetVolumeOfElement(element_index);
00982     return volume;
00983 }
00984 
00985 template<unsigned DIM>
00986 double MeshBasedCellPopulation<DIM>::GetSurfaceAreaOfVoronoiElement(unsigned index)
00987 {
00988     unsigned element_index = mpVoronoiTessellation->GetVoronoiElementIndexCorrespondingToDelaunayNodeIndex(index);
00989     double surface_area = mpVoronoiTessellation->GetSurfaceAreaOfElement(element_index);
00990     return surface_area;
00991 }
00992 
00993 template<unsigned DIM>
00994 double MeshBasedCellPopulation<DIM>::GetVoronoiEdgeLength(unsigned index1, unsigned index2)
00995 {
00996     unsigned element_index1 = mpVoronoiTessellation->GetVoronoiElementIndexCorrespondingToDelaunayNodeIndex(index1);
00997     unsigned element_index2 = mpVoronoiTessellation->GetVoronoiElementIndexCorrespondingToDelaunayNodeIndex(index2);
00998     double edge_length = mpVoronoiTessellation->GetEdgeLength(element_index1, element_index2);
00999     return edge_length;
01000 }
01001 
01002 template<unsigned DIM>
01003 void MeshBasedCellPopulation<DIM>::CheckCellPointers()
01004 {
01005     bool res = true;
01006     for (std::list<CellPtr>::iterator it=this->mCells.begin();
01007          it!=this->mCells.end();
01008          ++it)
01009     {
01010         CellPtr p_cell = *it;
01011         assert(p_cell);
01012         AbstractCellCycleModel* p_model = p_cell->GetCellCycleModel();
01013         assert(p_model);
01014 
01015         // Check cell exists in cell population
01016         unsigned node_index = this->mCellLocationMap[p_cell.get()];
01017         std::cout << "Cell at node " << node_index << " addr " << p_cell << std::endl << std::flush;
01018         CellPtr p_cell_in_cell_population = this->GetCellUsingLocationIndex(node_index);
01019 #define COVERAGE_IGNORE //Debugging code.  Shouldn't fail under normal conditions
01020         if (p_cell_in_cell_population != p_cell)
01021         {
01022             std::cout << "  Mismatch with cell population" << std::endl << std::flush;
01023             res = false;
01024         }
01025 
01026         // Check model links back to cell
01027         if (p_model->GetCell() != p_cell)
01028         {
01029             std::cout << "  Mismatch with cycle model" << std::endl << std::flush;
01030             res = false;
01031         }
01032     }
01033     assert(res);
01034 #undef COVERAGE_IGNORE
01035 
01036     res = true;
01037     for (std::set<std::pair<CellPtr,CellPtr> >::iterator it1 = mMarkedSprings.begin();
01038          it1 != mMarkedSprings.end();
01039          ++it1)
01040     {
01041         const std::pair<CellPtr,CellPtr>& r_pair = *it1;
01042 
01043         for (unsigned i=0; i<2; i++)
01044         {
01045             CellPtr p_cell = (i==0 ? r_pair.first : r_pair.second);
01046 
01047             assert(p_cell);
01048             AbstractCellCycleModel* p_model = p_cell->GetCellCycleModel();
01049             assert(p_model);
01050             unsigned node_index = this->mCellLocationMap[p_cell.get()];
01051             std::cout << "Cell at node " << node_index << " addr " << p_cell << std::endl << std::flush;
01052 
01053 #define COVERAGE_IGNORE //Debugging code.  Shouldn't fail under normal conditions
01054             // Check cell is alive
01055             if (p_cell->IsDead())
01056             {
01057                 std::cout << "  Cell is dead" << std::endl << std::flush;
01058                 res = false;
01059             }
01060 
01061             // Check cell exists in cell population
01062             CellPtr p_cell_in_cell_population = this->GetCellUsingLocationIndex(node_index);
01063             if (p_cell_in_cell_population != p_cell)
01064             {
01065                 std::cout << "  Mismatch with cell population" << std::endl << std::flush;
01066                 res = false;
01067             }
01068 
01069             // Check model links back to cell
01070             if (p_model->GetCell() != p_cell)
01071             {
01072                 std::cout << "  Mismatch with cycle model" << std::endl << std::flush;
01073                 res = false;
01074             }
01075         }
01076 #undef COVERAGE_IGNORE
01077     }
01078     assert(res);
01079 }
01080 
01081 template<unsigned DIM>
01082 std::pair<CellPtr,CellPtr> MeshBasedCellPopulation<DIM>::CreateCellPair(CellPtr pCell1, CellPtr pCell2)
01083 {
01084     assert(pCell1);
01085     assert(pCell2);
01086 
01087     std::pair<CellPtr,CellPtr> cell_pair;
01088 
01089     if (pCell1->GetCellId() < pCell2->GetCellId())
01090     {
01091         cell_pair.first = pCell1;
01092         cell_pair.second = pCell2;
01093     }
01094     else
01095     {
01096         cell_pair.first = pCell2;
01097         cell_pair.second = pCell1;
01098     }
01099     return cell_pair;
01100 }
01101 
01102 template<unsigned DIM>
01103 bool MeshBasedCellPopulation<DIM>::IsMarkedSpring(const std::pair<CellPtr,CellPtr>& rCellPair)
01104 {
01105     // the pair should be ordered like this (CreateCellPair will ensure this)
01106     assert(rCellPair.first->GetCellId() < rCellPair.second->GetCellId());
01107 
01108     return mMarkedSprings.find(rCellPair) != mMarkedSprings.end();
01109 }
01110 
01111 template<unsigned DIM>
01112 void MeshBasedCellPopulation<DIM>::MarkSpring(std::pair<CellPtr,CellPtr>& rCellPair)
01113 {
01114     // the pair should be ordered like this (CreateCellPair will ensure this)
01115     assert(rCellPair.first->GetCellId() < rCellPair.second->GetCellId());
01116 
01117     mMarkedSprings.insert(rCellPair);
01118 }
01119 
01120 template<unsigned DIM>
01121 void MeshBasedCellPopulation<DIM>::UnmarkSpring(std::pair<CellPtr,CellPtr>& rCellPair)
01122 {
01123     // the pair should be ordered like this (CreateCellPair will ensure this)
01124     assert(rCellPair.first->GetCellId() < rCellPair.second->GetCellId());
01125 
01126     mMarkedSprings.erase(rCellPair);
01127 }
01128 
01129 template<unsigned DIM>
01130 double MeshBasedCellPopulation<DIM>::GetAreaBasedDampingConstantParameter()
01131 {
01132     return mAreaBasedDampingConstantParameter;
01133 }
01134 
01135 template<unsigned DIM>
01136 void MeshBasedCellPopulation<DIM>::SetAreaBasedDampingConstantParameter(double areaBasedDampingConstantParameter)
01137 {
01138     assert(areaBasedDampingConstantParameter >= 0.0);
01139     mAreaBasedDampingConstantParameter = areaBasedDampingConstantParameter;
01140 }
01141 
01142 template<unsigned DIM>
01143 bool MeshBasedCellPopulation<DIM>::GetOutputVoronoiData()
01144 {
01145     return mOutputVoronoiData;
01146 }
01147 
01148 template<unsigned DIM>
01149 void MeshBasedCellPopulation<DIM>::SetOutputVoronoiData(bool outputVoronoiData)
01150 {
01151     mOutputVoronoiData = outputVoronoiData;
01152 }
01153 
01154 template<unsigned DIM>
01155 bool MeshBasedCellPopulation<DIM>::GetOutputCellPopulationVolumes()
01156 {
01157     return mOutputCellPopulationVolumes;
01158 }
01159 
01160 template<unsigned DIM>
01161 void MeshBasedCellPopulation<DIM>::SetOutputCellPopulationVolumes(bool outputCellPopulationVolumes)
01162 {
01163     mOutputCellPopulationVolumes = outputCellPopulationVolumes;
01164 }
01165 
01166 template<unsigned DIM>
01167 void MeshBasedCellPopulation<DIM>::OutputCellPopulationParameters(out_stream& rParamsFile)
01168 {
01169     *rParamsFile << "\t\t<UseAreaBasedDampingConstant>" << mUseAreaBasedDampingConstant << "</UseAreaBasedDampingConstant> \n";
01170     *rParamsFile << "\t\t<AreaBasedDampingConstantParameter>" <<  mAreaBasedDampingConstantParameter << "</AreaBasedDampingConstantParameter> \n";
01171     *rParamsFile << "\t\t<OutputVoronoiData>" <<  mOutputVoronoiData << "</OutputVoronoiData> \n";
01172     *rParamsFile << "\t\t<OutputCellPopulationVolumes>" << mOutputCellPopulationVolumes << "</OutputCellPopulationVolumes> \n";
01173 
01174     // Call method on direct parent class
01175     AbstractCentreBasedCellPopulation<DIM>::OutputCellPopulationParameters(rParamsFile);
01176 }
01177 
01178 template<unsigned DIM>
01179 double MeshBasedCellPopulation<DIM>::GetWidth(const unsigned& rDimension)
01180 {
01181     // Call GetWidth() on the mesh
01182     double width = mrMesh.GetWidth(rDimension);
01183     return width;
01184 }
01185 
01187 // Explicit instantiation
01189 
01190 template class MeshBasedCellPopulation<1>;
01191 template class MeshBasedCellPopulation<2>;
01192 template class MeshBasedCellPopulation<3>;
01193 
01194 // Serialization for Boost >= 1.36
01195 #include "SerializationExportWrapperForCpp.hpp"
01196 EXPORT_TEMPLATE_CLASS_SAME_DIMS(MeshBasedCellPopulation)

Generated on Mon Apr 18 11:35:27 2011 for Chaste by  doxygen 1.5.5