AbstractCellBasedSimulation.cpp

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

Generated by  doxygen 1.6.2