Chaste Commit::9e4a273f0754a391514ab12ed9d4a38fc9933db2
AbstractCellPopulation.cpp
1/*
2
3Copyright (c) 2005-2026, University of Oxford.
4All rights reserved.
5
6University of Oxford means the Chancellor, Masters and Scholars of the
7University of Oxford, having an administrative office at Wellington
8Square, Oxford OX1 2JD, UK.
9
10This file is part of Chaste.
11
12Redistribution and use in source and binary forms, with or without
13modification, 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
23THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
29GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
34*/
35
36#include <algorithm>
37#include <functional>
38
39#include "AbstractCellPopulation.hpp"
40#include "AbstractPhaseBasedCellCycleModel.hpp"
41#include "SmartPointers.hpp"
42#include "CellAncestor.hpp"
43#include "ApoptoticCellProperty.hpp"
44
45// Cell writers
46#include "BoundaryNodeWriter.hpp"
47#include "CellProliferativeTypesWriter.hpp"
48#include "LegacyCellProliferativeTypesWriter.hpp"
49#include "CellRemovalLocationsWriter.hpp"
50
51// Cell population writers
52#include "NodeLocationWriter.hpp"
53
54// These #includes are needed for SetDefaultCellMutationStateAndProliferativeTypeOrdering()
55#include "WildTypeCellMutationState.hpp"
56#include "ApcOneHitCellMutationState.hpp"
57#include "ApcTwoHitCellMutationState.hpp"
58#include "BetaCateninOneHitCellMutationState.hpp"
59#include "DefaultCellProliferativeType.hpp"
60#include "StemCellProliferativeType.hpp"
61#include "TransitCellProliferativeType.hpp"
62#include "DifferentiatedCellProliferativeType.hpp"
63
64template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
66 std::vector<CellPtr>& rCells,
67 const std::vector<unsigned> locationIndices)
68 : mrMesh(rMesh),
69 mCells(rCells.begin(), rCells.end()),
70 mCentroid(zero_vector<double>(SPACE_DIM)),
71 mpCellPropertyRegistry(CellPropertyRegistry::Instance()->TakeOwnership()),
72 mOutputResultsForChasteVisualizer(true)
73{
74 /*
75 * To avoid double-counting problems, clear the passed-in cells vector.
76 * We force a reallocation of memory so that subsequent usage of the
77 * vector is more likely to give an error.
78 */
79 std::vector<CellPtr>().swap(rCells);
80
81 // There must be a one-one correspondence between cells and location indices
82 if (!locationIndices.empty())
83 {
84 if (mCells.size() != locationIndices.size())
85 {
86 EXCEPTION("There is not a one-one correspondence between cells and location indices");
87 }
88 }
89
90 // Set up the map between location indices and cells
91 mLocationCellMap.clear();
92 mCellLocationMap.clear();
93
94 std::list<CellPtr>::iterator it = mCells.begin();
95 for (unsigned i=0; it != mCells.end(); ++it, ++i)
96 {
97 // Give each cell a pointer to the property registry (we have taken ownership in this constructor)
98 (*it)->rGetCellPropertyCollection().SetCellPropertyRegistry(mpCellPropertyRegistry.get());
99 }
100
101 // Clear stored divisions and removals information
104}
105
106template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
111
112template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
116
117template<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
129template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
130void 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
140template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
145
146template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
148{
149 return mCells;
150}
151
152template<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
165template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
167{
168 return mCells.size();
169}
170
171template<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
181template<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
192template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
194{
195 std::vector<unsigned> mutation_state_count;
196 const auto& r_cell_properties = mpCellPropertyRegistry->rGetAllCellProperties();
197
198 // Calculate mutation states count
199 for (unsigned i=0; i<r_cell_properties.size(); i++)
200 {
201 if (r_cell_properties[i]->IsSubType<AbstractCellMutationState>())
202 {
203 mutation_state_count.push_back(r_cell_properties[i]->GetCellCount());
204 }
205 }
206
207 // Reduce results onto all processes
209 {
210 // Make sure the vector on each process has the same size
211 unsigned local_size = mutation_state_count.size();
212 unsigned global_size;
213 MPI_Allreduce(&local_size, &global_size, 1, MPI_UNSIGNED, MPI_MAX, PetscTools::GetWorld());
214 assert(local_size == global_size);
215
216 std::vector<unsigned> mutation_counts(global_size);
217 MPI_Allreduce(mutation_state_count.data(), mutation_counts.data(), mutation_counts.size(), MPI_UNSIGNED, MPI_SUM, PetscTools::GetWorld());
218
219 mutation_state_count = mutation_counts;
220 }
221
222 return mutation_state_count;
223}
224
225template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
227{
228 std::vector<unsigned> proliferative_type_count;
229 const auto& r_cell_properties = mpCellPropertyRegistry->rGetAllCellProperties();
230
231 // Calculate proliferative types count
232 for (unsigned i=0; i<r_cell_properties.size(); i++)
233 {
234 if (r_cell_properties[i]->IsSubType<AbstractCellProliferativeType>())
235 {
236 proliferative_type_count.push_back(r_cell_properties[i]->GetCellCount());
237 }
238 }
239
240 // Reduce results onto all processes
242 {
243 // Make sure the vector on each process has the same size
244 unsigned local_size = proliferative_type_count.size();
245 unsigned global_size;
247 MPI_Allreduce(&local_size, &global_size, 1, MPI_UNSIGNED, MPI_MAX, PetscTools::GetWorld());
248 assert(local_size == global_size);
249
250 std::vector<unsigned> total_types_counts(global_size);
251 MPI_Allreduce(proliferative_type_count.data(), total_types_counts.data(), total_types_counts.size(), MPI_UNSIGNED, MPI_SUM, PetscTools::GetWorld());
252
253 proliferative_type_count = total_types_counts;
254 }
255
256 return proliferative_type_count;
257}
258
259template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
261{
262 std::vector<unsigned> cell_cycle_phase_count(5);
263 for (unsigned i=0; i<5; i++)
264 {
265 cell_cycle_phase_count[i] = 0;
266 }
268 /*
269 * Note that in parallel with a poor partition a process could end up with zero cells
270 * in which case the calculation should be skipped since `this->Begin()` is not defined.
271 */
272 if (GetNumAllCells() > 0u)
273 {
274 if (dynamic_cast<AbstractPhaseBasedCellCycleModel*>((*(this->Begin()))->GetCellCycleModel()) == nullptr)
275 {
276 EXCEPTION("You are trying to record the cell cycle phase of cells with a non phase based cell cycle model.");
277 }
278
279 for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter = this->Begin();
280 cell_iter != this->End();
281 ++cell_iter)
282 {
283 switch (static_cast<AbstractPhaseBasedCellCycleModel*>((*cell_iter)->GetCellCycleModel())->GetCurrentCellCyclePhase())
284 {
285 case G_ZERO_PHASE:
286 cell_cycle_phase_count[0]++;
287 break;
288 case G_ONE_PHASE:
289 cell_cycle_phase_count[1]++;
290 break;
291 case S_PHASE:
292 cell_cycle_phase_count[2]++;
293 break;
294 case G_TWO_PHASE:
295 cell_cycle_phase_count[3]++;
296 break;
297 case M_PHASE:
298 cell_cycle_phase_count[4]++;
299 break;
300 default:
302 }
303 }
304 }
305
306 // Reduce results onto all processes
308 {
309 std::vector<unsigned> phase_counts(cell_cycle_phase_count.size(), 0u);
310 MPI_Allreduce(cell_cycle_phase_count.data(), phase_counts.data(), phase_counts.size(), MPI_UNSIGNED, MPI_SUM, PetscTools::GetWorld());
311
312 cell_cycle_phase_count = phase_counts;
313 }
314
315 return cell_cycle_phase_count;
316}
317
318template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
320{
321 // Get the set of pointers to cells corresponding to this location index
322 std::set<CellPtr> cells = mLocationCellMap[index];
323
324 // If there is only one cell attached return the cell. Note currently only one cell per index.
325 if (cells.size() == 1)
326 {
327 return *(cells.begin());
328 }
329 if (cells.empty())
330 {
331 EXCEPTION("Location index input argument does not correspond to a Cell");
332 }
333 else
334 {
335 EXCEPTION("Multiple cells are attached to a single location index.");
336 }
337}
338
339template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
341{
342 // Return the set of pointers to cells corresponding to this location index, note the set may be empty.
343 return mLocationCellMap[index];
344}
345
346template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
348{
349 // Get the set of pointers to cells corresponding to this location index
350 std::set<CellPtr> cells = mLocationCellMap[index];
351
352 // Return whether there is a cell attached to the location index
353 return !(cells.empty());
355
356template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
360
361template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
363{
364 // Clear the maps
365 mLocationCellMap[index].clear();
366 mCellLocationMap.erase(pCell.get());
367
368 // Replace with new cell
369 mLocationCellMap[index].insert(pCell);
370
371 // Do other half of the map
372 mCellLocationMap[pCell.get()] = index;
373}
374
375template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
377{
378 mLocationCellMap[index].insert(pCell);
379 mCellLocationMap[pCell.get()] = index;
380}
381
382template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
384{
385 std::set<CellPtr>::iterator cell_iter = mLocationCellMap[index].find(pCell);
386
387 if (cell_iter == mLocationCellMap[index].end())
388 {
389 EXCEPTION("Tried to remove a cell which is not attached to the given location index");
390 }
391 else
392 {
393 mLocationCellMap[index].erase(cell_iter);
394 mCellLocationMap.erase(pCell.get());
395 }
396}
397
398template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
399void AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::MoveCellInLocationMap(CellPtr pCell, unsigned old_index, unsigned new_index)
400{
401 // Remove the cell from its current location
402 RemoveCellUsingLocationIndex(old_index, pCell);
403
404 // Add it to the new location
405 AddCellUsingLocationIndex(new_index, pCell);
406}
407
408template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
410{
411 // Check the cell is in the map
412 assert(this->mCellLocationMap.find(pCell.get()) != this->mCellLocationMap.end());
414 return mCellLocationMap[pCell.get()];
415}
416
417template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
419{
420 return mpCellPropertyRegistry;
421}
422
423template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
425{
426 boost::shared_ptr<CellPropertyRegistry> p_registry = GetCellPropertyRegistry();
427 if (!p_registry->HasOrderingBeenSpecified())
428 {
429 std::vector<boost::shared_ptr<AbstractCellProperty> > mutations_and_proliferative_types;
430 mutations_and_proliferative_types.push_back(p_registry->Get<WildTypeCellMutationState>());
431 mutations_and_proliferative_types.push_back(p_registry->Get<ApcOneHitCellMutationState>());
432 mutations_and_proliferative_types.push_back(p_registry->Get<ApcTwoHitCellMutationState>());
433 mutations_and_proliferative_types.push_back(p_registry->Get<BetaCateninOneHitCellMutationState>());
434 mutations_and_proliferative_types.push_back(p_registry->Get<StemCellProliferativeType>());
435 mutations_and_proliferative_types.push_back(p_registry->Get<TransitCellProliferativeType>());
436 mutations_and_proliferative_types.push_back(p_registry->Get<DifferentiatedCellProliferativeType>());
437
438 // Parallel process with no cells won't have the default property, so add it in
439 mutations_and_proliferative_types.push_back(p_registry->Get<DefaultCellProliferativeType>());
440 p_registry->SpecifyOrdering(mutations_and_proliferative_types);
441 }
442}
443
445 * We exclude the following from coverage, as these methods are implemented elsewhere and tested accordingly
446 */
447// LCOV_EXCL_START
448template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
449std::set<std::pair<unsigned, unsigned>> AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::GetNeighbouringEdgeIndices(CellPtr cell, unsigned pEdgeLocalIndex)
450{
451 return std::set<std::pair<unsigned, unsigned>>();
453// LCOV_EXCL_STOP
454
455template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
457{
458 mCentroid = zero_vector<double>(SPACE_DIM);
459 for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter = this->Begin();
460 cell_iter != this->End();
461 ++cell_iter)
462 {
463 mCentroid += GetLocationOfCellCentre(*cell_iter);
464 }
465 mCentroid /= this->GetNumRealCells();
467 return mCentroid;
468}
469
470template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
474
475template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
477{
479 for (boost::shared_ptr<cell_writer_t> p_cell_writer : mCellWriters)
480 {
481 p_cell_writer->CloseFile();
482 }
483
485 for (boost::shared_ptr<pop_writer_t> p_pop_writer : mCellPopulationWriters)
486 {
487 p_pop_writer->CloseFile();
488 }
490
491template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
493{
494 typedef AbstractCellWriter<ELEMENT_DIM, SPACE_DIM> cell_writer_t;
495 for (boost::shared_ptr<cell_writer_t> p_cell_writer : mCellWriters)
496 {
497 p_cell_writer->CloseFile();
499
501 for (boost::shared_ptr<pop_writer_t> p_pop_writer : mCellPopulationWriters)
502 {
503 p_pop_writer->CloseFile();
504 }
505
506#ifdef CHASTE_VTK
507 *mpVtkMetaFile << " </Collection>\n";
508 *mpVtkMetaFile << "</VTKFile>\n";
509 mpVtkMetaFile->close();
510#endif //CHASTE_VTK
511}
512
513template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
515{
516#ifdef CHASTE_VTK
517 mpVtkMetaFile = rOutputFileHandler.OpenOutputFile("results.pvd");
518 *mpVtkMetaFile << "<?xml version=\"1.0\"?>\n";
519 *mpVtkMetaFile << "<VTKFile type=\"Collection\" version=\"0.1\" byte_order=\"LittleEndian\" compressor=\"vtkZLibDataCompressor\">\n";
520 *mpVtkMetaFile << " <Collection>\n";
521#endif //CHASTE_VTK
522
523 if (mOutputResultsForChasteVisualizer)
524 {
525 if (!HasWriter<NodeLocationWriter>())
527 AddPopulationWriter<NodeLocationWriter>();
528 }
529 if (!HasWriter<BoundaryNodeWriter>())
530 {
531 AddPopulationWriter<BoundaryNodeWriter>();
532 }
533 if (!HasWriter<CellProliferativeTypesWriter>())
534 {
535 AddCellWriter<CellProliferativeTypesWriter>();
536 }
537 if (!HasWriter<LegacyCellProliferativeTypesWriter>())
538 {
539 AddCellWriter<LegacyCellProliferativeTypesWriter>();
540 }
541 }
542
543 // Open output files for any cell writers
544 typedef AbstractCellWriter<ELEMENT_DIM, SPACE_DIM> cell_writer_t;
545 for (boost::shared_ptr<cell_writer_t> p_cell_writer : mCellWriters)
547 p_cell_writer->OpenOutputFile(rOutputFileHandler);
548 }
549
550 // Open output files and write headers for any population writers
552 for (boost::shared_ptr<pop_writer_t> p_pop_writer : mCellPopulationWriters)
553 {
554 p_pop_writer->OpenOutputFile(rOutputFileHandler);
555 p_pop_writer->WriteHeader(this);
556 }
558 // Open output files and write headers for any population count writers
560 for (boost::shared_ptr<count_writer_t> p_count_writer : mCellPopulationCountWriters)
561 {
562 p_count_writer->OpenOutputFile(rOutputFileHandler);
563 p_count_writer->WriteHeader(this);
564 }
565
566 // Open output files and write headers for any population event writers
568 for (boost::shared_ptr<event_writer_t> p_event_writer : mCellPopulationEventWriters)
569 {
570 p_event_writer->OpenOutputFile(rOutputFileHandler);
571 p_event_writer->WriteHeader(this);
572 }
573}
574
575template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
577{
578 typedef AbstractCellWriter<ELEMENT_DIM, SPACE_DIM> cell_writer_t;
580 for (boost::shared_ptr<cell_writer_t> p_cell_writer : mCellWriters)
581 {
582 p_cell_writer->OpenOutputFileForAppend(rOutputFileHandler);
583 }
584 for (boost::shared_ptr<pop_writer_t> p_pop_writer : mCellPopulationWriters)
585 {
586 p_pop_writer->OpenOutputFileForAppend(rOutputFileHandler);
587 }
588}
589
590template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
592{
593 typedef AbstractCellWriter<ELEMENT_DIM, SPACE_DIM> cell_writer_t;
595 OutputFileHandler output_file_handler(rDirectory, false);
596
597 if (!(mCellWriters.empty() && mCellPopulationWriters.empty() && mCellPopulationCountWriters.empty()))
598 {
599 // An ordering must be specified for cell mutation states and cell proliferative types
600 SetDefaultCellMutationStateAndProliferativeTypeOrdering();
601
603 {
604 OpenRoundRobinWritersFilesForAppend(output_file_handler);
605
606 // The master process writes time stamps
608 {
609 for (boost::shared_ptr<cell_writer_t> p_cell_writer : mCellWriters)
610 {
611 p_cell_writer->WriteTimeStamp();
613 for (boost::shared_ptr<pop_writer_t> p_pop_writer : mCellPopulationWriters)
614 {
615 p_pop_writer->WriteTimeStamp();
616 }
618
619 for (typename std::vector<boost::shared_ptr<AbstractCellPopulationWriter<ELEMENT_DIM, SPACE_DIM> > >::iterator pop_writer_iter = mCellPopulationWriters.begin();
620 pop_writer_iter != mCellPopulationWriters.end();
621 ++pop_writer_iter)
622 {
623 AcceptPopulationWriter(*pop_writer_iter);
624 }
625
626 AcceptCellWritersAcrossPopulation();
627
628 // The top-most process adds a newline
630 {
631 for (boost::shared_ptr<cell_writer_t> p_cell_writer : mCellWriters)
633 p_cell_writer->WriteNewline();
634 }
635 for (boost::shared_ptr<pop_writer_t> p_pop_writer : mCellPopulationWriters)
636 {
637 p_pop_writer->WriteNewline();
638 }
639 }
640 CloseRoundRobinWritersFiles();
641 }
643
644 // Outside the round robin, deal with population count writers
646
648 {
649 // Open mCellPopulationCountWriters in append mode for writing, and write time stamps
650 for (boost::shared_ptr<count_writer_t> p_count_writer : mCellPopulationCountWriters)
651 {
652 p_count_writer->OpenOutputFileForAppend(output_file_handler);
653 p_count_writer->WriteTimeStamp();
654 }
655 }
656 for (typename std::vector<boost::shared_ptr<AbstractCellPopulationCountWriter<ELEMENT_DIM, SPACE_DIM> > >::iterator count_writer_iter = mCellPopulationCountWriters.begin();
657 count_writer_iter != mCellPopulationCountWriters.end();
658 ++count_writer_iter)
659 {
660 AcceptPopulationCountWriter(*count_writer_iter);
661 }
662
664 {
665 // Add a newline and close any output files
666 for (boost::shared_ptr<count_writer_t> p_count_writer : mCellPopulationCountWriters)
667 {
668 p_count_writer->WriteNewline();
669 p_count_writer->CloseFile();
670 }
671 }
672
673
674 // Outside the round robin, deal with population event writers
676
678 {
679 // Open mCellPopulationCountWriters in append mode for writing
680 for (boost::shared_ptr<event_writer_t> p_event_writer : mCellPopulationEventWriters)
681 {
682 p_event_writer->OpenOutputFileForAppend(output_file_handler);
683 }
684 }
685 for (typename std::vector<boost::shared_ptr<AbstractCellPopulationEventWriter<ELEMENT_DIM, SPACE_DIM> > >::iterator event_writer_iter = mCellPopulationEventWriters.begin();
686 event_writer_iter != mCellPopulationEventWriters.end();
687 ++event_writer_iter)
688 {
689 AcceptPopulationEventWriter(*event_writer_iter);
690 }
691
693 {
694 // Close any output files
695 for (boost::shared_ptr<event_writer_t> p_event_writer : mCellPopulationEventWriters)
696 {
697 p_event_writer->CloseFile();
698 }
699 }
700 }
701
702 // VTK can only be written in 2 or 3 dimensions
703 if (SPACE_DIM > 1)
705 WriteVtkResultsToFile(rDirectory);
706 }
707}
708
709template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
711{
712 for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter = this->Begin();
713 cell_iter != this->End();
714 ++cell_iter)
715 {
716 for (typename std::vector<boost::shared_ptr<AbstractCellWriter<ELEMENT_DIM, SPACE_DIM> > >::iterator cell_writer_iter = mCellWriters.begin();
717 cell_writer_iter != mCellWriters.end();
718 ++cell_writer_iter)
719 {
720 AcceptCellWriter(*cell_writer_iter, *cell_iter);
721 }
722 }
724
725template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
727{
728 std::string cell_population_type = GetIdentifier();
729
730 *rParamsFile << "\t<" << cell_population_type << ">\n";
731 OutputCellPopulationParameters(rParamsFile);
732 *rParamsFile << "\t</" << cell_population_type << ">\n";
733 *rParamsFile << "\n";
734 *rParamsFile << "\t<CellCycleModels>\n";
735
742 std::set<std::string> unique_cell_cycle_models;
743 std::vector<CellPtr> first_cell_with_unique_CCM;
744 for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter = this->Begin();
745 cell_iter != this->End();
746 ++cell_iter)
747 {
748 std::string identifier = cell_iter->GetCellCycleModel()->GetIdentifier();
749 if (unique_cell_cycle_models.count(identifier) == 0)
750 {
751 unique_cell_cycle_models.insert(identifier);
752 first_cell_with_unique_CCM.push_back((*cell_iter));
753 }
754 }
755
756 // Loop over unique cell-cycle models
757 for (unsigned i=0; i<first_cell_with_unique_CCM.size(); i++)
758 {
759 // Output cell-cycle model details
760 first_cell_with_unique_CCM[i]->GetCellCycleModel()->OutputCellCycleModelInfo(rParamsFile);
761 }
762 *rParamsFile << "\t</CellCycleModels>\n";
763
764 *rParamsFile << "\n";
765 *rParamsFile << "\t<SrnModels>\n";
766
773 std::set<std::string> unique_srn_models;
774 std::vector<CellPtr> first_cell_with_unique_SRN;
775 for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter = this->Begin();
776 cell_iter != this->End();
777 ++cell_iter)
778 {
779 std::string identifier = cell_iter->GetSrnModel()->GetIdentifier();
780 if (unique_srn_models.count(identifier) == 0)
781 {
782 unique_srn_models.insert(identifier);
783 first_cell_with_unique_SRN.push_back((*cell_iter));
784 }
786
787 // Loop over unique SRN models
788 for (unsigned i=0; i<first_cell_with_unique_SRN.size(); i++)
789 {
790 // Output SRN model details
791 first_cell_with_unique_SRN[i]->GetSrnModel()->OutputSrnModelInfo(rParamsFile);
792 }
793
794 *rParamsFile << "\t</SrnModels>\n";
795}
796
797template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
799{
800 *rParamsFile << "\t\t<OutputResultsForChasteVisualizer>" << mOutputResultsForChasteVisualizer << "</OutputResultsForChasteVisualizer>\n";
801}
802
803template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
807
808template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
810{
811 return mOutputResultsForChasteVisualizer;
812}
813
814template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
816{
817 mOutputResultsForChasteVisualizer = outputResultsForChasteVisualizer;
818}
819
820template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
822{
823 return mDivisionsInformation;
824}
825template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
827{
828 mDivisionsInformation.push_back(divisionInformation);
829}
830
831template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
833{
834 mDivisionsInformation.clear();
835}
836
837template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
839{
840 return mRemovalsInformation;
841}
842
843template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
845{
846 mRemovalsInformation.push_back(removalInformation);
847}
848
849template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
851{
852 mRemovalsInformation.clear();
853}
854
855template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
857{
858 //If necessary store the information about the cell removal
859 c_vector<double, SPACE_DIM> cell_location = GetLocationOfCellCentre(pCell);
860 if (HasWriter<CellRemovalLocationsWriter>())
861 {
862 std::stringstream removal_info;
863 removal_info << SimulationTime::Instance()->GetTime() << "\t";
864 for (unsigned i = 0; i < SPACE_DIM; i++)
865 {
866 removal_info << cell_location[i] << "\t";
867 }
868 removal_info << "\t" << pCell->GetAge() << "\t" << pCell->GetCellId() << "\t" << killerInfo << "\t";
869
870 AddRemovalInformation(removal_info.str());
871 }
872}
873
874template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
875void AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::KillCell(CellPtr pCell, std::string killerInfo)
876{
877 //If necessary store the information about the cell removal
878 GenerateRemovalInformation(pCell, killerInfo);
879
880 //Mark cell as dead
881 pCell->Kill();
882}
883
884template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
886{
887 //If necessary store the information about the cell removal
888 GenerateRemovalInformation(pCell, killerInfo);
889
890 //Mark cell as Apoptotic
891 pCell->StartApoptosis();
892}
893
894template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
896{
897 return true;
898}
899
900template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
902{
903 // Compute the centre of mass of the cell population
904 c_vector<double,SPACE_DIM> centre = GetCentroidOfCellPopulation();
905
906 // Loop over cells and find the maximum distance from the centre of mass in each dimension
907 c_vector<double,SPACE_DIM> max_distance_from_centre = zero_vector<double>(SPACE_DIM);
908 for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter = this->Begin();
909 cell_iter != this->End();
910 ++cell_iter)
911 {
912 c_vector<double,SPACE_DIM> cell_location = GetLocationOfCellCentre(*cell_iter);
913
914 // Note that we define this vector before setting it as otherwise the profiling build will break (see #2367)
915 c_vector<double,SPACE_DIM> displacement;
916 displacement = centre - cell_location;
917
918 for (unsigned i=0; i<SPACE_DIM; i++)
919 {
920 if (displacement[i] > max_distance_from_centre[i])
921 {
922 max_distance_from_centre[i] = displacement[i];
923 }
924 }
925 }
926
927 return max_distance_from_centre;
928}
929
930template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
931std::pair<unsigned,unsigned> AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>::CreateOrderedPair(unsigned index1, unsigned index2)
932{
933 assert(index1 != index2);
934
935 std::pair<unsigned, unsigned> ordered_pair;
936 if (index1 < index2)
937 {
938 ordered_pair.first = index1;
939 ordered_pair.second = index2;
940 }
941 else
943 ordered_pair.first = index2;
944 ordered_pair.second = index1;
945 }
946 return ordered_pair;
947}
948
949template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
951{
952 bool non_apoptotic_cell_present = false;
953
954 if (IsCellAttachedToLocationIndex(pdeNodeIndex))
955 {
956 non_apoptotic_cell_present = !(GetCellUsingLocationIndex(pdeNodeIndex)->template HasCellProperty<ApoptoticCellProperty>());
957 }
958
959 return non_apoptotic_cell_present;
960}
961
962
963// Explicit instantiation
964template class AbstractCellPopulation<1,1>;
965template class AbstractCellPopulation<1,2>;
966template class AbstractCellPopulation<2,2>;
967template class AbstractCellPopulation<1,3>;
968template class AbstractCellPopulation<2,3>;
969template class AbstractCellPopulation<3,3>;
#define EXCEPTION(message)
#define NEVER_REACHED
#define MAKE_PTR_ARGS(TYPE, NAME, ARGS)
virtual void OpenOutputFile(OutputFileHandler &rOutputFileHandler)
void OpenOutputFileForAppend(OutputFileHandler &rOutputFileHandler)
boost::shared_ptr< CellPropertyRegistry > mpCellPropertyRegistry
std::vector< std::string > GetDivisionsInformation()
void OpenRoundRobinWritersFilesForAppend(OutputFileHandler &rOutputFileHandler)
void SetCellUsingLocationIndex(unsigned index, CellPtr pCell)
std::vector< std::string > GetRemovalsInformation()
virtual void AddCellUsingLocationIndex(unsigned index, CellPtr pCell)
std::vector< unsigned > GetCellMutationStateCount()
std::list< CellPtr > & rGetCells()
void SetDataOnAllCells(const std::string &rDataName, double dataValue)
virtual void OpenWritersFiles(OutputFileHandler &rOutputFileHandler)
virtual bool IsCellAttachedToLocationIndex(unsigned index)
virtual bool IsRoomToDivide(CellPtr pCell)
virtual bool IsPdeNodeAssociatedWithNonApoptoticCell(unsigned pdeNodeIndex)
std::map< unsigned, std::set< CellPtr > > mLocationCellMap
unsigned GetLocationIndexUsingCell(CellPtr pCell)
void SetOutputResultsForChasteVisualizer(bool outputResultsForChasteVisualizer)
virtual void WriteResultsToFiles(const std::string &rDirectory)
std::set< CellPtr > GetCellsUsingLocationIndex(unsigned index)
std::set< unsigned > GetCellAncestors()
virtual void OutputCellPopulationParameters(out_stream &rParamsFile)=0
virtual std::set< std::pair< unsigned, unsigned > > GetNeighbouringEdgeIndices(CellPtr pCell, unsigned pEdgeIndex)
virtual void SimulationSetupHook(AbstractCellBasedSimulation< ELEMENT_DIM, SPACE_DIM > *pSimulation)
boost::shared_ptr< CellPropertyRegistry > GetCellPropertyRegistry()
virtual void WriteDataToVisualizerSetupFile(out_stream &pVizSetupFile)
void GenerateRemovalInformation(CellPtr pCell, std::string killerInfo)
std::map< Cell *, unsigned > mCellLocationMap
void OutputCellPopulationInfo(out_stream &rParamsFile)
virtual CellPtr GetCellUsingLocationIndex(unsigned index)
std::vector< unsigned > GetCellCyclePhaseCount()
AbstractCellPopulation(AbstractMesh< ELEMENT_DIM, SPACE_DIM > &rMesh)
AbstractMesh< ELEMENT_DIM, SPACE_DIM > & rGetMesh()
void StartApoptosisOnCell(CellPtr pCell, std::string killerInfo)
c_vector< double, SPACE_DIM > GetCentroidOfCellPopulation()
void KillCell(CellPtr pCell, std::string killerInfo)
std::vector< unsigned > GetCellProliferativeTypeCount()
void AddRemovalInformation(std::string removalInformation)
void SetDefaultCellMutationStateAndProliferativeTypeOrdering()
std::pair< unsigned, unsigned > CreateOrderedPair(unsigned index1, unsigned index2)
void MoveCellInLocationMap(CellPtr pCell, unsigned old_index, unsigned new_index)
c_vector< double, SPACE_DIM > GetSizeOfCellPopulation()
void AddDivisionInformation(std::string divisionInformation)
virtual void AcceptCellWritersAcrossPopulation()
virtual void RemoveCellUsingLocationIndex(unsigned index, CellPtr pCell)
out_stream OpenOutputFile(const std::string &rFileName, std::ios_base::openmode mode=std::ios::out|std::ios::trunc) const
static MPI_Comm GetWorld()
static bool AmMaster()
static bool AmTopMost()
static bool IsParallel()
static void EndRoundRobin()
static void BeginRoundRobin()
double GetTime() const
static SimulationTime * Instance()