Chaste Commit::f2ff7ee04e70ac9d06c57344df8d017dbb12b97b
AbstractCellBasedSimulation.cpp
1/*
2
3Copyright (c) 2005-2024, 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 <cmath>
37#include <iostream>
38#include <fstream>
39#include <set>
40#include "AbstractCellBasedSimulation.hpp"
41#include "CellBasedEventHandler.hpp"
42#include "LogFile.hpp"
43#include "ExecutableSupport.hpp"
44#include "AbstractPdeModifier.hpp"
45#include "CellDivisionLocationsWriter.hpp"
46#include "CellRemovalLocationsWriter.hpp"
47
48template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
50 bool deleteCellPopulationInDestructor,
51 bool initialiseCells)
52 : mDt(DOUBLE_UNSET),
53 mEndTime(DOUBLE_UNSET), // hours - this is set later on
54 mrCellPopulation(rCellPopulation),
55 mDeleteCellPopulationInDestructor(deleteCellPopulationInDestructor),
56 mInitialiseCells(initialiseCells),
57 mNoBirth(false),
58 mUpdateCellPopulation(true),
59 mOutputDirectory(""),
60 mSimulationOutputDirectory(mOutputDirectory),
61 mNumBirths(0),
62 mNumDeaths(0),
63 mOutputDivisionLocations(false),
64 mOutputCellVelocities(false),
65 mSamplingTimestepMultiple(1),
66 mUpdatingTimestepMultiple(1)
67{
68 // Set a random seed of 0 if it wasn't specified earlier
70
72 {
73 mrCellPopulation.InitialiseCells();
74 }
75
76 /*
77 * Specify a default time step to use, which may depend on the cell population type.
78 * Note that the time step may be reset using SetDt().
79 */
80 mDt = rCellPopulation.GetDefaultTimeStep();
81}
82
83template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
85{
86 if (mDeleteCellPopulationInDestructor)
87 {
88 delete &mrCellPopulation;
89 }
90}
91
92template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
94{
95 if (mNoBirth)
96 {
97 return 0;
98 }
99
100 unsigned num_births_this_step = 0;
101
102 // Iterate over all cells, seeing if each one can be divided
103 for (typename AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>::Iterator cell_iter = mrCellPopulation.Begin();
104 cell_iter != mrCellPopulation.End();
105 ++cell_iter)
106 {
107 // Check if this cell is ready to divide
108 double cell_age = cell_iter->GetAge();
109 if (cell_age > 0.0)
110 {
111 if (cell_iter->ReadyToDivide())
112 {
113 // Check if there is room into which the cell may divide
114 if (mrCellPopulation.IsRoomToDivide(*cell_iter))
115 {
116 // Store parent ID for output if required
117 unsigned parent_cell_id = cell_iter->GetCellId();
118
119 // Create a new cell
120 CellPtr p_new_cell = cell_iter->Divide();
121
128 if (mrCellPopulation.template HasWriter<CellDivisionLocationsWriter>())
129 {
130 c_vector<double, SPACE_DIM> cell_location = mrCellPopulation.GetLocationOfCellCentre(*cell_iter);
131
132 std::stringstream division_info;
133 division_info << SimulationTime::Instance()->GetTime() << "\t";
134 for (unsigned i = 0; i < SPACE_DIM; i++)
135 {
136 division_info << cell_location[i] << "\t";
137 }
138 division_info << "\t" << cell_age << "\t" << parent_cell_id << "\t" << cell_iter->GetCellId() << "\t" << p_new_cell->GetCellId() << "\t";
139
140 mrCellPopulation.AddDivisionInformation(division_info.str());
141 }
142
143 // Add the new cell to the cell population
144 mrCellPopulation.AddCell(p_new_cell, *cell_iter);
145
146 // Update counter
147 num_births_this_step++;
148 }
149 }
150 }
151 }
152 return num_births_this_step;
153}
154
155template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
157{
158 unsigned num_deaths_this_step = 0;
159
160 /*
161 * This labels cells as dead or apoptosing. It does not actually remove the cells,
162 * mrCellPopulation.RemoveDeadCells() needs to be called for this.
163 */
164 for (typename std::vector<boost::shared_ptr<AbstractCellKiller<SPACE_DIM> > >::iterator killer_iter = mCellKillers.begin();
165 killer_iter != mCellKillers.end();
166 ++killer_iter)
167 {
168 (*killer_iter)->CheckAndLabelCellsForApoptosisOrDeath();
169 }
170
171 num_deaths_this_step += mrCellPopulation.RemoveDeadCells();
172
173 return num_deaths_this_step;
174}
175
176template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
178{
179 assert(dt > 0);
180 mDt = dt;
181}
182
183template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
188
189template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
194
195template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
200
201template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
203{
204 assert(endTime > 0);
205 mEndTime = endTime;
206}
207
208template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
210{
211 mOutputDirectory = outputDirectory;
212 mSimulationOutputDirectory = mOutputDirectory;
213}
214
215template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
220
221template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
223{
224 assert(samplingTimestepMultiple > 0);
225 mSamplingTimestepMultiple = samplingTimestepMultiple;
226}
227
228template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
230{
231 assert(updatingTimestepMultiple > 0);
232 mUpdatingTimestepMultiple = updatingTimestepMultiple;
233}
235template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
240
241template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
246
247template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
249{
250 mUpdateCellPopulation = updateCellPopulation;
251}
252
253template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
258
259template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
261{
262 mNoBirth = noBirth;
263}
264
265template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
267{
268 mCellKillers.push_back(pCellKiller);
269}
270
271template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
276
277template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
279{
280 mSimulationModifiers.push_back(pSimulationModifier);
281}
283template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
284std::vector<boost::shared_ptr<AbstractCellBasedSimulationModifier<ELEMENT_DIM, SPACE_DIM> > >* AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::GetSimulationModifiers()
285{
286 return &mSimulationModifiers;
287}
288
289template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
292 mTopologyUpdateSimulationModifiers.push_back(pSimulationModifier);
293}
294
295template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
296std::vector<boost::shared_ptr<AbstractCellBasedSimulationModifier<ELEMENT_DIM, SPACE_DIM> > >* AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::GetTopologyUpdateSimulationModifiers()
297{
298 return &mTopologyUpdateSimulationModifiers;
300
301template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
302std::vector<double> AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::GetNodeLocation(const unsigned& rNodeIndex)
303{
304 std::vector<double> location;
305 for (unsigned i=0; i<SPACE_DIM; i++)
306 {
307 location.push_back(mrCellPopulation.GetNode(rNodeIndex)->rGetLocation()[i]);
308 }
309 return location;
310}
311
312template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
315 CellBasedEventHandler::BeginEvent(CellBasedEventHandler::EVERYTHING);
316 CellBasedEventHandler::BeginEvent(CellBasedEventHandler::SETUP);
317
318 // Set up the simulation time
320 double current_time = p_simulation_time->GetTime();
321
322 assert(mDt != DOUBLE_UNSET); //Subclass constructors take care of this
323
324 if (mEndTime == DOUBLE_UNSET)
325 {
326 EXCEPTION("SetEndTime has not yet been called.");
327 }
328
329 /*
330 * Note that mDt is used here for "ideal time step". If this step doesn't divide the time remaining
331 * then a *different* time step will be taken by the time-stepper. The real time-step (used in the
332 * SimulationTime singleton) is currently not available to this class.
334 * \todo Should we over-write the value of mDt, or change this behaviour? (see #2159)
335 */
336 unsigned num_time_steps = (unsigned) ((mEndTime-current_time)/mDt+0.5);
337 if (current_time > 0) // use the reset function if necessary
338 {
339 p_simulation_time->ResetEndTimeAndNumberOfTimeSteps(mEndTime, num_time_steps);
341 else
342 {
343 if (p_simulation_time->IsEndTimeAndNumberOfTimeStepsSetUp())
344 {
345 EXCEPTION("End time and number of timesteps already setup. You should not use SimulationTime::SetEndTimeAndNumberOfTimeSteps in cell-based tests.");
346 }
347 else
349 p_simulation_time->SetEndTimeAndNumberOfTimeSteps(mEndTime, num_time_steps);
350 }
351 }
352
353 if (mOutputDirectory == "")
354 {
355 EXCEPTION("OutputDirectory not set");
357
358 double time_now = p_simulation_time->GetTime();
359 std::ostringstream time_string;
360 time_string << time_now;
361
362 std::string results_directory = mOutputDirectory +"/results_from_time_" + time_string.str();
363 mSimulationOutputDirectory = results_directory;
364
365 // Set up simulation
366
367 // Create output files for the visualizer
368 OutputFileHandler output_file_handler(results_directory + "/", true);
369
370 if (mOutputDivisionLocations)
371 {
372 mrCellPopulation.template AddCellPopulationEventWriter<CellDivisionLocationsWriter>();
373 mrCellPopulation.template AddCellPopulationEventWriter<CellRemovalLocationsWriter>();
374 }
375 if (mOutputCellVelocities)
376 {
377 OutputFileHandler output_file_handler2(this->mSimulationOutputDirectory + "/", false);
378 mpCellVelocitiesFile = output_file_handler2.OpenOutputFile("cellvelocities.dat");
379 }
380
381 mrCellPopulation.OpenWritersFiles(output_file_handler);
382
385 mpVizSetupFile = output_file_handler.OpenOutputFile("results.vizsetup");
386
387 for (typename std::vector<boost::shared_ptr<AbstractCellBasedSimulationModifier<ELEMENT_DIM, SPACE_DIM> > >::iterator iter = mSimulationModifiers.begin();
388 iter != mSimulationModifiers.end();
389 ++iter)
390 {
391 if (boost::dynamic_pointer_cast<AbstractPdeModifier<SPACE_DIM> >(*iter))
392 {
393 *this->mpVizSetupFile << "PDE \n";
394 }
395 }
397
398 this->mrCellPopulation.SimulationSetupHook(this);
399
400 SetupSolve();
402 // Call SetupSolve() on each modifier
403 for (typename std::vector<boost::shared_ptr<AbstractCellBasedSimulationModifier<ELEMENT_DIM, SPACE_DIM> > >::iterator iter = mSimulationModifiers.begin();
404 iter != mSimulationModifiers.end();
405 ++iter)
406 {
407 (*iter)->SetupSolve(this->mrCellPopulation,this->mSimulationOutputDirectory);
408 }
410 // Call SetupSolve() on each topology update modifier
411 for (typename std::vector<boost::shared_ptr<AbstractCellBasedSimulationModifier<ELEMENT_DIM, SPACE_DIM> > >::iterator iter = mTopologyUpdateSimulationModifiers.begin();
412 iter != mTopologyUpdateSimulationModifiers.end();
413 ++iter)
415 (*iter)->SetupSolve(this->mrCellPopulation,this->mSimulationOutputDirectory);
416 }
417
418 /*
419 * Age the cells to the correct time. Note that cells are created with
420 * negative birth times so that some are initially almost ready to divide.
421 */
422 LOG(1, "Setting up cells...");
423 for (typename AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>::Iterator cell_iter = mrCellPopulation.Begin();
424 cell_iter != mrCellPopulation.End();
425 ++cell_iter)
426 {
427 /*
428 * We don't use the result; this call is just to force the cells to age
429 * to the current time running their cell-cycle models to get there.
430 */
431 cell_iter->ReadyToDivide();
432 }
433 LOG(1, "\tdone\n");
434
435 // Write initial conditions to file for the visualizer
436 WriteVisualizerSetupFile();
437
439 {
440 *mpVizSetupFile << std::flush;
441 }
442
443 mrCellPopulation.WriteResultsToFiles(results_directory+"/");
444
445 OutputSimulationSetup();
446 CellBasedEventHandler::EndEvent(CellBasedEventHandler::SETUP);
447
448 // Enter main time loop
449 while (!( p_simulation_time->IsFinished() || StoppingEventHasOccurred() ) )
450 {
451 LOG(1, "--TIME = " << p_simulation_time->GetTime() << "\n");
452
453
454 if (p_simulation_time->GetTimeStepsElapsed()%mUpdatingTimestepMultiple == 0)
455 {
456 // This function calls DoCellRemoval(), DoCellBirth() and CellPopulation::Update()
457 UpdateCellPopulation();
458 }
459
460 // Store whether we are sampling results at the current timestep
462 bool at_sampling_timestep = (p_time->GetTimeStepsElapsed()%this->mSamplingTimestepMultiple == 0);
463
464 /*
465 * If required, store the current locations of cell centres. Note that we need to
466 * use a std::map between cells and locations, rather than (say) a std::vector with
467 * location indices corresponding to cells, since once we call UpdateCellLocations()
468 * the location index of each cell may change. This is especially true in the case
469 * of a CaBasedCellPopulation.
470 */
471 std::map<CellPtr, c_vector<double, SPACE_DIM> > old_cell_locations;
472 if (mOutputCellVelocities && at_sampling_timestep)
473 {
474 for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter = mrCellPopulation.Begin();
475 cell_iter != mrCellPopulation.End();
476 ++cell_iter)
477 {
478 old_cell_locations[*cell_iter] = mrCellPopulation.GetLocationOfCellCentre(*cell_iter);
479 }
481
482 /* Call UpdateAtEndOfTimeStep() on each topology update modifier */
483 CellBasedEventHandler::BeginEvent(CellBasedEventHandler::UPDATESIMULATION);
484 for (typename std::vector<boost::shared_ptr<AbstractCellBasedSimulationModifier<ELEMENT_DIM, SPACE_DIM> > >::iterator iter = mTopologyUpdateSimulationModifiers.begin();
485 iter != mTopologyUpdateSimulationModifiers.end();
486 ++iter)
487 {
488 (*iter)->UpdateAtEndOfTimeStep(this->mrCellPopulation);
489 }
490 CellBasedEventHandler::EndEvent(CellBasedEventHandler::UPDATESIMULATION);
491
492 // Update cell locations and topology
493 UpdateCellLocationsAndTopology();
494
495 // Now write cell velocities to file if required
496 if (mOutputCellVelocities && at_sampling_timestep)
498 // Offset as doing this before we increase time by mDt
499 *mpCellVelocitiesFile << p_time->GetTime() + mDt<< "\t";
500
501 for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter = mrCellPopulation.Begin();
502 cell_iter != mrCellPopulation.End();
503 ++cell_iter)
505 unsigned index = mrCellPopulation.GetLocationIndexUsingCell(*cell_iter);
506 const c_vector<double,SPACE_DIM>& position = mrCellPopulation.GetLocationOfCellCentre(*cell_iter);
507
508 c_vector<double, SPACE_DIM> velocity; // Two lines for profile build
509 velocity = (position - old_cell_locations[*cell_iter])/mDt;
510
511 *mpCellVelocitiesFile << index << " ";
512 for (unsigned i=0; i<SPACE_DIM; i++)
513 {
514 *mpCellVelocitiesFile << position[i] << " ";
515 }
516
517 for (unsigned i=0; i<SPACE_DIM; i++)
518 {
519 *mpCellVelocitiesFile << velocity[i] << " ";
520 }
521 }
522 *mpCellVelocitiesFile << "\n";
523 }
524
525 // Update the assignment of cells to processes.
526 mrCellPopulation.UpdateCellProcessLocation();
527
528 // Increment simulation time here, so results files look sensible
529 p_simulation_time->IncrementTimeOneStep();
530
531 /* Call UpdateAtEndOfTimeStep() on each modifier */
532 CellBasedEventHandler::BeginEvent(CellBasedEventHandler::UPDATESIMULATION);
533 for (typename std::vector<boost::shared_ptr<AbstractCellBasedSimulationModifier<ELEMENT_DIM, SPACE_DIM> > >::iterator iter = mSimulationModifiers.begin();
534 iter != mSimulationModifiers.end();
535 ++iter)
536 {
537 (*iter)->UpdateAtEndOfTimeStep(this->mrCellPopulation);
538 }
539 CellBasedEventHandler::EndEvent(CellBasedEventHandler::UPDATESIMULATION);
540
541 // Output current results to file
542 CellBasedEventHandler::BeginEvent(CellBasedEventHandler::OUTPUT);
543 if (p_simulation_time->GetTimeStepsElapsed()%mSamplingTimestepMultiple == 0)// should be at_sampling_timestep !
544 {
545 mrCellPopulation.WriteResultsToFiles(results_directory+"/");
546
547 // Call UpdateAtEndOfOutputTimeStep() on each modifier
548 for (typename std::vector<boost::shared_ptr<AbstractCellBasedSimulationModifier<ELEMENT_DIM, SPACE_DIM> > >::iterator iter = mSimulationModifiers.begin();
549 iter != mSimulationModifiers.end();
550 ++iter)
551 {
552 (*iter)->UpdateAtEndOfOutputTimeStep(this->mrCellPopulation);
553 }
554 }
555 CellBasedEventHandler::EndEvent(CellBasedEventHandler::OUTPUT);
556 }
557
558 LOG(1, "--END TIME = " << p_simulation_time->GetTime() << "\n");
559
560 /*
561 * Carry out a final update so that cell population is coherent with new cell positions.
562 * Note that cell birth and death still need to be checked because they may be spatially
563 * dependent.
564 */
565 UpdateCellPopulation();
566
567 CellBasedEventHandler::BeginEvent(CellBasedEventHandler::UPDATESIMULATION);
568 // Call UpdateAtEndOfSolve(), on each modifier
569 for (typename std::vector<boost::shared_ptr<AbstractCellBasedSimulationModifier<ELEMENT_DIM, SPACE_DIM> > >::iterator iter = mSimulationModifiers.begin();
570 iter != mSimulationModifiers.end();
571 ++iter)
572 {
573 (*iter)->UpdateAtEndOfSolve(this->mrCellPopulation);
574 }
575 CellBasedEventHandler::EndEvent(CellBasedEventHandler::UPDATESIMULATION);
576
577 CellBasedEventHandler::BeginEvent(CellBasedEventHandler::OUTPUT);
578
579 mrCellPopulation.CloseWritersFiles();
580
581 if (mOutputCellVelocities)
582 {
583 mpCellVelocitiesFile->close();
584 }
585
587 {
588 *mpVizSetupFile << "Complete\n";
589 mpVizSetupFile->close();
590 }
591
592 CellBasedEventHandler::EndEvent(CellBasedEventHandler::OUTPUT);
593 CellBasedEventHandler::EndEvent(CellBasedEventHandler::EVERYTHING);
594}
595
596template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
601
602template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
604{
605 // Remove dead cells
606 CellBasedEventHandler::BeginEvent(CellBasedEventHandler::DEATH);
607 unsigned deaths_this_step = DoCellRemoval();
608 mNumDeaths += deaths_this_step;
609 LOG(1, "\tNum deaths = " << mNumDeaths << "\n");
610 CellBasedEventHandler::EndEvent(CellBasedEventHandler::DEATH);
611
612 // Divide cells
613 CellBasedEventHandler::BeginEvent(CellBasedEventHandler::BIRTH);
614 unsigned births_this_step = DoCellBirth();
615 mNumBirths += births_this_step;
616 LOG(1, "\tNum births = " << mNumBirths << "\n");
617 CellBasedEventHandler::EndEvent(CellBasedEventHandler::BIRTH);
618
619 // This allows NodeBasedCellPopulation::Update() to do the minimum amount of work
620 bool births_or_death_occurred = ((births_this_step>0) || (deaths_this_step>0));
621
622 // Update topology of cell population
623 CellBasedEventHandler::BeginEvent(CellBasedEventHandler::UPDATECELLPOPULATION);
625 if (mUpdateCellPopulation && (p_time->GetTimeStepsElapsed() % mUpdatingTimestepMultiple == 0) )
626 {
627 LOG(1, "\tUpdating cell population...");
628 mrCellPopulation.Update(births_or_death_occurred);
629 LOG(1, "\tdone.\n");
630 }
631 else if (births_or_death_occurred)
632 {
633 if (!mUpdateCellPopulation)
634 {
635 EXCEPTION("CellPopulation has had births or deaths but mUpdateCellPopulation is set to false, please set it to true.");
636 }
637 else if ((p_time->GetTimeStepsElapsed() % mUpdatingTimestepMultiple != 0))
638 {
639 EXCEPTION("CellPopulation has had births or deaths but you were on a non update step, make sure your cell cycle model and killer only operate on update steps.");
640 }
641 else
642 {
644 }
645 }
646 CellBasedEventHandler::EndEvent(CellBasedEventHandler::UPDATECELLPOPULATION);
647}
648
649template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
651{
652 return mOutputDivisionLocations;
653}
654
655template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
657{
658 mOutputDivisionLocations = outputDivisionLocations;
659}
660
661template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
666
667template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
669{
670 mOutputCellVelocities = outputCellVelocities;
671}
672
673template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
675{
676 OutputFileHandler output_file_handler(this->mSimulationOutputDirectory + "/", false);
677
678 // Output machine information
681
683 {
684 // Output Chaste provenance information
685 out_stream build_info_file = output_file_handler.OpenOutputFile("build.info");
686 std::string build_info;
688 *build_info_file << build_info;
689 build_info_file->close();
690
691 // Output simulation parameter and setup details
692 out_stream parameter_file = output_file_handler.OpenOutputFile("results.parameters");
693
694 // Output simulation details
695 std::string simulation_type = GetIdentifier();
696
697 *parameter_file << "<Chaste>\n";
698 *parameter_file << "\n\t<" << simulation_type << ">\n";
699 OutputSimulationParameters(parameter_file);
700 *parameter_file << "\t</" << simulation_type << ">\n";
701 *parameter_file << "\n";
702
703 // Output cell population details (includes cell-cycle model details)
704 mrCellPopulation.OutputCellPopulationInfo(parameter_file);
705
706 // Loop over cell killers
707 *parameter_file << "\n\t<CellKillers>\n";
708 for (typename std::vector<boost::shared_ptr<AbstractCellKiller<SPACE_DIM> > >::iterator iter = mCellKillers.begin();
709 iter != mCellKillers.end();
710 ++iter)
711 {
712 // Output cell killer details
713 (*iter)->OutputCellKillerInfo(parameter_file);
714 }
715 *parameter_file << "\t</CellKillers>\n";
716
717 // Iterate over simulationmodifiers
718 *parameter_file << "\n\t<SimulationModifiers>\n";
719 for (typename std::vector<boost::shared_ptr<AbstractCellBasedSimulationModifier<ELEMENT_DIM, SPACE_DIM> > >::iterator iter = mSimulationModifiers.begin();
720 iter != mSimulationModifiers.end();
721 ++iter)
722 {
723 // Output simulation modifier details
724 (*iter)->OutputSimulationModifierInfo(parameter_file);
725 }
726 *parameter_file << "\t</SimulationModifiers>\n";
727
728 // This is used to output information about subclasses
729 OutputAdditionalSimulationSetup(parameter_file);
730
731 *parameter_file << "\n</Chaste>\n";
732 parameter_file->close();
733 }
734}
735
736template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
738{
739 *rParamsFile << "\t\t<Dt>" << mDt << "</Dt>\n";
740 *rParamsFile << "\t\t<EndTime>" << mEndTime << "</EndTime>\n";
741 *rParamsFile << "\t\t<UpdateCellPopulation>" << mUpdateCellPopulation << "</UpdateCellPopulation>\n";
742 *rParamsFile << "\t\t<SamplingTimestepMultiple>" << mSamplingTimestepMultiple << "</SamplingTimestepMultiple>\n";
743 *rParamsFile << "\t\t<UpdatingTimestepMultiple>" << mUpdatingTimestepMultiple << "</UpdatingTimestepMultiple>\n";
744 *rParamsFile << "\t\t<OutputDivisionLocations>" << mOutputDivisionLocations << "</OutputDivisionLocations>\n";
745 *rParamsFile << "\t\t<OutputCellVelocities>" << mOutputCellVelocities << "</OutputCellVelocities>\n";
746}
747
748// Explicit instantiation
const double DOUBLE_UNSET
Definition Exception.hpp:57
#define EXCEPTION(message)
#define NEVER_REACHED
AbstractCellPopulation< ELEMENT_DIM, SPACE_DIM > & mrCellPopulation
void SetUpdateCellPopulationRule(bool updateCellPopulation)
void SetOutputCellVelocities(bool outputCellVelocities)
void SetUpdatingTimestepMultiple(unsigned updatingTimestepMultiple)
AbstractCellPopulation< ELEMENT_DIM, SPACE_DIM > & rGetCellPopulation()
std::vector< boost::shared_ptr< AbstractCellBasedSimulationModifier< ELEMENT_DIM, SPACE_DIM > > > * GetSimulationModifiers()
void AddSimulationModifier(boost::shared_ptr< AbstractCellBasedSimulationModifier< ELEMENT_DIM, SPACE_DIM > > pSimulationModifier)
void AddTopologyUpdateSimulationModifier(boost::shared_ptr< AbstractCellBasedSimulationModifier< ELEMENT_DIM, SPACE_DIM > > pSimulationModifier)
virtual void OutputSimulationParameters(out_stream &rParamsFile)=0
void SetOutputDirectory(std::string outputDirectory)
void AddCellKiller(boost::shared_ptr< AbstractCellKiller< SPACE_DIM > > pCellKiller)
std::vector< boost::shared_ptr< AbstractCellBasedSimulationModifier< ELEMENT_DIM, SPACE_DIM > > > * GetTopologyUpdateSimulationModifiers()
AbstractCellBasedSimulation(AbstractCellPopulation< ELEMENT_DIM, SPACE_DIM > &rCellPopulation, bool deleteCellPopulationInDestructor=false, bool initialiseCells=true)
std::vector< double > GetNodeLocation(const unsigned &rNodeIndex)
void SetSamplingTimestepMultiple(unsigned samplingTimestepMultiple)
void SetOutputDivisionLocations(bool outputDivisionLocations)
virtual double GetDefaultTimeStep()=0
static void SetOutputDirectory(const std::string &rOutputDirectory)
static void GetBuildInfo(std::string &rInfo)
static void WriteMachineInfoFile(std::string fileBaseName)
std::string GetOutputDirectoryFullPath() const
out_stream OpenOutputFile(const std::string &rFileName, std::ios_base::openmode mode=std::ios::out|std::ios::trunc) const
static bool AmMaster()
static RandomNumberGenerator * Instance()
bool IsFinished() const
double GetTime() const
void SetEndTimeAndNumberOfTimeSteps(double endTime, unsigned totalTimeStepsInSimulation)
bool IsEndTimeAndNumberOfTimeStepsSetUp() const
void IncrementTimeOneStep()
static SimulationTime * Instance()
void ResetEndTimeAndNumberOfTimeSteps(const double &rEndTime, const unsigned &rNumberOfTimeStepsInThisRun)
unsigned GetTimeStepsElapsed() const