Chaste  Release::2024.1
AbstractCellPopulation.cpp
1 /*
2 
3 Copyright (c) 2005-2021, 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 <boost/bind.hpp>
37 
38 #include <algorithm>
39 #include <functional>
40 
41 #include "AbstractCellPopulation.hpp"
42 #include "AbstractPhaseBasedCellCycleModel.hpp"
43 #include "SmartPointers.hpp"
44 #include "CellAncestor.hpp"
45 #include "ApoptoticCellProperty.hpp"
46 
47 // Cell writers
48 #include "BoundaryNodeWriter.hpp"
49 #include "CellProliferativeTypesWriter.hpp"
50 #include "LegacyCellProliferativeTypesWriter.hpp"
51 
52 // Cell population writers
53 #include "CellMutationStatesCountWriter.hpp"
54 #include "CellProliferativePhasesCountWriter.hpp"
55 #include "CellProliferativeTypesCountWriter.hpp"
56 #include "NodeLocationWriter.hpp"
57 
58 // These #includes are needed for SetDefaultCellMutationStateAndProliferativeTypeOrdering()
59 #include "WildTypeCellMutationState.hpp"
60 #include "ApcOneHitCellMutationState.hpp"
61 #include "ApcTwoHitCellMutationState.hpp"
62 #include "BetaCateninOneHitCellMutationState.hpp"
63 #include "DefaultCellProliferativeType.hpp"
64 #include "StemCellProliferativeType.hpp"
65 #include "TransitCellProliferativeType.hpp"
66 #include "DifferentiatedCellProliferativeType.hpp"
67 
68 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
70  std::vector<CellPtr>& rCells,
71  const std::vector<unsigned> locationIndices)
72  : mrMesh(rMesh),
73  mCells(rCells.begin(), rCells.end()),
74  mCentroid(zero_vector<double>(SPACE_DIM)),
75  mpCellPropertyRegistry(CellPropertyRegistry::Instance()->TakeOwnership()),
76  mOutputResultsForChasteVisualizer(true)
77 {
78  /*
79  * To avoid double-counting problems, clear the passed-in cells vector.
80  * We force a reallocation of memory so that subsequent usage of the
81  * vector is more likely to give an error.
82  */
83  std::vector<CellPtr>().swap(rCells);
84 
85  // There must be a one-one correspondence between cells and location indices
86  if (!locationIndices.empty())
87  {
88  if (mCells.size() != locationIndices.size())
89  {
90  EXCEPTION("There is not a one-one correspondence between cells and location indices");
91  }
92  }
93 
94  // Set up the map between location indices and cells
95  mLocationCellMap.clear();
96  mCellLocationMap.clear();
97 
98  std::list<CellPtr>::iterator it = mCells.begin();
99  for (unsigned i=0; it != mCells.end(); ++it, ++i)
100  {
101  // Give each cell a pointer to the property registry (we have taken ownership in this constructor)
102  (*it)->rGetCellPropertyCollection().SetCellPropertyRegistry(mpCellPropertyRegistry.get());
103  }
104 }
105 
106 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
108  : mrMesh(rMesh)
109 {
110 }
111 
112 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
114 {
115 }
116 
117 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
119 {
120  for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter=this->Begin();
121  cell_iter!=this->End();
122  ++cell_iter)
123  {
124  cell_iter->InitialiseCellCycleModel();
125  cell_iter->InitialiseSrnModel();
126  }
127 }
128 
129 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
130 void AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::SetDataOnAllCells(const std::string& rDataName, double dataValue)
131 {
132  for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter=this->Begin();
133  cell_iter!=this->End();
134  ++cell_iter)
135  {
136  cell_iter->GetCellData()->SetItem(rDataName, dataValue);
137  }
138 }
139 
140 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
142 {
143  return mrMesh;
144 }
145 
146 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
148 {
149  return mCells;
150 }
151 
152 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
154 {
155  unsigned counter = 0;
156  for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter=this->Begin();
157  cell_iter!=this->End();
158  ++cell_iter)
159  {
160  counter++;
161  }
162  return counter;
163 }
164 
165 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
167 {
168  return mCells.size();
169 }
170 
171 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
173 {
174  for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter=this->Begin(); cell_iter!=this->End(); ++cell_iter)
175  {
176  MAKE_PTR_ARGS(CellAncestor, p_cell_ancestor, (mCellLocationMap[(*cell_iter).get()]));
177  cell_iter->SetAncestor(p_cell_ancestor);
178  }
179 }
180 
181 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
183 {
184  std::set<unsigned> remaining_ancestors;
185  for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter=this->Begin(); cell_iter!=this->End(); ++cell_iter)
186  {
187  remaining_ancestors.insert(cell_iter->GetAncestor());
188  }
189  return remaining_ancestors;
190 }
191 
192 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
194 {
195  std::vector<unsigned> mutation_state_count;
196  const std::vector<boost::shared_ptr<AbstractCellProperty> >& r_cell_properties
197  = mpCellPropertyRegistry->rGetAllCellProperties();
198 
199  // Calculate mutation states count
200  for (unsigned i=0; i<r_cell_properties.size(); i++)
201  {
202  if (r_cell_properties[i]->IsSubType<AbstractCellMutationState>())
203  {
204  mutation_state_count.push_back(r_cell_properties[i]->GetCellCount());
205  }
206  }
207 
208  // Reduce results onto all processes
210  {
211  // Make sure the vector on each process has the same size
212  unsigned local_size = mutation_state_count.size();
213  unsigned global_size;
214  MPI_Allreduce(&local_size, &global_size, 1, MPI_UNSIGNED, MPI_MAX, PetscTools::GetWorld());
215  assert(local_size == global_size);
216 
217  std::vector<unsigned> mutation_counts(global_size);
218  MPI_Allreduce(&mutation_state_count[0], &mutation_counts[0], mutation_counts.size(), MPI_UNSIGNED, MPI_SUM, PetscTools::GetWorld());
219 
220  mutation_state_count = mutation_counts;
221  }
222 
223  return mutation_state_count;
224 }
225 
226 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
228 {
229  std::vector<unsigned> proliferative_type_count;
230  const std::vector<boost::shared_ptr<AbstractCellProperty> >& r_cell_properties
231  = mpCellPropertyRegistry->rGetAllCellProperties();
232 
233  // Calculate proliferative types count
234  for (unsigned i=0; i<r_cell_properties.size(); i++)
235  {
236  if (r_cell_properties[i]->IsSubType<AbstractCellProliferativeType>())
237  {
238  proliferative_type_count.push_back(r_cell_properties[i]->GetCellCount());
239  }
240  }
241 
242  // Reduce results onto all processes
244  {
245  // Make sure the vector on each process has the same size
246  unsigned local_size = proliferative_type_count.size();
247  unsigned global_size;
248 
249  MPI_Allreduce(&local_size, &global_size, 1, MPI_UNSIGNED, MPI_MAX, PetscTools::GetWorld());
250  assert(local_size == global_size);
251 
252  std::vector<unsigned> total_types_counts(global_size);
253  MPI_Allreduce(&proliferative_type_count[0], &total_types_counts[0], total_types_counts.size(), MPI_UNSIGNED, MPI_SUM, PetscTools::GetWorld());
254 
255  proliferative_type_count = total_types_counts;
256  }
257 
258  return proliferative_type_count;
259 }
260 
261 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
263 {
264  std::vector<unsigned> cell_cycle_phase_count(5);
265  for (unsigned i=0; i<5; i++)
266  {
267  cell_cycle_phase_count[i] = 0;
268  }
269 
270  /*
271  * Note that in parallel with a poor partition a process could end up with zero cells
272  * in which case the calculation should be skipped since `this->Begin()` is not defined.
273  */
274  if (GetNumAllCells() > 0u)
275  {
276  if (dynamic_cast<AbstractPhaseBasedCellCycleModel*>((*(this->Begin()))->GetCellCycleModel()) == nullptr)
277  {
278  EXCEPTION("You are trying to record the cell cycle phase of cells with a non phase based cell cycle model.");
279  }
280 
281  for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter = this->Begin();
282  cell_iter != this->End();
283  ++cell_iter)
284  {
285  switch (static_cast<AbstractPhaseBasedCellCycleModel*>((*cell_iter)->GetCellCycleModel())->GetCurrentCellCyclePhase())
286  {
287  case G_ZERO_PHASE:
288  cell_cycle_phase_count[0]++;
289  break;
290  case G_ONE_PHASE:
291  cell_cycle_phase_count[1]++;
292  break;
293  case S_PHASE:
294  cell_cycle_phase_count[2]++;
295  break;
296  case G_TWO_PHASE:
297  cell_cycle_phase_count[3]++;
298  break;
299  case M_PHASE:
300  cell_cycle_phase_count[4]++;
301  break;
302  default:
304  }
305  }
306  }
307 
308  // Reduce results onto all processes
310  {
311  std::vector<unsigned> phase_counts(cell_cycle_phase_count.size(), 0u);
312  MPI_Allreduce(&cell_cycle_phase_count[0], &phase_counts[0], phase_counts.size(), MPI_UNSIGNED, MPI_SUM, PetscTools::GetWorld());
313 
314  cell_cycle_phase_count = phase_counts;
315  }
316 
317  return cell_cycle_phase_count;
318 }
319 
320 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
322 {
323  // Get the set of pointers to cells corresponding to this location index
324  std::set<CellPtr> cells = mLocationCellMap[index];
325 
326  // If there is only one cell attached return the cell. Note currently only one cell per index.
327  if (cells.size() == 1)
328  {
329  return *(cells.begin());
330  }
331  if (cells.empty())
332  {
333  EXCEPTION("Location index input argument does not correspond to a Cell");
334  }
335  else
336  {
337  EXCEPTION("Multiple cells are attached to a single location index.");
338  }
339 }
340 
341 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
343 {
344  // Return the set of pointers to cells corresponding to this location index, note the set may be empty.
345  return mLocationCellMap[index];
346 }
347 
348 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
350 {
351  // Get the set of pointers to cells corresponding to this location index
352  std::set<CellPtr> cells = mLocationCellMap[index];
353 
354  // Return whether there is a cell attached to the location index
355  return !(cells.empty());
356 }
357 
358 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
360 {
361 }
362 
363 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
365 {
366  // Clear the maps
367  mLocationCellMap[index].clear();
368  mCellLocationMap.erase(pCell.get());
369 
370  // Replace with new cell
371  mLocationCellMap[index].insert(pCell);
372 
373  // Do other half of the map
374  mCellLocationMap[pCell.get()] = index;
375 }
376 
377 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
379 {
380  mLocationCellMap[index].insert(pCell);
381  mCellLocationMap[pCell.get()] = index;
382 }
383 
384 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
386 {
387  std::set<CellPtr>::iterator cell_iter = mLocationCellMap[index].find(pCell);
388 
389  if (cell_iter == mLocationCellMap[index].end())
390  {
391  EXCEPTION("Tried to remove a cell which is not attached to the given location index");
392  }
393  else
394  {
395  mLocationCellMap[index].erase(cell_iter);
396  mCellLocationMap.erase(pCell.get());
397  }
398 }
399 
400 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
401 void AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::MoveCellInLocationMap(CellPtr pCell, unsigned old_index, unsigned new_index)
402 {
403  // Remove the cell from its current location
404  RemoveCellUsingLocationIndex(old_index, pCell);
405 
406  // Add it to the new location
407  AddCellUsingLocationIndex(new_index, pCell);
408 }
409 
410 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
412 {
413  // Check the cell is in the map
414  assert(this->mCellLocationMap.find(pCell.get()) != this->mCellLocationMap.end());
415 
416  return mCellLocationMap[pCell.get()];
417 }
418 
419 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
421 {
422  return mpCellPropertyRegistry;
423 }
424 
425 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
427 {
428  boost::shared_ptr<CellPropertyRegistry> p_registry = GetCellPropertyRegistry();
429  if (!p_registry->HasOrderingBeenSpecified())
430  {
431  std::vector<boost::shared_ptr<AbstractCellProperty> > mutations_and_proliferative_types;
432  mutations_and_proliferative_types.push_back(p_registry->Get<WildTypeCellMutationState>());
433  mutations_and_proliferative_types.push_back(p_registry->Get<ApcOneHitCellMutationState>());
434  mutations_and_proliferative_types.push_back(p_registry->Get<ApcTwoHitCellMutationState>());
435  mutations_and_proliferative_types.push_back(p_registry->Get<BetaCateninOneHitCellMutationState>());
436  mutations_and_proliferative_types.push_back(p_registry->Get<StemCellProliferativeType>());
437  mutations_and_proliferative_types.push_back(p_registry->Get<TransitCellProliferativeType>());
438  mutations_and_proliferative_types.push_back(p_registry->Get<DifferentiatedCellProliferativeType>());
439 
440  // Parallel process with no cells won't have the default property, so add it in
441  mutations_and_proliferative_types.push_back(p_registry->Get<DefaultCellProliferativeType>());
442  p_registry->SpecifyOrdering(mutations_and_proliferative_types);
443  }
444 }
445 
446 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
448 {
449  mCentroid = zero_vector<double>(SPACE_DIM);
450  for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter = this->Begin();
451  cell_iter != this->End();
452  ++cell_iter)
453  {
454  mCentroid += GetLocationOfCellCentre(*cell_iter);
455  }
456  mCentroid /= this->GetNumRealCells();
457 
458  return mCentroid;
459 }
460 
461 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
463 {
464 }
465 
466 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
468 {
469  typedef AbstractCellWriter<ELEMENT_DIM, SPACE_DIM> cell_writer_t;
470  BOOST_FOREACH(boost::shared_ptr<cell_writer_t> p_cell_writer, mCellWriters)
471  {
472  p_cell_writer->CloseFile();
473  }
474 
476  BOOST_FOREACH(boost::shared_ptr<pop_writer_t> p_pop_writer, mCellPopulationWriters)
477  {
478  p_pop_writer->CloseFile();
479  }
480 }
481 
482 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
484 {
485  typedef AbstractCellWriter<ELEMENT_DIM, SPACE_DIM> cell_writer_t;
486  BOOST_FOREACH(boost::shared_ptr<cell_writer_t> p_cell_writer, mCellWriters)
487  {
488  p_cell_writer->CloseFile();
489  }
490 
492  BOOST_FOREACH(boost::shared_ptr<pop_writer_t> p_pop_writer, mCellPopulationWriters)
493  {
494  p_pop_writer->CloseFile();
495  }
496 
497 #ifdef CHASTE_VTK
498  *mpVtkMetaFile << " </Collection>\n";
499  *mpVtkMetaFile << "</VTKFile>\n";
500  mpVtkMetaFile->close();
501 #endif //CHASTE_VTK
502 }
503 
504 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
506 {
507 #ifdef CHASTE_VTK
508  mpVtkMetaFile = rOutputFileHandler.OpenOutputFile("results.pvd");
509  *mpVtkMetaFile << "<?xml version=\"1.0\"?>\n";
510  *mpVtkMetaFile << "<VTKFile type=\"Collection\" version=\"0.1\" byte_order=\"LittleEndian\" compressor=\"vtkZLibDataCompressor\">\n";
511  *mpVtkMetaFile << " <Collection>\n";
512 #endif //CHASTE_VTK
513 
515  {
516  if (!HasWriter<NodeLocationWriter>())
517  {
518  AddPopulationWriter<NodeLocationWriter>();
519  }
520  if (!HasWriter<BoundaryNodeWriter>())
521  {
522  AddPopulationWriter<BoundaryNodeWriter>();
523  }
524  if (!HasWriter<CellProliferativeTypesWriter>())
525  {
526  AddCellWriter<CellProliferativeTypesWriter>();
527  }
528  if (!HasWriter<LegacyCellProliferativeTypesWriter>())
529  {
530  AddCellWriter<LegacyCellProliferativeTypesWriter>();
531  }
532  }
533 
534  // Open output files for any cell writers
535  typedef AbstractCellWriter<ELEMENT_DIM, SPACE_DIM> cell_writer_t;
536  BOOST_FOREACH(boost::shared_ptr<cell_writer_t> p_cell_writer, mCellWriters)
537  {
538  p_cell_writer->OpenOutputFile(rOutputFileHandler);
539  }
540 
541  // Open output files and write headers for any population writers
543  BOOST_FOREACH(boost::shared_ptr<pop_writer_t> p_pop_writer, mCellPopulationWriters)
544  {
545  p_pop_writer->OpenOutputFile(rOutputFileHandler);
546  p_pop_writer->WriteHeader(this);
547  }
548 
549  // Open output files and write headers for any population count writers
551  BOOST_FOREACH(boost::shared_ptr<count_writer_t> p_count_writer, mCellPopulationCountWriters)
552  {
553  p_count_writer->OpenOutputFile(rOutputFileHandler);
554  p_count_writer->WriteHeader(this);
555  }
556 }
557 
558 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
560 {
561  typedef AbstractCellWriter<ELEMENT_DIM, SPACE_DIM> cell_writer_t;
563  BOOST_FOREACH(boost::shared_ptr<cell_writer_t> p_cell_writer, mCellWriters)
564  {
565  p_cell_writer->OpenOutputFileForAppend(rOutputFileHandler);
566  }
567  BOOST_FOREACH(boost::shared_ptr<pop_writer_t> p_pop_writer, mCellPopulationWriters)
568  {
569  p_pop_writer->OpenOutputFileForAppend(rOutputFileHandler);
570  }
571 }
572 
573 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
575 {
576  typedef AbstractCellWriter<ELEMENT_DIM, SPACE_DIM> cell_writer_t;
578  OutputFileHandler output_file_handler(rDirectory, false);
579 
580  if (!(mCellWriters.empty() && mCellPopulationWriters.empty() && mCellPopulationCountWriters.empty()))
581  {
582  // An ordering must be specified for cell mutation states and cell proliferative types
584 
586  {
587  OpenRoundRobinWritersFilesForAppend(output_file_handler);
588 
589  // The master process writes time stamps
590  if (PetscTools::AmMaster())
591  {
592  BOOST_FOREACH(boost::shared_ptr<cell_writer_t> p_cell_writer, mCellWriters)
593  {
594  p_cell_writer->WriteTimeStamp();
595  }
596  BOOST_FOREACH(boost::shared_ptr<pop_writer_t> p_pop_writer, mCellPopulationWriters)
597  {
598  p_pop_writer->WriteTimeStamp();
599  }
600  }
601 
602  for (typename std::vector<boost::shared_ptr<AbstractCellPopulationWriter<ELEMENT_DIM, SPACE_DIM> > >::iterator pop_writer_iter = mCellPopulationWriters.begin();
603  pop_writer_iter != mCellPopulationWriters.end();
604  ++pop_writer_iter)
605  {
606  AcceptPopulationWriter(*pop_writer_iter);
607  }
608 
610 
611  // The top-most process adds a newline
612  if (PetscTools::AmTopMost())
613  {
614  BOOST_FOREACH(boost::shared_ptr<cell_writer_t> p_cell_writer, mCellWriters)
615  {
616  p_cell_writer->WriteNewline();
617  }
618  BOOST_FOREACH(boost::shared_ptr<pop_writer_t> p_pop_writer, mCellPopulationWriters)
619  {
620  p_pop_writer->WriteNewline();
621  }
622  }
624  }
626 
627  // Outside the round robin, deal with population count writers
629 
630  if (PetscTools::AmMaster())
631  {
632  // Open mCellPopulationCountWriters in append mode for writing, and write time stamps
633  BOOST_FOREACH(boost::shared_ptr<count_writer_t> p_count_writer, mCellPopulationCountWriters)
634  {
635  p_count_writer->OpenOutputFileForAppend(output_file_handler);
636  p_count_writer->WriteTimeStamp();
637  }
638  }
639  for (typename std::vector<boost::shared_ptr<AbstractCellPopulationCountWriter<ELEMENT_DIM, SPACE_DIM> > >::iterator count_writer_iter = mCellPopulationCountWriters.begin();
640  count_writer_iter != mCellPopulationCountWriters.end();
641  ++count_writer_iter)
642  {
643  AcceptPopulationCountWriter(*count_writer_iter);
644  }
645 
646  if (PetscTools::AmMaster())
647  {
648  // Add a newline and close any output files
649  BOOST_FOREACH(boost::shared_ptr<count_writer_t> p_count_writer, mCellPopulationCountWriters)
650  {
651  p_count_writer->WriteNewline();
652  p_count_writer->CloseFile();
653  }
654  }
655  }
656 
657  // VTK can only be written in 2 or 3 dimensions
658  if (SPACE_DIM > 1)
659  {
660  WriteVtkResultsToFile(rDirectory);
661  }
662 }
663 
664 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
666 {
667  for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter = this->Begin();
668  cell_iter != this->End();
669  ++cell_iter)
670  {
671  for (typename std::vector<boost::shared_ptr<AbstractCellWriter<ELEMENT_DIM, SPACE_DIM> > >::iterator cell_writer_iter = mCellWriters.begin();
672  cell_writer_iter != mCellWriters.end();
673  ++cell_writer_iter)
674  {
675  AcceptCellWriter(*cell_writer_iter, *cell_iter);
676  }
677  }
678 }
679 
680 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
682 {
683  std::string cell_population_type = GetIdentifier();
684 
685  *rParamsFile << "\t<" << cell_population_type << ">\n";
686  OutputCellPopulationParameters(rParamsFile);
687  *rParamsFile << "\t</" << cell_population_type << ">\n";
688  *rParamsFile << "\n";
689  *rParamsFile << "\t<CellCycleModels>\n";
690 
697  std::set<std::string> unique_cell_cycle_models;
698  std::vector<CellPtr> first_cell_with_unique_CCM;
699  for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter = this->Begin();
700  cell_iter != this->End();
701  ++cell_iter)
702  {
703  std::string identifier = cell_iter->GetCellCycleModel()->GetIdentifier();
704  if (unique_cell_cycle_models.count(identifier) == 0)
705  {
706  unique_cell_cycle_models.insert(identifier);
707  first_cell_with_unique_CCM.push_back((*cell_iter));
708  }
709  }
710 
711  // Loop over unique cell-cycle models
712  for (unsigned i=0; i<first_cell_with_unique_CCM.size(); i++)
713  {
714  // Output cell-cycle model details
715  first_cell_with_unique_CCM[i]->GetCellCycleModel()->OutputCellCycleModelInfo(rParamsFile);
716  }
717  *rParamsFile << "\t</CellCycleModels>\n";
718 
719  *rParamsFile << "\n";
720  *rParamsFile << "\t<SrnModels>\n";
721 
728  std::set<std::string> unique_srn_models;
729  std::vector<CellPtr> first_cell_with_unique_SRN;
730  for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter = this->Begin();
731  cell_iter != this->End();
732  ++cell_iter)
733  {
734  std::string identifier = cell_iter->GetSrnModel()->GetIdentifier();
735  if (unique_srn_models.count(identifier) == 0)
736  {
737  unique_srn_models.insert(identifier);
738  first_cell_with_unique_SRN.push_back((*cell_iter));
739  }
740  }
741 
742  // Loop over unique SRN models
743  for (unsigned i=0; i<first_cell_with_unique_SRN.size(); i++)
744  {
745  // Output SRN model details
746  first_cell_with_unique_SRN[i]->GetSrnModel()->OutputSrnModelInfo(rParamsFile);
747  }
748 
749  *rParamsFile << "\t</SrnModels>\n";
750 }
751 
752 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
754 {
755  *rParamsFile << "\t\t<OutputResultsForChasteVisualizer>" << mOutputResultsForChasteVisualizer << "</OutputResultsForChasteVisualizer>\n";
756 }
757 
758 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
760 {
761 }
762 
763 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
765 {
767 }
768 
769 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
771 {
772  mOutputResultsForChasteVisualizer = outputResultsForChasteVisualizer;
773 }
774 
775 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
777 {
778  return true;
779 }
780 
781 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
783 {
784  // Compute the centre of mass of the cell population
785  c_vector<double,SPACE_DIM> centre = GetCentroidOfCellPopulation();
786 
787  // Loop over cells and find the maximum distance from the centre of mass in each dimension
788  c_vector<double,SPACE_DIM> max_distance_from_centre = zero_vector<double>(SPACE_DIM);
789  for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter = this->Begin();
790  cell_iter != this->End();
791  ++cell_iter)
792  {
793  c_vector<double,SPACE_DIM> cell_location = GetLocationOfCellCentre(*cell_iter);
794 
795  // Note that we define this vector before setting it as otherwise the profiling build will break (see #2367)
796  c_vector<double,SPACE_DIM> displacement;
797  displacement = centre - cell_location;
798 
799  for (unsigned i=0; i<SPACE_DIM; i++)
800  {
801  if (displacement[i] > max_distance_from_centre[i])
802  {
803  max_distance_from_centre[i] = displacement[i];
804  }
805  }
806  }
807 
808  return max_distance_from_centre;
809 }
810 
811 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
812 std::pair<unsigned,unsigned> AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>::CreateOrderedPair(unsigned index1, unsigned index2)
813 {
814  assert(index1 != index2);
815 
816  std::pair<unsigned, unsigned> ordered_pair;
817  if (index1 < index2)
818  {
819  ordered_pair.first = index1;
820  ordered_pair.second = index2;
821  }
822  else
823  {
824  ordered_pair.first = index2;
825  ordered_pair.second = index1;
826  }
827  return ordered_pair;
828 }
829 
830 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
832 {
833  bool non_apoptotic_cell_present = false;
834 
835  if (IsCellAttachedToLocationIndex(pdeNodeIndex))
836  {
837  non_apoptotic_cell_present = !(GetCellUsingLocationIndex(pdeNodeIndex)->template HasCellProperty<ApoptoticCellProperty>());
838  }
839 
840  return non_apoptotic_cell_present;
841 }
842 
843 // Explicit instantiation
844 template class AbstractCellPopulation<1,1>;
845 template class AbstractCellPopulation<1,2>;
846 template class AbstractCellPopulation<2,2>;
847 template class AbstractCellPopulation<1,3>;
848 template class AbstractCellPopulation<2,3>;
849 template class AbstractCellPopulation<3,3>;
virtual void AcceptPopulationWriter(boost::shared_ptr< AbstractCellPopulationWriter< ELEMENT_DIM, SPACE_DIM > > pPopulationWriter)=0
virtual void SimulationSetupHook(AbstractCellBasedSimulation< ELEMENT_DIM, SPACE_DIM > *pSimulation)
c_vector< double, SPACE_DIM > GetCentroidOfCellPopulation()
std::vector< boost::shared_ptr< AbstractCellPopulationWriter< ELEMENT_DIM, SPACE_DIM > > > mCellPopulationWriters
void OpenOutputFileForAppend(OutputFileHandler &rOutputFileHandler)
virtual CellPtr GetCellUsingLocationIndex(unsigned index)
void SetDefaultCellMutationStateAndProliferativeTypeOrdering()
unsigned GetLocationIndexUsingCell(CellPtr pCell)
std::vector< boost::shared_ptr< AbstractCellWriter< ELEMENT_DIM, SPACE_DIM > > > mCellWriters
void SetDataOnAllCells(const std::string &rDataName, double dataValue)
boost::shared_ptr< CellPropertyRegistry > mpCellPropertyRegistry
virtual void RemoveCellUsingLocationIndex(unsigned index, CellPtr pCell)
c_vector< double, SPACE_DIM > mCentroid
virtual void OutputCellPopulationParameters(out_stream &rParamsFile)=0
#define EXCEPTION(message)
Definition: Exception.hpp:143
std::vector< boost::shared_ptr< AbstractCellPopulationCountWriter< ELEMENT_DIM, SPACE_DIM > > > mCellPopulationCountWriters
static bool AmMaster()
Definition: PetscTools.cpp:120
static MPI_Comm GetWorld()
Definition: PetscTools.cpp:178
std::set< CellPtr > GetCellsUsingLocationIndex(unsigned index)
virtual bool IsCellAttachedToLocationIndex(unsigned index)
#define NEVER_REACHED
Definition: Exception.hpp:206
virtual void WriteResultsToFiles(const std::string &rDirectory)
void SetOutputResultsForChasteVisualizer(bool outputResultsForChasteVisualizer)
void MoveCellInLocationMap(CellPtr pCell, unsigned old_index, unsigned new_index)
std::list< CellPtr > & rGetCells()
std::vector< unsigned > GetCellCyclePhaseCount()
virtual void AcceptPopulationCountWriter(boost::shared_ptr< AbstractCellPopulationCountWriter< ELEMENT_DIM, SPACE_DIM > > pPopulationCountWriter)=0
c_vector< double, SPACE_DIM > GetSizeOfCellPopulation()
virtual void AcceptCellWritersAcrossPopulation()
std::pair< unsigned, unsigned > CreateOrderedPair(unsigned index1, unsigned index2)
std::map< unsigned, std::set< CellPtr > > mLocationCellMap
void SetCellUsingLocationIndex(unsigned index, CellPtr pCell)
std::map< Cell *, unsigned > mCellLocationMap
virtual void AcceptCellWriter(boost::shared_ptr< AbstractCellWriter< ELEMENT_DIM, SPACE_DIM > > pCellWriter, CellPtr pCell)=0
static void EndRoundRobin()
Definition: PetscTools.cpp:164
std::string GetIdentifier() const
boost::shared_ptr< CellPropertyRegistry > GetCellPropertyRegistry()
static void BeginRoundRobin()
Definition: PetscTools.cpp:154
void OpenRoundRobinWritersFilesForAppend(OutputFileHandler &rOutputFileHandler)
out_stream OpenOutputFile(const std::string &rFileName, std::ios_base::openmode mode=std::ios::out|std::ios::trunc) const
virtual bool IsPdeNodeAssociatedWithNonApoptoticCell(unsigned pdeNodeIndex)
virtual c_vector< double, SPACE_DIM > GetLocationOfCellCentre(CellPtr pCell)=0
virtual void OpenWritersFiles(OutputFileHandler &rOutputFileHandler)
static bool IsParallel()
Definition: PetscTools.cpp:97
void OutputCellPopulationInfo(out_stream &rParamsFile)
virtual bool IsRoomToDivide(CellPtr pCell)
AbstractMesh< ELEMENT_DIM, SPACE_DIM > & rGetMesh()
virtual void WriteDataToVisualizerSetupFile(out_stream &pVizSetupFile)
virtual void OpenOutputFile(OutputFileHandler &rOutputFileHandler)
static bool AmTopMost()
Definition: PetscTools.cpp:126
AbstractCellPopulation(AbstractMesh< ELEMENT_DIM, SPACE_DIM > &rMesh)
virtual void AddCellUsingLocationIndex(unsigned index, CellPtr pCell)
std::vector< unsigned > GetCellProliferativeTypeCount()
AbstractMesh< ELEMENT_DIM, SPACE_DIM > & mrMesh
#define MAKE_PTR_ARGS(TYPE, NAME, ARGS)
virtual void WriteVtkResultsToFile(const std::string &rDirectory)=0
std::vector< unsigned > GetCellMutationStateCount()
std::set< unsigned > GetCellAncestors()