Chaste Release::3.1
PottsBasedCellPopulation.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 "PottsBasedCellPopulation.hpp"
00037 #include "RandomNumberGenerator.hpp"
00038 #include "Warnings.hpp"
00039 
00040 // Needed to convert mesh in order to write nodes to VTK (visualize as glyphs)
00041 #include "VtkMeshWriter.hpp"
00042 #include "NodesOnlyMesh.hpp"
00043 #include "Exception.hpp"
00044 
00045 template<unsigned DIM>
00046 void PottsBasedCellPopulation<DIM>::Validate()
00047 {
00048     // Check each element has only one cell associated with it
00049     std::vector<unsigned> validated_element = std::vector<unsigned>(this->GetNumElements(), 0);
00050 
00051     for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->Begin();
00052          cell_iter != this->End();
00053          ++cell_iter)
00054     {
00055         unsigned elem_index = this->GetLocationIndexUsingCell(*cell_iter);
00056         validated_element[elem_index]++;
00057     }
00058 
00059     for (unsigned i=0; i<validated_element.size(); i++)
00060     {
00061         if (validated_element[i] == 0)
00062         {
00063             EXCEPTION("Element " << i << " does not appear to have a cell associated with it");
00064         }
00065 
00066         if (validated_element[i] > 1)
00067         {
00068             EXCEPTION("Element " << i << " appears to have " << validated_element[i] << " cells associated with it");
00069         }
00070     }
00071 }
00072 
00073 template<unsigned DIM>
00074 PottsBasedCellPopulation<DIM>::PottsBasedCellPopulation(PottsMesh<DIM>& rMesh,
00075                                                         std::vector<CellPtr>& rCells,
00076                                                         bool deleteMesh,
00077                                                         bool validate,
00078                                                         const std::vector<unsigned> locationIndices)
00079     : AbstractOnLatticeCellPopulation<DIM>(rMesh, rCells, locationIndices, deleteMesh),
00080       mpElementTessellation(NULL),
00081       mpMutableMesh(NULL),
00082       mTemperature(0.1),
00083       mNumSweepsPerTimestep(1)
00084 {
00085     mpPottsMesh = static_cast<PottsMesh<DIM>* >(&(this->mrMesh));
00086     // Check each element has only one cell associated with it
00087     if (validate)
00088     {
00089         Validate();
00090     }
00091 }
00092 
00093 template<unsigned DIM>
00094 PottsBasedCellPopulation<DIM>::PottsBasedCellPopulation(PottsMesh<DIM>& rMesh)
00095     : AbstractOnLatticeCellPopulation<DIM>(rMesh),
00096       mpElementTessellation(NULL),
00097       mpMutableMesh(NULL),
00098       mTemperature(0.1),
00099       mNumSweepsPerTimestep(1)
00100 {
00101     mpPottsMesh = static_cast<PottsMesh<DIM>* >(&(this->mrMesh));
00102 }
00103 
00104 template<unsigned DIM>
00105 PottsBasedCellPopulation<DIM>::~PottsBasedCellPopulation()
00106 {
00107     delete mpElementTessellation;
00108 
00109     delete mpMutableMesh;
00110 
00111     if (this->mDeleteMesh)
00112     {
00113         delete &this->mrMesh;
00114     }
00115 }
00116 
00117 template<unsigned DIM>
00118 PottsMesh<DIM>& PottsBasedCellPopulation<DIM>::rGetMesh()
00119 {
00120     return *mpPottsMesh;
00121 }
00122 
00123 template<unsigned DIM>
00124 const PottsMesh<DIM>& PottsBasedCellPopulation<DIM>::rGetMesh() const
00125 {
00126     return *mpPottsMesh;
00127 }
00128 
00129 template<unsigned DIM>
00130 PottsElement<DIM>* PottsBasedCellPopulation<DIM>::GetElement(unsigned elementIndex)
00131 {
00132     return mpPottsMesh->GetElement(elementIndex);
00133 }
00134 
00135 template<unsigned DIM>
00136 unsigned PottsBasedCellPopulation<DIM>::GetNumElements()
00137 {
00138     return mpPottsMesh->GetNumElements();
00139 }
00140 
00141 template<unsigned DIM>
00142 Node<DIM>* PottsBasedCellPopulation<DIM>::GetNode(unsigned index)
00143 {
00144     return this->mrMesh.GetNode(index);
00145 }
00146 
00147 template<unsigned DIM>
00148 unsigned PottsBasedCellPopulation<DIM>::GetNumNodes()
00149 {
00150     return this->mrMesh.GetNumNodes();
00151 }
00152 
00153 template<unsigned DIM>
00154 c_vector<double, DIM> PottsBasedCellPopulation<DIM>::GetLocationOfCellCentre(CellPtr pCell)
00155 {
00156     return mpPottsMesh->GetCentroidOfElement(this->GetLocationIndexUsingCell(pCell));
00157 }
00158 
00159 template<unsigned DIM>
00160 PottsElement<DIM>* PottsBasedCellPopulation<DIM>::GetElementCorrespondingToCell(CellPtr pCell)
00161 {
00162     return mpPottsMesh->GetElement(this->GetLocationIndexUsingCell(pCell));
00163 }
00164 
00165 template<unsigned DIM>
00166 CellPtr PottsBasedCellPopulation<DIM>::AddCell(CellPtr pNewCell, const c_vector<double,DIM>& rCellDivisionVector, CellPtr pParentCell)
00167 {
00168     // Get the element associated with this cell
00169     PottsElement<DIM>* p_element = GetElementCorrespondingToCell(pParentCell);
00170 
00171     // Divide the element
00172     unsigned new_element_index = mpPottsMesh->DivideElement(p_element, true); // new element will be below the existing element
00173 
00174     // Associate the new cell with the element
00175     this->mCells.push_back(pNewCell);
00176 
00177     // Update location cell map
00178     CellPtr p_created_cell = this->mCells.back();
00179     this->SetCellUsingLocationIndex(new_element_index,p_created_cell);
00180     return p_created_cell;
00181 }
00182 
00183 template<unsigned DIM>
00184 unsigned PottsBasedCellPopulation<DIM>::RemoveDeadCells()
00185 {
00186     unsigned num_removed = 0;
00187 
00188     for (std::list<CellPtr>::iterator it = this->mCells.begin();
00189          it != this->mCells.end();
00190          ++it)
00191     {
00192         if ((*it)->IsDead())
00193         {
00194             // Remove the element from the mesh
00195             num_removed++;
00196             mpPottsMesh->DeleteElement(this->GetLocationIndexUsingCell((*it)));
00197             it = this->mCells.erase(it);
00198             --it;
00199         }
00200     }
00201     return num_removed;
00202 }
00203 template<unsigned DIM>
00204 void PottsBasedCellPopulation<DIM>::UpdateCellLocations(double dt)
00205 {
00206     /*
00207      * This method implements a Monte Carlo method to update the cell population.
00208      * We sample randomly from all nodes in the mesh. Once we have selected a target
00209      * node we randomly select a neighbour. The Hamiltonian is evaluated in the
00210      * current configuration (H_0) and with the target node added to the same
00211      * element as the neighbour (H_1). Based on the vale of deltaH = H_1 - H_0,
00212      * the switch is either made or not.
00213      *
00214      * For each time step (i.e. each time this method is called) we sample
00215      * mrMesh.GetNumNodes() nodes. This is known as a Monte Carlo Step (MCS).
00216      */
00217 
00218     RandomNumberGenerator* p_gen = RandomNumberGenerator::Instance();
00219     unsigned num_nodes = this->mrMesh.GetNumNodes();
00220 
00221     // Randomly permute mUpdateRuleCollection if specified
00222     if (this->mIterateRandomlyOverUpdateRuleCollection)
00223     {
00224         // Randomly permute mUpdateRuleCollection
00225         p_gen->Shuffle(mUpdateRuleCollection);
00226     }
00227 
00228     for (unsigned i=0; i<num_nodes*mNumSweepsPerTimestep; i++)
00229     {
00230         unsigned node_index;
00231 
00232         if (this->mUpdateNodesInRandomOrder)
00233         {
00234             node_index = p_gen->randMod(num_nodes);
00235         }
00236         else
00237         {
00238             // Loop over nodes in index order.
00239             node_index = i%num_nodes;
00240         }
00241 
00242         Node<DIM>* p_node = this->mrMesh.GetNode(node_index);
00243 
00244         // Each node in the mesh must be in at most one element
00245         assert(p_node->GetNumContainingElements() <= 1);
00246 
00247         // Find a random available neighbouring node to overwrite current site
00248         std::set<unsigned> neighbouring_node_indices = mpPottsMesh->GetMooreNeighbouringNodeIndices(node_index);
00249         unsigned neighbour_location_index;
00250 
00251         if (!neighbouring_node_indices.empty())
00252         {
00253             unsigned num_neighbours = neighbouring_node_indices.size();
00254             unsigned chosen_neighbour = p_gen->randMod(num_neighbours);
00255 
00256             std::set<unsigned>::iterator neighbour_iter = neighbouring_node_indices.begin();
00257             for (unsigned j=0; j<chosen_neighbour; j++)
00258             {
00259                 neighbour_iter++;
00260             }
00261 
00262             neighbour_location_index = *neighbour_iter;
00263         }
00264         else
00265         {
00266             // Each node in the mesh must have at least one neighbour
00267             NEVER_REACHED;
00268         }
00269 
00270         std::set<unsigned> containing_elements = p_node->rGetContainingElementIndices();
00271         std::set<unsigned> neighbour_containing_elements = GetNode(neighbour_location_index)->rGetContainingElementIndices();
00272         // Only calculate Hamiltonian and update elements if the nodes are from different elements, or one is from the medium
00273         if (  (  *containing_elements.begin() != *neighbour_containing_elements.begin() && !containing_elements.empty() && !neighbour_containing_elements.empty() )
00274                 || ( !containing_elements.empty() && neighbour_containing_elements.empty() )
00275                 || ( containing_elements.empty() && !neighbour_containing_elements.empty() ) )
00276         {
00277             double delta_H = 0.0; // This is H_1-H_0.
00278 
00279             // Now add contributions to the Hamiltonian from each AbstractPottsUpdateRule
00280             for (typename std::vector<boost::shared_ptr<AbstractPottsUpdateRule<DIM> > >::iterator iter = mUpdateRuleCollection.begin();
00281                  iter != mUpdateRuleCollection.end();
00282                  ++iter)
00283             {
00284                 delta_H += (*iter)->EvaluateHamiltonianContribution(neighbour_location_index, p_node->GetIndex(), *this);
00285             }
00286 
00287             // Generate a uniform random number to do the random motion
00288             double random_number = p_gen->ranf();
00289             double p = exp(-delta_H/mTemperature);
00290             if (delta_H <= 0 || random_number < p)
00291             {
00292                 // Do swap
00293 
00294                 // Remove the current node from any elements containing it (there should be at most one such element)
00295                 for (std::set<unsigned>::iterator iter = containing_elements.begin();
00296                      iter != containing_elements.end();
00297                      ++iter)
00298                 {
00299                     GetElement(*iter)->DeleteNode(GetElement(*iter)->GetNodeLocalIndex(node_index));
00300 
00302                 }
00303 
00304                 // Next add the current node to any elements containing the neighbouring node (there should be at most one such element)
00305                 for (std::set<unsigned>::iterator iter = neighbour_containing_elements.begin();
00306                      iter != neighbour_containing_elements.end();
00307                      ++iter)
00308                 {
00309                     GetElement(*iter)->AddNode(this->mrMesh.GetNode(node_index));
00310                 }
00311             }
00312         }
00313     }
00314 }
00315 
00316 template<unsigned DIM>
00317 bool PottsBasedCellPopulation<DIM>::IsCellAssociatedWithADeletedLocation(CellPtr pCell)
00318 {
00319     return GetElementCorrespondingToCell(pCell)->IsDeleted();
00320 }
00321 
00322 template<unsigned DIM>
00323 void PottsBasedCellPopulation<DIM>::Update(bool hasHadBirthsOrDeaths)
00324 {
00325 }
00326 
00327 template<unsigned DIM>
00328 void PottsBasedCellPopulation<DIM>::CreateOutputFiles(const std::string& rDirectory, bool cleanOutputDirectory)
00329 {
00330     AbstractCellPopulation<DIM>::CreateOutputFiles(rDirectory, cleanOutputDirectory);
00331 
00332     OutputFileHandler output_file_handler(rDirectory, cleanOutputDirectory);
00333     mpVizElementsFile = output_file_handler.OpenOutputFile("results.vizelements");
00334 }
00335 
00336 template<unsigned DIM>
00337 void PottsBasedCellPopulation<DIM>::CloseOutputFiles()
00338 {
00339     AbstractCellPopulation<DIM>::CloseOutputFiles();
00340     mpVizElementsFile->close();
00341 }
00342 
00343 template<unsigned DIM>
00344 void PottsBasedCellPopulation<DIM>::WriteResultsToFiles()
00345 {
00346     AbstractCellPopulation<DIM>::WriteResultsToFiles();
00347 
00348     CreateElementTessellation(); // To be used to output to the visualizer
00349 
00350     SimulationTime* p_time = SimulationTime::Instance();
00351 
00352     // Write element data to file
00353     *mpVizElementsFile << p_time->GetTime() << "\t";
00354 
00355     // Loop over cells and find associated elements so in the same order as the cells in output files
00356     for (std::list<CellPtr>::iterator cell_iter = this->mCells.begin();
00357          cell_iter != this->mCells.end();
00358          ++cell_iter)
00359     {
00360         unsigned elem_index = this->GetLocationIndexUsingCell(*cell_iter);
00361 
00362         // Hack that covers the case where the element is associated with a cell that has just been killed (#1129)
00363         bool elem_corresponds_to_dead_cell = false;
00364 
00365         if (this->IsCellAttachedToLocationIndex(elem_index))
00366         {
00367             elem_corresponds_to_dead_cell = this->GetCellUsingLocationIndex(elem_index)->IsDead();
00368         }
00369 
00370         // Write node data to file
00371         if (!(GetElement(elem_index)->IsDeleted()) && !elem_corresponds_to_dead_cell)
00372         {
00373             PottsElement<DIM>* p_element = mpPottsMesh->GetElement(elem_index);
00374 
00375             unsigned num_nodes_in_element = p_element->GetNumNodes();
00376 
00377             // First write the number of Nodes belonging to this PottsElement
00378             *mpVizElementsFile << num_nodes_in_element << " ";
00379 
00380             // Then write the global index of each Node in this element
00381             for (unsigned i=0; i<num_nodes_in_element; i++)
00382             {
00383                 *mpVizElementsFile << p_element->GetNodeGlobalIndex(i) << " ";
00384             }
00385         }
00386     }
00387     *mpVizElementsFile << "\n";
00388 }
00389 
00390 template<unsigned DIM>
00391 double PottsBasedCellPopulation<DIM>::GetVolumeOfCell(CellPtr pCell)
00392 {
00393     // Get element index corresponding to this cell
00394     unsigned elem_index = this->GetLocationIndexUsingCell(pCell);
00395 
00396     // Get volume of this element in the Potts mesh
00397     double cell_volume = mpPottsMesh->GetVolumeOfElement(elem_index);
00398 
00399     return cell_volume;
00400 }
00401 
00402 template<unsigned DIM>
00403 void PottsBasedCellPopulation<DIM>::WriteCellVolumeResultsToFile()
00404 {
00405     // Write time to file
00406     *(this->mpCellVolumesFile) << SimulationTime::Instance()->GetTime() << " ";
00407 
00408     // Loop over cells and find associated elements so in the same order as the cells in output files
00409     for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->Begin();
00410          cell_iter != this->End();
00411          ++cell_iter)
00412     {
00413         unsigned elem_index = this->GetLocationIndexUsingCell(*cell_iter);
00414 
00415         // Hack that covers the case where the element is associated with a cell that has just been killed (#1129)
00416         bool elem_corresponds_to_dead_cell = false;
00417 
00418         if (this->IsCellAttachedToLocationIndex(elem_index))
00419         {
00420             elem_corresponds_to_dead_cell = this->GetCellUsingLocationIndex(elem_index)->IsDead();
00421         }
00422 
00423         // Write node data to file
00424         if (!(GetElement(elem_index)->IsDeleted()) && !elem_corresponds_to_dead_cell)
00425         {
00426            // Write element index to file
00427             *(this->mpCellVolumesFile) << elem_index << " ";
00428 
00429             // Write cell ID to file
00430             unsigned cell_index = cell_iter->GetCellId();
00431             *(this->mpCellVolumesFile) << cell_index << " ";
00432 
00433             // Write centroid location to file
00434             c_vector<double, DIM> centroid_location = mpPottsMesh->GetCentroidOfElement(elem_index);
00435 
00436             *(this->mpCellVolumesFile) << centroid_location[0] << " ";
00437             *(this->mpCellVolumesFile) << centroid_location[1] << " ";
00438 
00439             // Write cell volume (in 3D) or area (in 2D) to file
00440             double cell_volume = this->GetVolumeOfCell(*cell_iter);
00441             *(this->mpCellVolumesFile) << cell_volume << " ";
00442         }
00443     }
00444     *(this->mpCellVolumesFile) << "\n";
00445 }
00446 
00447 template<unsigned DIM>
00448 void PottsBasedCellPopulation<DIM>::GenerateCellResultsAndWriteToFiles()
00449 {
00450     // Set up cell type counter
00451     unsigned num_cell_types = this->mCellProliferativeTypeCount.size();
00452     std::vector<unsigned> cell_type_counter(num_cell_types);
00453     for (unsigned i=0; i<num_cell_types; i++)
00454     {
00455         cell_type_counter[i] = 0;
00456     }
00457 
00458     // Set up cell cycle phase counter
00459     unsigned num_cell_cycle_phases = this->mCellCyclePhaseCount.size();
00460     std::vector<unsigned> cell_cycle_phase_counter(num_cell_cycle_phases);
00461     for (unsigned i=0; i<num_cell_cycle_phases; i++)
00462     {
00463         cell_cycle_phase_counter[i] = 0;
00464     }
00465 
00466     for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->Begin();
00467          cell_iter != this->End();
00468          ++cell_iter)
00469     {
00470         this->GenerateCellResults(*cell_iter, cell_type_counter, cell_cycle_phase_counter);
00471     }
00472 
00473     this->WriteCellResultsToFiles(cell_type_counter, cell_cycle_phase_counter);
00474 }
00475 
00476 template<unsigned DIM>
00477 double PottsBasedCellPopulation<DIM>::GetWidth(const unsigned& rDimension)
00478 {
00479     // Call GetWidth() on the mesh
00480     double width = this->mrMesh.GetWidth(rDimension);
00481 
00482     return width;
00483 }
00484 
00485 template<unsigned DIM>
00486 void PottsBasedCellPopulation<DIM>::AddUpdateRule(boost::shared_ptr<AbstractPottsUpdateRule<DIM> > pUpdateRule)
00487 {
00488     mUpdateRuleCollection.push_back(pUpdateRule);
00489 }
00490 
00491 template<unsigned DIM>
00492 void PottsBasedCellPopulation<DIM>::RemoveAllUpdateRules()
00493 {
00494     mUpdateRuleCollection.clear();
00495 }
00496 
00497 template<unsigned DIM>
00498 const std::vector<boost::shared_ptr<AbstractPottsUpdateRule<DIM> > >& PottsBasedCellPopulation<DIM>::rGetUpdateRuleCollection() const
00499 {
00500     return mUpdateRuleCollection;
00501 }
00502 
00503 template<unsigned DIM>
00504 void PottsBasedCellPopulation<DIM>::CreateElementTessellation()
00505 {
00507 //  delete mpElementTessellation;
00508 //
00509 //    ///\todo this code would need to be extended if the domain were required to be periodic
00510 //
00511 //  std::vector<Node<2>*> nodes;
00512 //  for (unsigned node_index=0; node_index<mrMesh.GetNumNodes(); node_index++)
00513 //  {
00514 //      Node<2>* p_temp_node = mrMesh.GetNode(node_index);
00515 //      nodes.push_back(p_temp_node);
00516 //  }
00517 //  MutableMesh<2,2> mesh(nodes);
00518 //    mpElementTessellation = new VertexMesh<2,2>(mesh);
00519 }
00520 
00521 template<unsigned DIM>
00522 VertexMesh<DIM,DIM>* PottsBasedCellPopulation<DIM>::GetElementTessellation()
00523 {
00524 //    assert(mpElementTessellation != NULL);
00525     return mpElementTessellation;
00526 }
00527 
00528 template<unsigned DIM>
00529 void PottsBasedCellPopulation<DIM>::CreateMutableMesh()
00530 {
00531     delete mpMutableMesh;
00532 
00533     // Get the nodes of the PottsMesh
00534     std::vector<Node<DIM>*> nodes;
00535     for (unsigned node_index=0; node_index<this->mrMesh.GetNumNodes(); node_index++)
00536     {
00537       c_vector<double, DIM> location = this->mrMesh.GetNode(node_index)->rGetLocation();
00538       nodes.push_back(new Node<DIM>(node_index, location));
00539     }
00540 
00541     mpMutableMesh = new MutableMesh<DIM,DIM>(nodes);
00542 }
00543 
00544 template<unsigned DIM>
00545 MutableMesh<DIM,DIM>* PottsBasedCellPopulation<DIM>::GetMutableMesh()
00546 {
00547     assert(mpMutableMesh);
00548     return mpMutableMesh;
00549 }
00550 
00551 template<unsigned DIM>
00552 void PottsBasedCellPopulation<DIM>::OutputCellPopulationParameters(out_stream& rParamsFile)
00553 {
00554     *rParamsFile << "\t\t<Temperature>" << mTemperature << "</Temperature>\n";
00555     *rParamsFile << "\t\t<NumSweepsPerTimestep>" << mNumSweepsPerTimestep << "</NumSweepsPerTimestep>\n";
00556 
00557     // Call method on direct parent class
00558     AbstractOnLatticeCellPopulation<DIM>::OutputCellPopulationParameters(rParamsFile);
00559 }
00560 
00561 template<unsigned DIM>
00562 std::set<unsigned> PottsBasedCellPopulation<DIM>::GetNeighbouringNodeIndices(unsigned index)
00563 {
00564     EXCEPTION("Cannot call GetNeighbouringNodeIndices() on a PottsBasedCellPopulation, need to go through the PottsMesh instead");
00565     std::set<unsigned> neighbouring_node_indices;
00566     return neighbouring_node_indices;
00567 }
00568 
00569 template<unsigned DIM>
00570 void PottsBasedCellPopulation<DIM>::SetTemperature(double temperature)
00571 {
00572     mTemperature = temperature;
00573 }
00574 
00575 template<unsigned DIM>
00576 double PottsBasedCellPopulation<DIM>::GetTemperature()
00577 {
00578     return mTemperature;
00579 }
00580 
00581 template<unsigned DIM>
00582 void PottsBasedCellPopulation<DIM>::SetNumSweepsPerTimestep(unsigned numSweepsPerTimestep)
00583 {
00584     mNumSweepsPerTimestep = numSweepsPerTimestep;
00585 }
00586 
00587 template<unsigned DIM>
00588 unsigned PottsBasedCellPopulation<DIM>::GetNumSweepsPerTimestep()
00589 {
00590     return mNumSweepsPerTimestep;
00591 }
00592 
00593 template<unsigned DIM>
00594 void PottsBasedCellPopulation<DIM>::WriteVtkResultsToFile()
00595 {
00596 #ifdef CHASTE_VTK
00597     std::stringstream time;
00598     time << SimulationTime::Instance()->GetTimeStepsElapsed();
00599     VtkMeshWriter<DIM, DIM> mesh_writer(this->mDirPath, "results_"+time.str(), false);
00600 
00601     unsigned num_nodes = GetNumNodes();
00602     std::vector<double> cell_types;
00603     std::vector<double> cell_mutation_states;
00604     std::vector<double> cell_labels;
00605     std::vector<double> elem_ids;
00606     cell_types.reserve(num_nodes);
00607     cell_mutation_states.reserve(num_nodes);
00608     cell_labels.reserve(num_nodes);
00609     elem_ids.reserve(num_nodes);
00610     std::vector<std::vector<double> > cellwise_data;
00611 
00612     unsigned num_cell_data_items = 0;
00613     std::vector<std::string> cell_data_names;
00614     //We assume that the first cell is representative of all cells
00615     num_cell_data_items = this->Begin()->GetCellData()->GetNumItems();
00616     cell_data_names = this->Begin()->GetCellData()->GetKeys();
00617 
00618     for (unsigned var=0; var<num_cell_data_items; var++)
00619     {
00620         std::vector<double> cellwise_data_var(num_nodes);
00621         cellwise_data.push_back(cellwise_data_var);
00622     }
00623     for (typename AbstractMesh<DIM,DIM>::NodeIterator iter = mpPottsMesh->GetNodeIteratorBegin();
00624          iter != mpPottsMesh->GetNodeIteratorEnd();
00625          ++iter)
00626     {
00627         std::set<unsigned> element_indices = iter->rGetContainingElementIndices();
00628 
00629         if (element_indices.empty())
00630         {
00631             // No elements associated with this gridpoint
00632             cell_types.push_back(-1.0);
00633             elem_ids.push_back(-1.0);
00634             if (this->mOutputCellMutationStates)
00635             {
00636                 cell_mutation_states.push_back(-1.0);
00637                 cell_labels.push_back(-1.0);
00638             }
00639         }
00640         else
00641         {
00642             // The number of elements should be zero or one
00643             assert(element_indices.size() == 1);
00644 
00645             unsigned element_index = *(element_indices.begin());
00646             elem_ids.push_back((double)element_index);
00647 
00648             CellPtr p_cell = this->GetCellUsingLocationIndex(element_index);
00649             double cell_type = p_cell->GetCellProliferativeType();
00650             cell_types.push_back(cell_type);
00651 
00652             if (this->mOutputCellMutationStates)
00653             {
00654                 double cell_mutation_state = p_cell->GetMutationState()->GetColour();
00655                 cell_mutation_states.push_back(cell_mutation_state);
00656 
00657                 double cell_label = 0.0;
00658                 if (p_cell->HasCellProperty<CellLabel>())
00659                 {
00660                     CellPropertyCollection collection = p_cell->rGetCellPropertyCollection().GetProperties<CellLabel>();
00661                     boost::shared_ptr<CellLabel> p_label = boost::static_pointer_cast<CellLabel>(collection.GetProperty());
00662                     cell_label = p_label->GetColour();
00663                 }
00664                 cell_labels.push_back(cell_label);
00665             }
00666             for (unsigned var=0; var<num_cell_data_items; var++)
00667             {
00668                 cellwise_data[var][iter->GetIndex()] = p_cell->GetCellData()->GetItem(cell_data_names[var]);
00669             }
00670         }
00671     }
00672 
00673     assert(cell_types.size() == num_nodes);
00674     assert(elem_ids.size() == num_nodes);
00675 
00676     mesh_writer.AddPointData("Element index", elem_ids);
00677     mesh_writer.AddPointData("Cell types", cell_types);
00678 
00679     if (this->mOutputCellMutationStates)
00680     {
00681         assert(cell_mutation_states.size() == num_nodes);
00682         mesh_writer.AddPointData("Mutation states", cell_mutation_states);
00683         assert(cell_labels.size() == num_nodes);
00684         mesh_writer.AddPointData("Cell labels", cell_labels);
00685     }
00686 
00687     if (num_cell_data_items > 0)
00688     {
00689         for (unsigned var=0; var<cellwise_data.size(); var++)
00690         {
00691             mesh_writer.AddPointData(cell_data_names[var], cellwise_data[var]);
00692         }
00693     }
00694 
00695     /*
00696      * The current VTK writer can only write things which inherit from AbstractTetrahedralMeshWriter.
00697      * For now, we do an explicit conversion to NodesOnlyMesh. This can be written to VTK then visualized as glyphs.
00698      */
00699     NodesOnlyMesh<DIM> temp_mesh;
00700     temp_mesh.ConstructNodesWithoutMesh(*mpPottsMesh);
00701     mesh_writer.WriteFilesUsingMesh(temp_mesh);
00702 
00703     *(this->mpVtkMetaFile) << "        <DataSet timestep=\"";
00704     *(this->mpVtkMetaFile) << time.str();
00705     *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_";
00706     *(this->mpVtkMetaFile) << time.str();
00707     *(this->mpVtkMetaFile) << ".vtu\"/>\n";
00708 #endif //CHASTE_VTK
00709 }
00710 
00712 // Explicit instantiation
00714 
00715 template class PottsBasedCellPopulation<1>;
00716 template class PottsBasedCellPopulation<2>;
00717 template class PottsBasedCellPopulation<3>;
00718 
00719 // Serialization for Boost >= 1.36
00720 #include "SerializationExportWrapperForCpp.hpp"
00721 EXPORT_TEMPLATE_CLASS_SAME_DIMS(PottsBasedCellPopulation)