Chaste  Release::3.4
AbstractCellBasedSimulation.cpp
1 /*
2 
3 Copyright (c) 2005-2016, University of Oxford.
4 All rights reserved.
5 
6 University of Oxford means the Chancellor, Masters and Scholars of the
7 University of Oxford, having an administrative office at Wellington
8 Square, Oxford OX1 2JD, UK.
9 
10 This file is part of Chaste.
11 
12 Redistribution and use in source and binary forms, with or without
13 modification, are permitted provided that the following conditions are met:
14  * Redistributions of source code must retain the above copyright notice,
15  this list of conditions and the following disclaimer.
16  * Redistributions in binary form must reproduce the above copyright notice,
17  this list of conditions and the following disclaimer in the documentation
18  and/or other materials provided with the distribution.
19  * Neither the name of the University of Oxford nor the names of its
20  contributors may be used to endorse or promote products derived from this
21  software without specific prior written permission.
22 
23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
29 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 
34 */
35 
36 #include <cmath>
37 #include <iostream>
38 #include <fstream>
39 #include <set>
40 
41 #include "AbstractCellBasedSimulation.hpp"
42 #include "CellBasedEventHandler.hpp"
43 #include "LogFile.hpp"
44 #include "Version.hpp"
45 #include "ExecutableSupport.hpp"
46 #include "Exception.hpp"
47 #include <typeinfo>
48 
49 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
51  bool deleteCellPopulationInDestructor,
52  bool initialiseCells)
53  : mDt(DOUBLE_UNSET),
54  mEndTime(DOUBLE_UNSET), // hours - this is set later on
55  mrCellPopulation(rCellPopulation),
56  mDeleteCellPopulationInDestructor(deleteCellPopulationInDestructor),
57  mInitialiseCells(initialiseCells),
58  mNoBirth(false),
59  mUpdateCellPopulation(true),
60  mOutputDirectory(""),
61  mSimulationOutputDirectory(mOutputDirectory),
62  mNumBirths(0),
63  mNumDeaths(0),
64  mOutputDivisionLocations(false),
65  mOutputCellVelocities(false),
66  mSamplingTimestepMultiple(1),
67  mpCellBasedPdeHandler(NULL)
68 {
69  // Set a random seed of 0 if it wasn't specified earlier
71 
72  if (mInitialiseCells)
73  {
74  mrCellPopulation.InitialiseCells();
75  }
76 }
77 
78 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
80 {
81  if (mDeleteCellPopulationInDestructor)
82  {
83  delete &mrCellPopulation;
84  delete mpCellBasedPdeHandler;
85  }
86 }
87 
88 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
90 {
91  mpCellBasedPdeHandler = pCellBasedPdeHandler;
92 }
93 
94 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
96 {
97  return mpCellBasedPdeHandler;
98 }
99 
100 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
102 {
103  if (mNoBirth)
104  {
105  return 0;
106  }
107 
108  unsigned num_births_this_step = 0;
109 
110  // Iterate over all cells, seeing if each one can be divided
111  for (typename AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>::Iterator cell_iter = mrCellPopulation.Begin();
112  cell_iter != mrCellPopulation.End();
113  ++cell_iter)
114  {
115  // Check if this cell is ready to divide
116  double cell_age = cell_iter->GetAge();
117  if (cell_age > 0.0)
118  {
119  if (cell_iter->ReadyToDivide())
120  {
121  // Check if there is room into which the cell may divide
122  if (mrCellPopulation.IsRoomToDivide(*cell_iter))
123  {
124  // Create a new cell
125  CellPtr p_new_cell = cell_iter->Divide();
126 
127  // Call method that determines how cell division occurs and returns a vector
128  c_vector<double, SPACE_DIM> new_location = CalculateCellDivisionVector(*cell_iter);
129 
130  // If required, output this location to file
147  if (mOutputDivisionLocations)
148  {
149  c_vector<double, SPACE_DIM> cell_location = mrCellPopulation.GetLocationOfCellCentre(*cell_iter);
150 
151  *mpDivisionLocationFile << SimulationTime::Instance()->GetTime() << "\t";
152  for (unsigned i=0; i<SPACE_DIM; i++)
153  {
154  *mpDivisionLocationFile << cell_location[i] << "\t";
155  }
156  *mpDivisionLocationFile << "\t" << cell_age << "\n";
157  }
158 
159  // Add new cell to the cell population
160  mrCellPopulation.AddCell(p_new_cell, new_location, *cell_iter);
161 
162  // Update counter
163  num_births_this_step++;
164  }
165  }
166  }
167  }
168  return num_births_this_step;
169 }
170 
171 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
173 {
174  unsigned num_deaths_this_step = 0;
175 
176  /*
177  * This labels cells as dead or apoptosing. It does not actually remove the cells,
178  * mrCellPopulation.RemoveDeadCells() needs to be called for this.
179  */
180  for (typename std::vector<boost::shared_ptr<AbstractCellKiller<SPACE_DIM> > >::iterator killer_iter = mCellKillers.begin();
181  killer_iter != mCellKillers.end();
182  ++killer_iter)
183  {
184  (*killer_iter)->CheckAndLabelCellsForApoptosisOrDeath();
185  }
186 
187  num_deaths_this_step += mrCellPopulation.RemoveDeadCells();
188 
189  return num_deaths_this_step;
190 }
191 
192 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
194 {
195  assert(dt > 0);
196  mDt = dt;
197 }
198 
199 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
201 {
202  return mDt;
203 }
204 
205 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
207 {
208  return mNumBirths;
209 }
210 
211 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
213 {
214  return mNumDeaths;
215 }
216 
217 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
219 {
220  assert(endTime > 0);
221  mEndTime = endTime;
222 }
223 
224 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
226 {
227  mOutputDirectory = outputDirectory;
228  mSimulationOutputDirectory = mOutputDirectory;
229 }
230 
231 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
233 {
234  return mOutputDirectory;
235 }
236 
237 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
239 {
240  assert(samplingTimestepMultiple > 0);
241  mSamplingTimestepMultiple = samplingTimestepMultiple;
242 }
243 
244 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
246 {
247  return mrCellPopulation;
248 }
249 
250 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
252 {
253  return mrCellPopulation;
254 }
255 
256 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
258 {
259  mUpdateCellPopulation = updateCellPopulation;
260 }
261 
262 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
264 {
265  return mUpdateCellPopulation;
266 }
267 
268 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
270 {
271  mNoBirth = noBirth;
272 }
273 
274 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
276 {
277  mCellKillers.push_back(pCellKiller);
278 }
279 
280 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
282 {
283  mCellKillers.clear();
284 }
285 
286 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
288 {
289  mSimulationModifiers.push_back(pSimulationModifier);
290 }
291 
292 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
293 std::vector<boost::shared_ptr<AbstractCellBasedSimulationModifier<ELEMENT_DIM, SPACE_DIM> > >* AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::GetSimulationModifiers()
294 {
295  return &mSimulationModifiers;
296 }
297 
298 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
299 std::vector<double> AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::GetNodeLocation(const unsigned& rNodeIndex)
300 {
301  std::vector<double> location;
302  for (unsigned i=0; i<SPACE_DIM; i++)
303  {
304  location.push_back(mrCellPopulation.GetNode(rNodeIndex)->rGetLocation()[i]);
305  }
306  return location;
307 }
308 
309 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
311 {
312  CellBasedEventHandler::BeginEvent(CellBasedEventHandler::EVERYTHING);
313  CellBasedEventHandler::BeginEvent(CellBasedEventHandler::SETUP);
314 
315  // Set up the simulation time
316  SimulationTime* p_simulation_time = SimulationTime::Instance();
317  double current_time = p_simulation_time->GetTime();
318 
319  assert(mDt != DOUBLE_UNSET); //Subclass constructors take care of this
320 
321  if (mEndTime == DOUBLE_UNSET)
322  {
323  EXCEPTION("SetEndTime has not yet been called.");
324  }
325 
326  /*
327  * Note that mDt is used here for "ideal time step". If this step doesn't divide the time remaining
328  * then a *different* time step will be taken by the time-stepper. The real time-step (used in the
329  * SimulationTime singleton) is currently not available to this class.
330  *
331  * \todo Should we over-write the value of mDt, or change this behaviour? (see #2159)
332  */
333  unsigned num_time_steps = (unsigned) ((mEndTime-current_time)/mDt+0.5);
334  if (current_time > 0) // use the reset function if necessary
335  {
336  p_simulation_time->ResetEndTimeAndNumberOfTimeSteps(mEndTime, num_time_steps);
337  }
338  else
339  {
340  if (p_simulation_time->IsEndTimeAndNumberOfTimeStepsSetUp())
341  {
342  EXCEPTION("End time and number of timesteps already setup. You should not use SimulationTime::SetEndTimeAndNumberOfTimeSteps in cell-based tests.");
343  }
344  else
345  {
346  p_simulation_time->SetEndTimeAndNumberOfTimeSteps(mEndTime, num_time_steps);
347  }
348  }
349 
350  if (mOutputDirectory == "")
351  {
352  EXCEPTION("OutputDirectory not set");
353  }
354 
355  double time_now = p_simulation_time->GetTime();
356  std::ostringstream time_string;
357  time_string << time_now;
358 
359  std::string results_directory = mOutputDirectory +"/results_from_time_" + time_string.str();
360  mSimulationOutputDirectory = results_directory;
361 
362  // Set up simulation
363 
364  // Create output files for the visualizer
365  OutputFileHandler output_file_handler(results_directory+"/", true);
366 
367  mrCellPopulation.OpenWritersFiles(output_file_handler);
368 
369  if (mOutputDivisionLocations)
370  {
371  mpDivisionLocationFile = output_file_handler.OpenOutputFile("divisions.dat");
372  }
373  if (mOutputCellVelocities)
374  {
375  OutputFileHandler output_file_handler2(this->mSimulationOutputDirectory+"/", false);
376  mpCellVelocitiesFile = output_file_handler2.OpenOutputFile("cellvelocities.dat");
377  }
378 
379  if (PetscTools::AmMaster())
380  {
381  mpVizSetupFile = output_file_handler.OpenOutputFile("results.vizsetup");
382  }
383 
384  // If any PDEs have been defined, set up results files to store their solution
385  if (mpCellBasedPdeHandler != NULL)
386  {
387  mpCellBasedPdeHandler->OpenResultsFiles(this->mSimulationOutputDirectory);
388  if (PetscTools::AmMaster())
389  {
390  *this->mpVizSetupFile << "PDE \n";
391  }
392 
393  /*
394  * If any PDEs have been defined, solve them here before updating cells and store
395  * their solution in results files. This also initializes the relevant CellData.
396  * NOTE that this works as the PDEs are elliptic.
397  */
398  CellBasedEventHandler::BeginEvent(CellBasedEventHandler::PDE);
399  mpCellBasedPdeHandler->SolvePdeAndWriteResultsToFile(this->mSamplingTimestepMultiple);
400  CellBasedEventHandler::EndEvent(CellBasedEventHandler::PDE);
401  }
402 
403  SetupSolve();
404 
405  // Call SetupSolve() on each modifier
406  for (typename std::vector<boost::shared_ptr<AbstractCellBasedSimulationModifier<ELEMENT_DIM, SPACE_DIM> > >::iterator iter = mSimulationModifiers.begin();
407  iter != mSimulationModifiers.end();
408  ++iter)
409  {
410  (*iter)->SetupSolve(this->mrCellPopulation,this->mSimulationOutputDirectory);
411  }
412 
413  /*
414  * Age the cells to the correct time. Note that cells are created with
415  * negative birth times so that some are initially almost ready to divide.
416  */
417  LOG(1, "Setting up cells...");
418  for (typename AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>::Iterator cell_iter = mrCellPopulation.Begin();
419  cell_iter != mrCellPopulation.End();
420  ++cell_iter)
421  {
422  /*
423  * We don't use the result; this call is just to force the cells to age
424  * to the current time running their cell-cycle models to get there.
425  */
426  cell_iter->ReadyToDivide();
427  }
428  LOG(1, "\tdone\n");
429 
430  // Write initial conditions to file for the visualizer
431  WriteVisualizerSetupFile();
432 
433  if (PetscTools::AmMaster())
434  {
435  *mpVizSetupFile << std::flush;
436  }
437 
438  mrCellPopulation.WriteResultsToFiles(results_directory+"/");
439 
440  OutputSimulationSetup();
441  CellBasedEventHandler::EndEvent(CellBasedEventHandler::SETUP);
442 
443  // Enter main time loop
444  while (!( p_simulation_time->IsFinished() || StoppingEventHasOccurred() ) )
445  {
446  LOG(1, "--TIME = " << p_simulation_time->GetTime() << "\n");
447 
448  // This function calls DoCellRemoval(), DoCellBirth() and CellPopulation::Update()
449  UpdateCellPopulation();
450 
451  // Store whether we are sampling results at the current timestep
453  bool at_sampling_timestep = (p_time->GetTimeStepsElapsed()%this->mSamplingTimestepMultiple == 0);
454 
455  /*
456  * If required, store the current locations of cell centres. Note that we need to
457  * use a std::map between cells and locations, rather than (say) a std::vector with
458  * location indices corresponding to cells, since once we call UpdateCellLocations()
459  * the location index of each cell may change. This is especially true in the case
460  * of a CaBasedCellPopulation.
461  */
462  std::map<CellPtr, c_vector<double, SPACE_DIM> > old_cell_locations;
463  if (mOutputCellVelocities && at_sampling_timestep)
464  {
465  for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter = mrCellPopulation.Begin();
466  cell_iter != mrCellPopulation.End();
467  ++cell_iter)
468  {
469  old_cell_locations[*cell_iter] = mrCellPopulation.GetLocationOfCellCentre(*cell_iter);
470  }
471  }
472 
473  // Update cell locations and topology
474  UpdateCellLocationsAndTopology();
475 
476  // Now write cell velocities to file if required
477  if (mOutputCellVelocities && at_sampling_timestep)
478  {
479  // Offset as doing this before we increase time by mDt
480  *mpCellVelocitiesFile << p_time->GetTime() + mDt<< "\t";
481 
482  for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter = mrCellPopulation.Begin();
483  cell_iter != mrCellPopulation.End();
484  ++cell_iter)
485  {
486  unsigned index = mrCellPopulation.GetLocationIndexUsingCell(*cell_iter);
487  const c_vector<double,SPACE_DIM>& position = mrCellPopulation.GetLocationOfCellCentre(*cell_iter);
488 
489  c_vector<double, SPACE_DIM> velocity; // Two lines for profile build
490  velocity = (position - old_cell_locations[*cell_iter])/mDt;
491 
492  *mpCellVelocitiesFile << index << " ";
493  for (unsigned i=0; i<SPACE_DIM; i++)
494  {
495  *mpCellVelocitiesFile << position[i] << " ";
496  }
497 
498  for (unsigned i=0; i<SPACE_DIM; i++)
499  {
500  *mpCellVelocitiesFile << velocity[i] << " ";
501  }
502  }
503  *mpCellVelocitiesFile << "\n";
504  }
505 
506  // Update the assignment of cells to processes.
507  mrCellPopulation.UpdateCellProcessLocation();
508 
509  // Increment simulation time here, so results files look sensible
510  p_simulation_time->IncrementTimeOneStep();
511 
512  // If any PDEs have been defined, solve them and store their solution in results files
513  if (mpCellBasedPdeHandler != NULL)
514  {
515  CellBasedEventHandler::BeginEvent(CellBasedEventHandler::PDE);
516  mpCellBasedPdeHandler->SolvePdeAndWriteResultsToFile(this->mSamplingTimestepMultiple);
517  CellBasedEventHandler::EndEvent(CellBasedEventHandler::PDE);
518  }
519 
520  // Call UpdateAtEndOfTimeStep() on each modifier
521  CellBasedEventHandler::BeginEvent(CellBasedEventHandler::UPDATESIMULATION);
522  for (typename std::vector<boost::shared_ptr<AbstractCellBasedSimulationModifier<ELEMENT_DIM, SPACE_DIM> > >::iterator iter = mSimulationModifiers.begin();
523  iter != mSimulationModifiers.end();
524  ++iter)
525  {
526  (*iter)->UpdateAtEndOfTimeStep(this->mrCellPopulation);
527  }
528  CellBasedEventHandler::EndEvent(CellBasedEventHandler::UPDATESIMULATION);
529 
530  // Output current results to file
531  CellBasedEventHandler::BeginEvent(CellBasedEventHandler::OUTPUT);
532  if (p_simulation_time->GetTimeStepsElapsed()%mSamplingTimestepMultiple == 0)// should be at_sampling_timestep !
533  {
534  mrCellPopulation.WriteResultsToFiles(results_directory+"/");
535 
536  // Call UpdateAtEndOfOutputTimeStep() on each modifier
537  for (typename std::vector<boost::shared_ptr<AbstractCellBasedSimulationModifier<ELEMENT_DIM, SPACE_DIM> > >::iterator iter = mSimulationModifiers.begin();
538  iter != mSimulationModifiers.end();
539  ++iter)
540  {
541  (*iter)->UpdateAtEndOfOutputTimeStep(this->mrCellPopulation);
542  }
543  }
544  CellBasedEventHandler::EndEvent(CellBasedEventHandler::OUTPUT);
545  }
546 
547  LOG(1, "--END TIME = " << p_simulation_time->GetTime() << "\n");
548 
549  /*
550  * Carry out a final update so that cell population is coherent with new cell positions.
551  * Note that cell birth and death still need to be checked because they may be spatially
552  * dependent.
553  */
554  UpdateCellPopulation();
555 
556  // If any PDEs have been defined, close the results files storing their solution
557  if (mpCellBasedPdeHandler != NULL)
558  {
559  mpCellBasedPdeHandler->CloseResultsFiles();
560  }
561 
562  CellBasedEventHandler::BeginEvent(CellBasedEventHandler::UPDATESIMULATION);
563  // Call UpdateAtEndOfSolve(), on each modifier
564  for (typename std::vector<boost::shared_ptr<AbstractCellBasedSimulationModifier<ELEMENT_DIM, SPACE_DIM> > >::iterator iter = mSimulationModifiers.begin();
565  iter != mSimulationModifiers.end();
566  ++iter)
567  {
568  (*iter)->UpdateAtEndOfSolve(this->mrCellPopulation);
569  }
570  CellBasedEventHandler::EndEvent(CellBasedEventHandler::UPDATESIMULATION);
571 
572  CellBasedEventHandler::BeginEvent(CellBasedEventHandler::OUTPUT);
573 
574  mrCellPopulation.CloseWritersFiles();
575 
576  if (mOutputDivisionLocations)
577  {
578  mpDivisionLocationFile->close();
579  }
580  if (mOutputCellVelocities)
581  {
582  mpCellVelocitiesFile->close();
583  }
584 
585  if (PetscTools::AmMaster())
586  {
587  *mpVizSetupFile << "Complete\n";
588  mpVizSetupFile->close();
589  }
590 
591  CellBasedEventHandler::EndEvent(CellBasedEventHandler::OUTPUT);
592  CellBasedEventHandler::EndEvent(CellBasedEventHandler::EVERYTHING);
593 }
594 
595 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
597 {
598  return false;
599 }
600 
601 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
603 {
604  // Remove dead cells
605  CellBasedEventHandler::BeginEvent(CellBasedEventHandler::DEATH);
606  unsigned deaths_this_step = DoCellRemoval();
607  mNumDeaths += deaths_this_step;
608  LOG(1, "\tNum deaths = " << mNumDeaths << "\n");
609  CellBasedEventHandler::EndEvent(CellBasedEventHandler::DEATH);
610 
611  // Divide cells
612  CellBasedEventHandler::BeginEvent(CellBasedEventHandler::BIRTH);
613  unsigned births_this_step = DoCellBirth();
614  mNumBirths += births_this_step;
615  LOG(1, "\tNum births = " << mNumBirths << "\n");
616  CellBasedEventHandler::EndEvent(CellBasedEventHandler::BIRTH);
617 
618  // This allows NodeBasedCellPopulation::Update() to do the minimum amount of work
619  bool births_or_death_occurred = ((births_this_step>0) || (deaths_this_step>0));
620 
621  // Update topology of cell population
622  CellBasedEventHandler::BeginEvent(CellBasedEventHandler::UPDATECELLPOPULATION);
623  if (mUpdateCellPopulation)
624  {
625  LOG(1, "\tUpdating cell population...");
626  mrCellPopulation.Update(births_or_death_occurred);
627  LOG(1, "\tdone.\n");
628  }
629  else if (births_or_death_occurred)
630  {
631  EXCEPTION("CellPopulation has had births or deaths but mUpdateCellPopulation is set to false, please set it to true.");
632  }
633  CellBasedEventHandler::EndEvent(CellBasedEventHandler::UPDATECELLPOPULATION);
634 }
635 
636 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
638 {
639  return mOutputDivisionLocations;
640 }
641 
642 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
644 {
645  mOutputDivisionLocations = outputDivisionLocations;
646 }
647 
648 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
650 {
651  return mOutputCellVelocities;
652 }
653 
654 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
656 {
657  mOutputCellVelocities = outputCellVelocities;
658 }
659 
660 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
662 {
663  OutputFileHandler output_file_handler(this->mSimulationOutputDirectory + "/", false);
664 
665  // Output machine information
668 
669  if (PetscTools::AmMaster())
670  {
671  // Output Chaste provenance information
672  out_stream build_info_file = output_file_handler.OpenOutputFile("build.info");
673  std::string build_info;
675  *build_info_file << build_info;
676  build_info_file->close();
677 
678  // Output simulation parameter and setup details
679  out_stream parameter_file = output_file_handler.OpenOutputFile("results.parameters");
680 
681  // Output simulation details
682  std::string simulation_type = GetIdentifier();
683 
684  *parameter_file << "<Chaste>\n";
685  *parameter_file << "\n\t<" << simulation_type << ">\n";
686  OutputSimulationParameters(parameter_file);
687  *parameter_file << "\t</" << simulation_type << ">\n";
688  *parameter_file << "\n";
689 
690  // Output cell population details (includes cell-cycle model details)
691  mrCellPopulation.OutputCellPopulationInfo(parameter_file);
692 
693  // Loop over cell killers
694  *parameter_file << "\n\t<CellKillers>\n";
695  for (typename std::vector<boost::shared_ptr<AbstractCellKiller<SPACE_DIM> > >::iterator iter = mCellKillers.begin();
696  iter != mCellKillers.end();
697  ++iter)
698  {
699  // Output cell killer details
700  (*iter)->OutputCellKillerInfo(parameter_file);
701  }
702  *parameter_file << "\t</CellKillers>\n";
703 
704  // Iterate over simulationmodifiers
705  *parameter_file << "\n\t<SimulationModifiers>\n";
706  for (typename std::vector<boost::shared_ptr<AbstractCellBasedSimulationModifier<ELEMENT_DIM, SPACE_DIM> > >::iterator iter = mSimulationModifiers.begin();
707  iter != mSimulationModifiers.end();
708  ++iter)
709  {
710  // Output simulation modifier details
711  (*iter)->OutputSimulationModifierInfo(parameter_file);
712  }
713  *parameter_file << "\t</SimulationModifiers>\n";
714 
715  // This is used to output information about subclasses
716  OutputAdditionalSimulationSetup(parameter_file);
717 
718  *parameter_file << "\n</Chaste>\n";
719  parameter_file->close();
720  }
721 }
722 
723 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
725 {
726  if (mpCellBasedPdeHandler != NULL)
727  {
728  mpCellBasedPdeHandler->OutputParameters(rParamsFile);
729  }
730 
731  *rParamsFile << "\t\t<Dt>" << mDt << "</Dt>\n";
732  *rParamsFile << "\t\t<EndTime>" << mEndTime << "</EndTime>\n";
733  *rParamsFile << "\t\t<SamplingTimestepMultiple>" << mSamplingTimestepMultiple << "</SamplingTimestepMultiple>\n";
734  *rParamsFile << "\t\t<OutputDivisionLocations>" << mOutputDivisionLocations << "</OutputDivisionLocations>\n";
735  *rParamsFile << "\t\t<OutputCellVelocities>" << mOutputCellVelocities << "</OutputCellVelocities>\n";
736 }
737 
739 
740 template class AbstractCellBasedSimulation<1,1>;
741 template class AbstractCellBasedSimulation<1,2>;
742 template class AbstractCellBasedSimulation<2,2>;
743 template class AbstractCellBasedSimulation<1,3>;
744 template class AbstractCellBasedSimulation<2,3>;
745 template class AbstractCellBasedSimulation<3,3>;
CellBasedPdeHandler< SPACE_DIM > * GetCellBasedPdeHandler()
void AddCellKiller(boost::shared_ptr< AbstractCellKiller< SPACE_DIM > > pCellKiller)
bool IsEndTimeAndNumberOfTimeStepsSetUp() const
#define EXCEPTION(message)
Definition: Exception.hpp:143
static SimulationTime * Instance()
bool IsFinished() const
AbstractCellBasedSimulation(AbstractCellPopulation< ELEMENT_DIM, SPACE_DIM > &rCellPopulation, bool deleteCellPopulationInDestructor=false, bool initialiseCells=true)
static bool AmMaster()
Definition: PetscTools.cpp:120
AbstractCellPopulation< ELEMENT_DIM, SPACE_DIM > & rGetCellPopulation()
unsigned GetTimeStepsElapsed() const
void SetOutputCellVelocities(bool outputCellVelocities)
std::string GetOutputDirectoryFullPath() const
const double DOUBLE_UNSET
Definition: Exception.hpp:56
void SetUpdateCellPopulationRule(bool updateCellPopulation)
out_stream OpenOutputFile(const std::string &rFileName, std::ios_base::openmode mode=std::ios::out|std::ios::trunc) const
void SetOutputDivisionLocations(bool outputDivisionLocations)
virtual void OutputSimulationParameters(out_stream &rParamsFile)=0
void SetOutputDirectory(std::string outputDirectory)
void SetEndTimeAndNumberOfTimeSteps(double endTime, unsigned totalTimeStepsInSimulation)
static RandomNumberGenerator * Instance()
double GetTime() const
std::vector< double > GetNodeLocation(const unsigned &rNodeIndex)
void AddSimulationModifier(boost::shared_ptr< AbstractCellBasedSimulationModifier< ELEMENT_DIM, SPACE_DIM > > pSimulationModifier)
static void GetBuildInfo(std::string &rInfo)
void IncrementTimeOneStep()
static void WriteMachineInfoFile(std::string fileBaseName)
std::vector< boost::shared_ptr< AbstractCellBasedSimulationModifier< ELEMENT_DIM, SPACE_DIM > > > * GetSimulationModifiers()
void ResetEndTimeAndNumberOfTimeSteps(const double &rEndTime, const unsigned &rNumberOfTimeStepsInThisRun)
static void SetOutputDirectory(const std::string &rOutputDirectory)
void SetCellBasedPdeHandler(CellBasedPdeHandler< SPACE_DIM > *pCellBasedPdeHandler)
void SetSamplingTimestepMultiple(unsigned samplingTimestepMultiple)
AbstractCellPopulation< ELEMENT_DIM, SPACE_DIM > & mrCellPopulation