Chaste Release::3.1
VertexBasedCellPopulation.cpp
00001 /*
00002 
00003 Copyright (c) 2005-2012, 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 "VertexMeshWriter.hpp"
00038 #include "Warnings.hpp"
00039 
00040 template<unsigned DIM>
00041 VertexBasedCellPopulation<DIM>::VertexBasedCellPopulation(MutableVertexMesh<DIM, DIM>& rMesh,
00042                                           std::vector<CellPtr>& rCells,
00043                                           bool deleteMesh,
00044                                           bool validate,
00045                                           const std::vector<unsigned> locationIndices)
00046     : AbstractOffLatticeCellPopulation<DIM>(rMesh, rCells, locationIndices),
00047       mDeleteMesh(deleteMesh)
00048 {
00049     mpMutableVertexMesh = static_cast<MutableVertexMesh<DIM, DIM>* >(&(this->mrMesh));
00050 
00051     // Check the mesh contains boundary nodes
00052     bool contains_boundary_nodes = false;
00053     for (typename MutableVertexMesh<DIM,DIM>::NodeIterator node_iter = mpMutableVertexMesh->GetNodeIteratorBegin();
00054          node_iter != mpMutableVertexMesh->GetNodeIteratorEnd();
00055          ++node_iter)
00056     {
00057         if (node_iter->IsBoundaryNode())
00058         {
00059             contains_boundary_nodes = true;
00060         }
00061     }
00062     //if (mpMutableVertexMesh->GetNumBoundaryNodes() == 0)
00064     if (!contains_boundary_nodes)
00065     {
00066         EXCEPTION("No boundary nodes are defined in the supplied vertex mesh which are needed for vertex based simulations.");
00067     }
00068 
00069     // Check each element has only one cell attached
00070     if (validate)
00071     {
00072         Validate();
00073     }
00074 }
00075 
00076 template<unsigned DIM>
00077 VertexBasedCellPopulation<DIM>::VertexBasedCellPopulation(MutableVertexMesh<DIM, DIM>& rMesh)
00078     : AbstractOffLatticeCellPopulation<DIM>(rMesh),
00079       mDeleteMesh(true)
00080 {
00081     mpMutableVertexMesh = static_cast<MutableVertexMesh<DIM, DIM>* >(&(this->mrMesh));
00082 }
00083 
00084 template<unsigned DIM>
00085 VertexBasedCellPopulation<DIM>::~VertexBasedCellPopulation()
00086 {
00087     if (mDeleteMesh)
00088     {
00089         delete &this->mrMesh;
00090     }
00091 }
00092 
00093 template<unsigned DIM>
00094 double VertexBasedCellPopulation<DIM>::GetDampingConstant(unsigned nodeIndex)
00095 {
00096     // Take the average of the cells containing this vertex
00097     double average_damping_constant = 0.0;
00098 
00099     std::set<unsigned> containing_elements = GetNode(nodeIndex)->rGetContainingElementIndices();
00100     double temp = 1.0/((double) containing_elements.size());
00101 
00102     for (std::set<unsigned>::iterator iter = containing_elements.begin();
00103          iter != containing_elements.end();
00104          ++iter)
00105     {
00106         CellPtr p_cell = this->GetCellUsingLocationIndex(*iter);
00107         bool cell_is_wild_type = p_cell->GetMutationState()->IsType<WildTypeCellMutationState>();
00108         bool cell_is_labelled = p_cell->HasCellProperty<CellLabel>();
00109 
00110         if (cell_is_wild_type && !cell_is_labelled)
00111         {
00112             average_damping_constant += this->GetDampingConstantNormal()*temp;
00113         }
00114         else
00115         {
00116             average_damping_constant += this->GetDampingConstantMutant()*temp;
00117         }
00118     }
00119 
00120     return average_damping_constant;
00121 }
00122 
00123 template<unsigned DIM>
00124 MutableVertexMesh<DIM, DIM>& VertexBasedCellPopulation<DIM>::rGetMesh()
00125 {
00126     return *mpMutableVertexMesh;
00127 }
00128 
00129 template<unsigned DIM>
00130 const MutableVertexMesh<DIM, DIM>& VertexBasedCellPopulation<DIM>::rGetMesh() const
00131 {
00132     return *mpMutableVertexMesh;
00133 }
00134 
00135 template<unsigned DIM>
00136 VertexElement<DIM, DIM>* VertexBasedCellPopulation<DIM>::GetElement(unsigned elementIndex)
00137 {
00138     return mpMutableVertexMesh->GetElement(elementIndex);
00139 }
00140 
00141 template<unsigned DIM>
00142 unsigned VertexBasedCellPopulation<DIM>::GetNumNodes()
00143 {
00144     return this->mrMesh.GetNumNodes();
00145 }
00146 
00147 template<unsigned DIM>
00148 c_vector<double, DIM> VertexBasedCellPopulation<DIM>::GetLocationOfCellCentre(CellPtr pCell)
00149 {
00150     return mpMutableVertexMesh->GetCentroidOfElement(this->mCellLocationMap[pCell.get()]);
00151 }
00152 
00153 template<unsigned DIM>
00154 Node<DIM>* VertexBasedCellPopulation<DIM>::GetNode(unsigned index)
00155 {
00156     return this->mrMesh.GetNode(index);
00157 }
00158 
00159 template<unsigned DIM>
00160 unsigned VertexBasedCellPopulation<DIM>::AddNode(Node<DIM>* pNewNode)
00161 {
00162     return mpMutableVertexMesh->AddNode(pNewNode);
00163 }
00164 
00165 template<unsigned DIM>
00166 void VertexBasedCellPopulation<DIM>::SetNode(unsigned nodeIndex, ChastePoint<DIM>& rNewLocation)
00167 {
00168     mpMutableVertexMesh->SetNode(nodeIndex, rNewLocation);
00169 }
00170 
00171 template<unsigned DIM>
00172 VertexElement<DIM, DIM>* VertexBasedCellPopulation<DIM>::GetElementCorrespondingToCell(CellPtr pCell)
00173 {
00174     return mpMutableVertexMesh->GetElement(this->GetLocationIndexUsingCell(pCell));
00175 }
00176 
00177 template<unsigned DIM>
00178 unsigned VertexBasedCellPopulation<DIM>::GetNumElements()
00179 {
00180     return mpMutableVertexMesh->GetNumElements();
00181 }
00182 
00183 template<unsigned DIM>
00184 CellPtr VertexBasedCellPopulation<DIM>::AddCell(CellPtr pNewCell, const c_vector<double,DIM>& rCellDivisionVector, CellPtr pParentCell)
00185 {
00186     // Get the element associated with this cell
00187     VertexElement<DIM, DIM>* p_element = GetElementCorrespondingToCell(pParentCell);
00188 
00189     // Divide the element
00190     unsigned new_element_index;
00191     if (norm_2(rCellDivisionVector) < DBL_EPSILON)
00192     {
00193         // If the cell division vector is the default zero vector, divide the element along the short axis
00194         new_element_index = mpMutableVertexMesh->DivideElementAlongShortAxis(p_element, true);
00195     }
00196     else
00197     {
00198         // If the cell division vector has any non-zero component, divide the element along this axis
00199         new_element_index = mpMutableVertexMesh->DivideElementAlongGivenAxis(p_element, rCellDivisionVector, true);
00200     }
00201 
00202     // Associate the new cell with the element
00203     this->mCells.push_back(pNewCell);
00204 
00205     // Update location cell map
00206     CellPtr p_created_cell = this->mCells.back();
00207     this->SetCellUsingLocationIndex(new_element_index,p_created_cell);
00208     this->mCellLocationMap[p_created_cell.get()] = new_element_index;
00209     return p_created_cell;
00210 }
00211 
00212 template<unsigned DIM>
00213 unsigned VertexBasedCellPopulation<DIM>::RemoveDeadCells()
00214 {
00215     unsigned num_removed = 0;
00216 
00217     for (std::list<CellPtr>::iterator it = this->mCells.begin();
00218          it != this->mCells.end();
00219          ++it)
00220     {
00221         if ((*it)->IsDead())
00222         {
00223             // Remove the element from the mesh
00224             num_removed++;
00225             mpMutableVertexMesh->DeleteElementPriorToReMesh(this->GetLocationIndexUsingCell((*it)));
00226             it = this->mCells.erase(it);
00227             --it;
00228         }
00229     }
00230     return num_removed;
00231 }
00232 
00233 template<unsigned DIM>
00234 void VertexBasedCellPopulation<DIM>::UpdateNodeLocations(const std::vector< c_vector<double, DIM> >& rNodeForces, double dt)
00235 {
00236     // Iterate over all nodes associated with real cells to update their positions
00237     for (unsigned node_index=0; node_index<GetNumNodes(); node_index++)
00238     {
00239         // Get the damping constant for this node
00240         double damping_const = this->GetDampingConstant(node_index);
00241 
00242         // Compute the displacement of this node
00243         c_vector<double, DIM> displacement = dt*rNodeForces[node_index]/damping_const;
00244 
00245         /*
00246          * If the displacement of this node is greater than half the cell rearrangement threshold,
00247          * this could result in nodes moving into the interior of other elements, which should not
00248          * be possible. Therefore in this case we restrict the displacement of the node to the cell
00249          * rearrangement threshold and warn the user that a smaller timestep should be used. This
00250          * restriction ensures that vertex elements remain well defined (see #1376).
00251          */
00252         if (norm_2(displacement) > 0.5*mpMutableVertexMesh->GetCellRearrangementThreshold())
00253         {
00254             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.");
00255             displacement *= 0.5*mpMutableVertexMesh->GetCellRearrangementThreshold()/norm_2(displacement);
00256         }
00257 
00258         // Get new node location
00259         c_vector<double, DIM> new_node_location = this->GetNode(node_index)->rGetLocation() + displacement;
00260 
00261         for (unsigned i=0; i<DIM; i++)
00262         {
00263             assert(!std::isnan(new_node_location(i)));
00264         }
00265 
00266         // Create ChastePoint for new node location
00267         ChastePoint<DIM> new_point(new_node_location);
00268 
00269         // Move the node
00270         this->SetNode(node_index, new_point);
00271     }
00272 }
00273 
00274 template<unsigned DIM>
00275 bool VertexBasedCellPopulation<DIM>::IsCellAssociatedWithADeletedLocation(CellPtr pCell)
00276 {
00277     return GetElementCorrespondingToCell(pCell)->IsDeleted();;
00278 }
00279 
00280 template<unsigned DIM>
00281 void VertexBasedCellPopulation<DIM>::Update(bool hasHadBirthsOrDeaths)
00282 {
00283     VertexElementMap element_map(mpMutableVertexMesh->GetNumAllElements());
00284 
00285     mpMutableVertexMesh->ReMesh(element_map);
00286 
00287     if (!element_map.IsIdentityMap())
00288     {
00289         // Fix up the mappings between CellPtrs and VertexElements
00291         std::map<Cell*, unsigned> old_map = this->mCellLocationMap;
00292 
00293         this->mCellLocationMap.clear();
00294         this->mLocationCellMap.clear();
00295 
00296         for (std::list<CellPtr>::iterator cell_iter = this->mCells.begin();
00297              cell_iter != this->mCells.end();
00298              ++cell_iter)
00299         {
00300             // This shouldn't ever happen, as the cell vector only contains living cells
00301             unsigned old_elem_index = old_map[(*cell_iter).get()];
00302 
00303             if (element_map.IsDeleted(old_elem_index))
00304             {
00309                 WARNING("Cell removed due to T2Swap this is not counted in the dead cells counter");
00310                 cell_iter = this->mCells.erase(cell_iter);
00311                 --cell_iter;
00312             }
00313             else
00314             {
00315                 unsigned new_elem_index = element_map.GetNewIndex(old_elem_index);
00316 
00317                 this->SetCellUsingLocationIndex(new_elem_index,*cell_iter);
00318             }
00319         }
00320 
00321         // Check that each VertexElement has only one CellPtr associated with it in the updated cell population
00322         Validate();
00323     }
00324 
00325     element_map.ResetToIdentity();
00326 }
00327 
00328 template<unsigned DIM>
00329 void VertexBasedCellPopulation<DIM>::Validate()
00330 {
00331     // Check each element has only one cell attached
00332     std::vector<unsigned> validated_element = std::vector<unsigned>(this->GetNumElements(), 0);
00333 
00334     for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->Begin();
00335          cell_iter != this->End();
00336          ++cell_iter)
00337     {
00338         unsigned elem_index = this->GetLocationIndexUsingCell(*cell_iter);
00339         validated_element[elem_index]++;
00340     }
00341 
00342     for (unsigned i=0; i<validated_element.size(); i++)
00343     {
00344         if (validated_element[i] == 0)
00345         {
00346             EXCEPTION("Element " << i << " does not appear to have a cell associated with it");
00347         }
00348 
00349         if (validated_element[i] > 1)
00350         {
00351             // This should never be reached as you can only set one cell per element index.
00352             EXCEPTION("Element " << i << " appears to have " << validated_element[i] << " cells associated with it");
00353         }
00354     }
00355 }
00356 
00357 template<unsigned DIM>
00358 void VertexBasedCellPopulation<DIM>::WriteResultsToFiles()
00359 {
00360     AbstractOffLatticeCellPopulation<DIM>::WriteResultsToFiles();
00361 
00362     SimulationTime* p_time = SimulationTime::Instance();
00363 
00364     // Write Locations of T1Swaps to file
00365     *mpT1SwapLocationsFile << p_time->GetTime() << "\t";
00366     std::vector< c_vector<double, DIM> > t1_swap_locations = mpMutableVertexMesh->GetLocationsOfT1Swaps();
00367     *mpT1SwapLocationsFile << t1_swap_locations.size() << "\t";
00368     for (unsigned index = 0;  index < t1_swap_locations.size(); index++)
00369     {
00370         for (unsigned i=0; i<DIM; i++)
00371         {
00372             *mpT1SwapLocationsFile << t1_swap_locations[index][i] << "\t";
00373         }
00374     }
00375     *mpT1SwapLocationsFile << "\n";
00376     mpMutableVertexMesh->ClearLocationsOfT1Swaps();
00377 
00378     // Write Locations of T3Swaps to file
00379     *mpT3SwapLocationsFile << p_time->GetTime() << "\t";
00380     std::vector< c_vector<double, DIM> > t3_swap_locations = mpMutableVertexMesh->GetLocationsOfT3Swaps();
00381     *mpT3SwapLocationsFile << t3_swap_locations.size() << "\t";
00382     for (unsigned index = 0;  index < t3_swap_locations.size(); index++)
00383     {
00384         for (unsigned i=0; i<DIM; i++)
00385         {
00386             *mpT3SwapLocationsFile << t3_swap_locations[index][i] << "\t";
00387         }
00388     }
00389     *mpT3SwapLocationsFile << "\n";
00390     mpMutableVertexMesh->ClearLocationsOfT3Swaps();
00391 
00392     // Write element data to file
00393     *mpVizElementsFile << p_time->GetTime() << "\t";
00394 
00395     // Loop over cells and find associated elements so in the same order as the cells in output files
00396     for (std::list<CellPtr>::iterator cell_iter = this->mCells.begin();
00397          cell_iter != this->mCells.end();
00398          ++cell_iter)
00399     {
00400         unsigned elem_index = this->GetLocationIndexUsingCell(*cell_iter);
00401 
00402         // Hack that covers the case where the element is associated with a cell that has just been killed (#1129)
00403         bool elem_corresponds_to_dead_cell = false;
00404 
00405         if (this->IsCellAttachedToLocationIndex(elem_index))
00406         {
00407             elem_corresponds_to_dead_cell = this->GetCellUsingLocationIndex(elem_index)->IsDead();
00408         }
00409 
00410         // Write element data to file
00411         if (!(GetElement(elem_index)->IsDeleted()) && !elem_corresponds_to_dead_cell)
00412         {
00413             VertexElement<DIM, DIM>* p_element = mpMutableVertexMesh->GetElement(elem_index);
00414 
00415             unsigned num_nodes_in_element = p_element->GetNumNodes();
00416 
00417             // First write the number of Nodes belonging to this VertexElement
00418             *mpVizElementsFile << num_nodes_in_element << " ";
00419 
00420             // Then write the global index of each Node in this element
00421             for (unsigned i=0; i<num_nodes_in_element; i++)
00422             {
00423                 *mpVizElementsFile << p_element->GetNodeGlobalIndex(i) << " ";
00424             }
00425         }
00426     }
00427     *mpVizElementsFile << "\n";
00428 }
00429 
00430 template<unsigned DIM>
00431 double VertexBasedCellPopulation<DIM>::GetVolumeOfCell(CellPtr pCell)
00432 {
00433     // Get the vertex element index corresponding to this cell
00434     unsigned elem_index = this->GetLocationIndexUsingCell(pCell);
00435 
00436     // Get the cell's volume from the vertex mesh
00437     double cell_volume = mpMutableVertexMesh->GetVolumeOfElement(elem_index);
00438 
00439     return cell_volume;
00440 }
00441 
00442 template<unsigned DIM>
00443 void VertexBasedCellPopulation<DIM>::WriteCellVolumeResultsToFile()
00444 {
00445     assert(DIM==2);
00446 
00447     // Write time to file
00448     *(this->mpCellVolumesFile) << SimulationTime::Instance()->GetTime() << " ";
00449 
00450     // Loop over cells and find associated elements so in the same order as the cells in output files
00451     for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->Begin();
00452          cell_iter != this->End();
00453          ++cell_iter)
00454     {
00455         unsigned elem_index = this->GetLocationIndexUsingCell(*cell_iter);
00456 
00457         // Hack that covers the case where the element is associated with a cell that has just been killed (#1129)
00458         bool elem_corresponds_to_dead_cell = false;
00459 
00460         if (this->IsCellAttachedToLocationIndex(elem_index))
00461         {
00462             elem_corresponds_to_dead_cell = this->GetCellUsingLocationIndex(elem_index)->IsDead();
00463         }
00464 
00465         // Write node data to file
00466         if (!(GetElement(elem_index)->IsDeleted()) && !elem_corresponds_to_dead_cell)
00467         {
00468             // Write element index to file
00469             *(this->mpCellVolumesFile) << elem_index << " ";
00470 
00471             // Write cell ID to file
00472             unsigned cell_index = (*cell_iter)->GetCellId();
00473             *(this->mpCellVolumesFile) << cell_index << " ";
00474 
00475             // Write location of element centroid to file
00476             c_vector<double, DIM> centre_location = GetLocationOfCellCentre(*cell_iter);
00477             for (unsigned i=0; i<DIM; i++)
00478             {
00479                 *(this->mpCellVolumesFile) << centre_location[i] << " ";
00480             }
00481 
00482             // Write cell volume (in 3D) or area (in 2D) to file
00483             double cell_volume = this->GetVolumeOfCell(*cell_iter);
00484             *(this->mpCellVolumesFile) << cell_volume << " ";
00485         }
00486     }
00487     *(this->mpCellVolumesFile) << "\n";
00488 }
00489 
00490 template<unsigned DIM>
00491 void VertexBasedCellPopulation<DIM>::WriteVtkResultsToFile()
00492 {
00493 #ifdef CHASTE_VTK
00494     SimulationTime* p_time = SimulationTime::Instance();
00495 
00496     VertexMeshWriter<DIM, DIM> mesh_writer(this->mDirPath, "results", false);
00497     std::stringstream time;
00498     time << p_time->GetTimeStepsElapsed();
00499 
00500     unsigned num_elements = mpMutableVertexMesh->GetNumElements();
00501     std::vector<double> cell_types(num_elements);
00502     std::vector<double> cell_ancestors(num_elements);
00503     std::vector<double> cell_mutation_states(num_elements);
00504     std::vector<double> cell_ages(num_elements);
00505     std::vector<double> cell_cycle_phases(num_elements);
00506     std::vector<double> cell_volumes(num_elements);
00507     std::vector<std::vector<double> > cellwise_data;
00508 
00509     unsigned num_cell_data_items = 0;
00510     std::vector<std::string> cell_data_names;
00511     //We assume that the first cell is representative of all cells
00512     num_cell_data_items = this->Begin()->GetCellData()->GetNumItems();
00513     cell_data_names = this->Begin()->GetCellData()->GetKeys();
00514 
00515     for (unsigned var=0; var<num_cell_data_items; var++)
00516     {
00517         std::vector<double> cellwise_data_var(num_elements);
00518         cellwise_data.push_back(cellwise_data_var);
00519     }
00520 
00521     // Loop over vertex elements
00522     for (typename VertexMesh<DIM,DIM>::VertexElementIterator elem_iter = mpMutableVertexMesh->GetElementIteratorBegin();
00523          elem_iter != mpMutableVertexMesh->GetElementIteratorEnd();
00524          ++elem_iter)
00525     {
00526         // Get index of this element in the vertex mesh
00527         unsigned elem_index = elem_iter->GetIndex();
00528 
00529         // Get the cell corresponding to this element
00530         CellPtr p_cell = this->GetCellUsingLocationIndex(elem_index);
00531         assert(p_cell);
00532 
00533         if (this->mOutputCellAncestors)
00534         {
00535             double ancestor_index = (p_cell->GetAncestor() == UNSIGNED_UNSET) ? (-1.0) : (double)p_cell->GetAncestor();
00536             cell_ancestors[elem_index] = ancestor_index;
00537         }
00538         if (this->mOutputCellProliferativeTypes)
00539         {
00540             double cell_type = p_cell->GetCellProliferativeType();
00541             cell_types[elem_index] = cell_type;
00542         }
00543         if (this->mOutputCellMutationStates)
00544         {
00545             double mutation_state = p_cell->GetMutationState()->GetColour();
00546             cell_mutation_states[elem_index] = mutation_state;
00547         }
00548         if (this->mOutputCellAges)
00549         {
00550             double age = p_cell->GetAge();
00551             cell_ages[elem_index] = age;
00552         }
00553         if (this->mOutputCellCyclePhases)
00554         {
00555             double cycle_phase = p_cell->GetCellCycleModel()->GetCurrentCellCyclePhase();
00556             cell_cycle_phases[elem_index] = cycle_phase;
00557         }
00558         if (this->mOutputCellVolumes)
00559         {
00560             double cell_volume = mpMutableVertexMesh->GetVolumeOfElement(elem_index);
00561             cell_volumes[elem_index] = cell_volume;
00562         }
00563         for (unsigned var=0; var<num_cell_data_items; var++)
00564         {
00565             cellwise_data[var][elem_index] = p_cell->GetCellData()->GetItem(cell_data_names[var]);
00566         }
00567     }
00568 
00569     if (this->mOutputCellProliferativeTypes)
00570     {
00571         mesh_writer.AddCellData("Cell types", cell_types);
00572     }
00573     if (this->mOutputCellAncestors)
00574     {
00575         mesh_writer.AddCellData("Ancestors", cell_ancestors);
00576     }
00577     if (this->mOutputCellMutationStates)
00578     {
00579         mesh_writer.AddCellData("Mutation states", cell_mutation_states);
00580     }
00581     if (this->mOutputCellAges)
00582     {
00583         mesh_writer.AddCellData("Ages", cell_ages);
00584     }
00585     if (this->mOutputCellCyclePhases)
00586     {
00587         mesh_writer.AddCellData("Cycle phases", cell_cycle_phases);
00588     }
00589     if (this->mOutputCellVolumes)
00590     {
00591         mesh_writer.AddCellData("Cell volumes", cell_volumes);
00592     }
00593     if (num_cell_data_items > 0)
00594     {
00595         for (unsigned var=0; var<cellwise_data.size(); var++)
00596         {
00597             mesh_writer.AddCellData(cell_data_names[var], cellwise_data[var]);
00598         }
00599     }
00600 
00601     mesh_writer.WriteVtkUsingMesh(*mpMutableVertexMesh, time.str());
00602     *(this->mpVtkMetaFile) << "        <DataSet timestep=\"";
00603     *(this->mpVtkMetaFile) << p_time->GetTimeStepsElapsed();
00604     *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_";
00605     *(this->mpVtkMetaFile) << p_time->GetTimeStepsElapsed();
00606     *(this->mpVtkMetaFile) << ".vtu\"/>\n";
00607 #endif //CHASTE_VTK
00608 }
00609 
00610 template<unsigned DIM>
00611 void VertexBasedCellPopulation<DIM>::CreateOutputFiles(const std::string& rDirectory, bool cleanOutputDirectory)
00612 {
00613     AbstractOffLatticeCellPopulation<DIM>::CreateOutputFiles(rDirectory, cleanOutputDirectory);
00614 
00615     OutputFileHandler output_file_handler(rDirectory, cleanOutputDirectory);
00616     mpVizElementsFile = output_file_handler.OpenOutputFile("results.vizelements");
00617     mpT1SwapLocationsFile = output_file_handler.OpenOutputFile("T1SwapLocations.dat");
00618     mpT3SwapLocationsFile = output_file_handler.OpenOutputFile("T3SwapLocations.dat");
00619 }
00620 
00621 template<unsigned DIM>
00622 void VertexBasedCellPopulation<DIM>::CloseOutputFiles()
00623 {
00624     AbstractOffLatticeCellPopulation<DIM>::CloseOutputFiles();
00625     mpVizElementsFile->close();
00626     mpT1SwapLocationsFile->close();
00627     mpT3SwapLocationsFile->close();
00628 }
00629 
00630 template<unsigned DIM>
00631 void VertexBasedCellPopulation<DIM>::GenerateCellResultsAndWriteToFiles()
00632 {
00633     // Set up cell type counter
00634     unsigned num_cell_types = this->mCellProliferativeTypeCount.size();
00635     std::vector<unsigned> cell_type_counter(num_cell_types);
00636     for (unsigned i=0; i<num_cell_types; i++)
00637     {
00638         cell_type_counter[i] = 0;
00639     }
00640 
00641     // Set up cell cycle phase counter
00642     unsigned num_cell_cycle_phases = this->mCellCyclePhaseCount.size();
00643     std::vector<unsigned> cell_cycle_phase_counter(num_cell_cycle_phases);
00644     for (unsigned i=0; i<num_cell_cycle_phases; i++)
00645     {
00646         cell_cycle_phase_counter[i] = 0;
00647     }
00648 
00649     for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->Begin();
00650          cell_iter != this->End();
00651          ++cell_iter)
00652     {
00653         this->GenerateCellResults(*cell_iter, cell_type_counter, cell_cycle_phase_counter);
00654     }
00655 
00656     this->WriteCellResultsToFiles(cell_type_counter, cell_cycle_phase_counter);
00657 }
00658 
00659 template<unsigned DIM>
00660 void VertexBasedCellPopulation<DIM>::OutputCellPopulationParameters(out_stream& rParamsFile)
00661 {
00662     *rParamsFile << "\t\t<CellRearrangementThreshold>" << mpMutableVertexMesh->GetCellRearrangementThreshold() << "</CellRearrangementThreshold>\n";
00663     *rParamsFile << "\t\t<T2Threshold>" <<  mpMutableVertexMesh->GetT2Threshold() << "</T2Threshold>\n";
00664     *rParamsFile << "\t\t<CellRearrangementRatio>" << mpMutableVertexMesh->GetCellRearrangementRatio() << "</CellRearrangementRatio>\n";
00665 
00666     // Call method on direct parent class
00667     AbstractOffLatticeCellPopulation<DIM>::OutputCellPopulationParameters(rParamsFile);
00668 }
00669 
00670 template<unsigned DIM>
00671 double VertexBasedCellPopulation<DIM>::GetWidth(const unsigned& rDimension)
00672 {
00673     // Call GetWidth() on the mesh
00674     double width = this->mrMesh.GetWidth(rDimension);
00675 
00676     return width;
00677 }
00678 
00679 template<unsigned DIM>
00680 std::set<unsigned> VertexBasedCellPopulation<DIM>::GetNeighbouringNodeIndices(unsigned index)
00681 {
00682     return mpMutableVertexMesh->GetNeighbouringNodeIndices(index);
00683 }
00684 
00686 // Explicit instantiation
00688 
00689 template class VertexBasedCellPopulation<1>;
00690 template class VertexBasedCellPopulation<2>;
00691 template class VertexBasedCellPopulation<3>;
00692 
00693 // Serialization for Boost >= 1.36
00694 #include "SerializationExportWrapperForCpp.hpp"
00695 EXPORT_TEMPLATE_CLASS_SAME_DIMS(VertexBasedCellPopulation)