VertexBasedCellPopulation.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 "VertexBasedCellPopulation.hpp"
00037 #include <boost/foreach.hpp>
00038 #include "VertexMeshWriter.hpp"
00039 #include "Warnings.hpp"
00040 #include "ChasteSyscalls.hpp"
00041 #include "IsNan.hpp"
00042 #include "ShortAxisVertexBasedDivisionRule.hpp"
00043 
00044 // Cell writers
00045 #include "CellAgesWriter.hpp"
00046 #include "CellAncestorWriter.hpp"
00047 #include "CellProliferativePhasesWriter.hpp"
00048 #include "CellProliferativeTypesWriter.hpp"
00049 #include "CellVolumesWriter.hpp"
00050 
00051 // Cell population writers
00052 #include "CellMutationStatesCountWriter.hpp"
00053 #include "CellPopulationElementWriter.hpp"
00054 #include "VertexT1SwapLocationsWriter.hpp"
00055 #include "VertexT2SwapLocationsWriter.hpp"
00056 #include "VertexT3SwapLocationsWriter.hpp"
00057 
00058 template<unsigned DIM>
00059 VertexBasedCellPopulation<DIM>::VertexBasedCellPopulation(MutableVertexMesh<DIM, DIM>& rMesh,
00060                                           std::vector<CellPtr>& rCells,
00061                                           bool deleteMesh,
00062                                           bool validate,
00063                                           const std::vector<unsigned> locationIndices)
00064     : AbstractOffLatticeCellPopulation<DIM>(rMesh, rCells, locationIndices),
00065       mDeleteMesh(deleteMesh),
00066       mOutputCellRearrangementLocations(true)
00067 {
00068     mpMutableVertexMesh = static_cast<MutableVertexMesh<DIM, DIM>* >(&(this->mrMesh));
00069     mpVertexBasedDivisionRule.reset(new ShortAxisVertexBasedDivisionRule<DIM>());
00070 
00071     // If no location indices are specified, associate with elements from the mesh (assumed to be sequentially ordered).
00072     std::list<CellPtr>::iterator it = this->mCells.begin();
00073     for (unsigned i=0; it != this->mCells.end(); ++it, ++i)
00074     {
00075         unsigned index = locationIndices.empty() ? i : locationIndices[i]; // assume that the ordering matches
00076         AbstractCellPopulation<DIM, DIM>::AddCellUsingLocationIndex(index,*it);
00077     }
00078 
00079     // Check each element has only one cell attached
00080     if (validate)
00081     {
00082         Validate();
00083     }
00084 }
00085 
00086 template<unsigned DIM>
00087 VertexBasedCellPopulation<DIM>::VertexBasedCellPopulation(MutableVertexMesh<DIM, DIM>& rMesh)
00088     : AbstractOffLatticeCellPopulation<DIM>(rMesh),
00089       mDeleteMesh(true),
00090       mOutputCellRearrangementLocations(true)
00091 {
00092     mpMutableVertexMesh = static_cast<MutableVertexMesh<DIM, DIM>* >(&(this->mrMesh));
00093 }
00094 
00095 template<unsigned DIM>
00096 VertexBasedCellPopulation<DIM>::~VertexBasedCellPopulation()
00097 {
00098     if (mDeleteMesh)
00099     {
00100         delete &this->mrMesh;
00101     }
00102 }
00103 
00104 template<unsigned DIM>
00105 double VertexBasedCellPopulation<DIM>::GetDampingConstant(unsigned nodeIndex)
00106 {
00107     // Take the average of the cells containing this vertex
00108     double average_damping_constant = 0.0;
00109 
00110     std::set<unsigned> containing_elements = GetNode(nodeIndex)->rGetContainingElementIndices();
00111 
00112     unsigned num_containing_elements = containing_elements.size();
00113     if (num_containing_elements == 0)
00114     {
00115         EXCEPTION("At time " << SimulationTime::Instance()->GetTime() << ", Node " << nodeIndex << " is not contained in any elements, so GetDampingConstant() returns zero");
00116     }
00117 
00118     double temp = 1.0/((double) num_containing_elements);
00119     for (std::set<unsigned>::iterator iter = containing_elements.begin();
00120          iter != containing_elements.end();
00121          ++iter)
00122     {
00123         CellPtr p_cell = this->GetCellUsingLocationIndex(*iter);
00124         bool cell_is_wild_type = p_cell->GetMutationState()->IsType<WildTypeCellMutationState>();
00125         bool cell_is_labelled = p_cell->HasCellProperty<CellLabel>();
00126 
00127         if (cell_is_wild_type && !cell_is_labelled)
00128         {
00129             average_damping_constant += this->GetDampingConstantNormal()*temp;
00130         }
00131         else
00132         {
00133             average_damping_constant += this->GetDampingConstantMutant()*temp;
00134         }
00135     }
00136 
00137     return average_damping_constant;
00138 }
00139 
00140 template<unsigned DIM>
00141 MutableVertexMesh<DIM, DIM>& VertexBasedCellPopulation<DIM>::rGetMesh()
00142 {
00143     return *mpMutableVertexMesh;
00144 }
00145 
00146 template<unsigned DIM>
00147 const MutableVertexMesh<DIM, DIM>& VertexBasedCellPopulation<DIM>::rGetMesh() const
00148 {
00149     return *mpMutableVertexMesh;
00150 }
00151 
00152 template<unsigned DIM>
00153 VertexElement<DIM, DIM>* VertexBasedCellPopulation<DIM>::GetElement(unsigned elementIndex)
00154 {
00155     return mpMutableVertexMesh->GetElement(elementIndex);
00156 }
00157 
00158 template<unsigned DIM>
00159 unsigned VertexBasedCellPopulation<DIM>::GetNumNodes()
00160 {
00161     return this->mrMesh.GetNumNodes();
00162 }
00163 
00164 template<unsigned DIM>
00165 c_vector<double, DIM> VertexBasedCellPopulation<DIM>::GetLocationOfCellCentre(CellPtr pCell)
00166 {
00167     return mpMutableVertexMesh->GetCentroidOfElement(this->mCellLocationMap[pCell.get()]);
00168 }
00169 
00170 template<unsigned DIM>
00171 Node<DIM>* VertexBasedCellPopulation<DIM>::GetNode(unsigned index)
00172 {
00173     return this->mrMesh.GetNode(index);
00174 }
00175 
00176 template<unsigned DIM>
00177 std::set<unsigned> VertexBasedCellPopulation<DIM>::GetNeighbouringLocationIndices(CellPtr pCell)
00178 {
00179     unsigned elem_index = this->GetLocationIndexUsingCell(pCell);
00180     return this->rGetMesh().GetNeighbouringElementIndices(elem_index);
00181 }
00182 
00183 template<unsigned DIM>
00184 unsigned VertexBasedCellPopulation<DIM>::AddNode(Node<DIM>* pNewNode)
00185 {
00186     return mpMutableVertexMesh->AddNode(pNewNode);
00187 }
00188 
00189 template<unsigned DIM>
00190 void VertexBasedCellPopulation<DIM>::SetNode(unsigned nodeIndex, ChastePoint<DIM>& rNewLocation)
00191 {
00192     mpMutableVertexMesh->SetNode(nodeIndex, rNewLocation);
00193 }
00194 
00195 template<unsigned DIM>
00196 VertexElement<DIM, DIM>* VertexBasedCellPopulation<DIM>::GetElementCorrespondingToCell(CellPtr pCell)
00197 {
00198     return mpMutableVertexMesh->GetElement(this->GetLocationIndexUsingCell(pCell));
00199 }
00200 
00201 template<unsigned DIM>
00202 unsigned VertexBasedCellPopulation<DIM>::GetNumElements()
00203 {
00204     return mpMutableVertexMesh->GetNumElements();
00205 }
00206 
00207 template<unsigned DIM>
00208 CellPtr VertexBasedCellPopulation<DIM>::AddCell(CellPtr pNewCell,
00209                                                 const c_vector<double,DIM>& rCellDivisionVector,
00210                                                 CellPtr pParentCell)
00211 {
00212     // Get the element associated with this cell
00213     VertexElement<DIM, DIM>* p_element = GetElementCorrespondingToCell(pParentCell);
00214 
00215     // Divide the element
00216     unsigned new_element_index = mpMutableVertexMesh->DivideElementAlongGivenAxis(p_element,
00217                                                                                   rCellDivisionVector,
00218                                                                                   true);
00219     // Associate the new cell with the element
00220     this->mCells.push_back(pNewCell);
00221 
00222     // Update location cell map
00223     CellPtr p_created_cell = this->mCells.back();
00224     this->SetCellUsingLocationIndex(new_element_index,p_created_cell);
00225     this->mCellLocationMap[p_created_cell.get()] = new_element_index;
00226     return p_created_cell;
00227 }
00228 
00229 template<unsigned DIM>
00230 unsigned VertexBasedCellPopulation<DIM>::RemoveDeadCells()
00231 {
00232     unsigned num_removed = 0;
00233 
00234     for (std::list<CellPtr>::iterator it = this->mCells.begin();
00235          it != this->mCells.end();
00236          )
00237     {
00238         if ((*it)->IsDead())
00239         {
00240             // Count the cell as dead
00241             num_removed++;
00242 
00243             // Remove the element from the mesh if it is not deleted yet
00245             if (!(this->GetElement(this->GetLocationIndexUsingCell((*it)))->IsDeleted()))
00246             {
00247                 // This warning relies on the fact that there is only one other possibility for
00248                 // vertex elements to be marked as deleted: a T2 swap
00249                 WARN_ONCE_ONLY("A Cell is removed without performing a T2 swap. This could leave a void in the mesh.");
00250                 mpMutableVertexMesh->DeleteElementPriorToReMesh(this->GetLocationIndexUsingCell((*it)));
00251             }
00252 
00253             // Delete the cell
00254             it = this->mCells.erase(it);
00255         }
00256         else
00257         {
00258             ++it;
00259         }
00260     }
00261     return num_removed;
00262 }
00263 
00264 template<unsigned DIM>
00265 void VertexBasedCellPopulation<DIM>::UpdateNodeLocations(double dt)
00266 {
00267     // Iterate over all nodes associated with real cells to update their positions
00268     for (unsigned node_index=0; node_index<GetNumNodes(); node_index++)
00269     {
00270         // Get the damping constant for this node
00271         double damping_const = this->GetDampingConstant(node_index);
00272 
00273         // Compute the displacement of this node
00274         c_vector<double, DIM> displacement = dt*this->GetNode(node_index)->rGetAppliedForce()/damping_const;
00275 
00276         /*
00277          * If the displacement of this node is greater than half the cell rearrangement threshold,
00278          * this could result in nodes moving into the interior of other elements, which should not
00279          * be possible. Therefore in this case we restrict the displacement of the node to the cell
00280          * rearrangement threshold and warn the user that a smaller timestep should be used. This
00281          * restriction ensures that vertex elements remain well defined (see #1376).
00282          */
00283         if (norm_2(displacement) > 0.5*mpMutableVertexMesh->GetCellRearrangementThreshold())
00284         {
00285             WARN_ONCE_ONLY("Vertices are moving more than half the CellRearrangementThreshold. This could cause elements to become inverted so the motion has been restricted. Use a smaller timestep to avoid these warnings.");
00286             displacement *= 0.5*mpMutableVertexMesh->GetCellRearrangementThreshold()/norm_2(displacement);
00287         }
00288 
00289         // Get new node location
00290         c_vector<double, DIM> new_node_location = this->GetNode(node_index)->rGetLocation() + displacement;
00291 
00292         for (unsigned i=0; i<DIM; i++)
00293         {
00294             assert(!std::isnan(new_node_location(i)));
00295         }
00296 
00297         // Create ChastePoint for new node location
00298         ChastePoint<DIM> new_point(new_node_location);
00299 
00300         // Move the node
00301         this->SetNode(node_index, new_point);
00302     }
00303 }
00304 
00305 template<unsigned DIM>
00306 bool VertexBasedCellPopulation<DIM>::IsCellAssociatedWithADeletedLocation(CellPtr pCell)
00307 {
00308     return GetElementCorrespondingToCell(pCell)->IsDeleted();;
00309 }
00310 
00311 template<unsigned DIM>
00312 void VertexBasedCellPopulation<DIM>::Update(bool hasHadBirthsOrDeaths)
00313 {
00314     VertexElementMap element_map(mpMutableVertexMesh->GetNumAllElements());
00315     mpMutableVertexMesh->ReMesh(element_map);
00316 
00317     if (!element_map.IsIdentityMap())
00318     {
00319         // Fix up the mappings between CellPtrs and VertexElements
00321         std::map<Cell*, unsigned> old_map = this->mCellLocationMap;
00322 
00323         this->mCellLocationMap.clear();
00324         this->mLocationCellMap.clear();
00325 
00326         for (std::list<CellPtr>::iterator cell_iter = this->mCells.begin();
00327              cell_iter != this->mCells.end();
00328              ++cell_iter)
00329         {
00330             // The cell vector should only ever contain living cells
00331             unsigned old_elem_index = old_map[(*cell_iter).get()];
00332             assert(!element_map.IsDeleted(old_elem_index));
00333 
00334             unsigned new_elem_index = element_map.GetNewIndex(old_elem_index);
00335             this->SetCellUsingLocationIndex(new_elem_index, *cell_iter);
00336         }
00337 
00338         // Check that each VertexElement has only one CellPtr associated with it in the updated cell population
00339         Validate();
00340     }
00341 
00342     element_map.ResetToIdentity();
00343 }
00344 
00345 template<unsigned DIM>
00346 void VertexBasedCellPopulation<DIM>::Validate()
00347 {
00348     // Check each element has only one cell attached
00349     std::vector<unsigned> validated_element = std::vector<unsigned>(this->GetNumElements(), 0);
00350     for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->Begin();
00351          cell_iter != this->End();
00352          ++cell_iter)
00353     {
00354         unsigned elem_index = this->GetLocationIndexUsingCell(*cell_iter);
00355         validated_element[elem_index]++;
00356     }
00357 
00358     for (unsigned i=0; i<validated_element.size(); i++)
00359     {
00360         if (validated_element[i] == 0)
00361         {
00362             EXCEPTION("At time " << SimulationTime::Instance()->GetTime() <<", Element " << i << " does not appear to have a cell associated with it");
00363         }
00364 
00365         if (validated_element[i] > 1)
00366         {
00367             // This should never be reached as you can only set one cell per element index
00368             EXCEPTION("At time " << SimulationTime::Instance()->GetTime() <<", Element " << i << " appears to have " << validated_element[i] << " cells associated with it");
00369         }
00370     }
00371 }
00372 
00373 template<unsigned DIM>
00374 void VertexBasedCellPopulation<DIM>::AcceptPopulationWriter(boost::shared_ptr<AbstractCellPopulationWriter<DIM, DIM> > pPopulationWriter)
00375 {
00376     pPopulationWriter->Visit(this);
00377 }
00378 
00379 template<unsigned DIM>
00380 void VertexBasedCellPopulation<DIM>::AcceptPopulationCountWriter(boost::shared_ptr<AbstractCellPopulationCountWriter<DIM, DIM> > pPopulationCountWriter)
00381 {
00382     pPopulationCountWriter->Visit(this);
00383 }
00384 
00385 template<unsigned DIM>
00386 void VertexBasedCellPopulation<DIM>::AcceptCellWriter(boost::shared_ptr<AbstractCellWriter<DIM, DIM> > pCellWriter, CellPtr pCell)
00387 {
00388     pCellWriter->VisitCell(pCell, this);
00389 }
00390 
00391 template<unsigned DIM>
00392 double VertexBasedCellPopulation<DIM>::GetVolumeOfCell(CellPtr pCell)
00393 {
00394     // Get the vertex element index corresponding to this cell
00395     unsigned elem_index = this->GetLocationIndexUsingCell(pCell);
00396 
00397     // Get the cell's volume from the vertex mesh
00398     double cell_volume = mpMutableVertexMesh->GetVolumeOfElement(elem_index);
00399 
00400     return cell_volume;
00401 }
00402 
00403 template<unsigned DIM>
00404 void VertexBasedCellPopulation<DIM>::WriteVtkResultsToFile(const std::string& rDirectory)
00405 {
00406 #ifdef CHASTE_VTK
00407 
00408     // Create mesh writer for VTK output
00409     VertexMeshWriter<DIM, DIM> mesh_writer(rDirectory, "results", false);
00410 
00411     // Iterate over any cell writers that are present
00412     unsigned num_cells = this->GetNumAllCells();
00413     for (typename std::vector<boost::shared_ptr<AbstractCellWriter<DIM, DIM> > >::iterator cell_writer_iter = this->mCellWriters.begin();
00414          cell_writer_iter != this->mCellWriters.end();
00415          ++cell_writer_iter)
00416     {
00417         // Create vector to store VTK cell data
00418         std::vector<double> vtk_cell_data(num_cells);
00419 
00420         // Iterate over vertex elements ///\todo #2512 - replace with loop over cells
00421         for (typename VertexMesh<DIM,DIM>::VertexElementIterator elem_iter = mpMutableVertexMesh->GetElementIteratorBegin();
00422              elem_iter != mpMutableVertexMesh->GetElementIteratorEnd();
00423              ++elem_iter)
00424         {
00425             // Get index of this element in the vertex mesh
00426             unsigned elem_index = elem_iter->GetIndex();
00427 
00428             // Get the cell corresponding to this element
00429             CellPtr p_cell = this->GetCellUsingLocationIndex(elem_index);
00430             assert(p_cell);
00431 
00432             // Populate the vector of VTK cell data
00433             vtk_cell_data[elem_index] = (*cell_writer_iter)->GetCellDataForVtkOutput(p_cell, this);
00434         }
00435 
00436         mesh_writer.AddCellData((*cell_writer_iter)->GetVtkCellDataName(), vtk_cell_data);
00437     }
00438 
00439     // When outputting any CellData, we assume that the first cell is representative of all cells
00440     unsigned num_cell_data_items = this->Begin()->GetCellData()->GetNumItems();
00441     std::vector<std::string> cell_data_names = this->Begin()->GetCellData()->GetKeys();
00442 
00443     std::vector<std::vector<double> > cell_data;
00444     for (unsigned var=0; var<num_cell_data_items; var++)
00445     {
00446         std::vector<double> cell_data_var(num_cells);
00447         cell_data.push_back(cell_data_var);
00448     }
00449 
00450     // Loop over vertex elements ///\todo #2512 - replace with loop over cells
00451     for (typename VertexMesh<DIM,DIM>::VertexElementIterator elem_iter = mpMutableVertexMesh->GetElementIteratorBegin();
00452          elem_iter != mpMutableVertexMesh->GetElementIteratorEnd();
00453          ++elem_iter)
00454     {
00455         // Get index of this element in the vertex mesh
00456         unsigned elem_index = elem_iter->GetIndex();
00457 
00458         // Get the cell corresponding to this element
00459         CellPtr p_cell = this->GetCellUsingLocationIndex(elem_index);
00460         assert(p_cell);
00461 
00462         for (unsigned var=0; var<num_cell_data_items; var++)
00463         {
00464             cell_data[var][elem_index] = p_cell->GetCellData()->GetItem(cell_data_names[var]);
00465         }
00466     }
00467     for (unsigned var=0; var<num_cell_data_items; var++)
00468     {
00469         mesh_writer.AddCellData(cell_data_names[var], cell_data[var]);
00470     }
00471 
00472     unsigned num_timesteps = SimulationTime::Instance()->GetTimeStepsElapsed();
00473     std::stringstream time;
00474     time << num_timesteps;
00475 
00476     mesh_writer.WriteVtkUsingMesh(*mpMutableVertexMesh, time.str());
00477 
00478     *(this->mpVtkMetaFile) << "        <DataSet timestep=\"";
00479     *(this->mpVtkMetaFile) << num_timesteps;
00480     *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_";
00481     *(this->mpVtkMetaFile) << num_timesteps;
00482     *(this->mpVtkMetaFile) << ".vtu\"/>\n";
00483 #endif //CHASTE_VTK
00484 }
00485 
00486 template<unsigned DIM>
00487 void VertexBasedCellPopulation<DIM>::OpenWritersFiles(OutputFileHandler& rOutputFileHandler)
00488 {
00489     if (this->mOutputResultsForChasteVisualizer)
00490     {
00491         if (!this-> template HasWriter<CellPopulationElementWriter>())
00492         {
00493             this-> template AddPopulationWriter<CellPopulationElementWriter>();
00494         }
00495     }
00496 
00497     if (mOutputCellRearrangementLocations)
00498     {
00499         if (!this-> template HasWriter<VertexT1SwapLocationsWriter>())
00500         {
00501             this-> template AddPopulationWriter<VertexT1SwapLocationsWriter>();
00502         }
00503         if (!this-> template HasWriter<VertexT2SwapLocationsWriter>())
00504         {
00505             this-> template AddPopulationWriter<VertexT2SwapLocationsWriter>();
00506         }
00507         if (!this-> template HasWriter<VertexT3SwapLocationsWriter>())
00508         {
00509             this-> template AddPopulationWriter<VertexT3SwapLocationsWriter>();
00510         }
00511     }
00512 
00513     AbstractCellPopulation<DIM>::OpenWritersFiles(rOutputFileHandler);
00514 }
00515 
00516 template<unsigned DIM>
00517 bool VertexBasedCellPopulation<DIM>::GetOutputCellRearrangementLocations()
00518 {
00519     return mOutputCellRearrangementLocations;
00520 }
00521 
00522 template<unsigned DIM>
00523 void VertexBasedCellPopulation<DIM>::SetOutputCellRearrangementLocations(bool outputCellRearrangementLocations)
00524 {
00525     mOutputCellRearrangementLocations = outputCellRearrangementLocations;
00526 }
00527 
00528 template<unsigned DIM>
00529 void VertexBasedCellPopulation<DIM>::OutputCellPopulationParameters(out_stream& rParamsFile)
00530 {
00531     *rParamsFile << "\t\t<CellRearrangementThreshold>" << mpMutableVertexMesh->GetCellRearrangementThreshold() << "</CellRearrangementThreshold>\n";
00532     *rParamsFile << "\t\t<T2Threshold>" <<  mpMutableVertexMesh->GetT2Threshold() << "</T2Threshold>\n";
00533     *rParamsFile << "\t\t<CellRearrangementRatio>" << mpMutableVertexMesh->GetCellRearrangementRatio() << "</CellRearrangementRatio>\n";
00534     *rParamsFile << "\t\t<OutputCellRearrangementLocations>" << mOutputCellRearrangementLocations << "</OutputCellRearrangementLocations>\n";
00535 
00536     // Add the division rule parameters
00537     *rParamsFile << "\t\t<VertexBasedDivisionRule>\n";
00538     mpVertexBasedDivisionRule->OutputCellVertexBasedDivisionRuleInfo(rParamsFile);
00539     *rParamsFile << "\t\t</VertexBasedDivisionRule>\n";
00540 
00541     // Call method on direct parent class
00542     AbstractOffLatticeCellPopulation<DIM>::OutputCellPopulationParameters(rParamsFile);
00543 }
00544 
00545 template<unsigned DIM>
00546 double VertexBasedCellPopulation<DIM>::GetWidth(const unsigned& rDimension)
00547 {
00548     // Call GetWidth() on the mesh
00549     double width = this->mrMesh.GetWidth(rDimension);
00550 
00551     return width;
00552 }
00553 
00554 template<unsigned DIM>
00555 std::set<unsigned> VertexBasedCellPopulation<DIM>::GetNeighbouringNodeIndices(unsigned index)
00556 {
00557     return mpMutableVertexMesh->GetNeighbouringNodeIndices(index);
00558 }
00559 
00560 template<unsigned DIM>
00561 boost::shared_ptr<AbstractVertexBasedDivisionRule<DIM> > VertexBasedCellPopulation<DIM>::GetVertexBasedDivisionRule()
00562 {
00563     return mpVertexBasedDivisionRule;
00564 }
00565 
00566 template<unsigned DIM>
00567 void VertexBasedCellPopulation<DIM>::SetVertexBasedDivisionRule(boost::shared_ptr<AbstractVertexBasedDivisionRule<DIM> > pVertexBasedDivisionRule)
00568 {
00569     mpVertexBasedDivisionRule = pVertexBasedDivisionRule;
00570 }
00571 
00572 template<unsigned DIM>
00573 std::vector< c_vector< double, DIM > > VertexBasedCellPopulation<DIM>::GetLocationsOfT2Swaps()
00574 {
00575     return mLocationsOfT2Swaps;
00576 }
00577 
00578 template<unsigned DIM>
00579 std::vector< unsigned > VertexBasedCellPopulation<DIM>::GetCellIdsOfT2Swaps()
00580 {
00581     return mCellIdsOfT2Swaps;
00582 }
00583 
00584 template<unsigned DIM>
00585 void VertexBasedCellPopulation<DIM>::AddLocationOfT2Swap(c_vector< double, DIM> locationOfT2Swap)
00586 {
00587     mLocationsOfT2Swaps.push_back(locationOfT2Swap);
00588 }
00589 
00590 template<unsigned DIM>
00591 void VertexBasedCellPopulation<DIM>::AddCellIdOfT2Swap(unsigned idOfT2Swap)
00592 {
00593     mCellIdsOfT2Swaps.push_back(idOfT2Swap);
00594 }
00595 
00596 template<unsigned DIM>
00597 void VertexBasedCellPopulation<DIM>::ClearLocationsAndCellIdsOfT2Swaps()
00598 {
00599     mCellIdsOfT2Swaps.clear();
00600     mLocationsOfT2Swaps.clear();
00601 }
00602 
00603 template<unsigned DIM>
00604 TetrahedralMesh<DIM, DIM>* VertexBasedCellPopulation<DIM>::GetTetrahedralMeshUsingVertexMesh()
00605 {
00606     // This method only works in 2D sequential
00607     assert(DIM == 2);
00608     assert(PetscTools::IsSequential());
00609 
00610     unsigned num_vertex_nodes = mpMutableVertexMesh->GetNumNodes();
00611     unsigned num_vertex_elements = mpMutableVertexMesh->GetNumElements();
00612 
00613     std::string mesh_file_name = "mesh";
00614 
00615     // Get a unique temporary foldername
00616     std::stringstream pid;
00617     pid << getpid();
00618     OutputFileHandler output_file_handler("2D_temporary_tetrahedral_mesh_" + pid.str());
00619     std::string output_dir = output_file_handler.GetOutputDirectoryFullPath();
00620 
00621     // Compute the number of nodes in the TetrahedralMesh
00622     unsigned num_tetrahedral_nodes = num_vertex_nodes + num_vertex_elements;
00623 
00624     // Write node file
00625     out_stream p_node_file = output_file_handler.OpenOutputFile(mesh_file_name+".node");
00626     (*p_node_file) << std::scientific;
00627     (*p_node_file) << std::setprecision(20);
00628     (*p_node_file) << num_tetrahedral_nodes << "\t2\t0\t1" << std::endl;
00629 
00630     // Begin by writing each node in the VertexMesh
00631     for (unsigned node_index=0; node_index<num_vertex_nodes; node_index++)
00632     {
00633         Node<DIM>* p_node = mpMutableVertexMesh->GetNode(node_index);
00634 
00636         unsigned index = p_node->GetIndex();
00637 
00638         c_vector<double, DIM> location = p_node->rGetLocation();
00639 
00640         unsigned is_boundary_node = p_node->IsBoundaryNode() ? 1 : 0;
00641 
00642         (*p_node_file) << index << "\t" << location[0] << "\t" << location[1] << "\t" << is_boundary_node << std::endl;
00643     }
00644 
00645     // Now write an additional node at each VertexElement's centroid
00646     unsigned num_tetrahedral_elements = 0;
00647     for (unsigned vertex_elem_index=0; vertex_elem_index<num_vertex_elements; vertex_elem_index++)
00648     {
00649         unsigned index = num_vertex_nodes + vertex_elem_index;
00650 
00651         c_vector<double, DIM> location = mpMutableVertexMesh->GetCentroidOfElement(vertex_elem_index);
00652 
00653         // Any node located at a VertexElement's centroid will not be a boundary node
00654         unsigned is_boundary_node = 0;
00655         (*p_node_file) << index << "\t" << location[0] << "\t" << location[1] << "\t" << is_boundary_node << std::endl;
00656 
00657         // Also keep track of how many tetrahedral elements there will be
00658         num_tetrahedral_elements += mpMutableVertexMesh->GetElement(vertex_elem_index)->GetNumNodes();
00659     }
00660     p_node_file->close();
00661 
00662     // Write element file
00663     out_stream p_elem_file = output_file_handler.OpenOutputFile(mesh_file_name+".ele");
00664     (*p_elem_file) << std::scientific;
00665     (*p_elem_file) << num_tetrahedral_elements << "\t3\t0" << std::endl;
00666 
00667     std::set<std::pair<unsigned, unsigned> > tetrahedral_edges;
00668 
00669     unsigned tetrahedral_elem_index = 0;
00670     for (unsigned vertex_elem_index=0; vertex_elem_index<num_vertex_elements; vertex_elem_index++)
00671     {
00672         VertexElement<DIM, DIM>* p_vertex_element = mpMutableVertexMesh->GetElement(vertex_elem_index);
00673 
00674         // Iterate over nodes owned by this VertexElement
00675         unsigned num_nodes_in_vertex_element = p_vertex_element->GetNumNodes();
00676         for (unsigned local_index=0; local_index<num_nodes_in_vertex_element; local_index++)
00677         {
00678             unsigned node_0_index = p_vertex_element->GetNodeGlobalIndex(local_index);
00679             unsigned node_1_index = p_vertex_element->GetNodeGlobalIndex((local_index+1)%num_nodes_in_vertex_element);
00680             unsigned node_2_index = num_vertex_nodes + vertex_elem_index;
00681 
00682             (*p_elem_file) << tetrahedral_elem_index++ << "\t" << node_0_index << "\t" << node_1_index << "\t" << node_2_index << std::endl;
00683 
00684             // Add edges to the set if they are not already present
00685             std::pair<unsigned, unsigned> edge_0 = this->CreateOrderedPair(node_0_index, node_1_index);
00686             std::pair<unsigned, unsigned> edge_1 = this->CreateOrderedPair(node_1_index, node_2_index);
00687             std::pair<unsigned, unsigned> edge_2 = this->CreateOrderedPair(node_2_index, node_0_index);
00688 
00689             tetrahedral_edges.insert(edge_0);
00690             tetrahedral_edges.insert(edge_1);
00691             tetrahedral_edges.insert(edge_2);
00692         }
00693     }
00694     p_elem_file->close();
00695 
00696     // Write edge file
00697     out_stream p_edge_file = output_file_handler.OpenOutputFile(mesh_file_name+".edge");
00698     (*p_edge_file) << std::scientific;
00699     (*p_edge_file) << tetrahedral_edges.size() << "\t1" << std::endl;
00700 
00701     unsigned edge_index = 0;
00702     for (std::set<std::pair<unsigned, unsigned> >::iterator edge_iter = tetrahedral_edges.begin();
00703          edge_iter != tetrahedral_edges.end();
00704          ++edge_iter)
00705     {
00706         std::pair<unsigned, unsigned> this_edge = *edge_iter;
00707 
00708         // To be a boundary edge both nodes need to be boundary nodes.
00709         bool is_boundary_edge = false;
00710         if (this_edge.first  < mpMutableVertexMesh->GetNumNodes() &&
00711             this_edge.second  < mpMutableVertexMesh->GetNumNodes())
00712         {
00713             is_boundary_edge = (mpMutableVertexMesh->GetNode(this_edge.first)->IsBoundaryNode() &&
00714                                 mpMutableVertexMesh->GetNode(this_edge.second)->IsBoundaryNode() );
00715         }
00716         unsigned is_boundary_edge_unsigned = is_boundary_edge ? 1 : 0;
00717 
00718         (*p_edge_file) << edge_index++ << "\t" << this_edge.first << "\t" << this_edge.second << "\t" << is_boundary_edge_unsigned << std::endl;
00719     }
00720     p_edge_file->close();
00721 
00722     // Having written the mesh to file, now construct it using TrianglesMeshReader
00723     TetrahedralMesh<DIM, DIM>* p_mesh = new TetrahedralMesh<DIM, DIM>;
00724     // Nested scope so reader is destroyed before we remove the temporary files.
00725     {
00726         TrianglesMeshReader<DIM, DIM> mesh_reader(output_dir + mesh_file_name);
00727         p_mesh->ConstructFromMeshReader(mesh_reader);
00728     }
00729 
00730     // Delete the temporary files
00731     output_file_handler.FindFile("").Remove();
00732 
00733     // The original files have been deleted, it is better if the mesh object forgets about them
00734     p_mesh->SetMeshHasChangedSinceLoading();
00735 
00736     return p_mesh;
00737 }
00738 
00739 // Explicit instantiation
00740 template class VertexBasedCellPopulation<1>;
00741 template class VertexBasedCellPopulation<2>;
00742 template class VertexBasedCellPopulation<3>;
00743 
00744 // Serialization for Boost >= 1.36
00745 #include "SerializationExportWrapperForCpp.hpp"
00746 EXPORT_TEMPLATE_CLASS_SAME_DIMS(VertexBasedCellPopulation)

Generated by  doxygen 1.6.2