MeshBasedCellPopulation.cpp

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

Generated by  doxygen 1.6.2