MeshBasedCellPopulation.cpp

00001 /*
00002 
00003 Copyright (c) 2005-2015, 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 // Cell writers
00046 #include "CellAgesWriter.hpp"
00047 #include "CellAncestorWriter.hpp"
00048 #include "CellProliferativePhasesWriter.hpp"
00049 #include "CellProliferativeTypesWriter.hpp"
00050 #include "CellVolumesWriter.hpp"
00051 
00052 // Cell population writers
00053 #include "CellMutationStatesCountWriter.hpp"
00054 #include "CellPopulationElementWriter.hpp"
00055 #include "VoronoiDataWriter.hpp"
00056 #include "NodeVelocityWriter.hpp"
00057 #include "CellPopulationAreaWriter.hpp"
00058 
00059 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00060 MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::MeshBasedCellPopulation(MutableMesh<ELEMENT_DIM,SPACE_DIM>& rMesh,
00061                                       std::vector<CellPtr>& rCells,
00062                                       const std::vector<unsigned> locationIndices,
00063                                       bool deleteMesh,
00064                                       bool validate)
00065     : AbstractCentreBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>(rMesh, rCells, locationIndices),
00066       mpVoronoiTessellation(NULL),
00067       mDeleteMesh(deleteMesh),
00068       mUseAreaBasedDampingConstant(false),
00069       mAreaBasedDampingConstantParameter(0.1),
00070       mWriteVtkAsPoints(false),
00071       mOutputMeshInVtk(false),
00072       mHasVariableRestLength(false)
00073 {
00074     mpMutableMesh = static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>* >(&(this->mrMesh));
00075 
00076     assert(this->mCells.size() <= this->mrMesh.GetNumNodes());
00077 
00078     if (validate)
00079     {
00080         Validate();
00081     }
00082 
00083     // Initialise the applied force at each node to zero
00084     for (typename AbstractMesh<ELEMENT_DIM, SPACE_DIM>::NodeIterator node_iter = this->rGetMesh().GetNodeIteratorBegin();
00085          node_iter != this->rGetMesh().GetNodeIteratorEnd();
00086          ++node_iter)
00087     {
00088         node_iter->ClearAppliedForce();
00089     }
00090 }
00091 
00092 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00093 MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::MeshBasedCellPopulation(MutableMesh<ELEMENT_DIM,SPACE_DIM>& rMesh)
00094     : AbstractCentreBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>(rMesh)
00095 {
00096     mpMutableMesh = static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>* >(&(this->mrMesh));
00097     mpVoronoiTessellation = NULL;
00098     mDeleteMesh = true;
00099 }
00100 
00101 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00102 MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::~MeshBasedCellPopulation()
00103 {
00104     delete mpVoronoiTessellation;
00105 
00106     if (mDeleteMesh)
00107     {
00108         delete &this->mrMesh;
00109     }
00110 }
00111 
00112 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00113 bool MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::UseAreaBasedDampingConstant()
00114 {
00115     return mUseAreaBasedDampingConstant;
00116 }
00117 
00118 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00119 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SetAreaBasedDampingConstant(bool useAreaBasedDampingConstant)
00120 {
00121     assert(SPACE_DIM==2);
00122     mUseAreaBasedDampingConstant = useAreaBasedDampingConstant;
00123 }
00124 
00125 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00126 unsigned MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::AddNode(Node<SPACE_DIM>* pNewNode)
00127 {
00128     return mpMutableMesh->AddNode(pNewNode);
00129 }
00130 
00131 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00132 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SetNode(unsigned nodeIndex, ChastePoint<SPACE_DIM>& rNewLocation)
00133 {
00134     static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>&>((this->mrMesh)).SetNode(nodeIndex, rNewLocation, false);
00135 }
00136 
00137 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00138 double MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetDampingConstant(unsigned nodeIndex)
00139 {
00140     double damping_multiplier = AbstractCentreBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetDampingConstant(nodeIndex);
00141 
00142     /*
00143      * The next code block computes the area-dependent damping constant as given by equation
00144      * (5) in the following reference: van Leeuwen et al. 2009. An integrative computational model
00145      * for intestinal tissue renewal. Cell Prolif. 42(5):617-636. doi:10.1111/j.1365-2184.2009.00627.x
00146      */
00147     if (mUseAreaBasedDampingConstant)
00148     {
00158         assert(SPACE_DIM==2);
00159 
00160         double rest_length = 1.0;
00161         double d0 = mAreaBasedDampingConstantParameter;
00162 
00168         double d1 = 2.0*(1.0 - d0)/(sqrt(3.0)*rest_length*rest_length);
00169 
00170         double area_cell = GetVolumeOfVoronoiElement(nodeIndex);
00171 
00177         assert(area_cell < 1000);
00178 
00179         damping_multiplier = d0 + area_cell*d1;
00180     }
00181 
00182     return damping_multiplier;
00183 }
00184 
00185 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00186 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::Validate()
00187 {
00188     std::vector<bool> validated_node = std::vector<bool>(this->GetNumNodes(), false);
00189 
00190     for (typename AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>::Iterator cell_iter=this->Begin(); cell_iter!=this->End(); ++cell_iter)
00191     {
00192         unsigned node_index = this->GetLocationIndexUsingCell(*cell_iter);
00193         validated_node[node_index] = true;
00194     }
00195 
00196     for (unsigned i=0; i<validated_node.size(); i++)
00197     {
00198         if (!validated_node[i])
00199         {
00200             EXCEPTION("At time " << SimulationTime::Instance()->GetTime() << ", Node " << i << " does not appear to have a cell associated with it");
00201         }
00202     }
00203 }
00204 
00205 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00206 MutableMesh<ELEMENT_DIM,SPACE_DIM>& MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::rGetMesh()
00207 {
00208     return *mpMutableMesh;
00209 }
00210 
00211 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00212 const MutableMesh<ELEMENT_DIM,SPACE_DIM>& MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::rGetMesh() const
00213 {
00214     return *mpMutableMesh;
00215 }
00216 
00217 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00218 unsigned MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::RemoveDeadCells()
00219 {
00220     unsigned num_removed = 0;
00221     for (std::list<CellPtr>::iterator it = this->mCells.begin();
00222          it != this->mCells.end();
00223          )
00224     {
00225         if ((*it)->IsDead())
00226         {
00227             // Check if this cell is in a marked spring
00228             std::vector<const std::pair<CellPtr,CellPtr>*> pairs_to_remove; // Pairs that must be purged
00229             for (std::set<std::pair<CellPtr,CellPtr> >::iterator it1 = this->mMarkedSprings.begin();
00230                  it1 != this->mMarkedSprings.end();
00231                  ++it1)
00232             {
00233                 const std::pair<CellPtr,CellPtr>& r_pair = *it1;
00234 
00235                 for (unsigned i=0; i<2; i++)
00236                 {
00237                     CellPtr p_cell = (i==0 ? r_pair.first : r_pair.second);
00238 
00239                     if (p_cell == *it)
00240                     {
00241                         // Remember to purge this spring
00242                         pairs_to_remove.push_back(&r_pair);
00243                         break;
00244                     }
00245                 }
00246             }
00247 
00248             // Purge any marked springs that contained this cell
00249             for (std::vector<const std::pair<CellPtr,CellPtr>* >::iterator pair_it = pairs_to_remove.begin();
00250                  pair_it != pairs_to_remove.end();
00251                  ++pair_it)
00252             {
00253                 this->mMarkedSprings.erase(**pair_it);
00254             }
00255 
00256             // Remove the node from the mesh
00257             num_removed++;
00258             static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>&>((this->mrMesh)).DeleteNodePriorToReMesh(this->GetLocationIndexUsingCell((*it)));
00259 
00260             // Update mappings between cells and location indices
00261             unsigned location_index_of_removed_node = this->GetLocationIndexUsingCell((*it));
00262             this->RemoveCellUsingLocationIndex(location_index_of_removed_node, (*it));
00263 
00264             // Update vector of cells
00265             it = this->mCells.erase(it);
00266         }
00267         else
00268         {
00269             ++it;
00270         }
00271     }
00272 
00273     return num_removed;
00274 }
00275 
00276 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00277 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::Update(bool hasHadBirthsOrDeaths)
00278 {
00280     bool output_node_velocities = (this-> template HasWriter<NodeVelocityWriter>());
00281 
00282     std::map<unsigned, c_vector<double, SPACE_DIM> > old_node_applied_force_map;
00283     old_node_applied_force_map.clear();
00284     if (output_node_velocities)
00285     {
00286         /*
00287          * If outputting node velocities, we must keep a record of the applied force at each
00288          * node, since this will be cleared during the remeshing process. We then restore
00289          * these attributes to the nodes after calling ReMesh().
00290          */
00291         for (typename AbstractMesh<ELEMENT_DIM, SPACE_DIM>::NodeIterator node_iter = this->mrMesh.GetNodeIteratorBegin();
00292              node_iter != this->mrMesh.GetNodeIteratorEnd();
00293              ++node_iter)
00294         {
00295             unsigned node_index = node_iter->GetIndex();
00296             old_node_applied_force_map[node_index] = node_iter->rGetAppliedForce();
00297         }
00298     }
00299 
00300     NodeMap node_map(this->mrMesh.GetNumAllNodes());
00301 
00302     // We must use a static_cast to call ReMesh() as this method is not defined in parent mesh classes
00303     static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>&>((this->mrMesh)).ReMesh(node_map);
00304 
00305     if (!node_map.IsIdentityMap())
00306     {
00307         UpdateGhostNodesAfterReMesh(node_map);
00308 
00309         // Update the mappings between cells and location indices
00310         std::map<Cell*, unsigned> old_cell_location_map = this->mCellLocationMap;
00311 
00312         // Remove any dead pointers from the maps (needed to avoid archiving errors)
00313         this->mLocationCellMap.clear();
00314         this->mCellLocationMap.clear();
00315 
00316         for (std::list<CellPtr>::iterator it = this->mCells.begin(); it != this->mCells.end(); ++it)
00317         {
00318             unsigned old_node_index = old_cell_location_map[(*it).get()];
00319 
00320             // This shouldn't ever happen, as the cell vector only contains living cells
00321             assert(!node_map.IsDeleted(old_node_index));
00322 
00323             unsigned new_node_index = node_map.GetNewIndex(old_node_index);
00324             this->SetCellUsingLocationIndex(new_node_index,*it);
00325 
00326             if (output_node_velocities)
00327             {
00328                 this->GetNode(new_node_index)->AddAppliedForceContribution(old_node_applied_force_map[old_node_index]);
00329             }
00330         }
00331 
00332         this->Validate();
00333     }
00334     else if (output_node_velocities)
00335     {
00336         for (std::list<CellPtr>::iterator it = this->mCells.begin(); it != this->mCells.end(); ++it)
00337         {
00338             unsigned node_index = this->mCellLocationMap[(*it).get()];
00339             this->GetNode(node_index)->AddAppliedForceContribution(old_node_applied_force_map[node_index]);
00340         }
00341     }
00342 
00343     // Purge any marked springs that are no longer springs
00344     std::vector<const std::pair<CellPtr,CellPtr>*> springs_to_remove;
00345     for (std::set<std::pair<CellPtr,CellPtr> >::iterator spring_it = this->mMarkedSprings.begin();
00346          spring_it != this->mMarkedSprings.end();
00347          ++spring_it)
00348     {
00349         CellPtr p_cell_1 = spring_it->first;
00350         CellPtr p_cell_2 = spring_it->second;
00351         Node<SPACE_DIM>* p_node_1 = this->GetNodeCorrespondingToCell(p_cell_1);
00352         Node<SPACE_DIM>* p_node_2 = this->GetNodeCorrespondingToCell(p_cell_2);
00353 
00354         bool joined = false;
00355 
00356         // For each element containing node1, if it also contains node2 then the cells are joined
00357         std::set<unsigned> node2_elements = p_node_2->rGetContainingElementIndices();
00358         for (typename Node<SPACE_DIM>::ContainingElementIterator elem_iter = p_node_1->ContainingElementsBegin();
00359              elem_iter != p_node_1->ContainingElementsEnd();
00360              ++elem_iter)
00361         {
00362             if (node2_elements.find(*elem_iter) != node2_elements.end())
00363             {
00364                 joined = true;
00365                 break;
00366             }
00367         }
00368 
00369         // If no longer joined, remove this spring from the set
00370         if (!joined)
00371         {
00372             springs_to_remove.push_back(&(*spring_it));
00373         }
00374     }
00375 
00376     // Remove any springs necessary
00377     for (std::vector<const std::pair<CellPtr,CellPtr>* >::iterator spring_it = springs_to_remove.begin();
00378          spring_it != springs_to_remove.end();
00379          ++spring_it)
00380     {
00381         this->mMarkedSprings.erase(**spring_it);
00382     }
00383 
00384     // Tessellate if needed
00385     TessellateIfNeeded();
00386 
00387     static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>&>((this->mrMesh)).SetMeshHasChangedSinceLoading();
00388 }
00389 
00390 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00391 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::TessellateIfNeeded()
00392 {
00393     if ((SPACE_DIM==2 || SPACE_DIM==3)&&(ELEMENT_DIM==SPACE_DIM))
00394     {
00395         CellBasedEventHandler::BeginEvent(CellBasedEventHandler::TESSELLATION);
00396         if (mUseAreaBasedDampingConstant ||
00397             this-> template HasWriter<VoronoiDataWriter>() ||
00398             this-> template HasWriter<CellPopulationAreaWriter>() ||
00399             this-> template HasWriter<CellVolumesWriter>())
00400         {
00401             CreateVoronoiTessellation();
00402         }
00403         CellBasedEventHandler::EndEvent(CellBasedEventHandler::TESSELLATION);
00404     }
00405 }
00406 
00407 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00408 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::DivideLongSprings(double springDivisionThreshold)
00409 {
00410     // Only implemented for 2D elements
00411     assert(ELEMENT_DIM==2);
00412 
00413     std::vector<c_vector<unsigned, 5> > new_nodes;
00414     new_nodes = rGetMesh().SplitLongEdges(springDivisionThreshold);
00415 
00416     // Add new cells onto new nodes
00417     for (unsigned index=0; index<new_nodes.size(); index++)
00418     {
00419         // Copy the cell attached to one of the neighbouring nodes onto the new node
00420         unsigned new_node_index = new_nodes[index][0];
00421         unsigned node_a_index = new_nodes[index][1];
00422         unsigned node_b_index = new_nodes[index][2];
00423 
00424          CellPtr p_neighbour_cell = this->GetCellUsingLocationIndex(node_a_index);
00425 
00426         // Create copy of cell property collection to modify for daughter cell
00427         CellPropertyCollection daughter_property_collection = p_neighbour_cell->rGetCellPropertyCollection();
00428 
00429         // Remove the CellId from the daughter cell a new one will be assigned in the constructor
00430         daughter_property_collection.RemoveProperty<CellId>();
00431 
00432         CellPtr p_new_cell(new Cell(p_neighbour_cell->GetMutationState(),
00433                                     p_neighbour_cell->GetCellCycleModel()->CreateCellCycleModel(),
00434                                     false,
00435                                     daughter_property_collection));
00436 
00437         // Add new cell to cell population
00438         this->mCells.push_back(p_new_cell);
00439         this->AddCellUsingLocationIndex(new_node_index,p_new_cell);
00440 
00441         // Update rest lengths
00442 
00443         // Remove old node pair // note node_a_index < node_b_index
00444         std::pair<unsigned,unsigned> node_pair = this->CreateOrderedPair(node_a_index, node_b_index);
00445         double old_rest_length  = mSpringRestLengths[node_pair];
00446 
00447         std::map<std::pair<unsigned,unsigned>, double>::iterator  iter = mSpringRestLengths.find(node_pair);
00448         mSpringRestLengths.erase(iter);
00449 
00450         // Add new pairs
00451         node_pair = this->CreateOrderedPair(node_a_index, new_node_index);
00452         mSpringRestLengths[node_pair] = 0.5*old_rest_length;
00453 
00454         node_pair = this->CreateOrderedPair(node_b_index, new_node_index);
00455         mSpringRestLengths[node_pair] = 0.5*old_rest_length;
00456 
00457         // If necessary add other new spring rest lengths
00458         for (unsigned pair_index=3; pair_index<5; pair_index++)
00459         {
00460             unsigned other_node_index = new_nodes[index][pair_index];
00461 
00462             if (other_node_index != UNSIGNED_UNSET)
00463             {
00464                 node_pair = this->CreateOrderedPair(other_node_index, new_node_index);
00465                 double new_rest_length = rGetMesh().GetDistanceBetweenNodes(new_node_index, other_node_index);
00466                 mSpringRestLengths[node_pair] = new_rest_length;
00467             }
00468         }
00469     }
00470 }
00471 
00472 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00473 Node<SPACE_DIM>* MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetNode(unsigned index)
00474 {
00475     return this->mrMesh.GetNode(index);
00476 }
00477 
00478 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00479 unsigned MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetNumNodes()
00480 {
00481     return this->mrMesh.GetNumAllNodes();
00482 }
00483 
00484 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00485 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::UpdateGhostNodesAfterReMesh(NodeMap& rMap)
00486 {
00487 }
00488 
00489 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00490 CellPtr MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::AddCell(CellPtr pNewCell, const c_vector<double,SPACE_DIM>& rCellDivisionVector, CellPtr pParentCell)
00491 {
00492     assert(pNewCell);
00493     assert(pParentCell);
00494 
00495     // Add new cell to cell population
00496     CellPtr p_created_cell = AbstractCentreBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::AddCell(pNewCell, rCellDivisionVector, pParentCell);
00497     assert(p_created_cell == pNewCell);
00498 
00499     // Mark spring between parent cell and new cell
00500     std::pair<CellPtr,CellPtr> cell_pair = this->CreateCellPair(pParentCell, p_created_cell);
00501     this->MarkSpring(cell_pair);
00502 
00503     // Return pointer to new cell
00504     return p_created_cell;
00505 }
00506 
00508 //                             Output methods                               //
00510 
00511 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00512 void MeshBasedCellPopulation<ELEMENT_DIM, SPACE_DIM>::OpenWritersFiles(OutputFileHandler& rOutputFileHandler)
00513 {
00514     if (this->mOutputResultsForChasteVisualizer)
00515     {
00516         if (!this-> template HasWriter<CellPopulationElementWriter>())
00517         {
00518             this-> template AddPopulationWriter<CellPopulationElementWriter>();
00519         }
00520     }
00521 
00522     AbstractCentreBasedCellPopulation<ELEMENT_DIM, SPACE_DIM>::OpenWritersFiles(rOutputFileHandler);
00523 }
00524 
00525 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00526 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::WriteResultsToFiles(const std::string& rDirectory)
00527 {
00528     if (SimulationTime::Instance()->GetTimeStepsElapsed() == 0 && this->mpVoronoiTessellation == NULL)
00529     {
00530         TessellateIfNeeded(); // Update isn't run on time-step zero
00531     }
00532 
00533     AbstractCentreBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::WriteResultsToFiles(rDirectory);
00534 }
00535 
00536 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00537 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::AcceptPopulationWriter(boost::shared_ptr<AbstractCellPopulationWriter<ELEMENT_DIM, SPACE_DIM> > pPopulationWriter)
00538 {
00539     pPopulationWriter->Visit(this);
00540 }
00541 
00542 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00543 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::AcceptPopulationCountWriter(boost::shared_ptr<AbstractCellPopulationCountWriter<ELEMENT_DIM, SPACE_DIM> > pPopulationCountWriter)
00544 {
00545     pPopulationCountWriter->Visit(this);
00546 }
00547 
00548 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00549 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::AcceptCellWriter(boost::shared_ptr<AbstractCellWriter<ELEMENT_DIM, SPACE_DIM> > pCellWriter, CellPtr pCell)
00550 {
00551     pCellWriter->VisitCell(pCell, this);
00552 }
00553 
00554 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00555 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::WriteVtkResultsToFile(const std::string& rDirectory)
00556 {
00557 #ifdef CHASTE_VTK
00558     // Store the present time as a string
00559     unsigned num_timesteps = SimulationTime::Instance()->GetTimeStepsElapsed();
00560     std::stringstream time;
00561     time << num_timesteps;
00562 
00563     // Store the number of cells for which to output data to VTK
00564     unsigned num_cells_from_mesh = GetNumNodes();
00565     if (!mWriteVtkAsPoints && (mpVoronoiTessellation != NULL))
00566     {
00567         num_cells_from_mesh = mpVoronoiTessellation->GetNumElements();
00568     }
00569 
00570     // When outputting any CellData, we assume that the first cell is representative of all cells
00571     unsigned num_cell_data_items = this->Begin()->GetCellData()->GetNumItems();
00572     std::vector<std::string> cell_data_names = this->Begin()->GetCellData()->GetKeys();
00573 
00574     std::vector<std::vector<double> > cell_data;
00575     for (unsigned var=0; var<num_cell_data_items; var++)
00576     {
00577         std::vector<double> cell_data_var(num_cells_from_mesh);
00578         cell_data.push_back(cell_data_var);
00579     }
00580 
00581     if (mOutputMeshInVtk)
00582     {
00583         // Create mesh writer for VTK output
00584         VtkMeshWriter<ELEMENT_DIM, SPACE_DIM> mesh_writer(rDirectory, "mesh_"+time.str(), false);
00585         mesh_writer.WriteFilesUsingMesh(rGetMesh());
00586     }
00587 
00588     if (mWriteVtkAsPoints)
00589     {
00590         // Create mesh writer for VTK output
00591         VtkMeshWriter<SPACE_DIM, SPACE_DIM> cells_writer(rDirectory, "results_"+time.str(), false);
00592 
00593         // Iterate over any cell writers that are present
00594         unsigned num_cells = this->GetNumAllCells();
00595         for (typename std::vector<boost::shared_ptr<AbstractCellWriter<ELEMENT_DIM, SPACE_DIM> > >::iterator cell_writer_iter = this->mCellWriters.begin();
00596              cell_writer_iter != this->mCellWriters.end();
00597              ++cell_writer_iter)
00598         {
00599             // Create vector to store VTK cell data
00600             std::vector<double> vtk_cell_data(num_cells);
00601 
00602             // Loop over cells
00603             for (typename AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>::Iterator cell_iter = this->Begin();
00604                  cell_iter != this->End();
00605                  ++cell_iter)
00606             {
00607                 // Get the node index corresponding to this cell
00608                 unsigned node_index = this->GetLocationIndexUsingCell(*cell_iter);
00609 
00610                 // Populate the vector of VTK cell data
00611                 vtk_cell_data[node_index] = (*cell_writer_iter)->GetCellDataForVtkOutput(*cell_iter, this);
00612             }
00613 
00614             cells_writer.AddPointData((*cell_writer_iter)->GetVtkCellDataName(), vtk_cell_data);
00615         }
00616 
00617         // Loop over cells
00618         for (typename AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>::Iterator cell_iter = this->Begin();
00619              cell_iter != this->End();
00620              ++cell_iter)
00621         {
00622             // Get the node index corresponding to this cell
00623             unsigned node_index = this->GetLocationIndexUsingCell(*cell_iter);
00624 
00625             for (unsigned var=0; var<num_cell_data_items; var++)
00626             {
00627                 cell_data[var][node_index] = cell_iter->GetCellData()->GetItem(cell_data_names[var]);
00628             }
00629         }
00630         for (unsigned var=0; var<num_cell_data_items; var++)
00631         {
00632             cells_writer.AddPointData(cell_data_names[var], cell_data[var]);
00633         }
00634 
00635         // Make a copy of the nodes in a disposable mesh for writing
00636         {
00637             std::vector<Node<SPACE_DIM>* > nodes;
00638             for (unsigned index=0; index<this->mrMesh.GetNumNodes(); index++)
00639             {
00640                 Node<SPACE_DIM>* p_node = this->mrMesh.GetNode(index);
00641                 nodes.push_back(p_node);
00642             }
00643 
00644             NodesOnlyMesh<SPACE_DIM> mesh;
00645             mesh.ConstructNodesWithoutMesh(nodes, 1.5); // Arbitrary cut off as connectivity not used.
00646             cells_writer.WriteFilesUsingMesh(mesh);
00647         }
00648 
00649         *(this->mpVtkMetaFile) << "        <DataSet timestep=\"";
00650         *(this->mpVtkMetaFile) << num_timesteps;
00651         *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_";
00652         *(this->mpVtkMetaFile) << num_timesteps;
00653         *(this->mpVtkMetaFile) << ".vtu\"/>\n";
00654     }
00655     else if (mpVoronoiTessellation != NULL)
00656     {
00657         // Create mesh writer for VTK output
00658         VertexMeshWriter<ELEMENT_DIM, SPACE_DIM> mesh_writer(rDirectory, "results", false);
00659         std::vector<double> cell_volumes(num_cells_from_mesh);
00660 
00661         // Iterate over any cell writers that are present
00662         unsigned num_cells = this->GetNumAllCells();
00663         for (typename std::vector<boost::shared_ptr<AbstractCellWriter<ELEMENT_DIM, SPACE_DIM> > >::iterator cell_writer_iter = this->mCellWriters.begin();
00664              cell_writer_iter != this->mCellWriters.end();
00665              ++cell_writer_iter)
00666         {
00667             // Create vector to store VTK cell data
00668             std::vector<double> vtk_cell_data(num_cells);
00669 
00670             // Loop over elements of mpVoronoiTessellation
00671             for (typename VertexMesh<ELEMENT_DIM, SPACE_DIM>::VertexElementIterator elem_iter = mpVoronoiTessellation->GetElementIteratorBegin();
00672                  elem_iter != mpVoronoiTessellation->GetElementIteratorEnd();
00673                  ++elem_iter)
00674             {
00675                 // Get index of this element in mpVoronoiTessellation
00676                 unsigned elem_index = elem_iter->GetIndex();
00677 
00678                 // Get the cell corresponding to this element, via the index of the corresponding node in mrMesh
00679                 unsigned node_index = mpVoronoiTessellation->GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(elem_index);
00680                 CellPtr p_cell = this->GetCellUsingLocationIndex(node_index);
00681 
00682                 // Populate the vector of VTK cell data
00683                 vtk_cell_data[elem_index] = (*cell_writer_iter)->GetCellDataForVtkOutput(p_cell, this);
00684             }
00685 
00686             mesh_writer.AddCellData((*cell_writer_iter)->GetVtkCellDataName(), vtk_cell_data);
00687         }
00688 
00689         // Loop over elements of mpVoronoiTessellation
00690         for (typename VertexMesh<ELEMENT_DIM, SPACE_DIM>::VertexElementIterator elem_iter = mpVoronoiTessellation->GetElementIteratorBegin();
00691              elem_iter != mpVoronoiTessellation->GetElementIteratorEnd();
00692              ++elem_iter)
00693         {
00694             // Get index of this element in mpVoronoiTessellation
00695             unsigned elem_index = elem_iter->GetIndex();
00696 
00697             // Get the cell corresponding to this element, via the index of the corresponding node in mrMesh
00698             unsigned node_index = mpVoronoiTessellation->GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(elem_index);
00699             CellPtr p_cell = this->GetCellUsingLocationIndex(node_index);
00700 
00701             for (unsigned var=0; var<num_cell_data_items; var++)
00702             {
00703                 cell_data[var][elem_index] = p_cell->GetCellData()->GetItem(cell_data_names[var]);
00704             }
00705         }
00706 
00707         for (unsigned var=0; var<cell_data.size(); var++)
00708         {
00709             mesh_writer.AddCellData(cell_data_names[var], cell_data[var]);
00710         }
00711 
00712         mesh_writer.WriteVtkUsingMesh(*mpVoronoiTessellation, time.str());
00713         *(this->mpVtkMetaFile) << "        <DataSet timestep=\"";
00714         *(this->mpVtkMetaFile) << num_timesteps;
00715         *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_";
00716         *(this->mpVtkMetaFile) << num_timesteps;
00717         *(this->mpVtkMetaFile) << ".vtu\"/>\n";
00718     }
00719 #endif //CHASTE_VTK
00720 }
00721 
00722 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00723 double MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetVolumeOfCell(CellPtr pCell)
00724 {
00725     double cell_volume = 0;
00726 
00727     if (ELEMENT_DIM == SPACE_DIM)
00728     {
00729         // Ensure that the Voronoi tessellation exists
00730         if (mpVoronoiTessellation == NULL)
00731         {
00732             CreateVoronoiTessellation();
00733         }
00734 
00735         // Get the node index corresponding to this cell
00736         unsigned node_index = this->GetLocationIndexUsingCell(pCell);
00737 
00738         // Try to get the element index of the Voronoi tessellation corresponding to this node index
00739         try
00740         {
00741             unsigned element_index = mpVoronoiTessellation->GetVoronoiElementIndexCorrespondingToDelaunayNodeIndex(node_index);
00742 
00743             // Get the cell's volume from the Voronoi tessellation
00744             cell_volume = mpVoronoiTessellation->GetVolumeOfElement(element_index);
00745         }
00746         catch (Exception&)
00747         {
00748             // If it doesn't exist this must be a boundary cell, so return infinite volume.
00749             cell_volume = DBL_MAX;
00750         }
00751     }
00752     else if (SPACE_DIM==3 && ELEMENT_DIM==2)
00753     {
00754         unsigned node_index = this->GetLocationIndexUsingCell(pCell);
00755 
00756         Node<SPACE_DIM>* p_node = rGetMesh().GetNode(node_index);
00757 
00758         assert(p_node->rGetContainingElementIndices().size()>0);
00759 
00760         for (typename Node<SPACE_DIM>::ContainingElementIterator elem_iter = p_node->ContainingElementsBegin();
00761              elem_iter != p_node->ContainingElementsEnd();
00762              ++elem_iter)
00763         {
00764             Element<ELEMENT_DIM,SPACE_DIM>* p_element = rGetMesh().GetElement(*elem_iter);
00765 
00766             c_matrix<double, SPACE_DIM, ELEMENT_DIM> jacob;
00767             double det;
00768 
00769             p_element->CalculateJacobian(jacob, det);
00770 
00771             cell_volume += fabs(p_element->GetVolume(det));
00772         }
00773 
00774         // This calculation adds a third of each element to the total area.
00775         cell_volume /= 3.0;
00776     }
00777     else
00778     {
00779         // Not implemented for other dimensions
00780         NEVER_REACHED;
00781     }
00782 
00783     return cell_volume;
00784 }
00785 
00786 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00787 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SetWriteVtkAsPoints(bool writeVtkAsPoints)
00788 {
00789     mWriteVtkAsPoints = writeVtkAsPoints;
00790 }
00791 
00792 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00793 bool MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetWriteVtkAsPoints()
00794 {
00795     return mWriteVtkAsPoints;
00796 }
00797 
00798 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00799 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SetOutputMeshInVtk(bool outputMeshInVtk)
00800 {
00801     mOutputMeshInVtk = outputMeshInVtk;
00802 }
00803 
00804 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00805 bool MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetOutputMeshInVtk()
00806 {
00807     return mOutputMeshInVtk;
00808 }
00809 
00811 //                          Spring iterator class                           //
00813 
00814 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00815 Node<SPACE_DIM>* MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringIterator::GetNodeA()
00816 {
00817     return mEdgeIter.GetNodeA();
00818 }
00819 
00820 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00821 Node<SPACE_DIM>* MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringIterator::GetNodeB()
00822 {
00823     return mEdgeIter.GetNodeB();
00824 }
00825 
00826 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00827 CellPtr MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringIterator::GetCellA()
00828 {
00829     assert((*this) != mrCellPopulation.SpringsEnd());
00830     return mrCellPopulation.GetCellUsingLocationIndex(mEdgeIter.GetNodeA()->GetIndex());
00831 }
00832 
00833 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00834 CellPtr MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringIterator::GetCellB()
00835 {
00836     assert((*this) != mrCellPopulation.SpringsEnd());
00837     return mrCellPopulation.GetCellUsingLocationIndex(mEdgeIter.GetNodeB()->GetIndex());
00838 }
00839 
00840 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00841 bool MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringIterator::operator!=(const typename MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringIterator& rOther)
00842 {
00843     return (mEdgeIter != rOther.mEdgeIter);
00844 }
00845 
00846 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00847 typename MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringIterator& MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringIterator::operator++()
00848 {
00849     bool edge_is_ghost = false;
00850 
00851     do
00852     {
00853         ++mEdgeIter;
00854         if (*this != mrCellPopulation.SpringsEnd())
00855         {
00856             bool a_is_ghost = mrCellPopulation.IsGhostNode(mEdgeIter.GetNodeA()->GetIndex());
00857             bool b_is_ghost = mrCellPopulation.IsGhostNode(mEdgeIter.GetNodeB()->GetIndex());
00858 
00859             edge_is_ghost = (a_is_ghost || b_is_ghost);
00860         }
00861     }
00862     while (*this!=mrCellPopulation.SpringsEnd() && edge_is_ghost);
00863 
00864     return (*this);
00865 }
00866 
00867 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00868 MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringIterator::SpringIterator(
00869             MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>& rCellPopulation,
00870             typename MutableMesh<ELEMENT_DIM,SPACE_DIM>::EdgeIterator edgeIter)
00871     : mrCellPopulation(rCellPopulation),
00872       mEdgeIter(edgeIter)
00873 {
00874     if (mEdgeIter!=static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>*>(&(this->mrCellPopulation.mrMesh))->EdgesEnd())
00875     {
00876         bool a_is_ghost = mrCellPopulation.IsGhostNode(mEdgeIter.GetNodeA()->GetIndex());
00877         bool b_is_ghost = mrCellPopulation.IsGhostNode(mEdgeIter.GetNodeB()->GetIndex());
00878 
00879         if (a_is_ghost || b_is_ghost)
00880         {
00881             ++(*this);
00882         }
00883     }
00884 }
00885 
00886 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00887 typename MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringIterator MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringsBegin()
00888 {
00889     return SpringIterator(*this, static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>&>((this->mrMesh)).EdgesBegin());
00890 }
00891 
00892 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00893 typename MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringIterator MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringsEnd()
00894 {
00895     return SpringIterator(*this, static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>&>((this->mrMesh)).EdgesEnd());
00896 }
00897 
00901 template<>
00902 void MeshBasedCellPopulation<2>::CreateVoronoiTessellation()
00903 {
00904     delete mpVoronoiTessellation;
00905 
00906     // Check if the mesh associated with this cell population is periodic
00907     bool is_mesh_periodic = false;
00908     if (dynamic_cast<Cylindrical2dMesh*>(&mrMesh))
00909     {
00910         is_mesh_periodic = true;
00911     }
00912 
00913     mpVoronoiTessellation = new VertexMesh<2, 2>(static_cast<MutableMesh<2, 2> &>((this->mrMesh)), is_mesh_periodic);
00914 }
00915 
00919 template<>
00920 void MeshBasedCellPopulation<2,3>::CreateVoronoiTessellation()
00921 {
00922     // We don't allow tessellation yet.
00923     NEVER_REACHED;
00924 }
00925 
00931 template<>
00932 void MeshBasedCellPopulation<3>::CreateVoronoiTessellation()
00933 {
00934     delete mpVoronoiTessellation;
00935     mpVoronoiTessellation = new VertexMesh<3, 3>(static_cast<MutableMesh<3, 3> &>((this->mrMesh)));
00936 }
00937 
00942 template<>
00943 void MeshBasedCellPopulation<1, 1>::CreateVoronoiTessellation()
00944 {
00945     // No 1D Voronoi tessellation
00946     NEVER_REACHED;
00947 }
00948 
00953 template<>
00954 void MeshBasedCellPopulation<1, 2>::CreateVoronoiTessellation()
00955 {
00956     // No 1D Voronoi tessellation
00957     NEVER_REACHED;
00958 }
00959 
00964 template<>
00965 void MeshBasedCellPopulation<1, 3>::CreateVoronoiTessellation()
00966 {
00967     // No 1D Voronoi tessellation
00968     NEVER_REACHED;
00969 }
00970 
00971 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00972 VertexMesh<ELEMENT_DIM,SPACE_DIM>* MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetVoronoiTessellation()
00973 {
00974     assert(mpVoronoiTessellation!=NULL);
00975     return mpVoronoiTessellation;
00976 }
00977 
00978 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00979 double MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetVolumeOfVoronoiElement(unsigned index)
00980 {
00981     unsigned element_index = mpVoronoiTessellation->GetVoronoiElementIndexCorrespondingToDelaunayNodeIndex(index);
00982     double volume = mpVoronoiTessellation->GetVolumeOfElement(element_index);
00983     return volume;
00984 }
00985 
00986 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00987 double MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetSurfaceAreaOfVoronoiElement(unsigned index)
00988 {
00989     unsigned element_index = mpVoronoiTessellation->GetVoronoiElementIndexCorrespondingToDelaunayNodeIndex(index);
00990     double surface_area = mpVoronoiTessellation->GetSurfaceAreaOfElement(element_index);
00991     return surface_area;
00992 }
00993 
00994 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00995 double MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetVoronoiEdgeLength(unsigned index1, unsigned index2)
00996 {
00997     unsigned element_index1 = mpVoronoiTessellation->GetVoronoiElementIndexCorrespondingToDelaunayNodeIndex(index1);
00998     unsigned element_index2 = mpVoronoiTessellation->GetVoronoiElementIndexCorrespondingToDelaunayNodeIndex(index2);
00999     try
01000     {
01001         double edge_length = mpVoronoiTessellation->GetEdgeLength(element_index1, element_index2);
01002         return edge_length;
01003     }
01004     catch (Exception&)
01005     {
01006         // The edge was between two (potentially infinite) cells on the boundary of the mesh
01007         EXCEPTION("Spring iterator tried to calculate interaction between degenerate cells on the boundary of the mesh.  Have you set ghost layers correctly?");
01008     }
01009 }
01010 
01011 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01012 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::CheckCellPointers()
01013 {
01014     bool res = true;
01015     for (std::list<CellPtr>::iterator it=this->mCells.begin();
01016          it!=this->mCells.end();
01017          ++it)
01018     {
01019         CellPtr p_cell = *it;
01020         assert(p_cell);
01021         AbstractCellCycleModel* p_model = p_cell->GetCellCycleModel();
01022         assert(p_model);
01023 
01024         // Check cell exists in cell population
01025         unsigned node_index = this->GetLocationIndexUsingCell(p_cell);
01026         std::cout << "Cell at node " << node_index << " addr " << p_cell << std::endl << std::flush;
01027         CellPtr p_cell_in_cell_population = this->GetCellUsingLocationIndex(node_index);
01028 #define COVERAGE_IGNORE //Debugging code.  Shouldn't fail under normal conditions
01029         if (p_cell_in_cell_population != p_cell)
01030         {
01031             std::cout << "  Mismatch with cell population" << std::endl << std::flush;
01032             res = false;
01033         }
01034 
01035         // Check model links back to cell
01036         if (p_model->GetCell() != p_cell)
01037         {
01038             std::cout << "  Mismatch with cycle model" << std::endl << std::flush;
01039             res = false;
01040         }
01041     }
01042     UNUSED_OPT(res);
01043     assert(res);
01044 #undef COVERAGE_IGNORE
01045 
01046     res = true;
01047     for (std::set<std::pair<CellPtr,CellPtr> >::iterator it1 = this->mMarkedSprings.begin();
01048          it1 != this->mMarkedSprings.end();
01049          ++it1)
01050     {
01051         const std::pair<CellPtr,CellPtr>& r_pair = *it1;
01052 
01053         for (unsigned i=0; i<2; i++)
01054         {
01055             CellPtr p_cell = (i==0 ? r_pair.first : r_pair.second);
01056 
01057             assert(p_cell);
01058             AbstractCellCycleModel* p_model = p_cell->GetCellCycleModel();
01059             assert(p_model);
01060             unsigned node_index = this->GetLocationIndexUsingCell(p_cell);
01061             std::cout << "Cell at node " << node_index << " addr " << p_cell << std::endl << std::flush;
01062 
01063 #define COVERAGE_IGNORE //Debugging code.  Shouldn't fail under normal conditions
01064             // Check cell is alive
01065             if (p_cell->IsDead())
01066             {
01067                 std::cout << "  Cell is dead" << std::endl << std::flush;
01068                 res = false;
01069             }
01070 
01071             // Check cell exists in cell population
01072             CellPtr p_cell_in_cell_population = this->GetCellUsingLocationIndex(node_index);
01073             if (p_cell_in_cell_population != p_cell)
01074             {
01075                 std::cout << "  Mismatch with cell population" << std::endl << std::flush;
01076                 res = false;
01077             }
01078 
01079             // Check model links back to cell
01080             if (p_model->GetCell() != p_cell)
01081             {
01082                 std::cout << "  Mismatch with cycle model" << std::endl << std::flush;
01083                 res = false;
01084             }
01085         }
01086 #undef COVERAGE_IGNORE
01087     }
01088     assert(res);
01089 }
01090 
01091 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01092 double MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetAreaBasedDampingConstantParameter()
01093 {
01094     return mAreaBasedDampingConstantParameter;
01095 }
01096 
01097 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01098 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SetAreaBasedDampingConstantParameter(double areaBasedDampingConstantParameter)
01099 {
01100     assert(areaBasedDampingConstantParameter >= 0.0);
01101     mAreaBasedDampingConstantParameter = areaBasedDampingConstantParameter;
01102 }
01103 
01104 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01105 std::vector< std::pair<Node<SPACE_DIM>*, Node<SPACE_DIM>* > >& MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::rGetNodePairs()
01106 {
01107     //mNodePairs.Clear();
01108     NEVER_REACHED;
01109     return mNodePairs;
01110 }
01111 
01112 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01113 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::OutputCellPopulationParameters(out_stream& rParamsFile)
01114 {
01115     *rParamsFile << "\t\t<UseAreaBasedDampingConstant>" << mUseAreaBasedDampingConstant << "</UseAreaBasedDampingConstant>\n";
01116     *rParamsFile << "\t\t<AreaBasedDampingConstantParameter>" <<  mAreaBasedDampingConstantParameter << "</AreaBasedDampingConstantParameter>\n";
01117     *rParamsFile << "\t\t<WriteVtkAsPoints>" << mWriteVtkAsPoints << "</WriteVtkAsPoints>\n";
01118     *rParamsFile << "\t\t<OutputMeshInVtk>" << mOutputMeshInVtk << "</OutputMeshInVtk>\n";
01119     *rParamsFile << "\t\t<HasVariableRestLength>" << mHasVariableRestLength << "</HasVariableRestLength>\n";
01120 
01121     // Call method on direct parent class
01122     AbstractCentreBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::OutputCellPopulationParameters(rParamsFile);
01123 }
01124 
01125 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01126 double MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetWidth(const unsigned& rDimension)
01127 {
01128     // Call GetWidth() on the mesh
01129     double width = this->mrMesh.GetWidth(rDimension);
01130     return width;
01131 }
01132 
01133 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01134 std::set<unsigned> MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetNeighbouringNodeIndices(unsigned index)
01135 {
01136     // Get pointer to this node
01137     Node<SPACE_DIM>* p_node = this->mrMesh.GetNode(index);
01138 
01139     // Loop over containing elements
01140     std::set<unsigned> neighbouring_node_indices;
01141     for (typename Node<SPACE_DIM>::ContainingElementIterator elem_iter = p_node->ContainingElementsBegin();
01142          elem_iter != p_node->ContainingElementsEnd();
01143          ++elem_iter)
01144     {
01145         // Get pointer to this containing element
01146         Element<ELEMENT_DIM,SPACE_DIM>* p_element = static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>&>((this->mrMesh)).GetElement(*elem_iter);
01147 
01148         // Loop over nodes contained in this element
01149         for (unsigned i=0; i<p_element->GetNumNodes(); i++)
01150         {
01151             // Get index of this node and add its index to the set if not the original node
01152             unsigned node_index = p_element->GetNodeGlobalIndex(i);
01153             if (node_index != index)
01154             {
01155                 neighbouring_node_indices.insert(node_index);
01156             }
01157         }
01158     }
01159     return neighbouring_node_indices;
01160 }
01161 
01162 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01163 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::CalculateRestLengths()
01164 {
01165     mSpringRestLengths.clear();
01166 
01167     // Iterate over all springs and add calculate separation of adjacent  node pairs
01168     for (SpringIterator spring_iterator = SpringsBegin();
01169          spring_iterator != SpringsEnd();
01170          ++spring_iterator)
01171     {
01172         // Note that nodeA_global_index is always less than nodeB_global_index
01173         Node<SPACE_DIM>* p_nodeA = spring_iterator.GetNodeA();
01174         Node<SPACE_DIM>* p_nodeB = spring_iterator.GetNodeB();
01175 
01176         unsigned nodeA_global_index = p_nodeA->GetIndex();
01177         unsigned nodeB_global_index = p_nodeB->GetIndex();
01178 
01179         // Calculate the distance between nodes
01180         double separation = rGetMesh().GetDistanceBetweenNodes(nodeA_global_index, nodeB_global_index);
01181 
01182         // Order node indices
01183         std::pair<unsigned,unsigned> node_pair = this->CreateOrderedPair(nodeA_global_index, nodeB_global_index);
01184 
01185         mSpringRestLengths[node_pair] = separation;
01186     }
01187     mHasVariableRestLength = true;
01188 }
01189 
01190 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01191 double MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetRestLength(unsigned indexA, unsigned indexB)
01192 {
01193     if (mHasVariableRestLength)
01194     {
01195         std::pair<unsigned,unsigned> node_pair = this->CreateOrderedPair(indexA, indexB);
01196         std::map<std::pair<unsigned,unsigned>, double>::const_iterator iter = mSpringRestLengths.find(node_pair);
01197 
01198         if (iter != mSpringRestLengths.end())
01199         {
01200             // Return the stored rest length
01201             return iter->second;
01202         }
01203         else
01204         {
01205             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.");
01206         }
01207     }
01208     else
01209     {
01210         return 1.0;
01211     }
01212 }
01213 
01214 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01215 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SetRestLength(unsigned indexA, unsigned indexB, double restLength)
01216 {
01217     if (mHasVariableRestLength)
01218     {
01219         std::pair<unsigned,unsigned> node_pair = this->CreateOrderedPair(indexA, indexB);
01220         std::map<std::pair<unsigned,unsigned>, double>::iterator iter = mSpringRestLengths.find(node_pair);
01221 
01222         if (iter != mSpringRestLengths.end())
01223         {
01224             // modify the stored rest length
01225             iter->second = restLength;
01226         }
01227         else
01228         {
01229             EXCEPTION("Tried to set the rest length of an edge not in the mesh.");
01230         }
01231     }
01232     else
01233     {
01234         EXCEPTION("Tried to set a rest length in a simulation with fixed rest length. You can only use variable rest lengths if SetUpdateCellPopulationRule is set on the simulation.");
01235     }
01236 }
01237 
01238 // Explicit instantiation
01239 template class MeshBasedCellPopulation<1,1>;
01240 template class MeshBasedCellPopulation<1,2>;
01241 template class MeshBasedCellPopulation<2,2>;
01242 template class MeshBasedCellPopulation<1,3>;
01243 template class MeshBasedCellPopulation<2,3>;
01244 template class MeshBasedCellPopulation<3,3>;
01245 
01246 // Serialization for Boost >= 1.36
01247 #include "SerializationExportWrapperForCpp.hpp"
01248 EXPORT_TEMPLATE_CLASS_ALL_DIMS(MeshBasedCellPopulation)

Generated by  doxygen 1.6.2