Chaste Release::3.1
MeshBasedCellPopulation.cpp
00001 /*
00002 
00003 Copyright (c) 2005-2012, University of Oxford.
00004 All rights reserved.
00005 
00006 University of Oxford means the Chancellor, Masters and Scholars of the
00007 University of Oxford, having an administrative office at Wellington
00008 Square, Oxford OX1 2JD, UK.
00009 
00010 This file is part of Chaste.
00011 
00012 Redistribution and use in source and binary forms, with or without
00013 modification, are permitted provided that the following conditions are met:
00014  * Redistributions of source code must retain the above copyright notice,
00015    this list of conditions and the following disclaimer.
00016  * Redistributions in binary form must reproduce the above copyright notice,
00017    this list of conditions and the following disclaimer in the documentation
00018    and/or other materials provided with the distribution.
00019  * Neither the name of the University of Oxford nor the names of its
00020    contributors may be used to endorse or promote products derived from this
00021    software without specific prior written permission.
00022 
00023 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00024 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00025 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00026 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00027 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00028 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
00029 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00030 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
00032 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00033 
00034 */
00035 
00036 #include "MeshBasedCellPopulation.hpp"
00037 #include "TrianglesMeshWriter.hpp"
00038 #include "VtkMeshWriter.hpp"
00039 #include "CellBasedEventHandler.hpp"
00040 #include "ApoptoticCellProperty.hpp"
00041 #include "Cylindrical2dMesh.hpp"
00042 #include "NodesOnlyMesh.hpp"
00043 #include "Exception.hpp"
00044 
00045 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00046 MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::MeshBasedCellPopulation(MutableMesh<ELEMENT_DIM,SPACE_DIM>& rMesh,
00047                                       std::vector<CellPtr>& rCells,
00048                                       const std::vector<unsigned> locationIndices,
00049                                       bool deleteMesh,
00050                                       bool validate)
00051     : AbstractCentreBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>(rMesh, rCells, locationIndices),
00052       mpVoronoiTessellation(NULL),
00053       mDeleteMesh(deleteMesh),
00054       mUseAreaBasedDampingConstant(false),
00055       mAreaBasedDampingConstantParameter(0.1),
00056       mOutputVoronoiData(false),
00057       mOutputCellPopulationVolumes(false),
00058       mWriteVtkAsPoints(false),
00059       mHasVariableRestLength(false)
00060 {
00061     mpMutableMesh = static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>* >(&(this->mrMesh));
00062     // This must always be true
00063     assert(this->mCells.size() <= this->mrMesh.GetNumNodes());
00064 
00065     if (validate)
00066     {
00067         Validate();
00068     }
00069 }
00070 
00071 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00072 MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::MeshBasedCellPopulation(MutableMesh<ELEMENT_DIM,SPACE_DIM>& rMesh)
00073     : AbstractCentreBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>(rMesh)
00074 {
00075     mpMutableMesh = static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>* >(&(this->mrMesh));
00076     mpVoronoiTessellation = NULL;
00077     mDeleteMesh = true;
00078 }
00079 
00080 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00081 MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::~MeshBasedCellPopulation()
00082 {
00083     delete mpVoronoiTessellation;
00084 
00085     if (mDeleteMesh)
00086     {
00087         delete &this->mrMesh;
00088     }
00089 }
00090 
00091 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00092 bool MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::UseAreaBasedDampingConstant()
00093 {
00094     return mUseAreaBasedDampingConstant;
00095 }
00096 
00097 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00098 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SetAreaBasedDampingConstant(bool useAreaBasedDampingConstant)
00099 {
00100     assert(SPACE_DIM==2);
00101     mUseAreaBasedDampingConstant = useAreaBasedDampingConstant;
00102 }
00103 
00104 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00105 unsigned MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::AddNode(Node<SPACE_DIM>* pNewNode)
00106 {
00107     return mpMutableMesh->AddNode(pNewNode);
00108 }
00109 
00110 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00111 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SetNode(unsigned nodeIndex, ChastePoint<SPACE_DIM>& rNewLocation)
00112 {
00113     static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>&>((this->mrMesh)).SetNode(nodeIndex, rNewLocation, false);
00114 }
00115 
00116 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00117 double MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetDampingConstant(unsigned nodeIndex)
00118 {
00119     double damping_multiplier = AbstractCentreBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetDampingConstant(nodeIndex);
00120 
00121     if (mUseAreaBasedDampingConstant)
00122     {
00132         assert(SPACE_DIM==2);
00133 
00134         double rest_length = 1.0;
00135         double d0 = mAreaBasedDampingConstantParameter;
00136 
00142         double d1 = 2.0*(1.0 - d0)/(sqrt(3)*rest_length*rest_length);
00143 
00144         double area_cell = GetVolumeOfVoronoiElement(nodeIndex);
00145 
00151         assert(area_cell < 1000);
00152 
00153         damping_multiplier = d0 + area_cell*d1;
00154     }
00155 
00156     return damping_multiplier;
00157 }
00158 
00159 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00160 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::Validate()
00161 {
00162     std::vector<bool> validated_node = std::vector<bool>(this->GetNumNodes(), false);
00163 
00164     for (typename AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>::Iterator cell_iter=this->Begin(); cell_iter!=this->End(); ++cell_iter)
00165     {
00166         unsigned node_index = this->GetLocationIndexUsingCell(*cell_iter);
00167         validated_node[node_index] = true;
00168     }
00169 
00170     for (unsigned i=0; i<validated_node.size(); i++)
00171     {
00172         if (!validated_node[i])
00173         {
00174             EXCEPTION("Node " << i << " does not appear to have a cell associated with it");
00175         }
00176     }
00177 }
00178 
00179 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00180 MutableMesh<ELEMENT_DIM,SPACE_DIM>& MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::rGetMesh()
00181 {
00182     return *mpMutableMesh;
00183 }
00184 
00185 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00186 const MutableMesh<ELEMENT_DIM,SPACE_DIM>& MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::rGetMesh() const
00187 {
00188     return *mpMutableMesh;
00189 }
00190 
00191 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00192 unsigned MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::RemoveDeadCells()
00193 {
00194     unsigned num_removed = 0;
00195     for (std::list<CellPtr>::iterator it = this->mCells.begin();
00196          it != this->mCells.end();
00197          ++it)
00198     {
00199         if ((*it)->IsDead())
00200         {
00201             // Check if this cell is in a marked spring
00202             std::vector<const std::pair<CellPtr,CellPtr>*> pairs_to_remove; // Pairs that must be purged
00203             for (std::set<std::pair<CellPtr,CellPtr> >::iterator it1 = this->mMarkedSprings.begin();
00204                  it1 != this->mMarkedSprings.end();
00205                  ++it1)
00206             {
00207                 const std::pair<CellPtr,CellPtr>& r_pair = *it1;
00208 
00209                 for (unsigned i=0; i<2; i++)
00210                 {
00211                     CellPtr p_cell = (i==0 ? r_pair.first : r_pair.second);
00212 
00213                     if (p_cell == *it)
00214                     {
00215                         // Remember to purge this spring
00216                         pairs_to_remove.push_back(&r_pair);
00217                         break;
00218                     }
00219                 }
00220             }
00221 
00222             // Purge any marked springs that contained this cell
00223             for (std::vector<const std::pair<CellPtr,CellPtr>* >::iterator pair_it = pairs_to_remove.begin();
00224                  pair_it != pairs_to_remove.end();
00225                  ++pair_it)
00226             {
00227                 this->mMarkedSprings.erase(**pair_it);
00228             }
00229 
00230             // Remove the node from the mesh
00231             num_removed++;
00232             static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>&>((this->mrMesh)).DeleteNodePriorToReMesh(this->GetLocationIndexUsingCell((*it)));
00233 
00234             // Update mappings between cells and location indices
00235             unsigned location_index_of_removed_node = this->GetLocationIndexUsingCell((*it));
00236             this->RemoveCellUsingLocationIndex(location_index_of_removed_node, (*it));
00237 
00238             // Update vector of cells
00239             it = this->mCells.erase(it);
00240             --it;
00241         }
00242     }
00243 
00244     return num_removed;
00245 }
00246 
00247 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00248 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::Update(bool hasHadBirthsOrDeaths)
00249 {
00250     NodeMap map(static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>&>((this->mrMesh)).GetNumAllNodes());
00251     static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>&>((this->mrMesh)).ReMesh(map);
00252 
00253     if (!map.IsIdentityMap())
00254     {
00255         UpdateGhostNodesAfterReMesh(map);
00256 
00257         // Update the mappings between cells and location indices
00258         std::map<Cell*, unsigned> old_map = this->mCellLocationMap;
00259 
00260         // Remove any dead pointers from the maps (needed to avoid archiving errors)
00261         this->mLocationCellMap.clear();
00262         this->mCellLocationMap.clear();
00263 
00264         for (std::list<CellPtr>::iterator it = this->mCells.begin();
00265              it != this->mCells.end();
00266              ++it)
00267         {
00268             unsigned old_node_index = old_map[(*it).get()];
00269 
00270             // This shouldn't ever happen, as the cell vector only contains living cells
00271             assert(!map.IsDeleted(old_node_index));
00272 
00273             unsigned new_node_index = map.GetNewIndex(old_node_index);
00274             this->SetCellUsingLocationIndex(new_node_index,*it);
00275         }
00276 
00277         this->Validate();
00278     }
00279 
00280     // Purge any marked springs that are no longer springs
00281     std::vector<const std::pair<CellPtr,CellPtr>*> springs_to_remove;
00282     for (std::set<std::pair<CellPtr,CellPtr> >::iterator spring_it = this->mMarkedSprings.begin();
00283          spring_it != this->mMarkedSprings.end();
00284          ++spring_it)
00285     {
00286         CellPtr p_cell_1 = spring_it->first;
00287         CellPtr p_cell_2 = spring_it->second;
00288         Node<SPACE_DIM>* p_node_1 = this->GetNodeCorrespondingToCell(p_cell_1);
00289         Node<SPACE_DIM>* p_node_2 = this->GetNodeCorrespondingToCell(p_cell_2);
00290 
00291         bool joined = false;
00292 
00293         // For each element containing node1, if it also contains node2 then the cells are joined
00294         std::set<unsigned> node2_elements = p_node_2->rGetContainingElementIndices();
00295         for (typename Node<SPACE_DIM>::ContainingElementIterator elem_iter = p_node_1->ContainingElementsBegin();
00296              elem_iter != p_node_1->ContainingElementsEnd();
00297              ++elem_iter)
00298         {
00299             if (node2_elements.find(*elem_iter) != node2_elements.end())
00300             {
00301                 joined = true;
00302                 break;
00303             }
00304         }
00305 
00306         // If no longer joined, remove this spring from the set
00307         if (!joined)
00308         {
00309             springs_to_remove.push_back(&(*spring_it));
00310         }
00311     }
00312 
00313     // Remove any springs necessary
00314     for (std::vector<const std::pair<CellPtr,CellPtr>* >::iterator spring_it = springs_to_remove.begin();
00315          spring_it != springs_to_remove.end();
00316          ++spring_it)
00317     {
00318         this->mMarkedSprings.erase(**spring_it);
00319     }
00320 
00321     // Tessellate if needed
00322     TessellateIfNeeded();
00323 
00324     static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>&>((this->mrMesh)).SetMeshHasChangedSinceLoading();
00325 }
00326 
00327 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00328 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::TessellateIfNeeded()
00329 {
00330      if ((SPACE_DIM==2 || SPACE_DIM==3)&&(ELEMENT_DIM==SPACE_DIM))
00331     {
00332         CellBasedEventHandler::BeginEvent(CellBasedEventHandler::TESSELLATION);
00333         if (mUseAreaBasedDampingConstant || mOutputVoronoiData || mOutputCellPopulationVolumes || this->mOutputCellVolumes)
00334         {
00335             CreateVoronoiTessellation();
00336         }
00337         CellBasedEventHandler::EndEvent(CellBasedEventHandler::TESSELLATION);
00338     }
00339 }
00340 
00341 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00342 Node<SPACE_DIM>* MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetNode(unsigned index)
00343 {
00344     return this->mrMesh.GetNode(index);
00345 }
00346 
00347 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00348 unsigned MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetNumNodes()
00349 {
00350     return this->mrMesh.GetNumAllNodes();
00351 }
00352 
00353 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00354 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::UpdateGhostNodesAfterReMesh(NodeMap& rMap)
00355 {
00356 }
00357 
00358 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00359 CellPtr MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::AddCell(CellPtr pNewCell, const c_vector<double,SPACE_DIM>& rCellDivisionVector, CellPtr pParentCell)
00360 {
00361     assert(pNewCell);
00362     assert(pParentCell);
00363 
00364     // Add new cell to cell population
00365     CellPtr p_created_cell = AbstractCentreBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::AddCell(pNewCell, rCellDivisionVector, pParentCell);
00366     assert(p_created_cell == pNewCell);
00367 
00368     // Mark spring between parent cell and new cell
00369     std::pair<CellPtr,CellPtr> cell_pair = this->CreateCellPair(pParentCell, p_created_cell);
00370     this->MarkSpring(cell_pair);
00371 
00372     // Return pointer to new cell
00373     return p_created_cell;
00374 }
00375 
00377 //                             Output methods                               //
00379 
00380 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00381 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::CreateOutputFiles(const std::string& rDirectory, bool cleanOutputDirectory)
00382 {
00383     AbstractCentreBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::CreateOutputFiles(rDirectory, cleanOutputDirectory);
00384 
00385     OutputFileHandler output_file_handler(rDirectory, cleanOutputDirectory);
00386     mpVizElementsFile = output_file_handler.OpenOutputFile("results.vizelements");
00387 
00388     if (mOutputVoronoiData)
00389     {
00390         mpVoronoiFile = output_file_handler.OpenOutputFile("voronoi.dat");
00391     }
00392     if (mOutputCellPopulationVolumes)
00393     {
00394         mpCellPopulationVolumesFile = output_file_handler.OpenOutputFile("cellpopulationareas.dat");
00395     }
00396 }
00397 
00398 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00399 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::CloseOutputFiles()
00400 {
00401     AbstractCentreBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::CloseOutputFiles();
00402 
00403     mpVizElementsFile->close();
00404 
00405     if (mOutputVoronoiData)
00406     {
00407         mpVoronoiFile->close();
00408     }
00409     if (mOutputCellPopulationVolumes)
00410     {
00411         mpCellPopulationVolumesFile->close();
00412     }
00413 }
00414 
00415 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00416 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::WriteResultsToFiles()
00417 {
00418     if (SimulationTime::Instance()->GetTimeStepsElapsed() == 0 && this->mpVoronoiTessellation == NULL)
00419     {
00420         TessellateIfNeeded();//Update isn't run on time-step zero
00421     }
00422 
00423     AbstractCentreBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::WriteResultsToFiles();
00424 
00425     // Write element data to file
00426     *mpVizElementsFile << SimulationTime::Instance()->GetTime() << "\t";
00427 
00428     for (typename MutableMesh<ELEMENT_DIM,SPACE_DIM>::ElementIterator elem_iter = static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>&>((this->mrMesh)).GetElementIteratorBegin();
00429          elem_iter != static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>&>((this->mrMesh)).GetElementIteratorEnd();
00430          ++elem_iter)
00431     {
00432         bool element_contains_dead_cells_or_deleted_nodes = false;
00433 
00434         // Hack that covers the case where the element contains a node that is associated with a cell that has just been killed (#1129)
00435         for (unsigned i=0; i<ELEMENT_DIM+1; i++)
00436         {
00437             unsigned node_index = elem_iter->GetNodeGlobalIndex(i);
00438 
00439             if (this->GetNode(node_index)->IsDeleted())
00440             {
00441                 element_contains_dead_cells_or_deleted_nodes = true;
00442                 break;
00443             }
00444             else if (this->IsCellAttachedToLocationIndex(node_index))
00445             {
00446                 if (this->GetCellUsingLocationIndex(node_index)->IsDead())
00447                 {
00448                     element_contains_dead_cells_or_deleted_nodes = true;
00449                     break;
00450                 }
00451             }
00452         }
00453         if (!element_contains_dead_cells_or_deleted_nodes)
00454         {
00455             for (unsigned i=0; i<ELEMENT_DIM+1; i++)
00456             {
00457                 *mpVizElementsFile << elem_iter->GetNodeGlobalIndex(i) << " ";
00458             }
00459         }
00460     }
00461     *mpVizElementsFile << "\n";
00462 
00463     // Write data to file.
00464     if (mOutputVoronoiData)
00465     {
00466         WriteVoronoiResultsToFile();
00467     }
00468     if (mOutputCellPopulationVolumes)
00469     {
00470         WriteCellPopulationVolumeResultsToFile();
00471     }
00472 
00473 }
00474 
00475 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00476 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_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     unsigned num_cell_data_items = 0;
00497     std::vector<std::string> cell_data_names;
00498     //We assume that the first cell is representative of all cells
00499     num_cell_data_items = this->Begin()->GetCellData()->GetNumItems();
00500     cell_data_names = this->Begin()->GetCellData()->GetKeys();
00501 
00502     for (unsigned var=0; var<num_cell_data_items; var++)
00503     {
00504         std::vector<double> cellwise_data_var(num_points);
00505         cellwise_data.push_back(cellwise_data_var);
00506     }
00507 
00508     if (mWriteVtkAsPoints)
00509     {
00510         VtkMeshWriter<SPACE_DIM,SPACE_DIM> mesh_writer(this->mDirPath, "results_"+time.str(), false);
00511 
00512         // Loop over cells
00513         for (typename AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>::Iterator cell_iter = this->Begin();
00514              cell_iter != this->End();
00515              ++cell_iter)
00516         {
00517             // Get the node index corresponding to this cell
00518             unsigned node_index = this->GetLocationIndexUsingCell(*cell_iter);
00519 
00520             // Get this cell-cycle model
00521             AbstractCellCycleModel* p_model = cell_iter->GetCellCycleModel();
00522 
00523             if (this->mOutputCellAncestors)
00524             {
00525                 double ancestor_index = (cell_iter->GetAncestor() == UNSIGNED_UNSET) ? (-1.0) : (double)cell_iter->GetAncestor();
00526                 cell_ancestors[node_index] = ancestor_index;
00527             }
00528             if (this->mOutputCellProliferativeTypes)
00529             {
00530                 cell_types[node_index] = cell_iter->GetCellProliferativeType();
00531             }
00532             if (this->mOutputCellMutationStates)
00533             {
00534                 cell_mutation_states[node_index] = cell_iter->GetMutationState()->GetColour();
00535             }
00536             if (this->mOutputCellAges)
00537             {
00538                 cell_ages[node_index] = cell_iter->GetAge();
00539             }
00540             if (this->mOutputCellCyclePhases)
00541             {
00542                 cell_cycle_phases[node_index] = p_model->GetCurrentCellCyclePhase();
00543             }
00544             for (unsigned var=0; var<num_cell_data_items; var++)
00545             {
00546                 cellwise_data[var][node_index] = cell_iter->GetCellData()->GetItem(cell_data_names[var]);
00547             }
00548         }
00549 
00550         if (this->mOutputCellProliferativeTypes)
00551         {
00552             mesh_writer.AddPointData("Cell types", cell_types);
00553         }
00554         if (this->mOutputCellAncestors)
00555         {
00556             mesh_writer.AddPointData("Ancestors", cell_ancestors);
00557         }
00558         if (this->mOutputCellMutationStates)
00559         {
00560             mesh_writer.AddPointData("Mutation states", cell_mutation_states);
00561         }
00562         if (this->mOutputCellAges)
00563         {
00564             mesh_writer.AddPointData("Ages", cell_ages);
00565         }
00566         if (this->mOutputCellCyclePhases)
00567         {
00568             mesh_writer.AddPointData("Cycle phases", cell_cycle_phases);
00569         }
00570         if (num_cell_data_items > 0)
00571         {
00572             for (unsigned var=0; var<cellwise_data.size(); var++)
00573             {
00574                 mesh_writer.AddPointData(cell_data_names[var], cellwise_data[var]);
00575             }
00576         }
00577 
00578         {
00579             // Make a copy of the nodes in a disposable mesh for writing
00580             std::vector<Node<SPACE_DIM>* > nodes;
00581             for (unsigned index=0; index<this->mrMesh.GetNumNodes(); index++)
00582             {
00583                 Node<SPACE_DIM>* p_node = this->mrMesh.GetNode(index);
00584                 nodes.push_back(p_node);
00585             }
00586 
00587             NodesOnlyMesh<SPACE_DIM> mesh;
00588             mesh.ConstructNodesWithoutMesh(nodes);
00589             mesh_writer.WriteFilesUsingMesh(mesh);
00590         }
00591 
00592         *(this->mpVtkMetaFile) << "        <DataSet timestep=\"";
00593         *(this->mpVtkMetaFile) << SimulationTime::Instance()->GetTimeStepsElapsed();
00594         *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_";
00595         *(this->mpVtkMetaFile) << SimulationTime::Instance()->GetTimeStepsElapsed();
00596         *(this->mpVtkMetaFile) << ".vtu\"/>\n";
00597     }
00598     else if (mpVoronoiTessellation != NULL)
00599     {
00600         VertexMeshWriter<ELEMENT_DIM,SPACE_DIM> mesh_writer(this->mDirPath, "results", false);
00601         std::vector<double> cell_volumes(num_points);
00602 
00603         // Loop over elements of mpVoronoiTessellation
00604         for (typename VertexMesh<ELEMENT_DIM,SPACE_DIM>::VertexElementIterator elem_iter = mpVoronoiTessellation->GetElementIteratorBegin();
00605              elem_iter != mpVoronoiTessellation->GetElementIteratorEnd();
00606              ++elem_iter)
00607         {
00608             // Get index of this element in mpVoronoiTessellation
00609             unsigned elem_index = elem_iter->GetIndex();
00610 
00611             // Get the index of the corresponding node in mrMesh
00612             unsigned node_index = mpVoronoiTessellation->GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(elem_index);
00613 
00614             // There should be no ghost nodes
00615             assert(!this->IsGhostNode(node_index));
00616 
00617             // Get the cell corresponding to this element
00618             CellPtr p_cell = this->GetCellUsingLocationIndex(node_index);
00619 
00620             // Get this cell-cycle model
00621             AbstractCellCycleModel* p_model = p_cell->GetCellCycleModel();
00622 
00623             if (this->mOutputCellAncestors)
00624             {
00625                 double ancestor_index = (p_cell->GetAncestor() == UNSIGNED_UNSET) ? (-1.0) : (double)p_cell->GetAncestor();
00626                 cell_ancestors[elem_index] = ancestor_index;
00627             }
00628             if (this->mOutputCellProliferativeTypes)
00629             {
00630                 cell_types[elem_index] = p_cell->GetCellProliferativeType();
00631             }
00632             if (this->mOutputCellMutationStates)
00633             {
00634                 cell_mutation_states[elem_index] = p_cell->GetMutationState()->GetColour();
00635             }
00636             if (this->mOutputCellAges)
00637             {
00638                 cell_ages[elem_index] = p_cell->GetAge();
00639             }
00640             if (this->mOutputCellCyclePhases)
00641             {
00642                 cell_cycle_phases[elem_index] = p_model->GetCurrentCellCyclePhase();
00643             }
00644             if (this->mOutputCellVolumes)
00645             {
00646                 cell_volumes[elem_index] = mpVoronoiTessellation->GetVolumeOfElement(elem_index);
00647             }
00648             for (unsigned var=0; var<num_cell_data_items; var++)
00649             {
00650                 cellwise_data[var][elem_index] = p_cell->GetCellData()->GetItem(cell_data_names[var]);
00651             }
00652         }
00653 
00654         if (this->mOutputCellProliferativeTypes)
00655         {
00656             mesh_writer.AddCellData("Cell types", cell_types);
00657         }
00658         if (this->mOutputCellAncestors)
00659         {
00660             mesh_writer.AddCellData("Ancestors", cell_ancestors);
00661         }
00662         if (this->mOutputCellMutationStates)
00663         {
00664             mesh_writer.AddCellData("Mutation states", cell_mutation_states);
00665         }
00666         if (this->mOutputCellAges)
00667         {
00668             mesh_writer.AddCellData("Ages", cell_ages);
00669         }
00670         if (this->mOutputCellCyclePhases)
00671         {
00672             mesh_writer.AddCellData("Cycle phases", cell_cycle_phases);
00673         }
00674         if (this->mOutputCellVolumes)
00675         {
00676             mesh_writer.AddCellData("Cell volumes", cell_volumes);
00677         }
00678         if (num_cell_data_items > 0)
00679         {
00680             for (unsigned var=0; var<cellwise_data.size(); var++)
00681             {
00682                 mesh_writer.AddCellData(cell_data_names[var], cellwise_data[var]);
00683             }
00684         }
00685 
00686         mesh_writer.WriteVtkUsingMesh(*mpVoronoiTessellation, time.str());
00687         *(this->mpVtkMetaFile) << "        <DataSet timestep=\"";
00688         *(this->mpVtkMetaFile) << SimulationTime::Instance()->GetTimeStepsElapsed();
00689         *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_";
00690         *(this->mpVtkMetaFile) << SimulationTime::Instance()->GetTimeStepsElapsed();
00691         *(this->mpVtkMetaFile) << ".vtu\"/>\n";
00692     }
00693 #endif //CHASTE_VTK
00694 }
00695 
00696 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00697 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::WriteVoronoiResultsToFile()
00698 {
00699     assert(SPACE_DIM==2 || SPACE_DIM==3);
00700     assert(mpVoronoiTessellation != NULL);
00701     // Write time to file
00702     *mpVoronoiFile << SimulationTime::Instance()->GetTime() << " ";
00703 
00704     // Loop over elements of mpVoronoiTessellation
00705     for (typename VertexMesh<ELEMENT_DIM,SPACE_DIM>::VertexElementIterator elem_iter = mpVoronoiTessellation->GetElementIteratorBegin();
00706          elem_iter != mpVoronoiTessellation->GetElementIteratorEnd();
00707          ++elem_iter)
00708     {
00709         // Get index of this element in mpVoronoiTessellation
00710         unsigned elem_index = elem_iter->GetIndex();
00711 
00712         // Get the index of the corresponding node in mrMesh
00713         unsigned node_index = mpVoronoiTessellation->GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(elem_index);
00714 
00715         // Write node index and location to file
00716         *mpVoronoiFile << node_index << " ";
00717         c_vector<double, SPACE_DIM> node_location = this->GetNode(node_index)->rGetLocation();
00718         for (unsigned i=0; i<SPACE_DIM; i++)
00719         {
00720             *mpVoronoiFile << node_location[i] << " ";
00721         }
00722 
00723         double cell_volume = mpVoronoiTessellation->GetVolumeOfElement(elem_index);
00724         double cell_surface_area = mpVoronoiTessellation->GetSurfaceAreaOfElement(elem_index);
00725         *mpVoronoiFile << cell_volume << " " << cell_surface_area << " ";
00726     }
00727     *mpVoronoiFile << "\n";
00728 }
00729 
00730 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00731 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::WriteCellPopulationVolumeResultsToFile()
00732 {
00733     assert(SPACE_DIM==2 || SPACE_DIM==3);
00734 
00735     // Write time to file
00736     *mpCellPopulationVolumesFile << SimulationTime::Instance()->GetTime() << " ";
00737     assert (this->mpVoronoiTessellation != NULL);
00738 
00739     // Don't use the Voronoi tessellation to calculate the total area of the mesh because it gives huge areas for boundary cells
00740     double total_area = static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>&>((this->mrMesh)).GetVolume();
00741     double apoptotic_area = 0.0;
00742 
00743     // Loop over elements of mpVoronoiTessellation
00744     for (typename VertexMesh<ELEMENT_DIM,SPACE_DIM>::VertexElementIterator elem_iter = mpVoronoiTessellation->GetElementIteratorBegin();
00745          elem_iter != mpVoronoiTessellation->GetElementIteratorEnd();
00746          ++elem_iter)
00747     {
00748         // Get index of this element in mpVoronoiTessellation
00749         unsigned elem_index = elem_iter->GetIndex();
00750 
00751         // Get the index of the corresponding node in mrMesh
00752         unsigned node_index = mpVoronoiTessellation->GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(elem_index);
00753 
00754         // Discount ghost nodes
00755         if (!this->IsGhostNode(node_index))
00756         {
00757             // Get the cell corresponding to this node
00758             CellPtr p_cell =  this->GetCellUsingLocationIndex(node_index);
00759 
00760             // Only bother calculating the area/volume of apoptotic cells
00761             bool cell_is_apoptotic = p_cell->HasCellProperty<ApoptoticCellProperty>();
00762             if (cell_is_apoptotic)
00763             {
00764                 double cell_volume = mpVoronoiTessellation->GetVolumeOfElement(elem_index);
00765                 apoptotic_area += cell_volume;
00766             }
00767         }
00768     }
00769     *mpCellPopulationVolumesFile << total_area << " " << apoptotic_area << "\n";
00770 }
00771 
00772 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00773 double MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetVolumeOfCell(CellPtr pCell)
00774 {
00775     // Ensure that the Voronoi tessellation exists
00776     if (mpVoronoiTessellation == NULL)
00777     {
00778         CreateVoronoiTessellation();
00779     }
00780 
00781     // Get the node index corresponding to this cell
00782     unsigned node_index = this->GetLocationIndexUsingCell(pCell);
00783 
00784     // Get the element index of the Voronoi tessellation corresponding to this node index
00785     unsigned element_index = mpVoronoiTessellation->GetVoronoiElementIndexCorrespondingToDelaunayNodeIndex(node_index);
00786 
00787     // Get the cell's volume from the Voronoi tessellation
00788     double cell_volume = mpVoronoiTessellation->GetVolumeOfElement(element_index);
00789 
00790     return cell_volume;
00791 }
00792 
00793 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00794 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::WriteCellVolumeResultsToFile()
00795 {
00796     assert (mpVoronoiTessellation != NULL);
00797     assert(SPACE_DIM==2 || SPACE_DIM==3);
00798 
00799     // Write time to file
00800     *(this->mpCellVolumesFile) << SimulationTime::Instance()->GetTime() << " ";
00801 
00803 
00804     // Loop over elements of mpVoronoiTessellation
00805     for (typename VertexMesh<ELEMENT_DIM,SPACE_DIM>::VertexElementIterator elem_iter = mpVoronoiTessellation->GetElementIteratorBegin();
00806          elem_iter != mpVoronoiTessellation->GetElementIteratorEnd();
00807          ++elem_iter)
00808     {
00809         // Get index of this element in mpVoronoiTessellation
00810         unsigned elem_index = elem_iter->GetIndex();
00811 
00812         // Get the index of the corresponding node in mrMesh
00813         unsigned node_index = mpVoronoiTessellation->GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(elem_index);
00814 
00815         // Discount ghost nodes
00816         if (!this->IsGhostNode(node_index))
00817         {
00818             // Write node index to file
00819             *(this->mpCellVolumesFile) << node_index << " ";
00820 
00821             // Get the cell corresponding to this node
00822             CellPtr p_cell = this->GetCellUsingLocationIndex(node_index);
00823 
00824             // Write cell ID to file
00825             unsigned cell_index = p_cell->GetCellId();
00826             *(this->mpCellVolumesFile) << cell_index << " ";
00827 
00828             // Write node location to file
00829             c_vector<double, SPACE_DIM> node_location = this->GetNode(node_index)->rGetLocation();
00830             for (unsigned i=0; i<SPACE_DIM; i++)
00831             {
00832                 *(this->mpCellVolumesFile) << node_location[i] << " ";
00833             }
00834 
00835             // Write cell volume (in 3D) or area (in 2D) to file
00836             double cell_volume = this->GetVolumeOfCell(p_cell);
00837             *(this->mpCellVolumesFile) << cell_volume << " ";
00838         }
00839     }
00840     *(this->mpCellVolumesFile) << "\n";
00841 
00842 }
00843 
00844 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00845 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SetWriteVtkAsPoints(bool writeVtkAsPoints)
00846 {
00847     mWriteVtkAsPoints = writeVtkAsPoints;
00848 }
00849 
00850 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00851 bool MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetWriteVtkAsPoints()
00852 {
00853     return mWriteVtkAsPoints;
00854 }
00855 
00857 //                          Spring iterator class                           //
00859 
00860 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00861 Node<SPACE_DIM>* MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringIterator::GetNodeA()
00862 {
00863     return mEdgeIter.GetNodeA();
00864 }
00865 
00866 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00867 Node<SPACE_DIM>* MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringIterator::GetNodeB()
00868 {
00869     return mEdgeIter.GetNodeB();
00870 }
00871 
00872 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00873 CellPtr MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringIterator::GetCellA()
00874 {
00875     assert((*this) != mrCellPopulation.SpringsEnd());
00876     return mrCellPopulation.GetCellUsingLocationIndex(mEdgeIter.GetNodeA()->GetIndex());
00877 }
00878 
00879 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00880 CellPtr MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringIterator::GetCellB()
00881 {
00882     assert((*this) != mrCellPopulation.SpringsEnd());
00883     return mrCellPopulation.GetCellUsingLocationIndex(mEdgeIter.GetNodeB()->GetIndex());
00884 }
00885 
00886 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00887 bool MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringIterator::operator!=(const MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringIterator& rOther)
00888 {
00889     return (mEdgeIter != rOther.mEdgeIter);
00890 }
00891 
00892 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00893 typename MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringIterator& MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringIterator::operator++()
00894 {
00895     bool edge_is_ghost = false;
00896 
00897     do
00898     {
00899         ++mEdgeIter;
00900         if (*this != mrCellPopulation.SpringsEnd())
00901         {
00902             bool a_is_ghost = mrCellPopulation.IsGhostNode(mEdgeIter.GetNodeA()->GetIndex());
00903             bool b_is_ghost = mrCellPopulation.IsGhostNode(mEdgeIter.GetNodeB()->GetIndex());
00904 
00905             edge_is_ghost = (a_is_ghost || b_is_ghost);
00906         }
00907     }
00908     while (*this!=mrCellPopulation.SpringsEnd() && edge_is_ghost);
00909 
00910     return (*this);
00911 }
00912 
00913 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00914 MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringIterator::SpringIterator(
00915             MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>& rCellPopulation,
00916             typename MutableMesh<ELEMENT_DIM,SPACE_DIM>::EdgeIterator edgeIter)
00917     : mrCellPopulation(rCellPopulation),
00918       mEdgeIter(edgeIter)
00919 {
00920     if (mEdgeIter!=static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>*>(&(this->mrCellPopulation.mrMesh))->EdgesEnd())
00921     {
00922         bool a_is_ghost = mrCellPopulation.IsGhostNode(mEdgeIter.GetNodeA()->GetIndex());
00923         bool b_is_ghost = mrCellPopulation.IsGhostNode(mEdgeIter.GetNodeB()->GetIndex());
00924 
00925         if (a_is_ghost || b_is_ghost)
00926         {
00927             ++(*this);
00928         }
00929     }
00930 }
00931 
00932 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00933 typename MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringIterator MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringsBegin()
00934 {
00935     return SpringIterator(*this, static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>&>((this->mrMesh)).EdgesBegin());
00936 }
00937 
00938 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00939 typename MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringIterator MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringsEnd()
00940 {
00941     return SpringIterator(*this, static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>&>((this->mrMesh)).EdgesEnd());
00942 }
00943 
00947 template<>
00948 void MeshBasedCellPopulation<2>::CreateVoronoiTessellation()
00949 {
00950     delete mpVoronoiTessellation;
00951 
00952     // Check if the mesh associated with this cell population is periodic
00953     bool is_mesh_periodic = false;
00954     if (dynamic_cast<Cylindrical2dMesh*>(&mrMesh))
00955     {
00956         is_mesh_periodic = true;
00957     }
00958 
00959     mpVoronoiTessellation = new VertexMesh<2, 2>(static_cast<MutableMesh<2, 2> &>((this->mrMesh)), is_mesh_periodic);
00960 }
00961 
00965 template<>
00966 void MeshBasedCellPopulation<2,3>::CreateVoronoiTessellation()
00967 {
00968     // We don't allow tessellation yet.
00969     NEVER_REACHED;
00970 }
00971 
00977 template<>
00978 void MeshBasedCellPopulation<3>::CreateVoronoiTessellation()
00979 {
00980     delete mpVoronoiTessellation;
00981     mpVoronoiTessellation = new VertexMesh<3, 3>(static_cast<MutableMesh<3, 3> &>((this->mrMesh)));
00982 }
00983 
00988 template<>
00989 void MeshBasedCellPopulation<1, 1>::CreateVoronoiTessellation()
00990 {
00991     // No 1D Voronoi tessellation
00992     NEVER_REACHED;
00993 }
00994 
00999 template<>
01000 void MeshBasedCellPopulation<1, 2>::CreateVoronoiTessellation()
01001 {
01002     // No 1D Voronoi tessellation
01003     NEVER_REACHED;
01004 }
01005 
01010 template<>
01011 void MeshBasedCellPopulation<1, 3>::CreateVoronoiTessellation()
01012 {
01013     // No 1D Voronoi tessellation
01014     NEVER_REACHED;
01015 }
01016 
01017 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01018 VertexMesh<ELEMENT_DIM,SPACE_DIM>* MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetVoronoiTessellation()
01019 {
01020     assert(mpVoronoiTessellation!=NULL);
01021     return mpVoronoiTessellation;
01022 }
01023 
01024 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01025 double MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetVolumeOfVoronoiElement(unsigned index)
01026 {
01027     unsigned element_index = mpVoronoiTessellation->GetVoronoiElementIndexCorrespondingToDelaunayNodeIndex(index);
01028     double volume = mpVoronoiTessellation->GetVolumeOfElement(element_index);
01029     return volume;
01030 }
01031 
01032 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01033 double MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetSurfaceAreaOfVoronoiElement(unsigned index)
01034 {
01035     unsigned element_index = mpVoronoiTessellation->GetVoronoiElementIndexCorrespondingToDelaunayNodeIndex(index);
01036     double surface_area = mpVoronoiTessellation->GetSurfaceAreaOfElement(element_index);
01037     return surface_area;
01038 }
01039 
01040 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01041 double MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetVoronoiEdgeLength(unsigned index1, unsigned index2)
01042 {
01043     unsigned element_index1 = mpVoronoiTessellation->GetVoronoiElementIndexCorrespondingToDelaunayNodeIndex(index1);
01044     unsigned element_index2 = mpVoronoiTessellation->GetVoronoiElementIndexCorrespondingToDelaunayNodeIndex(index2);
01045     try
01046     {
01047         double edge_length = mpVoronoiTessellation->GetEdgeLength(element_index1, element_index2);
01048         return edge_length;
01049     }
01050     catch (Exception& e)
01051     {
01052         // The edge was between two (potentially infinite) cells on the boundary of the mesh
01053         EXCEPTION("Spring iterator tried to calculate interaction between degenerate cells on the boundary of the mesh.  Have you set ghost layers correctly?");
01054     }
01055 }
01056 
01057 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01058 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::CheckCellPointers()
01059 {
01060     bool res = true;
01061     for (std::list<CellPtr>::iterator it=this->mCells.begin();
01062          it!=this->mCells.end();
01063          ++it)
01064     {
01065         CellPtr p_cell = *it;
01066         assert(p_cell);
01067         AbstractCellCycleModel* p_model = p_cell->GetCellCycleModel();
01068         assert(p_model);
01069 
01070         // Check cell exists in cell population
01071         unsigned node_index = this->GetLocationIndexUsingCell(p_cell);
01072         std::cout << "Cell at node " << node_index << " addr " << p_cell << std::endl << std::flush;
01073         CellPtr p_cell_in_cell_population = this->GetCellUsingLocationIndex(node_index);
01074 #define COVERAGE_IGNORE //Debugging code.  Shouldn't fail under normal conditions
01075         if (p_cell_in_cell_population != p_cell)
01076         {
01077             std::cout << "  Mismatch with cell population" << std::endl << std::flush;
01078             res = false;
01079         }
01080 
01081         // Check model links back to cell
01082         if (p_model->GetCell() != p_cell)
01083         {
01084             std::cout << "  Mismatch with cycle model" << std::endl << std::flush;
01085             res = false;
01086         }
01087     }
01088     assert(res);
01089 #undef COVERAGE_IGNORE
01090 
01091     res = true;
01092     for (std::set<std::pair<CellPtr,CellPtr> >::iterator it1 = this->mMarkedSprings.begin();
01093          it1 != this->mMarkedSprings.end();
01094          ++it1)
01095     {
01096         const std::pair<CellPtr,CellPtr>& r_pair = *it1;
01097 
01098         for (unsigned i=0; i<2; i++)
01099         {
01100             CellPtr p_cell = (i==0 ? r_pair.first : r_pair.second);
01101 
01102             assert(p_cell);
01103             AbstractCellCycleModel* p_model = p_cell->GetCellCycleModel();
01104             assert(p_model);
01105             unsigned node_index = this->GetLocationIndexUsingCell(p_cell);
01106             std::cout << "Cell at node " << node_index << " addr " << p_cell << std::endl << std::flush;
01107 
01108 #define COVERAGE_IGNORE //Debugging code.  Shouldn't fail under normal conditions
01109             // Check cell is alive
01110             if (p_cell->IsDead())
01111             {
01112                 std::cout << "  Cell is dead" << std::endl << std::flush;
01113                 res = false;
01114             }
01115 
01116             // Check cell exists in cell population
01117             CellPtr p_cell_in_cell_population = this->GetCellUsingLocationIndex(node_index);
01118             if (p_cell_in_cell_population != p_cell)
01119             {
01120                 std::cout << "  Mismatch with cell population" << std::endl << std::flush;
01121                 res = false;
01122             }
01123 
01124             // Check model links back to cell
01125             if (p_model->GetCell() != p_cell)
01126             {
01127                 std::cout << "  Mismatch with cycle model" << std::endl << std::flush;
01128                 res = false;
01129             }
01130         }
01131 #undef COVERAGE_IGNORE
01132     }
01133     assert(res);
01134 }
01135 
01136 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01137 double MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetAreaBasedDampingConstantParameter()
01138 {
01139     return mAreaBasedDampingConstantParameter;
01140 }
01141 
01142 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01143 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SetAreaBasedDampingConstantParameter(double areaBasedDampingConstantParameter)
01144 {
01145     assert(areaBasedDampingConstantParameter >= 0.0);
01146     mAreaBasedDampingConstantParameter = areaBasedDampingConstantParameter;
01147 }
01148 
01149 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01150 bool MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetOutputVoronoiData()
01151 {
01152     return mOutputVoronoiData;
01153 }
01154 
01155 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01156 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SetOutputVoronoiData(bool outputVoronoiData)
01157 {
01158     mOutputVoronoiData = outputVoronoiData;
01159 }
01160 
01161 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01162 bool MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetOutputCellPopulationVolumes()
01163 {
01164     return mOutputCellPopulationVolumes;
01165 }
01166 
01167 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01168 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SetOutputCellPopulationVolumes(bool outputCellPopulationVolumes)
01169 {
01170     mOutputCellPopulationVolumes = outputCellPopulationVolumes;
01171 }
01172 
01173 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01174 std::set< std::pair<Node<SPACE_DIM>*, Node<SPACE_DIM>* > >& MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::rGetNodePairs()
01175 {
01176     //mNodePairs.Clear();
01177     NEVER_REACHED;
01178     return mNodePairs;
01179 }
01180 
01181 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01182 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::OutputCellPopulationParameters(out_stream& rParamsFile)
01183 {
01184     *rParamsFile << "\t\t<UseAreaBasedDampingConstant>" << mUseAreaBasedDampingConstant << "</UseAreaBasedDampingConstant>\n";
01185     *rParamsFile << "\t\t<AreaBasedDampingConstantParameter>" <<  mAreaBasedDampingConstantParameter << "</AreaBasedDampingConstantParameter>\n";
01186     *rParamsFile << "\t\t<OutputVoronoiData>" <<  mOutputVoronoiData << "</OutputVoronoiData>\n";
01187     *rParamsFile << "\t\t<OutputCellPopulationVolumes>" << mOutputCellPopulationVolumes << "</OutputCellPopulationVolumes>\n";
01188 
01189     // Call method on direct parent class
01190     AbstractCentreBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::OutputCellPopulationParameters(rParamsFile);
01191 }
01192 
01193 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01194 double MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetWidth(const unsigned& rDimension)
01195 {
01196     // Call GetWidth() on the mesh
01197     double width = this->mrMesh.GetWidth(rDimension);
01198     return width;
01199 }
01200 
01201 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01202 std::set<unsigned> MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetNeighbouringNodeIndices(unsigned index)
01203 {
01204     // Get pointer to this node
01205     Node<SPACE_DIM>* p_node = this->mrMesh.GetNode(index);
01206 
01207     // Loop over containing elements
01208     std::set<unsigned> neighbouring_node_indices;
01209     for (typename Node<SPACE_DIM>::ContainingElementIterator elem_iter = p_node->ContainingElementsBegin();
01210          elem_iter != p_node->ContainingElementsEnd();
01211          ++elem_iter)
01212     {
01213         // Get pointer to this containing element
01214         Element<ELEMENT_DIM,SPACE_DIM>* p_element = static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>&>((this->mrMesh)).GetElement(*elem_iter);
01215 
01216         // Loop over nodes contained in this element
01217         for (unsigned i=0; i<p_element->GetNumNodes(); i++)
01218         {
01219             // Get index of this node and add its index to the set if not the original node
01220             unsigned node_index = p_element->GetNodeGlobalIndex(i);
01221             if (node_index != index)
01222             {
01223                 neighbouring_node_indices.insert(node_index);
01224             }
01225         }
01226     }
01227     return neighbouring_node_indices;
01228 }
01229 
01230 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01231 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::CalculateRestLengths()
01232 {
01233     mSpringRestLengths.clear();
01234 
01235     // Iterate over all springs and add calculate separation of adjacent  node pairs
01236     for (SpringIterator spring_iterator = SpringsBegin();
01237          spring_iterator != SpringsEnd();
01238          ++spring_iterator)
01239     {
01240         // Note that nodeA_global_index is always less than nodeB_global_index
01241         Node<SPACE_DIM>* p_nodeA = spring_iterator.GetNodeA();
01242         Node<SPACE_DIM>* p_nodeB = spring_iterator.GetNodeB();
01243 
01244         unsigned nodeA_global_index = p_nodeA->GetIndex();
01245         unsigned nodeB_global_index = p_nodeB->GetIndex();
01246 
01247         // Calculate the distance between nodes
01248         c_vector<double, SPACE_DIM> node_a_location = p_nodeA->rGetLocation();
01249         c_vector<double, SPACE_DIM> node_b_location = p_nodeB->rGetLocation();
01250 
01251        double separation = norm_2(rGetMesh().GetVectorFromAtoB(node_a_location, node_b_location));
01252 
01253        std::pair<unsigned,unsigned> node_pair (nodeA_global_index, nodeB_global_index) ;
01254 
01255        mSpringRestLengths[node_pair]= separation;
01256     }
01257     mHasVariableRestLength = true;
01258 }
01259 
01260 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01261 double MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetRestLength(unsigned indexA, unsigned indexB)
01262 {
01263     if (mHasVariableRestLength)
01264     {
01265         std::pair<unsigned,unsigned> node_pair (indexA, indexB) ;
01266 
01267         std::map<std::pair<unsigned,unsigned>, double>::const_iterator  iter = mSpringRestLengths.find(node_pair);
01268 
01269         if (iter != mSpringRestLengths.end() )
01270         {
01271             // Return the stored rest length.
01272             return iter->second;
01273         }
01274         else
01275         {
01276             NEVER_REACHED;
01278             //EXCEPTION("Tried to get a rest length of an edge that doesn't exist. You can only use variable rest lengths if SetUpdateCellPopulationRule is set on the simulation.");
01279         }
01280     }
01281     else
01282     {
01283         return 1.0;
01284     }
01285 }
01286 
01287 
01289 // Explicit instantiation
01291 
01292 template class MeshBasedCellPopulation<1,1>;
01293 template class MeshBasedCellPopulation<1,2>;
01294 template class MeshBasedCellPopulation<2,2>;
01295 template class MeshBasedCellPopulation<1,3>;
01296 template class MeshBasedCellPopulation<2,3>;
01297 template class MeshBasedCellPopulation<3,3>;
01298 
01299 // Serialization for Boost >= 1.36
01300 #include "SerializationExportWrapperForCpp.hpp"
01301 EXPORT_TEMPLATE_CLASS_ALL_DIMS(MeshBasedCellPopulation)