Chaste  Release::3.4
CaBasedCellPopulation.cpp
1 /*
2 
3 Copyright (c) 2005-2016, University of Oxford.
4 All rights reserved.
5 
6 University of Oxford means the Chancellor, Masters and Scholars of the
7 University of Oxford, having an administrative office at Wellington
8 Square, Oxford OX1 2JD, UK.
9 
10 This file is part of Chaste.
11 
12 Redistribution and use in source and binary forms, with or without
13 modification, are permitted provided that the following conditions are met:
14  * Redistributions of source code must retain the above copyright notice,
15  this list of conditions and the following disclaimer.
16  * Redistributions in binary form must reproduce the above copyright notice,
17  this list of conditions and the following disclaimer in the documentation
18  and/or other materials provided with the distribution.
19  * Neither the name of the University of Oxford nor the names of its
20  contributors may be used to endorse or promote products derived from this
21  software without specific prior written permission.
22 
23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
29 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 
34 */
35 
36 #include "CaBasedCellPopulation.hpp"
37 
38 #include <boost/scoped_array.hpp>
39 
40 #include "RandomNumberGenerator.hpp"
41 #include "Warnings.hpp"
42 
43 // Needed to convert mesh in order to write nodes to VTK (visualize as glyphs)
44 #include "VtkMeshWriter.hpp"
45 
46 // Cell writers
47 #include "CellAgesWriter.hpp"
48 #include "CellAncestorWriter.hpp"
49 #include "CellLocationIndexWriter.hpp"
50 #include "CellProliferativePhasesWriter.hpp"
51 #include "CellProliferativeTypesWriter.hpp"
52 
53 // Cell population writers
54 #include "CellMutationStatesWriter.hpp"
55 
56 //Ca division rules
57 #include "ExclusionCaBasedDivisionRule.hpp"
58 
59 #include "NodesOnlyMesh.hpp"
60 #include "Exception.hpp"
61 
62 template<unsigned DIM>
64 {
66 }
67 
68 template<unsigned DIM>
70  std::vector<CellPtr>& rCells,
71  const std::vector<unsigned> locationIndices,
72  unsigned latticeCarryingCapacity,
73  bool deleteMesh,
74  bool validate)
75  : AbstractOnLatticeCellPopulation<DIM>(rMesh, rCells, locationIndices, deleteMesh),
76  mLatticeCarryingCapacity(latticeCarryingCapacity)
77 {
78  mAvailableSpaces = std::vector<unsigned>(this->GetNumNodes(), latticeCarryingCapacity);
80 
81  // This must always be true
82  assert(this->mCells.size() <= this->mrMesh.GetNumNodes()*latticeCarryingCapacity);
83 
84  if (locationIndices.empty())
85  {
86  EXCEPTION("No location indices being passed. Specify where cells lie before creating the cell population.");
87  }
88  else
89  {
90  // Create a set of node indices corresponding to empty sites.
91  // Note iterating over mCells is OK as it has the same order as location indices at this point (its just coppied from rCells)
92  std::list<CellPtr>::iterator it = this->mCells.begin();
93  for (unsigned i=0; it != this->mCells.end(); ++it, ++i)
94  {
95  assert(i<locationIndices.size());
96  if (!IsSiteAvailable(locationIndices[i],*it))
97  {
98  EXCEPTION("One of the lattice sites has more cells than the carrying capacity. Check the initial cell locations.");
99  }
100  mAvailableSpaces[locationIndices[i]]--;
101  }
102  }
103  if (validate)
104  {
105  EXCEPTION("There is no validation for CaBasedCellPopulation.");
106  }
107 }
108 
109 template<unsigned DIM>
111  : AbstractOnLatticeCellPopulation<DIM>(rMesh)
112 {
113 }
114 
115 template<unsigned DIM>
117 {
118  if (this->mDeleteMesh)
119  {
120  delete &this->mrMesh;
121  }
122 }
123 
124 template<unsigned DIM>
126 {
127  return mAvailableSpaces;
128 }
129 
130 template<unsigned DIM>
131 bool CaBasedCellPopulation<DIM>::IsSiteAvailable(unsigned index, CellPtr pCell)
132 {
134  return (mAvailableSpaces[index] != 0);
135 }
136 
137 template<unsigned DIM>
139 {
140  return static_cast<PottsMesh<DIM>& >((this->mrMesh));
141 }
142 
143 template<unsigned DIM>
145 {
146  return static_cast<PottsMesh<DIM>& >((this->mrMesh));
147 }
148 
149 template<unsigned DIM>
151 {
152  return this->mrMesh.GetNode(index);
153 }
154 
155 template<unsigned DIM>
157 {
158  return this->mrMesh.GetNumNodes();
159 }
160 
161 template<unsigned DIM>
163 {
164  unsigned index = this->GetLocationIndexUsingCell(pCell);
165  std::set<unsigned> candidates = static_cast<PottsMesh<DIM>& >((this->mrMesh)).GetMooreNeighbouringNodeIndices(index);
166 
167  std::set<unsigned> neighbour_indices;
168  for (std::set<unsigned>::iterator iter = candidates.begin();
169  iter != candidates.end();
170  ++iter)
171  {
172  if (!IsSiteAvailable(*iter, pCell))
173  {
174  neighbour_indices.insert(*iter);
175  }
176  }
177 
178  return neighbour_indices;
179 }
180 
181 template<unsigned DIM>
182 c_vector<double, DIM> CaBasedCellPopulation<DIM>::GetLocationOfCellCentre(CellPtr pCell)
183 {
184  return this->mrMesh.GetNode(this->GetLocationIndexUsingCell(pCell))->rGetLocation();
185 }
186 
187 template<unsigned DIM>
189 {
190  return this->mrMesh.GetNode(this->GetLocationIndexUsingCell(pCell));
191 }
192 
193 template<unsigned DIM>
194 void CaBasedCellPopulation<DIM>::AddCellUsingLocationIndex(unsigned index, CellPtr pCell)
195 {
196  if (!IsSiteAvailable(index, pCell))
197  {
198  EXCEPTION("No available spaces at location index " << index << ".");
199  }
200 
201  mAvailableSpaces[index]--;
203 }
204 
205 template<unsigned DIM>
207 {
209 
210  mAvailableSpaces[index]++;
211 
212  assert(mAvailableSpaces[index] <= mLatticeCarryingCapacity);
213 }
214 
215 template<unsigned DIM>
217 {
218  return mpCaBasedDivisionRule->IsRoomToDivide(pCell, *this);
219 }
220 
221 template<unsigned DIM>
222 CellPtr CaBasedCellPopulation<DIM>::AddCell(CellPtr pNewCell, const c_vector<double,DIM>& rCellDivisionVector, CellPtr pParentCell)
223 {
224  unsigned daughter_node_index = mpCaBasedDivisionRule->CalculateDaughterNodeIndex(pNewCell,pParentCell,*this);
225 
226  // Associate the new cell with the neighboring node
227  this->mCells.push_back(pNewCell);
228 
229  // Update location cell map
230  CellPtr p_created_cell = this->mCells.back();
231  AddCellUsingLocationIndex(daughter_node_index,p_created_cell);
232 
233  return p_created_cell;
234 }
235 
236 template<unsigned DIM>
238  unsigned targetNodeIndex,
239  CellPtr pCell)
240 {
241  return 1.0;
242 }
243 
244 template<unsigned DIM>
246 {
247  unsigned num_removed = 0;
248 
249  for (std::list<CellPtr>::iterator cell_iter = this->mCells.begin();
250  cell_iter != this->mCells.end();
251  )
252  {
253  if ((*cell_iter)->IsDead())
254  {
255  // Get the index of the node corresponding to this cell
256  unsigned node_index = this->GetLocationIndexUsingCell(*cell_iter);
257 
258  RemoveCellUsingLocationIndex(node_index, (*cell_iter));
259 
260  // Erase cell and update counter
261  num_removed++;
262  cell_iter = this->mCells.erase(cell_iter);
263  }
264  else
265  {
266  ++cell_iter;
267  }
268  }
269  return num_removed;
270 }
271 
272 template<unsigned DIM>
274 {
275  /*
276  * Here we loop over the nodes and calculate the probability of moving
277  * and then select the node to move to.
278  */
279  if (!(mUpdateRuleCollection.empty()))
280  {
281  // Iterate over cells
283  for (std::list<CellPtr>::iterator cell_iter = this->mCells.begin();
284  cell_iter != this->mCells.end();
285  ++cell_iter)
286  {
287  // Loop over neighbours and calculate probability of moving (make sure all probabilities are <1)
288  unsigned node_index = this->GetLocationIndexUsingCell(*cell_iter);
289 
290  // Find a random available neighbouring node to overwrite current site
291  std::set<unsigned> neighbouring_node_indices = static_cast<PottsMesh<DIM>& >((this->mrMesh)).GetMooreNeighbouringNodeIndices(node_index);
292  std::vector<double> neighbouring_node_propensities;
293  std::vector<unsigned> neighbouring_node_indices_vector;
294 
295  if (!neighbouring_node_indices.empty())
296  {
297  unsigned num_neighbours = neighbouring_node_indices.size();
298  double probability_of_not_moving = 1.0;
299 
300  for (std::set<unsigned>::iterator iter = neighbouring_node_indices.begin();
301  iter != neighbouring_node_indices.end();
302  ++iter)
303  {
304  double probability_of_moving = 0.0;
305 
306  neighbouring_node_indices_vector.push_back(*iter);
307 
308  if (IsSiteAvailable(*iter, *cell_iter))
309  {
310  // Iterating over the update rule
311  for (typename std::vector<boost::shared_ptr<AbstractCaUpdateRule<DIM> > >::iterator iterRule = mUpdateRuleCollection.begin();
312  iterRule != mUpdateRuleCollection.end();
313  ++iterRule)
314  {
315  probability_of_moving += (*iterRule)->EvaluateProbability(node_index, *iter, *this, dt, 1, *cell_iter);
316  if (probability_of_moving < 0)
317  {
318  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");
319  }
320 
321  if (probability_of_moving > 1)
322  {
323  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");
324  }
325  }
326 
327  probability_of_not_moving -= probability_of_moving;
328  neighbouring_node_propensities.push_back(probability_of_moving);
329  }
330  else
331  {
332  neighbouring_node_propensities.push_back(0.0);
333  }
334  }
335  if (probability_of_not_moving < 0)
336  {
337  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");
338  }
339 
340  // Sample random number to specify which move to make
342  double random_number = p_gen->ranf();
343 
344  double total_probability = 0.0;
345  for (unsigned counter=0; counter<num_neighbours; counter++)
346  {
347  total_probability += neighbouring_node_propensities[counter];
348  if (total_probability >= random_number)
349  {
350  //Move the cell to this neighbour location
351  unsigned chosen_neighbour_location_index = neighbouring_node_indices_vector[counter];
352  this->MoveCellInLocationMap((*cell_iter), node_index, chosen_neighbour_location_index);
353  break;
354  }
355  }
356  // If loop completes with total_probability < random_number then stay in the same location
357  }
358  else
359  {
360  // Each node in the mesh must have at least one neighbour
362  }
363  }
364  }
365 
366  /*
367  * Here we loop over the nodes and select a neighbour to test if
368  * the cells (associated with the nodes) should swap locations
369  * or if a cell should move to an empty node
370  * Note this currently only works for latticeCarryingCapacity = 1
371  */
372  if (!(mSwitchingUpdateRuleCollection.empty()))
373  {
374  assert(mLatticeCarryingCapacity == 1);
375 
377  unsigned num_nodes = this->mrMesh.GetNumNodes();
378 
379  // Randomly permute mUpdateRuleCollection if specified
380  if (this->mIterateRandomlyOverUpdateRuleCollection)
381  {
382  // Randomly permute mUpdateRuleCollection
383  p_gen->Shuffle(mSwitchingUpdateRuleCollection);
384  }
385 
386  for (unsigned i=0; i<num_nodes; i++)
387  {
388  unsigned node_index;
389 
390  if (this->mUpdateNodesInRandomOrder)
391  {
392  node_index = p_gen->randMod(num_nodes);
393  }
394  else
395  {
396  // Loop over nodes in index order
397  node_index = i%num_nodes;
398  }
399 
400  // Find a random available neighbouring node to switch cells with the current site
401  std::set<unsigned> neighbouring_node_indices = static_cast<PottsMesh<DIM>& >((this->mrMesh)).GetMooreNeighbouringNodeIndices(node_index);
402 
403  unsigned neighbour_location_index;
404 
405  if (!neighbouring_node_indices.empty())
406  {
407  unsigned num_neighbours = neighbouring_node_indices.size();
408  unsigned chosen_neighbour = p_gen->randMod(num_neighbours);
409 
410  std::set<unsigned>::iterator neighbour_iter = neighbouring_node_indices.begin();
411  for (unsigned j=0; j<chosen_neighbour; j++)
412  {
413  neighbour_iter++;
414  }
415  neighbour_location_index = *neighbour_iter;
416 
417  bool is_cell_on_node_index = mAvailableSpaces[node_index] == 0 ? true : false;
418  bool is_cell_on_neighbour_location_index = mAvailableSpaces[neighbour_location_index] == 0 ? true : false;
419 
420  if (is_cell_on_node_index || is_cell_on_neighbour_location_index)
421  {
422  double probability_of_switch = 0.0;
423 
424  // Now add contributions to the probability from each AbstractPottsUpdateRule
425  for (typename std::vector<boost::shared_ptr<AbstractCaSwitchingUpdateRule<DIM> > >::iterator iter = mSwitchingUpdateRuleCollection.begin();
426  iter != mSwitchingUpdateRuleCollection.end();
427  ++iter)
428  {
429  probability_of_switch += (*iter)->EvaluateSwitchingProbability(node_index, neighbour_location_index, *this, dt, 1);
430  }
431  assert(probability_of_switch>=0);
432  assert(probability_of_switch<=1);
433 
434  // Generate a uniform random number to do the random switch
435  double random_number = p_gen->ranf();
436 
437  if (random_number < probability_of_switch)
438  {
439  if (is_cell_on_node_index && is_cell_on_neighbour_location_index)
440  {
441  // Swap the cells associated with the node and the neighbour node
442  CellPtr p_cell = this->GetCellUsingLocationIndex(node_index);
443  CellPtr p_neighbour_cell = this->GetCellUsingLocationIndex(neighbour_location_index);
444 
445  // Remove the cells from their current location
446  RemoveCellUsingLocationIndex(node_index, p_cell);
447  RemoveCellUsingLocationIndex(neighbour_location_index, p_neighbour_cell);
448 
449  // Add cells to their new locations
450  AddCellUsingLocationIndex(node_index, p_neighbour_cell);
451  AddCellUsingLocationIndex(neighbour_location_index, p_cell);
452  }
453  else if (is_cell_on_node_index && !is_cell_on_neighbour_location_index)
454  {
455  // Nove the cells associated with the node to the neighbour node
456  CellPtr p_cell = this->GetCellUsingLocationIndex(node_index);
457  RemoveCellUsingLocationIndex(node_index, p_cell);
458  AddCellUsingLocationIndex(neighbour_location_index, p_cell);
459  }
460  else if (!is_cell_on_node_index && is_cell_on_neighbour_location_index)
461  {
462  // Move the cell associated with the neighbour node onto the node
463  CellPtr p_neighbour_cell = this->GetCellUsingLocationIndex(neighbour_location_index);
464  RemoveCellUsingLocationIndex(neighbour_location_index, p_neighbour_cell);
465  AddCellUsingLocationIndex(node_index, p_neighbour_cell);
466  }
467  else
468  {
470  }
471 
472  }
473  }
474  }
475  }
476  }
477 }
478 
479 template<unsigned DIM>
481 {
482  return false;
483 }
484 
485 template<unsigned DIM>
486 void CaBasedCellPopulation<DIM>::Update(bool hasHadBirthsOrDeaths)
487 {
488 }
489 
490 template<unsigned DIM>
492 {
493  pPopulationWriter->Visit(this);
494 }
495 
496 template<unsigned DIM>
498 {
499  pPopulationCountWriter->Visit(this);
500 }
501 
502 template<unsigned DIM>
503 void CaBasedCellPopulation<DIM>::AcceptCellWriter(boost::shared_ptr<AbstractCellWriter<DIM, DIM> > pCellWriter, CellPtr pCell)
504 {
505  pCellWriter->VisitCell(pCell, this);
506 }
507 
508 template<unsigned DIM>
510 {
511  if (this->mOutputResultsForChasteVisualizer)
512  {
513  if (!this-> template HasWriter<CellLocationIndexWriter>())
514  {
515  this-> template AddCellWriter<CellLocationIndexWriter>();
516  }
517  }
518 
520 }
521 
522 template<unsigned DIM>
524 {
525  double cell_volume = 1.0;
526  return cell_volume;
527 }
528 
529 template<unsigned DIM>
530 double CaBasedCellPopulation<DIM>::GetWidth(const unsigned& rDimension)
531 {
532  double width = this->mrMesh.GetWidth(rDimension);
533  return width;
534 }
535 
536 template<unsigned DIM>
538 {
539  mUpdateRuleCollection.push_back(pUpdateRule);
540 }
541 
542 template<unsigned DIM>
544 {
545  mUpdateRuleCollection.clear();
546 }
547 
548 template<unsigned DIM>
549 const std::vector<boost::shared_ptr<AbstractCaUpdateRule<DIM> > >& CaBasedCellPopulation<DIM>::rGetUpdateRuleCollection() const
550 {
551  return mUpdateRuleCollection;
552 }
553 
554 template<unsigned DIM>
556 {
557  mSwitchingUpdateRuleCollection.push_back(pUpdateRule);
558 }
559 
560 template<unsigned DIM>
562 {
563  mSwitchingUpdateRuleCollection.clear();
564 }
565 
566 template<unsigned DIM>
567 const std::vector<boost::shared_ptr<AbstractCaSwitchingUpdateRule<DIM> > >& CaBasedCellPopulation<DIM>::rGetSwitchingUpdateRuleCollection() const
568 {
569  return mSwitchingUpdateRuleCollection;
570 }
571 
572 template<unsigned DIM>
573 boost::shared_ptr<AbstractCaBasedDivisionRule<DIM> > CaBasedCellPopulation<DIM>::GetCaBasedDivisionRule()
574 {
575  return mpCaBasedDivisionRule;
576 }
577 
578 template<unsigned DIM>
580 {
581  mpCaBasedDivisionRule = pCaBasedDivisionRule;
582 }
583 
584 template<unsigned DIM>
586 {
587  // Add the division rule parameters
588  *rParamsFile << "\t\t<CaBasedDivisionRule>\n";
589  mpCaBasedDivisionRule->OutputCellCaBasedDivisionRuleInfo(rParamsFile);
590  *rParamsFile << "\t\t</CaBasedDivisionRule>\n";
591 
592  // Call method on direct parent class
594 }
595 
596 template<unsigned DIM>
597 void CaBasedCellPopulation<DIM>::WriteVtkResultsToFile(const std::string& rDirectory)
598 {
599 #ifdef CHASTE_VTK
600  // Store the present time as a string
601  unsigned num_timesteps = SimulationTime::Instance()->GetTimeStepsElapsed();
602  std::stringstream time;
603  time << num_timesteps;
604 
605  // Store the number of cells for which to output data to VTK
606  unsigned num_cells = this->GetNumAllCells();
607 
608  // When outputting any CellData, we assume that the first cell is representative of all cells
609  unsigned num_cell_data_items = 0u;
610  std::vector<std::string> cell_data_names;
611  if (num_cells > 0u)
612  {
613  num_cell_data_items = this->Begin()->GetCellData()->GetNumItems();
614  cell_data_names = this->Begin()->GetCellData()->GetKeys();
615  }
616  std::vector<std::vector<double> > cell_data;
617  for (unsigned var=0; var<num_cell_data_items; var++)
618  {
619  std::vector<double> cell_data_var(num_cells);
620  cell_data.push_back(cell_data_var);
621  }
622 
623  // Create mesh writer for VTK output
624  VtkMeshWriter<DIM, DIM> mesh_writer(rDirectory, "results_"+time.str(), false);
625 
626  // Create a counter to keep track of how many cells are at a lattice site
627  unsigned num_sites = this->mrMesh.GetNumNodes();
628  boost::scoped_array<unsigned> number_of_cells_at_site(new unsigned[num_sites]);
629  for (unsigned i=0; i<num_sites; i++)
630  {
631  number_of_cells_at_site[i] = 0;
632  }
633 
634  // Populate a vector of nodes associated with cell locations, by iterating through the list of cells
635  std::vector<Node<DIM>*> nodes;
636  unsigned node_index = 0;
637  for (std::list<CellPtr>::iterator cell_iter = this->mCells.begin();
638  cell_iter != this->mCells.end();
639  ++cell_iter)
640  {
641  // Get the location index of this cell and update the counter number_of_cells_at_site
642  unsigned location_index = this->GetLocationIndexUsingCell(*cell_iter);
643  number_of_cells_at_site[location_index]++;
644  assert(number_of_cells_at_site[location_index] <= mLatticeCarryingCapacity);
645 
646  // Note that we define this vector before setting it as otherwise the profiling build will break (see #2367)
647  c_vector<double, DIM> coords;
648  coords = this->mrMesh.GetNode(location_index)->rGetLocation();
649 
650  // Move the coordinates slightly so that we can visualise all cells in a lattice site if there is more than one per site
651  if (mLatticeCarryingCapacity > 1)
652  {
653  c_vector<double, DIM> offset;
654 
655  if (DIM == 2)
656  {
657  double angle = (double)number_of_cells_at_site[location_index]*2.0*M_PI/(double)mLatticeCarryingCapacity;
658  offset[0] = 0.2*sin(angle);
659  offset[1] = 0.2*cos(angle);
660  }
661  else
662  {
664  for (unsigned i=0; i<DIM; i++)
665  {
666  offset[i] = p_gen->ranf(); // This assumes that all sites are 1 unit apart
667  }
668  }
669 
670  for (unsigned i=0; i<DIM; i++)
671  {
672  coords[i] += offset[i];
673  }
674  }
675 
676  nodes.push_back(new Node<DIM>(node_index, coords, false));
677  node_index++;
678  }
679 
680  // Iterate over any cell writers that are present
681  for (typename std::vector<boost::shared_ptr<AbstractCellWriter<DIM, DIM> > >::iterator cell_writer_iter = this->mCellWriters.begin();
682  cell_writer_iter != this->mCellWriters.end();
683  ++cell_writer_iter)
684  {
685  // Create vector to store VTK cell data
686  // (using a default value of -1 to correspond to an empty lattice site)
687  std::vector<double> vtk_cell_data(num_cells, -1.0);
688 
689  // Loop over cells
690  unsigned cell_index = 0;
691  for (std::list<CellPtr>::iterator cell_iter = this->mCells.begin();
692  cell_iter != this->mCells.end();
693  ++cell_iter)
694  {
695  // Populate the vector of VTK cell data
696  vtk_cell_data[cell_index] = (*cell_writer_iter)->GetCellDataForVtkOutput(*cell_iter, this);
697  cell_index++;
698  }
699 
700  mesh_writer.AddPointData((*cell_writer_iter)->GetVtkCellDataName(), vtk_cell_data);
701  }
702 
703  // Loop over cells to output the cell data
704  unsigned cell_index = 0;
705  for (typename AbstractCellPopulation<DIM,DIM>::Iterator cell_iter = this->Begin();
706  cell_iter != this->End();
707  ++cell_iter)
708  {
709  for (unsigned var=0; var<num_cell_data_items; var++)
710  {
711  cell_data[var][cell_index] = cell_iter->GetCellData()->GetItem(cell_data_names[var]);
712  }
713  cell_index++;
714  }
715  for (unsigned var=0; var<num_cell_data_items; var++)
716  {
717  mesh_writer.AddPointData(cell_data_names[var], cell_data[var]);
718  }
719 
720  /*
721  * At present, the VTK writer can only write things which inherit from AbstractTetrahedralMeshWriter.
722  * For now, we do an explicit conversion to NodesOnlyMesh. This can be written to VTK, then visualized
723  * as glyphs in Paraview.
724  */
725  NodesOnlyMesh<DIM> temp_mesh;
726 
727  // Use an approximation of the node spacing as the interaction distance for the nodes only mesh. This is to
728  // avoid rounding errors in distributed box collection.
729  double volume = this->mrMesh.GetWidth(0);
730  for(unsigned idx=1; idx<DIM; idx++)
731  {
732  volume *= this->mrMesh.GetWidth(idx);
733  }
734 
735  double spacing;
736  if(this->mrMesh.GetNumNodes() >0 && volume > 0.0)
737  {
738  spacing = std::pow(volume / double(this->mrMesh.GetNumNodes()), 1.0/double(DIM));
739  }
740  else
741  {
742  spacing = 1.0;
743  }
744 
745  temp_mesh.ConstructNodesWithoutMesh(nodes, spacing * 1.2);
746  mesh_writer.WriteFilesUsingMesh(temp_mesh);
747 
748  *(this->mpVtkMetaFile) << " <DataSet timestep=\"";
749  *(this->mpVtkMetaFile) << num_timesteps;
750  *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_";
751  *(this->mpVtkMetaFile) << num_timesteps;
752  *(this->mpVtkMetaFile) << ".vtu\"/>\n";
753 
754  // Tidy up
755  for (unsigned i=0; i<nodes.size(); i++)
756  {
757  delete nodes[i];
758  }
759 #endif //CHASTE_VTK
760 }
761 
762 // Explicit instantiation
763 template class CaBasedCellPopulation<1>;
764 template class CaBasedCellPopulation<2>;
765 template class CaBasedCellPopulation<3>;
766 
767 // Serialization for Boost >= 1.36
bool IsCellAssociatedWithADeletedLocation(CellPtr pCell)
boost::shared_ptr< AbstractCaBasedDivisionRule< DIM > > GetCaBasedDivisionRule()
std::vector< unsigned > mAvailableSpaces
unsigned randMod(unsigned base)
std::vector< unsigned > & rGetAvailableSpaces()
void AddCellUsingLocationIndex(unsigned index, CellPtr pCell)
virtual double EvaluateDivisionPropensity(unsigned currentNodeIndex, unsigned targetNodeIndex, CellPtr pCell)
Definition: Node.hpp:58
PottsMesh< DIM > & rGetMesh()
void OutputCellPopulationParameters(out_stream &rParamsFile)
virtual void RemoveCellUsingLocationIndex(unsigned index, CellPtr pCell)
Node< DIM > * GetNode(unsigned index)
#define EXCEPTION(message)
Definition: Exception.hpp:143
virtual void AcceptPopulationCountWriter(boost::shared_ptr< AbstractCellPopulationCountWriter< DIM, DIM > > pPopulationCountWriter)
static SimulationTime * Instance()
virtual bool IsSiteAvailable(unsigned index, CellPtr pCell)
virtual unsigned GetNumNodes()
boost::shared_ptr< AbstractCaBasedDivisionRule< DIM > > mpCaBasedDivisionRule
virtual unsigned GetNumNodes() const
unsigned GetTimeStepsElapsed() const
const std::vector< boost::shared_ptr< AbstractCaUpdateRule< DIM > > > & rGetUpdateRuleCollection() const
std::set< unsigned > GetMooreNeighbouringNodeIndices(unsigned nodeIndex)
Definition: PottsMesh.cpp:234
virtual void OutputCellPopulationParameters(out_stream &rParamsFile)
void RemoveCellUsingLocationIndex(unsigned index, CellPtr pCell)
virtual void WriteVtkResultsToFile(const std::string &rDirectory)
#define NEVER_REACHED
Definition: Exception.hpp:206
CaBasedCellPopulation(PottsMesh< DIM > &rMesh, std::vector< CellPtr > &rCells, const std::vector< unsigned > locationIndices, unsigned latticeCarryingCapacity=1u, bool deleteMesh=false, bool validate=false)
void Shuffle(std::vector< boost::shared_ptr< T > > &rValues)
bool IsRoomToDivide(CellPtr pCell)
void SetCaBasedDivisionRule(boost::shared_ptr< AbstractCaBasedDivisionRule< DIM > > pCaBasedDivisionRule)
#define EXPORT_TEMPLATE_CLASS_SAME_DIMS(CLASS)
double GetWidth(const unsigned &rDimension) const
std::set< unsigned > GetNeighbouringLocationIndices(CellPtr pCell)
void Update(bool hasHadBirthsOrDeaths=true)
const std::vector< boost::shared_ptr< AbstractCaSwitchingUpdateRule< DIM > > > & rGetSwitchingUpdateRuleCollection() const
void AddSwitchingUpdateRule(boost::shared_ptr< AbstractCaSwitchingUpdateRule< DIM > > pUpdateRule)
static RandomNumberGenerator * Instance()
virtual void OpenWritersFiles(OutputFileHandler &rOutputFileHandler)
void ConstructNodesWithoutMesh(const std::vector< Node< SPACE_DIM > * > &rNodes, double maxInteractionDistance)
void AddUpdateRule(boost::shared_ptr< AbstractCaUpdateRule< DIM > > pUpdateRule)
Node< DIM > * GetNodeCorrespondingToCell(CellPtr pCell)
c_vector< double, DIM > GetLocationOfCellCentre(CellPtr pCell)
double GetWidth(const unsigned &rDimension)
virtual void AcceptPopulationWriter(boost::shared_ptr< AbstractCellPopulationWriter< DIM, DIM > > pPopulationWriter)
double GetVolumeOfCell(CellPtr pCell)
virtual void AddCellUsingLocationIndex(unsigned index, CellPtr pCell)
AbstractMesh< ELEMENT_DIM, ELEMENT_DIM > & mrMesh
CellPtr AddCell(CellPtr pNewCell, const c_vector< double, DIM > &rCellDivisionVector, CellPtr pParentCell=CellPtr())
virtual void AcceptCellWriter(boost::shared_ptr< AbstractCellWriter< DIM, DIM > > pCellWriter, CellPtr pCell)
virtual void OpenWritersFiles(OutputFileHandler &rOutputFileHandler)