CaBasedCellPopulation.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 "CaBasedCellPopulation.hpp"
00037 
00038 #include <boost/scoped_array.hpp>
00039 
00040 #include "RandomNumberGenerator.hpp"
00041 #include "Warnings.hpp"
00042 
00043 // Needed to convert mesh in order to write nodes to VTK (visualize as glyphs)
00044 #include "VtkMeshWriter.hpp"
00045 
00046 // Cell writers
00047 #include "CellAgesWriter.hpp"
00048 #include "CellAncestorWriter.hpp"
00049 #include "CellLocationIndexWriter.hpp"
00050 #include "CellProliferativePhasesWriter.hpp"
00051 #include "CellProliferativeTypesWriter.hpp"
00052 
00053 // Cell population writers
00054 #include "CellMutationStatesWriter.hpp"
00055 
00056 #include "NodesOnlyMesh.hpp"
00057 #include "Exception.hpp"
00058 
00059 template<unsigned DIM>
00060 void CaBasedCellPopulation<DIM>::Validate()
00061 {
00062     NEVER_REACHED;
00063 }
00064 
00065 template<unsigned DIM>
00066 CaBasedCellPopulation<DIM>::CaBasedCellPopulation(PottsMesh<DIM>& rMesh,
00067                                                         std::vector<CellPtr>& rCells,
00068                                                         const std::vector<unsigned> locationIndices,
00069                                                         unsigned latticeCarryingCapacity,
00070                                                         bool deleteMesh,
00071                                                         bool validate)
00072     : AbstractOnLatticeCellPopulation<DIM>(rMesh, rCells, locationIndices, deleteMesh),
00073       mLatticeCarryingCapacity(latticeCarryingCapacity)
00074 {
00075     mAvailableSpaces = std::vector<unsigned>(this->GetNumNodes(), latticeCarryingCapacity);
00076 
00077     // This must always be true
00078     assert(this->mCells.size() <= this->mrMesh.GetNumNodes()*latticeCarryingCapacity);
00079 
00080     if (locationIndices.empty())
00081     {
00082         EXCEPTION("No location indices being passed. Specify where cells lie before creating the cell population.");
00083     }
00084     else
00085     {
00086         // Create a set of node indices corresponding to empty sites.
00087         // Note iterating over mCells is OK as it has the same order as location indices at this point (its just coppied from rCells)
00088         std::list<CellPtr>::iterator it = this->mCells.begin();
00089         for (unsigned i=0; it != this->mCells.end(); ++it, ++i)
00090         {
00091             assert(i<locationIndices.size());
00092             if (!IsSiteAvailable(locationIndices[i],*it))
00093             {
00094                 EXCEPTION("One of the lattice sites has more cells than the carrying capacity. Check the initial cell locations.");
00095             }
00096             mAvailableSpaces[locationIndices[i]]--;
00097         }
00098     }
00099     if (validate)
00100     {
00101         EXCEPTION("There is no validation for CaBasedCellPopulation.");
00102     }
00103 }
00104 
00105 template<unsigned DIM>
00106 CaBasedCellPopulation<DIM>::CaBasedCellPopulation(PottsMesh<DIM>& rMesh)
00107     : AbstractOnLatticeCellPopulation<DIM>(rMesh)
00108 {
00109 }
00110 
00111 template<unsigned DIM>
00112 CaBasedCellPopulation<DIM>::~CaBasedCellPopulation()
00113 {
00114     if (this->mDeleteMesh)
00115     {
00116         delete &this->mrMesh;
00117     }
00118 }
00119 
00120 template<unsigned DIM>
00121 std::vector<unsigned>& CaBasedCellPopulation<DIM>::rGetAvailableSpaces()
00122 {
00123     return mAvailableSpaces;
00124 }
00125 
00126 template<unsigned DIM>
00127 bool CaBasedCellPopulation<DIM>::IsSiteAvailable(unsigned index, CellPtr pCell)
00128 {
00130     return (mAvailableSpaces[index] != 0);
00131 }
00132 
00133 template<unsigned DIM>
00134 PottsMesh<DIM>& CaBasedCellPopulation<DIM>::rGetMesh()
00135 {
00136     return static_cast<PottsMesh<DIM>& >((this->mrMesh));
00137 }
00138 
00139 template<unsigned DIM>
00140 const PottsMesh<DIM>& CaBasedCellPopulation<DIM>::rGetMesh() const
00141 {
00142     return static_cast<PottsMesh<DIM>& >((this->mrMesh));
00143 }
00144 
00145 template<unsigned DIM>
00146 Node<DIM>* CaBasedCellPopulation<DIM>::GetNode(unsigned index)
00147 {
00148     return this->mrMesh.GetNode(index);
00149 }
00150 
00151 template<unsigned DIM>
00152 unsigned CaBasedCellPopulation<DIM>::GetNumNodes()
00153 {
00154     return this->mrMesh.GetNumNodes();
00155 }
00156 
00157 template<unsigned DIM>
00158 std::set<unsigned> CaBasedCellPopulation<DIM>::GetNeighbouringLocationIndices(CellPtr pCell)
00159 {
00160     unsigned index = this->GetLocationIndexUsingCell(pCell);
00161     std::set<unsigned> candidates = static_cast<PottsMesh<DIM>& >((this->mrMesh)).GetMooreNeighbouringNodeIndices(index);
00162 
00163     std::set<unsigned> neighbour_indices;
00164     for (std::set<unsigned>::iterator iter = candidates.begin();
00165          iter != candidates.end();
00166          ++iter)
00167     {
00168         if (!IsSiteAvailable(*iter, pCell))
00169         {
00170             neighbour_indices.insert(*iter);
00171         }
00172     }
00173 
00174     return neighbour_indices;
00175 }
00176 
00177 template<unsigned DIM>
00178 c_vector<double, DIM> CaBasedCellPopulation<DIM>::GetLocationOfCellCentre(CellPtr pCell)
00179 {
00180     return this->mrMesh.GetNode(this->GetLocationIndexUsingCell(pCell))->rGetLocation();
00181 }
00182 
00183 template<unsigned DIM>
00184 Node<DIM>* CaBasedCellPopulation<DIM>::GetNodeCorrespondingToCell(CellPtr pCell)
00185 {
00186     return this->mrMesh.GetNode(this->GetLocationIndexUsingCell(pCell));
00187 }
00188 
00189 template<unsigned DIM>
00190 void CaBasedCellPopulation<DIM>::AddCellUsingLocationIndex(unsigned index, CellPtr pCell)
00191 {
00192     if (!IsSiteAvailable(index, pCell))
00193     {
00194         EXCEPTION("No available spaces at location index " << index << ".");
00195     }
00196 
00197     mAvailableSpaces[index]--;
00198     AbstractCellPopulation<DIM,DIM>::AddCellUsingLocationIndex(index, pCell);
00199 }
00200 
00201 template<unsigned DIM>
00202 void CaBasedCellPopulation<DIM>::RemoveCellUsingLocationIndex(unsigned index, CellPtr pCell)
00203 {
00204     AbstractCellPopulation<DIM,DIM>::RemoveCellUsingLocationIndex(index, pCell);
00205 
00206     mAvailableSpaces[index]++;
00207 
00208     assert(mAvailableSpaces[index] <= mLatticeCarryingCapacity);
00209 }
00210 
00211 template<unsigned DIM>
00212 bool CaBasedCellPopulation<DIM>::IsRoomToDivide(CellPtr pCell)
00213 {
00214     bool is_room = false;
00215 
00216     // Get node index corresponding to this cell
00217     unsigned node_index = this->GetLocationIndexUsingCell(pCell);
00218 
00219     // Get the set of neighbouring node indices
00220     std::set<unsigned> neighbouring_node_indices = static_cast<PottsMesh<DIM>& >((this->mrMesh)).GetMooreNeighbouringNodeIndices(node_index);
00221 
00222     // Iterate through the neighbours to see if there are any available sites
00223     for (std::set<unsigned>::iterator neighbour_iter = neighbouring_node_indices.begin();
00224          neighbour_iter != neighbouring_node_indices.end();
00225          ++neighbour_iter)
00226     {
00227         if (IsSiteAvailable(*neighbour_iter, pCell))
00228         {
00229             is_room = true;
00230             break;
00231         }
00232     }
00233 
00234     return is_room;
00235 }
00236 
00237 template<unsigned DIM>
00238 CellPtr CaBasedCellPopulation<DIM>::AddCell(CellPtr pNewCell, const c_vector<double,DIM>& rCellDivisionVector, CellPtr pParentCell)
00239 {
00240     // Get node index corresponding to the parent cell
00241     unsigned parent_node_index = this->GetLocationIndexUsingCell(pParentCell);
00242 
00243     // Get the set of neighbouring node indices
00244     std::set<unsigned> neighbouring_node_indices = static_cast<PottsMesh<DIM>& >((this->mrMesh)).GetMooreNeighbouringNodeIndices(parent_node_index);
00245     unsigned num_neighbours = neighbouring_node_indices.size();
00246 
00247     // Each node must have at least one neighbour
00248     assert(!neighbouring_node_indices.empty());
00249 
00250     std::vector<double> neighbouring_node_propensities;
00251     std::vector<unsigned> neighbouring_node_indices_vector;
00252 
00253     double total_propensity = 0.0;
00254 
00255     for (std::set<unsigned>::iterator neighbour_iter = neighbouring_node_indices.begin();
00256             neighbour_iter != neighbouring_node_indices.end();
00257          ++neighbour_iter)
00258     {
00259         neighbouring_node_indices_vector.push_back(*neighbour_iter);
00260 
00261         double propensity_dividing_into_neighbour = EvaluateDivisionPropensity(parent_node_index,*neighbour_iter,pParentCell);
00262 
00263         if (!IsSiteAvailable(*neighbour_iter, pParentCell))
00264         {
00265             propensity_dividing_into_neighbour = 0.0;
00266         }
00267         neighbouring_node_propensities.push_back(propensity_dividing_into_neighbour);
00268         total_propensity += propensity_dividing_into_neighbour;
00269     }
00270 
00271     assert(total_propensity>0); // if this trips the cell cant divided so need to include this in the IsSiteAvailable method
00272 
00273     for (unsigned i=0; i<num_neighbours; i++)
00274     {
00275         neighbouring_node_propensities[i] /= total_propensity;
00276     }
00277 
00278      // Sample random number to specify which move to make
00279     RandomNumberGenerator* p_gen = RandomNumberGenerator::Instance();
00280     double random_number = p_gen->ranf();
00281 
00282     double total_probability = 0.0;
00283     unsigned daughter_node_index = UNSIGNED_UNSET;
00284 
00285     unsigned counter;
00286     for (counter=0; counter < num_neighbours; counter++)
00287     {
00288         total_probability += neighbouring_node_propensities[counter];
00289         if (total_probability >= random_number)
00290         {
00291             // Divide the parent cell to this neighbour location
00292             daughter_node_index = neighbouring_node_indices_vector[counter];
00293             break;
00294         }
00295     }
00296     // This loop should always break as sum(neighbouring_node_propensities) = 1
00297 
00298     assert(daughter_node_index != UNSIGNED_UNSET);
00299     assert(daughter_node_index < this->mrMesh.GetNumNodes());
00300 
00301     // Associate the new cell with the element
00302     this->mCells.push_back(pNewCell);
00303 
00304     // Update location cell map
00305     CellPtr p_created_cell = this->mCells.back();
00306     AddCellUsingLocationIndex(daughter_node_index,p_created_cell);
00307 
00308     return p_created_cell;
00309 }
00310 
00311 template<unsigned DIM>
00312 double CaBasedCellPopulation<DIM>:: EvaluateDivisionPropensity(unsigned currentNodeIndex,
00313                                                                        unsigned targetNodeIndex,
00314                                                                        CellPtr pCell)
00315 {
00316     return 1.0;
00317 }
00318 
00319 template<unsigned DIM>
00320 unsigned CaBasedCellPopulation<DIM>::RemoveDeadCells()
00321 {
00322     unsigned num_removed = 0;
00323 
00324     for (std::list<CellPtr>::iterator cell_iter = this->mCells.begin();
00325          cell_iter != this->mCells.end();
00326          )
00327     {
00328         if ((*cell_iter)->IsDead())
00329         {
00330             // Get the index of the node corresponding to this cell
00331             unsigned node_index = this->GetLocationIndexUsingCell(*cell_iter);
00332 
00333             RemoveCellUsingLocationIndex(node_index, (*cell_iter));
00334 
00335             // Erase cell and update counter
00336             num_removed++;
00337             cell_iter = this->mCells.erase(cell_iter);
00338         }
00339         else
00340         {
00341             ++cell_iter;
00342         }
00343     }
00344     return num_removed;
00345 }
00346 
00347 template<unsigned DIM>
00348 void CaBasedCellPopulation<DIM>::UpdateCellLocations(double dt)
00349 {
00350     // Iterate over cells
00352     for (std::list<CellPtr>::iterator cell_iter = this->mCells.begin();
00353          cell_iter != this->mCells.end();
00354          ++cell_iter)
00355     {
00356         // Loop over neighbours and calculate probability of moving (make sure all probabilities are <1)
00357         unsigned node_index = this->GetLocationIndexUsingCell(*cell_iter);
00358 
00359         // Find a random available neighbouring node to overwrite current site
00360         std::set<unsigned> neighbouring_node_indices = static_cast<PottsMesh<DIM>& >((this->mrMesh)).GetMooreNeighbouringNodeIndices(node_index);
00361         std::vector<double> neighbouring_node_propensities;
00362         std::vector<unsigned> neighbouring_node_indices_vector;
00363 
00364         if (!neighbouring_node_indices.empty())
00365         {
00366             unsigned num_neighbours = neighbouring_node_indices.size();
00367             double probability_of_not_moving = 1.0;
00368 
00369             for (std::set<unsigned>::iterator iter = neighbouring_node_indices.begin();
00370                  iter != neighbouring_node_indices.end();
00371                  ++iter)
00372             {
00373                 double probability_of_moving = 0.0;
00374 
00375                 neighbouring_node_indices_vector.push_back(*iter);
00376 
00377                 if (IsSiteAvailable(*iter, *cell_iter))
00378                 {
00379                     // Iterating over the update rule
00380                     for (typename std::vector<boost::shared_ptr<AbstractCaUpdateRule<DIM> > >::iterator iterRule = mUpdateRuleCollection.begin();
00381                          iterRule != mUpdateRuleCollection.end();
00382                          ++iterRule)
00383                     {
00384                         probability_of_moving += (*iterRule)->EvaluateProbability(node_index, *iter, *this, dt, 1, *cell_iter);
00385                         if (probability_of_moving < 0)
00386                         {
00387                             EXCEPTION("The probability of cellular movement is smaller than zero. In order to prevent it from happening you should change your time step and parameters");
00388                         }
00389 
00390                         if (probability_of_moving > 1)
00391                         {
00392                             EXCEPTION("The probability of the cellular movement is bigger than one. In order to prevent it from happening you should change your time step and parameters");
00393                         }
00394                     }
00395 
00396                     probability_of_not_moving -= probability_of_moving;
00397                     neighbouring_node_propensities.push_back(probability_of_moving);
00398                 }
00399                 else
00400                 {
00401                     neighbouring_node_propensities.push_back(0.0);
00402                 }
00403             }
00404             if (probability_of_not_moving < 0)
00405             {
00406                 EXCEPTION("The probability of the cell not moving is smaller than zero. In order to prevent it from happening you should change your time step and parameters");
00407             }
00408 
00409             // Sample random number to specify which move to make
00410             RandomNumberGenerator* p_gen = RandomNumberGenerator::Instance();
00411             double random_number = p_gen->ranf();
00412 
00413             double total_probability = 0.0;
00414             for (unsigned counter=0; counter<num_neighbours; counter++)
00415             {
00416                 total_probability += neighbouring_node_propensities[counter];
00417                 if (total_probability >= random_number)
00418                 {
00419                     //Move the cell to this neighbour location
00420                     unsigned chosen_neighbour_location_index = neighbouring_node_indices_vector[counter];
00421                     this->MoveCellInLocationMap((*cell_iter), node_index, chosen_neighbour_location_index);
00422                     break;
00423                 }
00424             }
00425             // If loop completes with total_probability < random_number then stay in the same location
00426         }
00427         else
00428         {
00429             // Each node in the mesh must have at least one neighbour
00430             NEVER_REACHED;
00431         }
00432     }
00433 }
00434 
00435 template<unsigned DIM>
00436 bool CaBasedCellPopulation<DIM>::IsCellAssociatedWithADeletedLocation(CellPtr pCell)
00437 {
00438     return false;
00439 }
00440 
00441 template<unsigned DIM>
00442 void CaBasedCellPopulation<DIM>::Update(bool hasHadBirthsOrDeaths)
00443 {
00444 }
00445 
00446 template<unsigned DIM>
00447 void CaBasedCellPopulation<DIM>::AcceptPopulationWriter(boost::shared_ptr<AbstractCellPopulationWriter<DIM, DIM> > pPopulationWriter)
00448 {
00449     pPopulationWriter->Visit(this);
00450 }
00451 
00452 template<unsigned DIM>
00453 void CaBasedCellPopulation<DIM>::AcceptPopulationCountWriter(boost::shared_ptr<AbstractCellPopulationCountWriter<DIM, DIM> > pPopulationCountWriter)
00454 {
00455     pPopulationCountWriter->Visit(this);
00456 }
00457 
00458 template<unsigned DIM>
00459 void CaBasedCellPopulation<DIM>::AcceptCellWriter(boost::shared_ptr<AbstractCellWriter<DIM, DIM> > pCellWriter, CellPtr pCell)
00460 {
00461     pCellWriter->VisitCell(pCell, this);
00462 }
00463 
00464 template<unsigned DIM>
00465 void CaBasedCellPopulation<DIM>::OpenWritersFiles(OutputFileHandler& rOutputFileHandler)
00466 {
00467     if (this->mOutputResultsForChasteVisualizer)
00468     {
00469         if (!this-> template HasWriter<CellLocationIndexWriter>())
00470         {
00471             this-> template AddCellWriter<CellLocationIndexWriter>();
00472         }
00473     }
00474 
00475     AbstractCellPopulation<DIM>::OpenWritersFiles(rOutputFileHandler);
00476 }
00477 
00478 template<unsigned DIM>
00479 double CaBasedCellPopulation<DIM>::GetVolumeOfCell(CellPtr pCell)
00480 {
00481     double cell_volume = 1.0;
00482     return cell_volume;
00483 }
00484 
00485 template<unsigned DIM>
00486 double CaBasedCellPopulation<DIM>::GetWidth(const unsigned& rDimension)
00487 {
00488     double width = this->mrMesh.GetWidth(rDimension);
00489     return width;
00490 }
00491 
00492 template<unsigned DIM>
00493 void CaBasedCellPopulation<DIM>::AddUpdateRule(boost::shared_ptr<AbstractCaUpdateRule<DIM> > pUpdateRule)
00494 {
00495     mUpdateRuleCollection.push_back(pUpdateRule);
00496 }
00497 
00498 template<unsigned DIM>
00499 void CaBasedCellPopulation<DIM>::RemoveAllUpdateRules()
00500 {
00501     mUpdateRuleCollection.clear();
00502 }
00503 
00504 template<unsigned DIM>
00505 const std::vector<boost::shared_ptr<AbstractCaUpdateRule<DIM> > >& CaBasedCellPopulation<DIM>::rGetUpdateRuleCollection() const
00506 {
00507     return mUpdateRuleCollection;
00508 }
00509 
00510 template<unsigned DIM>
00511 void CaBasedCellPopulation<DIM>::OutputCellPopulationParameters(out_stream& rParamsFile)
00512 {
00513     // Call method on direct parent class
00514     AbstractOnLatticeCellPopulation<DIM>::OutputCellPopulationParameters(rParamsFile);
00515 }
00516 
00517 template<unsigned DIM>
00518 void CaBasedCellPopulation<DIM>::WriteVtkResultsToFile(const std::string& rDirectory)
00519 {
00520 #ifdef CHASTE_VTK
00521     // Store the present time as a string
00522     unsigned num_timesteps = SimulationTime::Instance()->GetTimeStepsElapsed();
00523     std::stringstream time;
00524     time << num_timesteps;
00525 
00526     // Store the number of cells for which to output data to VTK
00527     unsigned num_cells = this->GetNumRealCells();
00528 
00529     // When outputting any CellData, we assume that the first cell is representative of all cells
00530     unsigned num_cell_data_items = 0u;
00531     if (num_cells > 0u)
00532     {
00533         num_cell_data_items = this->Begin()->GetCellData()->GetNumItems();
00534     // Not used here: std::vector<std::string> cell_data_names = this->Begin()->GetCellData()->GetKeys();
00535     }
00536     std::vector<std::vector<double> > cell_data;
00537     for (unsigned var=0; var<num_cell_data_items; var++)
00538     {
00539         std::vector<double> cell_data_var(num_cells);
00540         cell_data.push_back(cell_data_var);
00541     }
00542 
00543     // Create mesh writer for VTK output
00544     VtkMeshWriter<DIM, DIM> mesh_writer(rDirectory, "results_"+time.str(), false);
00545 
00546     // Create a counter to keep track of how many cells are at a lattice site
00547     unsigned num_sites = this->mrMesh.GetNumNodes();
00548     boost::scoped_array<unsigned> number_of_cells_at_site(new unsigned[num_sites]);
00549     for (unsigned i=0; i<num_sites; i++)
00550     {
00551         number_of_cells_at_site[i] = 0;
00552     }
00553 
00554     // Populate a vector of nodes associated with cell locations, by iterating through the list of cells
00555     std::vector<Node<DIM>*> nodes;
00556     unsigned node_index = 0;
00557     for (std::list<CellPtr>::iterator cell_iter = this->mCells.begin();
00558          cell_iter != this->mCells.end();
00559          ++cell_iter)
00560     {
00561         // Get the location index of this cell and update the counter number_of_cells_at_site
00562         unsigned location_index = this->GetLocationIndexUsingCell(*cell_iter);
00563         number_of_cells_at_site[location_index]++;
00564         assert(number_of_cells_at_site[location_index] <= mLatticeCarryingCapacity);
00565 
00566         // Note that we define this vector before setting it as otherwise the profiling build will break (see #2367)
00567         c_vector<double, DIM> coords;
00568         coords = this->mrMesh.GetNode(location_index)->rGetLocation();
00569 
00570         // Move the coordinates slightly so that we can visualise all cells in a lattice site if there is more than one per site
00571         if (mLatticeCarryingCapacity > 1)
00572         {
00573             c_vector<double, DIM> offset;
00574 
00575             if (DIM == 2)
00576             {
00577                 double angle = (double)number_of_cells_at_site[location_index]*2.0*M_PI/(double)mLatticeCarryingCapacity;
00578                 offset[0] = 0.2*sin(angle);
00579                 offset[1] = 0.2*cos(angle);
00580             }
00581             else
00582             {
00583                 RandomNumberGenerator* p_gen = RandomNumberGenerator::Instance();
00584                 for (unsigned i=0; i<DIM; i++)
00585                 {
00586                     offset[i] = p_gen->ranf(); // This assumes that all sites are 1 unit apart
00587                 }
00588             }
00589 
00590             for (unsigned i=0; i<DIM; i++)
00591             {
00592                 coords[i] += offset[i];
00593             }
00594         }
00595 
00596         nodes.push_back(new Node<DIM>(node_index, coords, false));
00597         node_index++;
00598     }
00599 
00600     // Iterate over any cell writers that are present
00601     for (typename std::vector<boost::shared_ptr<AbstractCellWriter<DIM, DIM> > >::iterator cell_writer_iter = this->mCellWriters.begin();
00602          cell_writer_iter != this->mCellWriters.end();
00603          ++cell_writer_iter)
00604     {
00605         // Create vector to store VTK cell data
00606         // (using a default value of -1 to correspond to an empty lattice site)
00607         std::vector<double> vtk_cell_data(num_cells, -1.0);
00608 
00609         // Loop over cells
00610         unsigned cell_index = 0;
00611         for (std::list<CellPtr>::iterator cell_iter = this->mCells.begin();
00612              cell_iter != this->mCells.end();
00613              ++cell_iter)
00614         {
00615             // Populate the vector of VTK cell data
00616             vtk_cell_data[cell_index] = (*cell_writer_iter)->GetCellDataForVtkOutput(*cell_iter, this);
00617             cell_index++;
00618         }
00619 
00620         mesh_writer.AddPointData((*cell_writer_iter)->GetVtkCellDataName(), vtk_cell_data);
00621     }
00622 
00623     /*
00624      * At present, the VTK writer can only write things which inherit from AbstractTetrahedralMeshWriter.
00625      * For now, we do an explicit conversion to NodesOnlyMesh. This can be written to VTK, then visualized
00626      * as glyphs in Paraview.
00627      */
00628     NodesOnlyMesh<DIM> temp_mesh;
00629     temp_mesh.ConstructNodesWithoutMesh(nodes, 1.5);  // Arbitrary cut off as connectivity not used.
00630     mesh_writer.WriteFilesUsingMesh(temp_mesh);
00631 
00632     *(this->mpVtkMetaFile) << "        <DataSet timestep=\"";
00633     *(this->mpVtkMetaFile) << num_timesteps;
00634     *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_";
00635     *(this->mpVtkMetaFile) << num_timesteps;
00636     *(this->mpVtkMetaFile) << ".vtu\"/>\n";
00637 
00638     // Tidy up
00639     for (unsigned i=0; i<nodes.size(); i++)
00640     {
00641         delete nodes[i];
00642     }
00643 #endif //CHASTE_VTK
00644 }
00645 
00646 // Explicit instantiation
00647 template class CaBasedCellPopulation<1>;
00648 template class CaBasedCellPopulation<2>;
00649 template class CaBasedCellPopulation<3>;
00650 
00651 // Serialization for Boost >= 1.36
00652 #include "SerializationExportWrapperForCpp.hpp"
00653 EXPORT_TEMPLATE_CLASS_SAME_DIMS(CaBasedCellPopulation)

Generated by  doxygen 1.6.2