MeshBasedTissue.cpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2010
00004 
00005 University of Oxford means the Chancellor, Masters and Scholars of the
00006 University of Oxford, having an administrative office at Wellington
00007 Square, Oxford OX1 2JD, UK.
00008 
00009 This file is part of Chaste.
00010 
00011 Chaste is free software: you can redistribute it and/or modify it
00012 under the terms of the GNU Lesser General Public License as published
00013 by the Free Software Foundation, either version 2.1 of the License, or
00014 (at your option) any later version.
00015 
00016 Chaste is distributed in the hope that it will be useful, but WITHOUT
00017 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
00019 License for more details. The offer of Chaste under the terms of the
00020 License is subject to the License being interpreted in accordance with
00021 English Law and subject to any action against the University of Oxford
00022 being under the jurisdiction of the English Courts.
00023 
00024 You should have received a copy of the GNU Lesser General Public License
00025 along with Chaste. If not, see <http://www.gnu.org/licenses/>.
00026 
00027 */
00028 #include "MeshBasedTissue.hpp"
00029 #include "TrianglesMeshWriter.hpp"
00030 #include "CellBasedEventHandler.hpp"
00031 
00032 template<unsigned DIM>
00033 MeshBasedTissue<DIM>::MeshBasedTissue(MutableMesh<DIM, DIM>& rMesh,
00034                                       std::vector<TissueCell>& rCells,
00035                                       const std::vector<unsigned> locationIndices,
00036                                       bool deleteMesh,
00037                                       bool validate)
00038     : AbstractCellCentreBasedTissue<DIM>(rCells, locationIndices),
00039       mrMesh(rMesh),
00040       mpVoronoiTessellation(NULL),
00041       mDeleteMesh(deleteMesh),
00042       mUseAreaBasedDampingConstant(false)
00043 {
00044     // This must always be true
00045     assert(this->mCells.size() <= mrMesh.GetNumNodes());
00046 
00047     this->mTissueContainsMesh = true;
00048 
00049     if (validate)
00050     {
00051         Validate();
00052     }
00053 }
00054 
00055 template<unsigned DIM>
00056 MeshBasedTissue<DIM>::MeshBasedTissue(MutableMesh<DIM, DIM>& rMesh)
00057              : mrMesh(rMesh)
00058 {
00059     this->mTissueContainsMesh = true;
00060     mpVoronoiTessellation = NULL;
00061     mDeleteMesh = true;
00062 }
00063 
00064 template<unsigned DIM>
00065 MeshBasedTissue<DIM>::~MeshBasedTissue()
00066 {
00067     delete mpVoronoiTessellation;
00068     if (mDeleteMesh)
00069     {
00070         delete &mrMesh;
00071     }
00072 }
00073 
00074 template<unsigned DIM>
00075 bool MeshBasedTissue<DIM>::UseAreaBasedDampingConstant()
00076 {
00077     return mUseAreaBasedDampingConstant;
00078 }
00079 
00080 template<unsigned DIM>
00081 void MeshBasedTissue<DIM>::SetAreaBasedDampingConstant(bool useAreaBasedDampingConstant)
00082 {
00083     #define COVERAGE_IGNORE
00084     assert(DIM==2);
00085     #undef COVERAGE_IGNORE
00086     mUseAreaBasedDampingConstant = useAreaBasedDampingConstant;
00087 }
00088 
00089 template<unsigned DIM>
00090 unsigned MeshBasedTissue<DIM>::AddNode(Node<DIM>* pNewNode)
00091 {
00092     return mrMesh.AddNode(pNewNode);
00093 }
00094 
00095 template<unsigned DIM>
00096 void MeshBasedTissue<DIM>::SetNode(unsigned nodeIndex, ChastePoint<DIM>& rNewLocation)
00097 {
00098     mrMesh.SetNode(nodeIndex, rNewLocation, false);
00099 }
00100 
00101 template<unsigned DIM>
00102 double MeshBasedTissue<DIM>::GetDampingConstant(unsigned nodeIndex)
00103 {
00104     double damping_multiplier = AbstractCellCentreBasedTissue<DIM>::GetDampingConstant(nodeIndex);
00105 
00106     if (mUseAreaBasedDampingConstant)
00107     {
00117         #define COVERAGE_IGNORE
00118         assert(DIM==2);
00119         #undef COVERAGE_IGNORE
00120 
00121         double rest_length = 1.0;
00122         double d0 = TissueConfig::Instance()->GetAreaBasedDampingConstantParameter();
00123 
00129         double d1 = 2.0*(1.0 - d0)/(sqrt(3)*rest_length*rest_length);
00130 
00131         VoronoiTessellation<DIM>& tess = this->rGetVoronoiTessellation();
00132 
00133         double area_cell = tess.GetFaceArea(nodeIndex);
00134 
00140         assert(area_cell < 1000);
00141 
00142         damping_multiplier = d0 + area_cell*d1;
00143     }
00144 
00145     return damping_multiplier;
00146 }
00147 
00148 template<unsigned DIM>
00149 void MeshBasedTissue<DIM>::Validate()
00150 {
00151     std::vector<bool> validated_node = std::vector<bool>(this->GetNumNodes(), false);
00152 
00153     for (typename AbstractTissue<DIM>::Iterator cell_iter=this->Begin(); cell_iter!=this->End(); ++cell_iter)
00154     {
00155         unsigned node_index = GetLocationIndexUsingCell(*cell_iter);
00156         validated_node[node_index] = true;
00157     }
00158 
00159     for (unsigned i=0; i<validated_node.size(); i++)
00160     {
00161         if (!validated_node[i])
00162         {
00163             std::stringstream ss;
00164             ss << "Node " << i << " does not appear to have a cell associated with it";
00165             EXCEPTION(ss.str());
00166         }
00167     }
00168 }
00169 
00170 template<unsigned DIM>
00171 MutableMesh<DIM, DIM>& MeshBasedTissue<DIM>::rGetMesh()
00172 {
00173     return mrMesh;
00174 }
00175 
00176 template<unsigned DIM>
00177 const MutableMesh<DIM, DIM>& MeshBasedTissue<DIM>::rGetMesh() const
00178 {
00179     return mrMesh;
00180 }
00181 
00182 template<unsigned DIM>
00183 unsigned MeshBasedTissue<DIM>::RemoveDeadCells()
00184 {
00185     unsigned num_removed = 0;
00186     for (std::list<TissueCell>::iterator it = this->mCells.begin();
00187          it != this->mCells.end();
00188          ++it)
00189     {
00190         if (it->IsDead())
00191         {
00192             // Check if this cell is in a marked spring
00193             std::vector<const std::set<TissueCell*>*> pairs_to_remove; // Pairs that must be purged
00194             for (std::set<std::set<TissueCell*> >::iterator it1 = mMarkedSprings.begin();
00195                  it1 != mMarkedSprings.end();
00196                  ++it1)
00197             {
00198                 const std::set<TissueCell*>& r_pair = *it1;
00199                 for (std::set<TissueCell*>::iterator it2 = r_pair.begin();
00200                      it2 != r_pair.end();
00201                      ++it2)
00202                 {
00203                     if (*it2 == &(*it))
00204                     {
00205                         // Remember to purge this spring
00206                         pairs_to_remove.push_back(&r_pair);
00207                         break;
00208                     }
00209                 }
00210             }
00211             // Purge any marked springs that contained this cell
00212             for (std::vector<const std::set<TissueCell*>* >::iterator pair_it = pairs_to_remove.begin();
00213                  pair_it != pairs_to_remove.end();
00214                  ++pair_it)
00215             {
00216                 mMarkedSprings.erase(**pair_it);
00217             }
00218 
00219             // Remove the node from the mesh
00220             num_removed++;
00221             mrMesh.DeleteNodePriorToReMesh(this->mCellLocationMap[&(*it)]);
00222 
00223             // Update mappings between cells and location indices
00224             unsigned location_index_of_removed_node = this->mCellLocationMap[&(*it)];
00225             this->mCellLocationMap.erase(&(*it));
00226             this->mLocationCellMap.erase(location_index_of_removed_node);
00227 
00228             // Update vector of cells
00229             it = this->mCells.erase(it);
00230             --it;
00231         }
00232     }
00233 
00234     return num_removed;
00235 }
00236 
00237 
00238 template<unsigned DIM>
00239 void MeshBasedTissue<DIM>::Update(bool hasHadBirthsOrDeaths)
00240 {
00241     NodeMap map(mrMesh.GetNumAllNodes());
00242     mrMesh.ReMesh(map);
00243 
00244     if (!map.IsIdentityMap())
00245     {
00246         UpdateGhostNodesAfterReMesh(map);
00247 
00248         // Update the mappings between cells and location indices
00249         std::map<TissueCell*, unsigned> old_map = this->mCellLocationMap;
00250 
00251         // Remove any dead pointers from the maps (needed to avoid archiving errors)
00252         this->mLocationCellMap.clear();
00253         this->mCellLocationMap.clear();
00254 
00255         for (std::list<TissueCell>::iterator it = this->mCells.begin();
00256              it != this->mCells.end();
00257              ++it)
00258         {
00259             unsigned old_node_index = old_map[&(*it)];
00260 
00261             // This shouldn't ever happen, as the cell vector only contains living cells
00262             assert(!map.IsDeleted(old_node_index));
00263 
00264             unsigned new_node_index = map.GetNewIndex(old_node_index);
00265             this->mLocationCellMap[new_node_index] = &(*it);
00266             this->mCellLocationMap[&(*it)] = new_node_index;
00267         }
00268     }
00269 
00270     // Purge any marked springs that are no longer springs
00271     std::vector<const std::set<TissueCell*>*> springs_to_remove;
00272     for (std::set<std::set<TissueCell*> >::iterator spring_it = mMarkedSprings.begin();
00273          spring_it != mMarkedSprings.end();
00274          ++spring_it)
00275     {
00276         const std::set<TissueCell*>& r_pair = *spring_it;
00277         assert(r_pair.size() == 2);
00278         TissueCell* p_cell_1 = *(r_pair.begin());
00279         TissueCell* p_cell_2 = *(++r_pair.begin());
00280         Node<DIM>* p_node_1 = this->GetNodeCorrespondingToCell(*p_cell_1);
00281         Node<DIM>* p_node_2 = this->GetNodeCorrespondingToCell(*p_cell_2);
00282 
00283         bool joined = false;
00284 
00285         // For each element containing node1, if it also contains node2 then the cells are joined
00286         std::set<unsigned> node2_elements = p_node_2->rGetContainingElementIndices();
00287         for (typename Node<DIM>::ContainingElementIterator elem_iter = p_node_1->ContainingElementsBegin();
00288              elem_iter != p_node_1->ContainingElementsEnd();
00289              ++elem_iter)
00290         {
00291             if (node2_elements.find(*elem_iter) != node2_elements.end())
00292             {
00293                 joined = true;
00294                 break;
00295             }
00296         }
00297 
00298         // If no longer joined, remove this spring from the set
00299         if (!joined)
00300         {
00301             springs_to_remove.push_back(&r_pair);
00302         }
00303     }
00304 
00305     // Remove any springs necessary
00306     for (std::vector<const std::set<TissueCell*>* >::iterator spring_it = springs_to_remove.begin();
00307          spring_it != springs_to_remove.end();
00308          ++spring_it)
00309     {
00310         mMarkedSprings.erase(**spring_it);
00311     }
00312 
00313     this->Validate();
00314 
00315     // Tessellate if needed
00316     if (DIM==2)
00317     {
00318         CellBasedEventHandler::BeginEvent(CellBasedEventHandler::TESSELLATION);
00319         if (mUseAreaBasedDampingConstant || TissueConfig::Instance()->GetOutputVoronoiData() ||
00320             TissueConfig::Instance()->GetOutputTissueAreas() || TissueConfig::Instance()->GetOutputCellAreas() )
00321         {
00322             std::vector<unsigned> location_indices;
00323             for (typename AbstractTissue<DIM>::Iterator cell_iter = this->Begin();
00324                  cell_iter != this->End();
00325                  ++cell_iter)
00326             {
00327                 unsigned node_index = this->mCellLocationMap[&(*cell_iter)];
00328                 location_indices.push_back(node_index);
00329             }
00330             CreateVoronoiTessellation(location_indices);
00331         }
00332         CellBasedEventHandler::EndEvent(CellBasedEventHandler::TESSELLATION);
00333     }
00334 }
00335 
00336 template<unsigned DIM>
00337 Node<DIM>* MeshBasedTissue<DIM>::GetNode(unsigned index)
00338 {
00339     return mrMesh.GetNode(index);
00340 }
00341 
00342 template<unsigned DIM>
00343 unsigned MeshBasedTissue<DIM>::GetNumNodes()
00344 {
00345     return mrMesh.GetNumAllNodes();
00346 }
00347 
00348 template<unsigned DIM>
00349 void MeshBasedTissue<DIM>::UpdateGhostNodesAfterReMesh(NodeMap& rMap)
00350 {
00351 }
00352 
00353 template<unsigned DIM>
00354 TissueCell* MeshBasedTissue<DIM>::AddCell(TissueCell& rNewCell, const c_vector<double,DIM>& rCellDivisionVector, TissueCell* pParentCell)
00355 {
00356     // Add new cell to tissue
00357     TissueCell* p_created_cell = AbstractCellCentreBasedTissue<DIM>::AddCell(rNewCell, rCellDivisionVector, pParentCell);
00358 
00359     // Mark spring between parent cell and new cell
00360     std::set<TissueCell*> cell_pair = CreateCellPair(*pParentCell, *p_created_cell);
00361     MarkSpring(cell_pair);
00362 
00363     // Return pointer to new cell
00364     return p_created_cell;
00365 }
00366 
00368 //                             Output methods                               //
00370 
00371 
00372 template<unsigned DIM>
00373 void MeshBasedTissue<DIM>::CreateOutputFiles(const std::string& rDirectory, bool cleanOutputDirectory)
00374 {
00375     AbstractTissue<DIM>::CreateOutputFiles(rDirectory, cleanOutputDirectory);
00376 
00377     OutputFileHandler output_file_handler(rDirectory, cleanOutputDirectory);
00378     mpElementFile = output_file_handler.OpenOutputFile("results.vizelements");
00379 
00380     if (TissueConfig::Instance()->GetOutputVoronoiData())
00381     {
00382         mpVoronoiFile = output_file_handler.OpenOutputFile("results.vizvoronoi");
00383     }
00384     if (TissueConfig::Instance()->GetOutputTissueAreas())
00385     {
00386         mpTissueAreasFile = output_file_handler.OpenOutputFile("tissueareas.dat");
00387     }
00388     if (TissueConfig::Instance()->GetOutputCellAreas())
00389     {
00390         mpCellAreasFile = output_file_handler.OpenOutputFile("cellareas.dat");
00391     }
00392 }
00393 
00394 template<unsigned DIM>
00395 void MeshBasedTissue<DIM>::CloseOutputFiles()
00396 {
00397     AbstractTissue<DIM>::CloseOutputFiles();
00398 
00399     mpElementFile->close();
00400 
00401     if (TissueConfig::Instance()->GetOutputVoronoiData())
00402     {
00403         mpVoronoiFile->close();
00404     }
00405     if (TissueConfig::Instance()->GetOutputTissueAreas())
00406     {
00407         mpTissueAreasFile->close();
00408     }
00409     if (TissueConfig::Instance()->GetOutputCellAreas())
00410     {
00411         mpCellAreasFile->close();
00412     }
00413 }
00414 
00415 template<unsigned DIM>
00416 void MeshBasedTissue<DIM>::WriteResultsToFiles()
00417 {
00418     AbstractCellCentreBasedTissue<DIM>::WriteResultsToFiles();
00419 
00420     // Write element data to file
00421 
00422     *mpElementFile <<  SimulationTime::Instance()->GetTime() << "\t";
00423 
00424     for (typename MutableMesh<DIM,DIM>::ElementIterator elem_iter = mrMesh.GetElementIteratorBegin();
00425          elem_iter != mrMesh.GetElementIteratorEnd();
00426          ++elem_iter)
00427     {
00428         bool element_contains_dead_cells_or_deleted_nodes = false;
00429 
00430         // Hack that covers the case where the element contains a node that is associated with a cell that has just been killed (#1129)
00431         for (unsigned i=0; i<DIM+1; i++)
00432         {
00433             unsigned node_index = elem_iter->GetNodeGlobalIndex(i);
00434 
00435             if (this->GetNode(node_index)->IsDeleted())
00436             {
00437                 element_contains_dead_cells_or_deleted_nodes = true;
00438                 break;
00439             }
00440             else if (this->mLocationCellMap[node_index])
00441             {
00442                 if (this->mLocationCellMap[node_index]->IsDead())
00443                 {
00444                     element_contains_dead_cells_or_deleted_nodes = true;
00445                     break;
00446                 }
00447             }
00448         }
00449         if (!element_contains_dead_cells_or_deleted_nodes)
00450         {
00451             for (unsigned i=0; i<DIM+1; i++)
00452             {
00453                 *mpElementFile << elem_iter->GetNodeGlobalIndex(i) << " ";
00454             }
00455         }
00456     }
00457     *mpElementFile << "\n";
00458 
00459     switch (DIM)
00460     {
00461         case 1:
00462         {
00464             break;
00465         }
00466         case 2:
00467         {
00468             if (mpVoronoiTessellation!=NULL)
00469             {
00470                 if (TissueConfig::Instance()->GetOutputVoronoiData())
00471                 {
00472                     WriteVoronoiResultsToFile();
00473                 }
00474                 if (TissueConfig::Instance()->GetOutputTissueAreas())
00475                 {
00476                     WriteTissueAreaResultsToFile();
00477                 }
00478                 if (TissueConfig::Instance()->GetOutputCellAreas())
00479                 {
00480                     WriteCellAreaResultsToFile();
00481                 }
00482             }
00483             break;
00484         }
00485         case 3:
00486         {
00488             break;
00489         }
00490         default:
00491             // This can't happen
00492             NEVER_REACHED;
00493     }
00494 }
00495 
00496 template<unsigned DIM>
00497 void MeshBasedTissue<DIM>::WriteVoronoiResultsToFile()
00498 {
00499     // Write time to file
00500     *mpVoronoiFile << SimulationTime::Instance()->GetTime() << " ";
00501 
00502     // Output vizvoronoi for all nodes
00503     for (typename AbstractTissue<DIM>::Iterator cell_iter = this->Begin();
00504          cell_iter != this->End();
00505          ++cell_iter)
00506     {
00507         unsigned node_index = this->mCellLocationMap[&(*cell_iter)];
00508         double x = this->GetLocationOfCellCentre(*cell_iter)[0];
00509         double y = this->GetLocationOfCellCentre(*cell_iter)[1];
00510 
00511         double cell_area = rGetVoronoiTessellation().GetFaceArea(node_index);
00512         double cell_perimeter = rGetVoronoiTessellation().GetFacePerimeter(node_index);
00513 
00514         *mpVoronoiFile << node_index << " " << x << " " << y << " " << cell_area << " " << cell_perimeter << " ";
00515     }
00516     *mpVoronoiFile << "\n";
00517 }
00518 
00519 template<unsigned DIM>
00520 void MeshBasedTissue<DIM>::WriteTissueAreaResultsToFile()
00521 {
00522     #define COVERAGE_IGNORE
00523     assert(DIM==2);
00524     #undef COVERAGE_IGNORE
00525 
00526     // Write time to file
00527     *mpTissueAreasFile << SimulationTime::Instance()->GetTime() << " ";
00528 
00529     // Don't use the Voronoi tessellation to calculate the total area
00530     // because it gives huge areas for boundary cells
00531     double total_area = mrMesh.GetVolume();
00532     double apoptotic_area = 0.0;
00533 
00534     for (typename AbstractTissue<DIM>::Iterator cell_iter = this->Begin();
00535          cell_iter != this->End();
00536          ++cell_iter)
00537     {
00538         // Only bother calculating the cell area if it is apoptotic
00539         if (cell_iter->GetCellProliferativeType() == APOPTOTIC)
00540         {
00541             unsigned node_index = this->mCellLocationMap[&(*cell_iter)];
00542             double cell_area = rGetVoronoiTessellation().GetFaceArea(node_index);
00543             apoptotic_area += cell_area;
00544         }
00545     }
00546     *mpTissueAreasFile << total_area << " " << apoptotic_area << "\n";
00547 }
00548 
00549 template<unsigned DIM>
00550 void MeshBasedTissue<DIM>::WriteCellAreaResultsToFile()
00551 {
00552     #define COVERAGE_IGNORE
00553     assert(DIM==2);
00554     #undef COVERAGE_IGNORE
00555 
00556     // Write time to file
00557     *mpCellAreasFile << SimulationTime::Instance()->GetTime() << " ";
00558 
00559     for (typename AbstractTissue<DIM>::Iterator cell_iter = this->Begin();
00560          cell_iter != this->End();
00561          ++cell_iter)
00562     {
00563         // Write cell index
00564         unsigned cell_index = cell_iter->GetCellId();
00565         *mpCellAreasFile << cell_index << " ";
00566 
00567         // Write cell location
00568         c_vector<double, DIM> cell_location = this->GetLocationOfCellCentre(*cell_iter);
00569         for (unsigned i=0; i<DIM; i++)
00570         {
00571             *mpCellAreasFile << cell_location[i] << " ";
00572         }
00573 
00574         // Write cell area
00575         unsigned node_index = this->mCellLocationMap[&(*cell_iter)];
00576         double cell_area = rGetVoronoiTessellation().GetFaceArea(node_index);
00577         *mpCellAreasFile << cell_area << " ";
00578     }
00579     *mpCellAreasFile << "\n";
00580 }
00581 
00582 
00584 //                          Spring iterator class                           //
00586 
00587 template<unsigned DIM>
00588 Node<DIM>* MeshBasedTissue<DIM>::SpringIterator::GetNodeA()
00589 {
00590     return mEdgeIter.GetNodeA();
00591 }
00592 
00593 template<unsigned DIM>
00594 Node<DIM>* MeshBasedTissue<DIM>::SpringIterator::GetNodeB()
00595 {
00596     return mEdgeIter.GetNodeB();
00597 }
00598 
00599 template<unsigned DIM>
00600 TissueCell& MeshBasedTissue<DIM>::SpringIterator::rGetCellA()
00601 {
00602     assert((*this) != mrTissue.SpringsEnd());
00603     return mrTissue.rGetCellUsingLocationIndex(mEdgeIter.GetNodeA()->GetIndex());
00604 }
00605 
00606 template<unsigned DIM>
00607 TissueCell& MeshBasedTissue<DIM>::SpringIterator::rGetCellB()
00608 {
00609     assert((*this) != mrTissue.SpringsEnd());
00610     return mrTissue.rGetCellUsingLocationIndex(mEdgeIter.GetNodeB()->GetIndex());
00611 }
00612 
00613 template<unsigned DIM>
00614 bool MeshBasedTissue<DIM>::SpringIterator::operator!=(const MeshBasedTissue<DIM>::SpringIterator& rOther)
00615 {
00616     return (mEdgeIter != rOther.mEdgeIter);
00617 }
00618 
00619 template<unsigned DIM>
00620 typename MeshBasedTissue<DIM>::SpringIterator& MeshBasedTissue<DIM>::SpringIterator::operator++()
00621 {
00622     bool edge_is_ghost = false;
00623 
00624     do
00625     {
00626         ++mEdgeIter;
00627         if (*this != mrTissue.SpringsEnd())
00628         {
00629             bool a_is_ghost = mrTissue.IsGhostNode(mEdgeIter.GetNodeA()->GetIndex());
00630             bool b_is_ghost = mrTissue.IsGhostNode(mEdgeIter.GetNodeB()->GetIndex());
00631 
00632             edge_is_ghost = (a_is_ghost || b_is_ghost);
00633         }
00634     }
00635     while (*this!=mrTissue.SpringsEnd() && edge_is_ghost);
00636 
00637     return (*this);
00638 }
00639 
00640 template<unsigned DIM>
00641 MeshBasedTissue<DIM>::SpringIterator::SpringIterator(
00642             MeshBasedTissue<DIM>& rTissue,
00643             typename MutableMesh<DIM,DIM>::EdgeIterator edgeIter)
00644     : mrTissue(rTissue),
00645       mEdgeIter(edgeIter)
00646 {
00647     if (mEdgeIter!=mrTissue.mrMesh.EdgesEnd())
00648     {
00649         bool a_is_ghost = mrTissue.IsGhostNode(mEdgeIter.GetNodeA()->GetIndex());
00650         bool b_is_ghost = mrTissue.IsGhostNode(mEdgeIter.GetNodeB()->GetIndex());
00651 
00652         if (a_is_ghost || b_is_ghost)
00653         {
00654             ++(*this);
00655         }
00656     }
00657 }
00658 
00659 template<unsigned DIM>
00660 typename MeshBasedTissue<DIM>::SpringIterator MeshBasedTissue<DIM>::SpringsBegin()
00661 {
00662     return SpringIterator(*this, mrMesh.EdgesBegin());
00663 }
00664 
00665 template<unsigned DIM>
00666 typename MeshBasedTissue<DIM>::SpringIterator MeshBasedTissue<DIM>::SpringsEnd()
00667 {
00668     return SpringIterator(*this, mrMesh.EdgesEnd());
00669 }
00670 
00671 template<unsigned DIM>
00672 void MeshBasedTissue<DIM>::CreateVoronoiTessellation(const std::vector<unsigned> locationIndices)
00673 {
00674     delete mpVoronoiTessellation;
00675     mpVoronoiTessellation = new VoronoiTessellation<DIM>(mrMesh, locationIndices);
00676 }
00677 
00682 template<>
00683 void MeshBasedTissue<1>::CreateVoronoiTessellation(const std::vector<unsigned> locationIndices)
00684 {
00685     // No 1D Voronoi tessellation
00686     NEVER_REACHED;
00687 }
00688 
00689 template<unsigned DIM>
00690 VoronoiTessellation<DIM>& MeshBasedTissue<DIM>::rGetVoronoiTessellation()
00691 {
00692     assert(mpVoronoiTessellation!=NULL);
00693     return *mpVoronoiTessellation;
00694 }
00695 
00696 template<unsigned DIM>
00697 void MeshBasedTissue<DIM>::CheckTissueCellPointers()
00698 {
00699     bool res = true;
00700     for (std::list<TissueCell>::iterator it=this->mCells.begin();
00701          it!=this->mCells.end();
00702          ++it)
00703     {
00704         TissueCell* p_cell = &(*it);
00705         assert(p_cell);
00706         AbstractCellCycleModel* p_model = p_cell->GetCellCycleModel();
00707         assert(p_model);
00708 
00709         // Check cell exists in tissue
00710         unsigned node_index = this->mCellLocationMap[p_cell];
00711         std::cout << "Cell at node " << node_index << " addr " << p_cell << std::endl << std::flush;
00712         TissueCell& r_cell = this->rGetCellUsingLocationIndex(node_index);
00713 #define COVERAGE_IGNORE //Debugging code.  Shouldn't fail under normal conditions
00714         if (&r_cell != p_cell)
00715         {
00716             std::cout << "  Mismatch with tissue" << std::endl << std::flush;
00717             res = false;
00718         }
00719 
00720         // Check model links back to cell
00721         if (p_model->GetCell() != p_cell)
00722         {
00723             std::cout << "  Mismatch with cycle model" << std::endl << std::flush;
00724             res = false;
00725         }
00726     }
00727     assert(res);
00728 #undef COVERAGE_IGNORE
00729 
00730     res = true;
00731     for (std::set<std::set<TissueCell*> >::iterator it1 = mMarkedSprings.begin();
00732          it1 != mMarkedSprings.end();
00733          ++it1)
00734     {
00735         const std::set<TissueCell*>& r_pair = *it1;
00736         assert(r_pair.size() == 2);
00737         for (std::set<TissueCell*>::iterator it2 = r_pair.begin();
00738              it2 != r_pair.end();
00739              ++it2)
00740         {
00741             TissueCell* p_cell = *it2;
00742             assert(p_cell);
00743             AbstractCellCycleModel* p_model = p_cell->GetCellCycleModel();
00744             assert(p_model);
00745             unsigned node_index = this->mCellLocationMap[p_cell];
00746             std::cout << "Cell at node " << node_index << " addr " << p_cell << std::endl << std::flush;
00747 
00748 #define COVERAGE_IGNORE //Debugging code.  Shouldn't fail under normal conditions
00749             // Check cell is alive
00750             if (p_cell->IsDead())
00751             {
00752                 std::cout << "  Cell is dead" << std::endl << std::flush;
00753                 res = false;
00754             }
00755 
00756             // Check cell exists in tissue
00757             TissueCell& r_cell = this->rGetCellUsingLocationIndex(node_index);
00758             if (&r_cell != p_cell)
00759             {
00760                 std::cout << "  Mismatch with tissue" << std::endl << std::flush;
00761                 res = false;
00762             }
00763 
00764             // Check model links back to cell
00765             if (p_model->GetCell() != p_cell)
00766             {
00767                 std::cout << "  Mismatch with cycle model" << std::endl << std::flush;
00768                 res = false;
00769             }
00770         }
00771 #undef COVERAGE_IGNORE
00772     }
00773     assert(res);
00774 }
00775 
00776 template<unsigned DIM>
00777 std::set<TissueCell*> MeshBasedTissue<DIM>::CreateCellPair(TissueCell& rCell1, TissueCell& rCell2)
00778 {
00779     std::set<TissueCell *> cell_pair;
00780     cell_pair.insert(&rCell1);
00781     cell_pair.insert(&rCell2);
00782     return cell_pair;
00783 }
00784 
00785 template<unsigned DIM>
00786 bool MeshBasedTissue<DIM>::IsMarkedSpring(const std::set<TissueCell*>& rCellPair)
00787 {
00788     return mMarkedSprings.find(rCellPair) != mMarkedSprings.end();
00789 }
00790 
00791 template<unsigned DIM>
00792 void MeshBasedTissue<DIM>::MarkSpring(std::set<TissueCell*>& rCellPair)
00793 {
00794     mMarkedSprings.insert(rCellPair);
00795 }
00796 
00797 template<unsigned DIM>
00798 void MeshBasedTissue<DIM>::UnmarkSpring(std::set<TissueCell*>& rCellPair)
00799 {
00800     mMarkedSprings.erase(rCellPair);
00801 }
00802 
00803 
00805 // Explicit instantiation
00807 
00808 
00809 template class MeshBasedTissue<1>;
00810 template class MeshBasedTissue<2>;
00811 template class MeshBasedTissue<3>;
00812 
00813 
00814 // Serialization for Boost >= 1.36
00815 #include "SerializationExportWrapperForCpp.hpp"
00816 EXPORT_TEMPLATE_CLASS_SAME_DIMS(MeshBasedTissue)

Generated by  doxygen 1.6.2