MeshBasedCellPopulation.cpp

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