MeshBasedCellPopulation.cpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2010
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 "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     // This must always be true
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             // Check if this cell is in a marked spring
00195             std::vector<const std::pair<CellPtr,CellPtr>*> pairs_to_remove; // Pairs that must be purged
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                         // Remember to purge this spring
00209                         pairs_to_remove.push_back(&r_pair);
00210                         break;
00211                     }
00212                 }
00213             }
00214             // Purge any marked springs that contained this cell
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             // Remove the node from the mesh
00223             num_removed++;
00224             mrMesh.DeleteNodePriorToReMesh(this->mCellLocationMap[(*it).get()]);
00225 
00226             // Update mappings between cells and location indices
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             // Update vector of cells
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         // Update the mappings between cells and location indices
00252         std::map<Cell*, unsigned> old_map = this->mCellLocationMap;
00253 
00254         // Remove any dead pointers from the maps (needed to avoid archiving errors)
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             // This shouldn't ever happen, as the cell vector only contains living cells
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     // Purge any marked springs that are no longer springs
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         // For each element containing node1, if it also contains node2 then the cells are joined
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         // If no longer joined, remove this spring from the set
00302         if (!joined)
00303         {
00304             springs_to_remove.push_back(&(*spring_it));
00305         }
00306     }
00307 
00308     // Remove any springs necessary
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     // Tessellate if needed
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     // Add new cell to cell population
00352     CellPtr p_created_cell = AbstractCentreBasedCellPopulation<DIM>::AddCell(pNewCell, rCellDivisionVector, pParentCell);
00353     assert(p_created_cell == pNewCell);
00354 
00355     // Mark spring between parent cell and new cell
00356     std::pair<CellPtr,CellPtr> cell_pair = CreateCellPair(pParentCell, p_created_cell);
00357     MarkSpring(cell_pair);
00358 
00359     // Return pointer to new cell
00360     return p_created_cell;
00361 }
00362 
00364 //                             Output methods                               //
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     // Write element data to file
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         // Hack that covers the case where the element contains a node that is associated with a cell that has just been killed (#1129)
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     // Write time to file
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     // Loop over elements of mpVoronoiTessellation
00516     for (typename VertexMesh<DIM,DIM>::VertexElementIterator elem_iter = mpVoronoiTessellation->GetElementIteratorBegin();
00517          elem_iter != mpVoronoiTessellation->GetElementIteratorEnd();
00518          ++elem_iter)
00519     {
00520         // Get index of this element in mpVoronoiTessellation
00521         unsigned elem_index = elem_iter->GetIndex();
00522 
00523         // Get the index of the corresponding node in mrMesh
00524         unsigned node_index = mpVoronoiTessellation->GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(elem_index);
00525 
00526         // There should be no ghost nodes
00527         assert(!this->IsGhostNode(node_index));
00528 
00529         // Get the cell corresponding to this element
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     // Write time to file
00623     *mpVoronoiFile << SimulationTime::Instance()->GetTime() << " ";
00624 
00625     // Loop over elements of mpVoronoiTessellation
00626     for (typename VertexMesh<DIM,DIM>::VertexElementIterator elem_iter = mpVoronoiTessellation->GetElementIteratorBegin();
00627          elem_iter != mpVoronoiTessellation->GetElementIteratorEnd();
00628          ++elem_iter)
00629     {
00630         // Get index of this element in mpVoronoiTessellation
00631         unsigned elem_index = elem_iter->GetIndex();
00632 
00633         // Get the index of the corresponding node in mrMesh
00634         unsigned node_index = mpVoronoiTessellation->GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(elem_index);
00635 
00636         // Write node index and location to file
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     // Write time to file
00657     *mpCellPopulationVolumesFile << SimulationTime::Instance()->GetTime() << " ";
00658 
00659     // Don't use the Voronoi tessellation to calculate the total area of the mesh because it gives huge areas for boundary cells
00660     double total_area = mrMesh.GetVolume();
00661     double apoptotic_area = 0.0;
00662 
00663     // Loop over elements of mpVoronoiTessellation
00664     for (typename VertexMesh<DIM,DIM>::VertexElementIterator elem_iter = mpVoronoiTessellation->GetElementIteratorBegin();
00665          elem_iter != mpVoronoiTessellation->GetElementIteratorEnd();
00666          ++elem_iter)
00667     {
00668         // Get index of this element in mpVoronoiTessellation
00669         unsigned elem_index = elem_iter->GetIndex();
00670 
00671         // Get the index of the corresponding node in mrMesh
00672         unsigned node_index = mpVoronoiTessellation->GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(elem_index);
00673 
00674         // Discount ghost nodes
00675         if (!this->IsGhostNode(node_index))
00676         {
00677             // Get the cell corresponding to this node
00678             CellPtr p_cell =  this->mLocationCellMap[node_index];
00679 
00680             // Only bother calculating the area/volume of apoptotic cells
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      // Write time to file
00698     *mpCellVolumesFile << SimulationTime::Instance()->GetTime() << " ";
00699 
00700     // Loop over elements of mpVoronoiTessellation
00701     for (typename VertexMesh<DIM,DIM>::VertexElementIterator elem_iter = mpVoronoiTessellation->GetElementIteratorBegin();
00702          elem_iter != mpVoronoiTessellation->GetElementIteratorEnd();
00703          ++elem_iter)
00704     {
00705         // Get index of this element in mpVoronoiTessellation
00706         unsigned elem_index = elem_iter->GetIndex();
00707 
00708         // Get the index of the corresponding node in mrMesh
00709         unsigned node_index = mpVoronoiTessellation->GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(elem_index);
00710 
00711         // Discount ghost nodes
00712         if (!this->IsGhostNode(node_index))
00713         {
00714             // Write node index to file
00715             *mpCellVolumesFile << node_index << " ";
00716 
00717             // Get the cell corresponding to this node
00718             CellPtr p_cell =  this->mLocationCellMap[node_index];
00719 
00720             // Write cell ID to file
00721             unsigned cell_index = p_cell->GetCellId();
00722             *mpCellVolumesFile << cell_index << " ";
00723 
00724             // Write node location to file
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             // Write cell volume (in 3D) or area (in 2D) to file
00732             double cell_volume = mpVoronoiTessellation->GetVolumeOfElement(elem_index);
00733             *mpCellVolumesFile << cell_volume << " ";
00734         }
00735     }
00736     *mpCellVolumesFile << "\n";
00737 }
00738 
00739 
00741 //                          Spring iterator class                           //
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     // Check if the mesh associated with this cell population is periodic
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     // No 1D Voronoi tessellation
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         // Check cell exists in cell population
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         // Check model links back to cell
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             // Check cell is alive
00954             if (p_cell->IsDead())
00955             {
00956                 std::cout << "  Cell is dead" << std::endl << std::flush;
00957                 res = false;
00958             }
00959 
00960             // Check cell exists in cell population
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             // Check model links back to cell
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     // the pair should be ordered like this (CreateCellPair will ensure this)
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     // the pair should be ordered like this (CreateCellPair will ensure this)
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     // the pair should be ordered like this (CreateCellPair will ensure this)
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     // Call direct parent class
01074     AbstractCentreBasedCellPopulation<DIM>::OutputCellPopulationParameters(rParamsFile);
01075 }
01076 
01077 template<unsigned DIM>
01078 double MeshBasedCellPopulation<DIM>::GetWidth(const unsigned& rDimension)
01079 {
01080     // Call GetWidth() on the mesh
01081     double width = mrMesh.GetWidth(rDimension);
01082     return width;
01083 }
01084 
01086 // Explicit instantiation
01088 
01089 template class MeshBasedCellPopulation<1>;
01090 template class MeshBasedCellPopulation<2>;
01091 template class MeshBasedCellPopulation<3>;
01092 
01093 // Serialization for Boost >= 1.36
01094 #include "SerializationExportWrapperForCpp.hpp"
01095 EXPORT_TEMPLATE_CLASS_SAME_DIMS(MeshBasedCellPopulation)

Generated on Mon Nov 1 12:35:16 2010 for Chaste by  doxygen 1.5.5