Chaste Commit::29c3c4ab2bee00ddd311a035a1e522c03cbe928a
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 *mpVtkMetaFile << " </Collection>\n";
507 *mpVtkMetaFile << "</VTKFile>\n";
508 mpVtkMetaFile->close();
509}
511template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
513{
514 mpVtkMetaFile = rOutputFileHandler.OpenOutputFile("results.pvd");
515 *mpVtkMetaFile << "<?xml version=\"1.0\"?>\n";
516 *mpVtkMetaFile << "<VTKFile type=\"Collection\" version=\"0.1\" byte_order=\"LittleEndian\" compressor=\"vtkZLibDataCompressor\">\n";
517 *mpVtkMetaFile << " <Collection>\n";
519 if (mOutputResultsForChasteVisualizer)
520 {
521 if (!HasWriter<NodeLocationWriter>())
522 {
523 AddPopulationWriter<NodeLocationWriter>();
524 }
525 if (!HasWriter<BoundaryNodeWriter>())
527 AddPopulationWriter<BoundaryNodeWriter>();
528 }
529 if (!HasWriter<CellProliferativeTypesWriter>())
530 {
531 AddCellWriter<CellProliferativeTypesWriter>();
532 }
533 if (!HasWriter<LegacyCellProliferativeTypesWriter>())
534 {
535 AddCellWriter<LegacyCellProliferativeTypesWriter>();
536 }
537 }
538
539 // Open output files for any cell writers
540 typedef AbstractCellWriter<ELEMENT_DIM, SPACE_DIM> cell_writer_t;
541 for (boost::shared_ptr<cell_writer_t> p_cell_writer : mCellWriters)
542 {
543 p_cell_writer->OpenOutputFile(rOutputFileHandler);
544 }
545
546 // Open output files and write headers for any population writers
548 for (boost::shared_ptr<pop_writer_t> p_pop_writer : mCellPopulationWriters)
549 {
550 p_pop_writer->OpenOutputFile(rOutputFileHandler);
551 p_pop_writer->WriteHeader(this);
552 }
553
554 // Open output files and write headers for any population count writers
556 for (boost::shared_ptr<count_writer_t> p_count_writer : mCellPopulationCountWriters)
558 p_count_writer->OpenOutputFile(rOutputFileHandler);
559 p_count_writer->WriteHeader(this);
560 }
561
562 // Open output files and write headers for any population event writers
564 for (boost::shared_ptr<event_writer_t> p_event_writer : mCellPopulationEventWriters)
565 {
566 p_event_writer->OpenOutputFile(rOutputFileHandler);
567 p_event_writer->WriteHeader(this);
568 }
569}
570
571template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
573{
574 typedef AbstractCellWriter<ELEMENT_DIM, SPACE_DIM> cell_writer_t;
576 for (boost::shared_ptr<cell_writer_t> p_cell_writer : mCellWriters)
577 {
578 p_cell_writer->OpenOutputFileForAppend(rOutputFileHandler);
579 }
580 for (boost::shared_ptr<pop_writer_t> p_pop_writer : mCellPopulationWriters)
581 {
582 p_pop_writer->OpenOutputFileForAppend(rOutputFileHandler);
583 }
584}
585
586template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
588{
589 typedef AbstractCellWriter<ELEMENT_DIM, SPACE_DIM> cell_writer_t;
591 OutputFileHandler output_file_handler(rDirectory, false);
592
593 if (!(mCellWriters.empty() && mCellPopulationWriters.empty() && mCellPopulationCountWriters.empty()))
594 {
595 // An ordering must be specified for cell mutation states and cell proliferative types
596 SetDefaultCellMutationStateAndProliferativeTypeOrdering();
597
599 {
600 OpenRoundRobinWritersFilesForAppend(output_file_handler);
601
602 // The master process writes time stamps
604 {
605 for (boost::shared_ptr<cell_writer_t> p_cell_writer : mCellWriters)
606 {
607 p_cell_writer->WriteTimeStamp();
608 }
609 for (boost::shared_ptr<pop_writer_t> p_pop_writer : mCellPopulationWriters)
610 {
611 p_pop_writer->WriteTimeStamp();
613 }
614
615 for (typename std::vector<boost::shared_ptr<AbstractCellPopulationWriter<ELEMENT_DIM, SPACE_DIM> > >::iterator pop_writer_iter = mCellPopulationWriters.begin();
616 pop_writer_iter != mCellPopulationWriters.end();
617 ++pop_writer_iter)
618 {
619 AcceptPopulationWriter(*pop_writer_iter);
620 }
621
622 AcceptCellWritersAcrossPopulation();
623
624 // The top-most process adds a newline
626 {
627 for (boost::shared_ptr<cell_writer_t> p_cell_writer : mCellWriters)
628 {
629 p_cell_writer->WriteNewline();
630 }
631 for (boost::shared_ptr<pop_writer_t> p_pop_writer : mCellPopulationWriters)
633 p_pop_writer->WriteNewline();
634 }
635 }
636 CloseRoundRobinWritersFiles();
637 }
639
640 // Outside the round robin, deal with population count writers
642
644 {
645 // Open mCellPopulationCountWriters in append mode for writing, and write time stamps
646 for (boost::shared_ptr<count_writer_t> p_count_writer : mCellPopulationCountWriters)
648 p_count_writer->OpenOutputFileForAppend(output_file_handler);
649 p_count_writer->WriteTimeStamp();
650 }
651 }
652 for (typename std::vector<boost::shared_ptr<AbstractCellPopulationCountWriter<ELEMENT_DIM, SPACE_DIM> > >::iterator count_writer_iter = mCellPopulationCountWriters.begin();
653 count_writer_iter != mCellPopulationCountWriters.end();
654 ++count_writer_iter)
655 {
656 AcceptPopulationCountWriter(*count_writer_iter);
657 }
658
660 {
661 // Add a newline and close any output files
662 for (boost::shared_ptr<count_writer_t> p_count_writer : mCellPopulationCountWriters)
663 {
664 p_count_writer->WriteNewline();
665 p_count_writer->CloseFile();
666 }
667 }
668
669
670 // Outside the round robin, deal with population event writers
672
674 {
675 // Open mCellPopulationCountWriters in append mode for writing
676 for (boost::shared_ptr<event_writer_t> p_event_writer : mCellPopulationEventWriters)
677 {
678 p_event_writer->OpenOutputFileForAppend(output_file_handler);
679 }
680 }
681 for (typename std::vector<boost::shared_ptr<AbstractCellPopulationEventWriter<ELEMENT_DIM, SPACE_DIM> > >::iterator event_writer_iter = mCellPopulationEventWriters.begin();
682 event_writer_iter != mCellPopulationEventWriters.end();
683 ++event_writer_iter)
684 {
685 AcceptPopulationEventWriter(*event_writer_iter);
686 }
687
689 {
690 // Close any output files
691 for (boost::shared_ptr<event_writer_t> p_event_writer : mCellPopulationEventWriters)
692 {
693 p_event_writer->CloseFile();
694 }
696 }
697
698 // VTK can only be written in 2 or 3 dimensions
699 if (SPACE_DIM > 1)
700 {
701 WriteVtkResultsToFile(rDirectory);
702 }
703}
705template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
707{
708 for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter = this->Begin();
709 cell_iter != this->End();
710 ++cell_iter)
711 {
712 for (typename std::vector<boost::shared_ptr<AbstractCellWriter<ELEMENT_DIM, SPACE_DIM> > >::iterator cell_writer_iter = mCellWriters.begin();
713 cell_writer_iter != mCellWriters.end();
714 ++cell_writer_iter)
715 {
716 AcceptCellWriter(*cell_writer_iter, *cell_iter);
717 }
718 }
719}
720
721template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
724 std::string cell_population_type = GetIdentifier();
725
726 *rParamsFile << "\t<" << cell_population_type << ">\n";
727 OutputCellPopulationParameters(rParamsFile);
728 *rParamsFile << "\t</" << cell_population_type << ">\n";
729 *rParamsFile << "\n";
730 *rParamsFile << "\t<CellCycleModels>\n";
731
738 std::set<std::string> unique_cell_cycle_models;
739 std::vector<CellPtr> first_cell_with_unique_CCM;
740 for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter = this->Begin();
741 cell_iter != this->End();
742 ++cell_iter)
743 {
744 std::string identifier = cell_iter->GetCellCycleModel()->GetIdentifier();
745 if (unique_cell_cycle_models.count(identifier) == 0)
746 {
747 unique_cell_cycle_models.insert(identifier);
748 first_cell_with_unique_CCM.push_back((*cell_iter));
749 }
750 }
751
752 // Loop over unique cell-cycle models
753 for (unsigned i=0; i<first_cell_with_unique_CCM.size(); i++)
754 {
755 // Output cell-cycle model details
756 first_cell_with_unique_CCM[i]->GetCellCycleModel()->OutputCellCycleModelInfo(rParamsFile);
757 }
758 *rParamsFile << "\t</CellCycleModels>\n";
760 *rParamsFile << "\n";
761 *rParamsFile << "\t<SrnModels>\n";
762
769 std::set<std::string> unique_srn_models;
770 std::vector<CellPtr> first_cell_with_unique_SRN;
771 for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter = this->Begin();
772 cell_iter != this->End();
773 ++cell_iter)
774 {
775 std::string identifier = cell_iter->GetSrnModel()->GetIdentifier();
776 if (unique_srn_models.count(identifier) == 0)
777 {
778 unique_srn_models.insert(identifier);
779 first_cell_with_unique_SRN.push_back((*cell_iter));
780 }
781 }
782
783 // Loop over unique SRN models
784 for (unsigned i=0; i<first_cell_with_unique_SRN.size(); i++)
786 // Output SRN model details
787 first_cell_with_unique_SRN[i]->GetSrnModel()->OutputSrnModelInfo(rParamsFile);
788 }
789
790 *rParamsFile << "\t</SrnModels>\n";
791}
792
793template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
795{
796 *rParamsFile << "\t\t<OutputResultsForChasteVisualizer>" << mOutputResultsForChasteVisualizer << "</OutputResultsForChasteVisualizer>\n";
797}
798
799template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
803
804template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
806{
807 return mOutputResultsForChasteVisualizer;
808}
809
810template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
812{
813 mOutputResultsForChasteVisualizer = outputResultsForChasteVisualizer;
814}
815
816template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
818{
819 return mDivisionsInformation;
820}
821template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
823{
824 mDivisionsInformation.push_back(divisionInformation);
825}
826
827template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
829{
830 mDivisionsInformation.clear();
831}
832
833template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
835{
836 return mRemovalsInformation;
837}
838
839template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
841{
842 mRemovalsInformation.push_back(removalInformation);
843}
844
845template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
847{
848 mRemovalsInformation.clear();
849}
850
851template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
853{
854 //If necessary store the information about the cell removal
855 c_vector<double, SPACE_DIM> cell_location = GetLocationOfCellCentre(pCell);
856 if (HasWriter<CellRemovalLocationsWriter>())
857 {
858 std::stringstream removal_info;
859 removal_info << SimulationTime::Instance()->GetTime() << "\t";
860 for (unsigned i = 0; i < SPACE_DIM; i++)
861 {
862 removal_info << cell_location[i] << "\t";
863 }
864 removal_info << "\t" << pCell->GetAge() << "\t" << pCell->GetCellId() << "\t" << killerInfo << "\t";
865
866 AddRemovalInformation(removal_info.str());
867 }
868}
869
870template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
871void AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::KillCell(CellPtr pCell, std::string killerInfo)
872{
873 //If necessary store the information about the cell removal
874 GenerateRemovalInformation(pCell, killerInfo);
875
876 //Mark cell as dead
877 pCell->Kill();
878}
879
880template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
882{
883 //If necessary store the information about the cell removal
884 GenerateRemovalInformation(pCell, killerInfo);
885
886 //Mark cell as Apoptotic
887 pCell->StartApoptosis();
888}
889
890template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
892{
893 return true;
894}
895
896template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
898{
899 // Compute the centre of mass of the cell population
900 c_vector<double,SPACE_DIM> centre = GetCentroidOfCellPopulation();
901
902 // Loop over cells and find the maximum distance from the centre of mass in each dimension
903 c_vector<double,SPACE_DIM> max_distance_from_centre = zero_vector<double>(SPACE_DIM);
904 for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter = this->Begin();
905 cell_iter != this->End();
906 ++cell_iter)
907 {
908 c_vector<double,SPACE_DIM> cell_location = GetLocationOfCellCentre(*cell_iter);
909
910 // Note that we define this vector before setting it as otherwise the profiling build will break (see #2367)
911 c_vector<double,SPACE_DIM> displacement;
912 displacement = centre - cell_location;
913
914 for (unsigned i=0; i<SPACE_DIM; i++)
915 {
916 if (displacement[i] > max_distance_from_centre[i])
917 {
918 max_distance_from_centre[i] = displacement[i];
919 }
920 }
921 }
922
923 return max_distance_from_centre;
924}
925
926template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
927std::pair<unsigned,unsigned> AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>::CreateOrderedPair(unsigned index1, unsigned index2)
928{
929 assert(index1 != index2);
930
931 std::pair<unsigned, unsigned> ordered_pair;
932 if (index1 < index2)
933 {
934 ordered_pair.first = index1;
935 ordered_pair.second = index2;
937 else
938 {
939 ordered_pair.first = index2;
940 ordered_pair.second = index1;
941 }
942 return ordered_pair;
943}
944
945template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
947{
948 bool non_apoptotic_cell_present = false;
949
950 if (IsCellAttachedToLocationIndex(pdeNodeIndex))
951 {
952 non_apoptotic_cell_present = !(GetCellUsingLocationIndex(pdeNodeIndex)->template HasCellProperty<ApoptoticCellProperty>());
953 }
954
955 return non_apoptotic_cell_present;
956}
957
958
959// Explicit instantiation
960template class AbstractCellPopulation<1,1>;
961template class AbstractCellPopulation<1,2>;
962template class AbstractCellPopulation<2,2>;
963template class AbstractCellPopulation<1,3>;
964template class AbstractCellPopulation<2,3>;
965template 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()