AbstractCellBasedSimulation.cpp

00001 /*
00002 
00003 Copyright (c) 2005-2014, University of Oxford.
00004 All rights reserved.
00005 
00006 University of Oxford means the Chancellor, Masters and Scholars of the
00007 University of Oxford, having an administrative office at Wellington
00008 Square, Oxford OX1 2JD, UK.
00009 
00010 This file is part of Chaste.
00011 
00012 Redistribution and use in source and binary forms, with or without
00013 modification, are permitted provided that the following conditions are met:
00014  * Redistributions of source code must retain the above copyright notice,
00015    this list of conditions and the following disclaimer.
00016  * Redistributions in binary form must reproduce the above copyright notice,
00017    this list of conditions and the following disclaimer in the documentation
00018    and/or other materials provided with the distribution.
00019  * Neither the name of the University of Oxford nor the names of its
00020    contributors may be used to endorse or promote products derived from this
00021    software without specific prior written permission.
00022 
00023 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00024 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00025 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00026 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00027 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00028 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
00029 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00030 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
00032 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00033 
00034 */
00035 
00036 #include <cmath>
00037 #include <ctime>
00038 #include <iostream>
00039 #include <fstream>
00040 #include <set>
00041 
00042 #include "AbstractCellBasedSimulation.hpp"
00043 #include "CellBasedEventHandler.hpp"
00044 #include "LogFile.hpp"
00045 #include "Version.hpp"
00046 #include "ExecutableSupport.hpp"
00047 #include "Exception.hpp"
00048 #include <typeinfo>
00049 
00050 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00051 AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::AbstractCellBasedSimulation(AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>& rCellPopulation,
00052                                               bool deleteCellPopulationInDestructor,
00053                                               bool initialiseCells)
00054     : mDt(DOUBLE_UNSET),
00055       mEndTime(DOUBLE_UNSET),  // hours - this is set later on
00056       mrCellPopulation(rCellPopulation),
00057       mDeleteCellPopulationInDestructor(deleteCellPopulationInDestructor),
00058       mInitialiseCells(initialiseCells),
00059       mNoBirth(false),
00060       mUpdateCellPopulation(true),
00061       mOutputDirectory(""),
00062       mSimulationOutputDirectory(mOutputDirectory),
00063       mNumBirths(0),
00064       mNumDeaths(0),
00065       mOutputDivisionLocations(false),
00066       mOutputCellVelocities(false),
00067       mSamplingTimestepMultiple(1),
00068       mpCellBasedPdeHandler(NULL)
00069 {
00070     // Set a random seed of 0 if it wasn't specified earlier
00071     RandomNumberGenerator::Instance();
00072 
00073     if (mInitialiseCells)
00074     {
00075         mrCellPopulation.InitialiseCells();
00076     }
00077 }
00078 
00079 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00080 AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::~AbstractCellBasedSimulation()
00081 {
00082     if (mDeleteCellPopulationInDestructor)
00083     {
00084         delete &mrCellPopulation;
00085         delete mpCellBasedPdeHandler;
00086     }
00087 }
00088 
00089 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00090 void AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::SetCellBasedPdeHandler(CellBasedPdeHandler<SPACE_DIM>* pCellBasedPdeHandler)
00091 {
00092     mpCellBasedPdeHandler = pCellBasedPdeHandler;
00093 }
00094 
00095 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00096 CellBasedPdeHandler<SPACE_DIM>* AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::GetCellBasedPdeHandler()
00097 {
00098     return mpCellBasedPdeHandler;
00099 }
00100 
00101 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00102 unsigned AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::DoCellBirth()
00103 {
00104     if (mNoBirth)
00105     {
00106         return 0;
00107     }
00108 
00109     unsigned num_births_this_step = 0;
00110 
00111     // Iterate over all cells, seeing if each one can be divided
00112     for (typename AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>::Iterator cell_iter = mrCellPopulation.Begin();
00113          cell_iter != mrCellPopulation.End();
00114          ++cell_iter)
00115     {
00116         // Check if this cell is ready to divide
00117         double cell_age = cell_iter->GetAge();
00118         if (cell_age > 0.0)
00119         {
00120             if (cell_iter->ReadyToDivide())
00121             {
00122                 // Check if there is room into which the cell may divide
00123                 if (mrCellPopulation.IsRoomToDivide(*cell_iter))
00124                 {
00125                     // Create a new cell
00126                     CellPtr p_new_cell = cell_iter->Divide();
00127 
00128                     // Call method that determines how cell division occurs and returns a vector
00129                     c_vector<double, SPACE_DIM> new_location = CalculateCellDivisionVector(*cell_iter);
00130 
00131                     // If required, output this location to file
00148                     if (mOutputDivisionLocations)
00149                     {
00150                         c_vector<double, SPACE_DIM> cell_location = mrCellPopulation.GetLocationOfCellCentre(*cell_iter);
00151 
00152                         *mpDivisionLocationFile << SimulationTime::Instance()->GetTime() << "\t";
00153                         for (unsigned i=0; i<SPACE_DIM; i++)
00154                         {
00155                             *mpDivisionLocationFile << cell_location[i] << "\t";
00156                         }
00157                         *mpDivisionLocationFile << "\t" << cell_age << "\n";
00158                     }
00159 
00160                     // Add new cell to the cell population
00161                     mrCellPopulation.AddCell(p_new_cell, new_location, *cell_iter);
00162 
00163                     // Update counter
00164                     num_births_this_step++;
00165                 }
00166             }
00167         }
00168     }
00169     return num_births_this_step;
00170 }
00171 
00172 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00173 unsigned AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::DoCellRemoval()
00174 {
00175     unsigned num_deaths_this_step = 0;
00176 
00177     /*
00178      * This labels cells as dead or apoptosing. It does not actually remove the cells,
00179      * mrCellPopulation.RemoveDeadCells() needs to be called for this.
00180      */
00181     for (typename std::vector<boost::shared_ptr<AbstractCellKiller<SPACE_DIM> > >::iterator killer_iter = mCellKillers.begin();
00182          killer_iter != mCellKillers.end();
00183          ++killer_iter)
00184     {
00185         (*killer_iter)->CheckAndLabelCellsForApoptosisOrDeath();
00186     }
00187 
00188     num_deaths_this_step += mrCellPopulation.RemoveDeadCells();
00189 
00190     return num_deaths_this_step;
00191 }
00192 
00193 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00194 void AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::SetDt(double dt)
00195 {
00196     assert(dt > 0);
00197     mDt = dt;
00198 }
00199 
00200 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00201 double AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::GetDt()
00202 {
00203     return mDt;
00204 }
00205 
00206 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00207 unsigned AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::GetNumBirths()
00208 {
00209     return mNumBirths;
00210 }
00211 
00212 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00213 unsigned AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::GetNumDeaths()
00214 {
00215     return mNumDeaths;
00216 }
00217 
00218 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00219 void AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::SetEndTime(double endTime)
00220 {
00221     assert(endTime > 0);
00222     mEndTime = endTime;
00223 }
00224 
00225 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00226 void AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::SetOutputDirectory(std::string outputDirectory)
00227 {
00228     mOutputDirectory = outputDirectory;
00229     mSimulationOutputDirectory = mOutputDirectory;
00230 }
00231 
00232 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00233 std::string AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::GetOutputDirectory()
00234 {
00235     return mOutputDirectory;
00236 }
00237 
00238 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00239 void AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::SetSamplingTimestepMultiple(unsigned samplingTimestepMultiple)
00240 {
00241     assert(samplingTimestepMultiple > 0);
00242     mSamplingTimestepMultiple = samplingTimestepMultiple;
00243 }
00244 
00245 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00246 AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>& AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::rGetCellPopulation()
00247 {
00248     return mrCellPopulation;
00249 }
00250 
00251 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00252 const AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>& AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::rGetCellPopulation() const
00253 {
00254     return mrCellPopulation;
00255 }
00256 
00257 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00258 void AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::SetUpdateCellPopulationRule(bool updateCellPopulation)
00259 {
00260     mUpdateCellPopulation = updateCellPopulation;
00261 }
00262 
00263 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00264 bool AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::GetUpdateCellPopulationRule()
00265 {
00266     return mUpdateCellPopulation;
00267 }
00268 
00269 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00270 void AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::SetNoBirth(bool noBirth)
00271 {
00272     mNoBirth = noBirth;
00273 }
00274 
00275 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00276 void AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::AddCellKiller(boost::shared_ptr<AbstractCellKiller<SPACE_DIM> > pCellKiller)
00277 {
00278     mCellKillers.push_back(pCellKiller);
00279 }
00280 
00281 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00282 void AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::RemoveAllCellKillers()
00283 {
00284     mCellKillers.clear();
00285 }
00286 
00287 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00288 void AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::AddSimulationModifier(boost::shared_ptr<AbstractCellBasedSimulationModifier<ELEMENT_DIM,SPACE_DIM> > pSimulationModifier)
00289 {
00290     mSimulationModifiers.push_back(pSimulationModifier);
00291 }
00292 
00293 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00294 std::vector<double> AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::GetNodeLocation(const unsigned& rNodeIndex)
00295 {
00296     std::vector<double> location;
00297     for (unsigned i=0; i<SPACE_DIM; i++)
00298     {
00299         location.push_back(mrCellPopulation.GetNode(rNodeIndex)->rGetLocation()[i]);
00300     }
00301     return location;
00302 }
00303 
00304 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00305 void AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::Solve()
00306 {
00307     CellBasedEventHandler::BeginEvent(CellBasedEventHandler::EVERYTHING);
00308     CellBasedEventHandler::BeginEvent(CellBasedEventHandler::SETUP);
00309 
00310     // Set up the simulation time
00311     SimulationTime* p_simulation_time = SimulationTime::Instance();
00312     double current_time = p_simulation_time->GetTime();
00313 
00314     assert(mDt != DOUBLE_UNSET);  //Subclass constructors take care of this
00315 
00316     if (mEndTime == DOUBLE_UNSET)
00317     {
00318         EXCEPTION("SetEndTime has not yet been called.");
00319     }
00320 
00321     /*
00322      * Note that mDt is used here for "ideal time step". If this step doesn't divide the time remaining
00323      * then a *different* time step will be taken by the time-stepper. The real time-step (used in the
00324      * SimulationTime singleton) is currently not available to this class.
00325      *
00326      * \todo Should we over-write the value of mDt, or change this behaviour? (see #2159)
00327      */
00328     unsigned num_time_steps = (unsigned) ((mEndTime-current_time)/mDt+0.5);
00329     if (current_time > 0) // use the reset function if necessary
00330     {
00331         p_simulation_time->ResetEndTimeAndNumberOfTimeSteps(mEndTime, num_time_steps);
00332     }
00333     else
00334     {
00335         if (p_simulation_time->IsEndTimeAndNumberOfTimeStepsSetUp())
00336         {
00337             EXCEPTION("End time and number of timesteps already setup. You should not use SimulationTime::SetEndTimeAndNumberOfTimeSteps in cell-based tests.");
00338         }
00339         else
00340         {
00341             p_simulation_time->SetEndTimeAndNumberOfTimeSteps(mEndTime, num_time_steps);
00342         }
00343     }
00344 
00345     if (mOutputDirectory == "")
00346     {
00347         EXCEPTION("OutputDirectory not set");
00348     }
00349 
00350     double time_now = p_simulation_time->GetTime();
00351     std::ostringstream time_string;
00352     time_string << time_now;
00353 
00354     std::string results_directory = mOutputDirectory +"/results_from_time_" + time_string.str();
00355     mSimulationOutputDirectory = results_directory;
00356 
00357     // Set up simulation
00358 
00359     // Create output files for the visualizer
00360     OutputFileHandler output_file_handler(results_directory+"/", true);
00361 
00362     mrCellPopulation.OpenWritersFiles(results_directory+"/");
00363 
00364     if (mOutputDivisionLocations)
00365     {
00366         mpDivisionLocationFile = output_file_handler.OpenOutputFile("divisions.dat");
00367     }
00368     if (mOutputCellVelocities)
00369     {
00370         OutputFileHandler output_file_handler2(this->mSimulationOutputDirectory+"/", false);
00371         mpCellVelocitiesFile = output_file_handler2.OpenOutputFile("cellvelocities.dat");
00372     }
00373 
00374 
00375     if (PetscTools::AmMaster())
00376     {
00377         mpVizSetupFile = output_file_handler.OpenOutputFile("results.vizsetup");
00378     }
00379 
00380     // If any PDEs have been defined, set up results files to store their solution
00381     if (mpCellBasedPdeHandler != NULL)
00382     {
00383         mpCellBasedPdeHandler->OpenResultsFiles(this->mSimulationOutputDirectory);
00384         if (PetscTools::AmMaster())
00385         {
00386             *this->mpVizSetupFile << "PDE \n";
00387         }
00388 
00389         /*
00390          * If any PDEs have been defined, solve them here before updating cells and store
00391          * their solution in results files. This also initializes the relevant CellData.
00392          * NOTE that this works as the PDEs are elliptic.
00393          */
00394         CellBasedEventHandler::BeginEvent(CellBasedEventHandler::PDE);
00395         mpCellBasedPdeHandler->SolvePdeAndWriteResultsToFile(this->mSamplingTimestepMultiple);
00396         CellBasedEventHandler::EndEvent(CellBasedEventHandler::PDE);
00397     }
00398 
00399     SetupSolve();
00400 
00401     // Call SetupSolve() on each modifier
00402     for (typename std::vector<boost::shared_ptr<AbstractCellBasedSimulationModifier<ELEMENT_DIM, SPACE_DIM> > >::iterator iter = mSimulationModifiers.begin();
00403          iter != mSimulationModifiers.end();
00404          ++iter)
00405     {
00406         (*iter)->SetupSolve(this->mrCellPopulation,this->mSimulationOutputDirectory);
00407     }
00408 
00409     /*
00410      * Age the cells to the correct time. Note that cells are created with
00411      * negative birth times so that some are initially almost ready to divide.
00412      */
00413     LOG(1, "Setting up cells...");
00414     for (typename AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>::Iterator cell_iter = mrCellPopulation.Begin();
00415          cell_iter != mrCellPopulation.End();
00416          ++cell_iter)
00417     {
00418         /*
00419          * We don't use the result; this call is just to force the cells to age
00420          * to the current time running their cell-cycle models to get there.
00421          */
00422         cell_iter->ReadyToDivide();
00423     }
00424     LOG(1, "\tdone\n");
00425 
00426     // Write initial conditions to file for the visualizer
00427     WriteVisualizerSetupFile();
00428 
00429     if (PetscTools::AmMaster())
00430     {
00431         *mpVizSetupFile << std::flush;
00432     }
00433 
00434     mrCellPopulation.WriteResultsToFiles(results_directory+"/");
00435 
00436     OutputSimulationSetup();
00437     CellBasedEventHandler::EndEvent(CellBasedEventHandler::SETUP);
00438 
00439     // Enter main time loop
00440     while (!( p_simulation_time->IsFinished() || StoppingEventHasOccurred() ) )
00441     {
00442         LOG(1, "--TIME = " << p_simulation_time->GetTime() << "\n");
00443 
00444         // This function calls DoCellRemoval(), DoCellBirth() and CellPopulation::Update()
00445         UpdateCellPopulation();
00446 
00447 
00448         // Store whether we are sampling results at the current timestep
00449         SimulationTime* p_time = SimulationTime::Instance();
00450         bool at_sampling_timestep = (p_time->GetTimeStepsElapsed()%this->mSamplingTimestepMultiple == 0);
00451 
00452         /*
00453          * If required, store the current locations of cell centres. Note that we need to
00454          * use a std::map between cells and locations, rather than (say) a std::vector with
00455          * location indices corresponding to cells, since once we call UpdateCellLocations()
00456          * the location index of each cell may change. This is especially true in the case
00457          * of a CaBasedCellPopulation.
00458          */
00459         std::map<CellPtr, c_vector<double, SPACE_DIM> > old_cell_locations;
00460         if (mOutputCellVelocities && at_sampling_timestep)
00461         {
00462             for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter = mrCellPopulation.Begin();
00463                  cell_iter != mrCellPopulation.End();
00464                  ++cell_iter)
00465             {
00466                 old_cell_locations[*cell_iter] = mrCellPopulation.GetLocationOfCellCentre(*cell_iter);
00467             }
00468         }
00469 
00470         // Update cell locations and topology
00471         UpdateCellLocationsAndTopology();
00472 
00473         // Now write cell velocities to file if required
00474         if (mOutputCellVelocities && at_sampling_timestep)
00475         {
00476             // Offset as doing this before we increase time by mDt
00477             *mpCellVelocitiesFile << p_time->GetTime() + mDt<< "\t";
00478 
00479             for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter = mrCellPopulation.Begin();
00480                  cell_iter != mrCellPopulation.End();
00481                  ++cell_iter)
00482             {
00483                 unsigned index = mrCellPopulation.GetLocationIndexUsingCell(*cell_iter);
00484                 const c_vector<double,SPACE_DIM>& position = mrCellPopulation.GetLocationOfCellCentre(*cell_iter);
00485 
00486                 c_vector<double, SPACE_DIM> velocity; // Two lines for profile build
00487                 velocity = (position - old_cell_locations[*cell_iter])/mDt;
00488 
00489                 *mpCellVelocitiesFile << index  << " ";
00490                 for (unsigned i=0; i<SPACE_DIM; i++)
00491                 {
00492                     *mpCellVelocitiesFile << position[i] << " ";
00493                 }
00494 
00495                 for (unsigned i=0; i<SPACE_DIM; i++)
00496                 {
00497                     *mpCellVelocitiesFile << velocity[i] << " ";
00498                 }
00499             }
00500             *mpCellVelocitiesFile << "\n";
00501         }
00502 
00503         // Update the assignment of cells to processes.
00504         mrCellPopulation.UpdateCellProcessLocation();
00505 
00506         // Increment simulation time here, so results files look sensible
00507         p_simulation_time->IncrementTimeOneStep();
00508 
00509         // If any PDEs have been defined, solve them and store their solution in results files
00510         if (mpCellBasedPdeHandler != NULL)
00511         {
00512             CellBasedEventHandler::BeginEvent(CellBasedEventHandler::PDE);
00513             mpCellBasedPdeHandler->SolvePdeAndWriteResultsToFile(this->mSamplingTimestepMultiple);
00514             CellBasedEventHandler::EndEvent(CellBasedEventHandler::PDE);
00515         }
00516 
00517         // Call UpdateAtEndOfTimeStep() on each modifier
00518         CellBasedEventHandler::BeginEvent(CellBasedEventHandler::UPDATESIMULATION);
00519         for (typename std::vector<boost::shared_ptr<AbstractCellBasedSimulationModifier<ELEMENT_DIM, SPACE_DIM> > >::iterator iter = mSimulationModifiers.begin();
00520              iter != mSimulationModifiers.end();
00521              ++iter)
00522         {
00523             (*iter)->UpdateAtEndOfTimeStep(this->mrCellPopulation);
00524         }
00525         CellBasedEventHandler::EndEvent(CellBasedEventHandler::UPDATESIMULATION);
00526 
00527         // Output current results to file
00528         CellBasedEventHandler::BeginEvent(CellBasedEventHandler::OUTPUT);
00529         if (p_simulation_time->GetTimeStepsElapsed()%mSamplingTimestepMultiple == 0)
00530         {
00531             mrCellPopulation.WriteResultsToFiles(results_directory+"/");
00532 
00533             // Call UpdateAtEndOfOutputTimeStep() on each modifier
00534             for (typename std::vector<boost::shared_ptr<AbstractCellBasedSimulationModifier<ELEMENT_DIM, SPACE_DIM> > >::iterator iter = mSimulationModifiers.begin();
00535                  iter != mSimulationModifiers.end();
00536                  ++iter)
00537             {
00538                 (*iter)->UpdateAtEndOfOutputTimeStep(this->mrCellPopulation);
00539             }
00540         }
00541         CellBasedEventHandler::EndEvent(CellBasedEventHandler::OUTPUT);
00542     }
00543 
00544     LOG(1, "--END TIME = " << p_simulation_time->GetTime() << "\n");
00545 
00546     /*
00547      * Carry out a final update so that cell population is coherent with new cell positions.
00548      * Note that cell birth and death still need to be checked because they may be spatially
00549      * dependent.
00550      */
00551     UpdateCellPopulation();
00552 
00553     // If any PDEs have been defined, close the results files storing their solution
00554     if (mpCellBasedPdeHandler != NULL)
00555     {
00556         mpCellBasedPdeHandler->CloseResultsFiles();
00557     }
00558 
00559     CellBasedEventHandler::BeginEvent(CellBasedEventHandler::UPDATESIMULATION);
00560     // Call UpdateAtEndOfSolve(), on each modifier
00561     for (typename std::vector<boost::shared_ptr<AbstractCellBasedSimulationModifier<ELEMENT_DIM, SPACE_DIM> > >::iterator iter = mSimulationModifiers.begin();
00562          iter != mSimulationModifiers.end();
00563          ++iter)
00564     {
00565         (*iter)->UpdateAtEndOfSolve(this->mrCellPopulation);
00566     }
00567     CellBasedEventHandler::EndEvent(CellBasedEventHandler::UPDATESIMULATION);
00568 
00569     CellBasedEventHandler::BeginEvent(CellBasedEventHandler::OUTPUT);
00570 
00571     mrCellPopulation.CloseOutputFiles();
00572 
00573     if (mOutputDivisionLocations)
00574     {
00575         mpDivisionLocationFile->close();
00576     }
00577     if (mOutputCellVelocities)
00578     {
00579         mpCellVelocitiesFile->close();
00580     }
00581 
00582     if (PetscTools::AmMaster())
00583     {
00584         *mpVizSetupFile << "Complete\n";
00585         mpVizSetupFile->close();
00586     }
00587 
00588     CellBasedEventHandler::EndEvent(CellBasedEventHandler::OUTPUT);
00589     CellBasedEventHandler::EndEvent(CellBasedEventHandler::EVERYTHING);
00590 }
00591 
00592 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00593 bool AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::StoppingEventHasOccurred()
00594 {
00595     return false;
00596 }
00597 
00598 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00599 void AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::UpdateCellPopulation()
00600 {
00601     // Remove dead cells
00602     CellBasedEventHandler::BeginEvent(CellBasedEventHandler::DEATH);
00603     unsigned deaths_this_step = DoCellRemoval();
00604     mNumDeaths += deaths_this_step;
00605     LOG(1, "\tNum deaths = " << mNumDeaths << "\n");
00606     CellBasedEventHandler::EndEvent(CellBasedEventHandler::DEATH);
00607 
00608     // Divide cells
00609     CellBasedEventHandler::BeginEvent(CellBasedEventHandler::BIRTH);
00610     unsigned births_this_step = DoCellBirth();
00611     mNumBirths += births_this_step;
00612     LOG(1, "\tNum births = " << mNumBirths << "\n");
00613     CellBasedEventHandler::EndEvent(CellBasedEventHandler::BIRTH);
00614 
00615     // This allows NodeBasedCellPopulation::Update() to do the minimum amount of work
00616     bool births_or_death_occurred = ((births_this_step>0) || (deaths_this_step>0));
00617 
00618     // Update topology of cell population
00619     CellBasedEventHandler::BeginEvent(CellBasedEventHandler::UPDATECELLPOPULATION);
00620     if (mUpdateCellPopulation)
00621     {
00622         LOG(1, "\tUpdating cell population...");
00623         mrCellPopulation.Update(births_or_death_occurred);
00624         LOG(1, "\tdone.\n");
00625     }
00626     else if (births_or_death_occurred)
00627     {
00628         EXCEPTION("CellPopulation has had births or deaths but mUpdateCellPopulation is set to false, please set it to true.");
00629     }
00630     CellBasedEventHandler::EndEvent(CellBasedEventHandler::UPDATECELLPOPULATION);
00631 }
00632 
00633 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00634 bool AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::GetOutputDivisionLocations()
00635 {
00636     return mOutputDivisionLocations;
00637 }
00638 
00639 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00640 void AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::SetOutputDivisionLocations(bool outputDivisionLocations)
00641 {
00642     mOutputDivisionLocations = outputDivisionLocations;
00643 }
00644 
00645 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00646 bool AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::GetOutputCellVelocities()
00647 {
00648     return mOutputCellVelocities;
00649 }
00650 
00651 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00652 void AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::SetOutputCellVelocities(bool outputCellVelocities)
00653 {
00654     mOutputCellVelocities = outputCellVelocities;
00655 }
00656 
00657 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00658 void AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::OutputSimulationSetup()
00659 {
00660     OutputFileHandler output_file_handler(this->mSimulationOutputDirectory + "/", false);
00661 
00662     // Output machine information
00663     ExecutableSupport::SetOutputDirectory(output_file_handler.GetOutputDirectoryFullPath());
00664     ExecutableSupport::WriteMachineInfoFile("system_info");
00665 
00666     if (PetscTools::AmMaster())
00667     {
00668         // Output Chaste provenance information
00669         out_stream build_info_file = output_file_handler.OpenOutputFile("build.info");
00670         std::string build_info;
00671         ExecutableSupport::GetBuildInfo(build_info);
00672         *build_info_file << build_info;
00673         build_info_file->close();
00674 
00675         // Output simulation parameter and setup details
00676         out_stream parameter_file = output_file_handler.OpenOutputFile("results.parameters");
00677 
00678         // Output simulation details
00679         std::string simulation_type = GetIdentifier();
00680 
00681         *parameter_file << "<Chaste>\n";
00682         *parameter_file << "\n\t<" << simulation_type << ">\n";
00683         OutputSimulationParameters(parameter_file);
00684         *parameter_file << "\t</" << simulation_type << ">\n";
00685         *parameter_file << "\n";
00686 
00687         // Output cell population details (includes cell-cycle model details)
00688         mrCellPopulation.OutputCellPopulationInfo(parameter_file);
00689 
00690         // Loop over cell killers
00691         *parameter_file << "\n\t<CellKillers>\n";
00692         for (typename std::vector<boost::shared_ptr<AbstractCellKiller<SPACE_DIM> > >::iterator iter = mCellKillers.begin();
00693              iter != mCellKillers.end();
00694              ++iter)
00695         {
00696             // Output cell killer details
00697             (*iter)->OutputCellKillerInfo(parameter_file);
00698         }
00699         *parameter_file << "\t</CellKillers>\n";
00700 
00701         // Iterate over simulationmodifiers
00702         *parameter_file << "\n\t<SimulationModifiers>\n";
00703         for (typename std::vector<boost::shared_ptr<AbstractCellBasedSimulationModifier<ELEMENT_DIM, SPACE_DIM> > >::iterator iter = mSimulationModifiers.begin();
00704              iter != mSimulationModifiers.end();
00705              ++iter)
00706         {
00707             // Output simulation modifier details
00708             (*iter)->OutputSimulationModifierInfo(parameter_file);
00709         }
00710         *parameter_file << "\t</SimulationModifiers>\n";
00711 
00712         // This is used to output information about subclasses
00713         OutputAdditionalSimulationSetup(parameter_file);
00714 
00715         *parameter_file << "\n</Chaste>\n";
00716         parameter_file->close();
00717     }
00718 }
00719 
00720 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00721 void AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::OutputSimulationParameters(out_stream& rParamsFile)
00722 {
00723     if (mpCellBasedPdeHandler != NULL)
00724     {
00725         mpCellBasedPdeHandler->OutputParameters(rParamsFile);
00726     }
00727 
00728     *rParamsFile << "\t\t<Dt>" << mDt << "</Dt>\n";
00729     *rParamsFile << "\t\t<EndTime>" << mEndTime << "</EndTime>\n";
00730     *rParamsFile << "\t\t<SamplingTimestepMultiple>" << mSamplingTimestepMultiple << "</SamplingTimestepMultiple>\n";
00731     *rParamsFile << "\t\t<OutputDivisionLocations>" << mOutputDivisionLocations << "</OutputDivisionLocations>\n";
00732     *rParamsFile << "\t\t<OutputCellVelocities>" << mOutputCellVelocities << "</OutputCellVelocities>\n";
00733 }
00734 
00736 // Explicit instantiation
00738 
00739 template class AbstractCellBasedSimulation<1,1>;
00740 template class AbstractCellBasedSimulation<1,2>;
00741 template class AbstractCellBasedSimulation<2,2>;
00742 template class AbstractCellBasedSimulation<1,3>;
00743 template class AbstractCellBasedSimulation<2,3>;
00744 template class AbstractCellBasedSimulation<3,3>;

Generated by  doxygen 1.6.2