AbstractCellBasedSimulation.cpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2011
00004 
00005 University of Oxford means the Chancellor, Masters and Scholars of the
00006 University of Oxford, having an administrative office at Wellington
00007 Square, Oxford OX1 2JD, UK.
00008 
00009 This file is part of Chaste.
00010 
00011 Chaste is free software: you can redistribute it and/or modify it
00012 under the terms of the GNU Lesser General Public License as published
00013 by the Free Software Foundation, either version 2.1 of the License, or
00014 (at your option) any later version.
00015 
00016 Chaste is distributed in the hope that it will be useful, but WITHOUT
00017 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
00019 License for more details. The offer of Chaste under the terms of the
00020 License is subject to the License being interpreted in accordance with
00021 English Law and subject to any action against the University of Oxford
00022 being under the jurisdiction of the English Courts.
00023 
00024 You should have received a copy of the GNU Lesser General Public License
00025 along with Chaste. If not, see <http://www.gnu.org/licenses/>.
00026 
00027 */
00028 
00029 #include <cmath>
00030 #include <ctime>
00031 #include <iostream>
00032 #include <fstream>
00033 #include <set>
00034 
00035 #include "AbstractCellBasedSimulation.hpp"
00036 #include "CellBasedEventHandler.hpp"
00037 #include "LogFile.hpp"
00038 #include "Version.hpp"
00039 #include "ExecutableSupport.hpp"
00040 #include "Exception.hpp"
00041 
00042 #include <typeinfo>
00043 
00044 template<unsigned DIM>
00045 AbstractCellBasedSimulation<DIM>::AbstractCellBasedSimulation(AbstractCellPopulation<DIM>& rCellPopulation,
00046                                               bool deleteCellPopulationInDestructor,
00047                                               bool initialiseCells)
00048     : mDt(DOUBLE_UNSET),
00049       mEndTime(0.0),  // hours - this is set later on
00050       mrCellPopulation(rCellPopulation),
00051       mDeleteCellPopulationInDestructor(deleteCellPopulationInDestructor),
00052       mInitialiseCells(initialiseCells),
00053       mNoBirth(false),
00054       mUpdateCellPopulation(true),
00055       mOutputDirectory(""),
00056       mSimulationOutputDirectory(mOutputDirectory),
00057       mNumBirths(0),
00058       mNumDeaths(0),
00059       mSamplingTimestepMultiple(1),
00060       mpCellBasedPdeHandler(NULL)
00061 {
00062     // Set a random seed of 0 if it wasn't specified earlier
00063     RandomNumberGenerator::Instance();
00064 
00065     if (mInitialiseCells)
00066     {
00067         mrCellPopulation.InitialiseCells();
00068     }
00069 }
00070 
00071 template<unsigned DIM>
00072 AbstractCellBasedSimulation<DIM>::~AbstractCellBasedSimulation()
00073 {
00074     if (mDeleteCellPopulationInDestructor)
00075     {
00076         delete &mrCellPopulation;
00077         delete mpCellBasedPdeHandler;
00078     }
00079 }
00080 
00081 template<unsigned DIM>
00082 void AbstractCellBasedSimulation<DIM>::SetCellBasedPdeHandler(CellBasedPdeHandler<DIM>* pCellBasedPdeHandler)
00083 {
00084     mpCellBasedPdeHandler = pCellBasedPdeHandler;
00085 }
00086 
00087 template<unsigned DIM>
00088 CellBasedPdeHandler<DIM>* AbstractCellBasedSimulation<DIM>::GetCellBasedPdeHandler()
00089 {
00090     return mpCellBasedPdeHandler;
00091 }
00092 
00093 template<unsigned DIM>
00094 unsigned AbstractCellBasedSimulation<DIM>::DoCellBirth()
00095 {
00096     if (mNoBirth)
00097     {
00098         return 0;
00099     }
00100 
00101     unsigned num_births_this_step = 0;
00102 
00103     // Iterate over all cells, seeing if each one can be divided
00104     for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = mrCellPopulation.Begin();
00105          cell_iter != mrCellPopulation.End();
00106          ++cell_iter)
00107     {
00108         // Check if this cell is ready to divide - if so create a new cell etc.
00109         if (cell_iter->GetAge() > 0.0)
00110         {
00111             if (cell_iter->ReadyToDivide())
00112             {
00113                 // Create a new cell
00114                 CellPtr p_new_cell = cell_iter->Divide();
00115 
00116                 // Call method that determines how cell division occurs and returns a vector
00117                 c_vector<double, DIM> new_location = CalculateCellDivisionVector(*cell_iter);
00118 
00119                 // Add new cell to the cell population
00120                 mrCellPopulation.AddCell(p_new_cell, new_location, *cell_iter);
00121 
00122                 // Update counter
00123                 num_births_this_step++;
00124             }
00125         }
00126     }
00127     return num_births_this_step;
00128 }
00129 
00130 template<unsigned DIM>
00131 unsigned AbstractCellBasedSimulation<DIM>::DoCellRemoval()
00132 {
00133     unsigned num_deaths_this_step = 0;
00134 
00135     /*
00136      * This labels cells as dead or apoptosing. It does not actually remove the cells,
00137      * mrCellPopulation.RemoveDeadCells() needs to be called for this.
00138      */
00139     for (typename std::vector<boost::shared_ptr<AbstractCellKiller<DIM> > >::iterator killer_iter = mCellKillers.begin();
00140          killer_iter != mCellKillers.end();
00141          ++killer_iter)
00142     {
00143         (*killer_iter)->TestAndLabelCellsForApoptosisOrDeath();
00144     }
00145 
00146     num_deaths_this_step += mrCellPopulation.RemoveDeadCells();
00147 
00148     return num_deaths_this_step;
00149 }
00150 
00151 template<unsigned DIM>
00152 void AbstractCellBasedSimulation<DIM>::SetDt(double dt)
00153 {
00154     assert(dt > 0);
00155     mDt = dt;
00156 }
00157 
00158 template<unsigned DIM>
00159 double AbstractCellBasedSimulation<DIM>::GetDt()
00160 {
00161     return mDt;
00162 }
00163 
00164 template<unsigned DIM>
00165 unsigned AbstractCellBasedSimulation<DIM>::GetNumBirths()
00166 {
00167     return mNumBirths;
00168 }
00169 
00170 template<unsigned DIM>
00171 unsigned AbstractCellBasedSimulation<DIM>::GetNumDeaths()
00172 {
00173     return mNumDeaths;
00174 }
00175 
00176 template<unsigned DIM>
00177 void AbstractCellBasedSimulation<DIM>::SetEndTime(double endTime)
00178 {
00179     assert(endTime > 0);
00180     mEndTime = endTime;
00181 }
00182 
00183 template<unsigned DIM>
00184 void AbstractCellBasedSimulation<DIM>::SetOutputDirectory(std::string outputDirectory)
00185 {
00186     mOutputDirectory = outputDirectory;
00187     mSimulationOutputDirectory = mOutputDirectory;
00188 }
00189 
00190 template<unsigned DIM>
00191 std::string AbstractCellBasedSimulation<DIM>::GetOutputDirectory()
00192 {
00193     return mOutputDirectory;
00194 }
00195 
00196 template<unsigned DIM>
00197 void AbstractCellBasedSimulation<DIM>::SetSamplingTimestepMultiple(unsigned samplingTimestepMultiple)
00198 {
00199     assert(samplingTimestepMultiple > 0);
00200     mSamplingTimestepMultiple = samplingTimestepMultiple;
00201 }
00202 
00203 template<unsigned DIM>
00204 AbstractCellPopulation<DIM>& AbstractCellBasedSimulation<DIM>::rGetCellPopulation()
00205 {
00206     return mrCellPopulation;
00207 }
00208 
00209 template<unsigned DIM>
00210 const AbstractCellPopulation<DIM>& AbstractCellBasedSimulation<DIM>::rGetCellPopulation() const
00211 {
00212     return mrCellPopulation;
00213 }
00214 
00215 template<unsigned DIM>
00216 void AbstractCellBasedSimulation<DIM>::SetUpdateCellPopulationRule(bool updateCellPopulation)
00217 {
00218     mUpdateCellPopulation = updateCellPopulation;
00219 }
00220 
00221 template<unsigned DIM>
00222 void AbstractCellBasedSimulation<DIM>::SetNoBirth(bool noBirth)
00223 {
00224     mNoBirth = noBirth;
00225 }
00226 
00227 template<unsigned DIM>
00228 void AbstractCellBasedSimulation<DIM>::AddCellKiller(boost::shared_ptr<AbstractCellKiller<DIM> > pCellKiller)
00229 {
00230     mCellKillers.push_back(pCellKiller);
00231 }
00232 
00233 template<unsigned DIM>
00234 std::vector<double> AbstractCellBasedSimulation<DIM>::GetNodeLocation(const unsigned& rNodeIndex)
00235 {
00236     std::vector<double> location;
00237     for (unsigned i=0; i<DIM; i++)
00238     {
00239         location.push_back(mrCellPopulation.GetNode(rNodeIndex)->rGetLocation()[i]);
00240     }
00241     return location;
00242 }
00243 
00244 template<unsigned DIM>
00245 void AbstractCellBasedSimulation<DIM>::SetupSolve()
00246 {
00247     if (mpCellBasedPdeHandler != NULL)
00248     {
00249         mpCellBasedPdeHandler->OpenResultsFiles(this->mSimulationOutputDirectory);
00250         *this->mpVizSetupFile << "PDE \n";
00251     }
00252 }
00253 
00254 template<unsigned DIM>
00255 void AbstractCellBasedSimulation<DIM>::PostSolve()
00256 {
00257     if (mpCellBasedPdeHandler != NULL)
00258     {
00259         CellBasedEventHandler::BeginEvent(CellBasedEventHandler::PDE);
00260         mpCellBasedPdeHandler->SolvePdeAndWriteResultsToFile(this->mSamplingTimestepMultiple);
00261         CellBasedEventHandler::EndEvent(CellBasedEventHandler::PDE);
00262     }
00263 }
00264 
00265 template<unsigned DIM>
00266 void AbstractCellBasedSimulation<DIM>::AfterSolve()
00267 {
00268     if (mpCellBasedPdeHandler != NULL)
00269     {
00270         mpCellBasedPdeHandler->CloseResultsFiles();
00271     }
00272 }
00273 
00274 template<unsigned DIM>
00275 void AbstractCellBasedSimulation<DIM>::Solve()
00276 {
00277     CellBasedEventHandler::BeginEvent(CellBasedEventHandler::EVERYTHING);
00278     CellBasedEventHandler::BeginEvent(CellBasedEventHandler::SETUP);
00279 
00280     // Set up the simulation time
00281     SimulationTime* p_simulation_time = SimulationTime::Instance();
00282     double current_time = p_simulation_time->GetTime();
00283 
00284     unsigned num_time_steps = (unsigned) ((mEndTime-current_time)/mDt+0.5);
00285 
00286     if (current_time > 0) // use the reset function if necessary
00287     {
00288         p_simulation_time->ResetEndTimeAndNumberOfTimeSteps(mEndTime, num_time_steps);
00289     }
00290     else
00291     {
00292         if(p_simulation_time->IsEndTimeAndNumberOfTimeStepsSetUp())
00293         {
00294             EXCEPTION("End time and number of timesteps already setup. You should not use SimulationTime::SetEndTimeAndNumberOfTimeSteps in cell-based tests.");
00295         }
00296         else
00297         {
00298             p_simulation_time->SetEndTimeAndNumberOfTimeSteps(mEndTime, num_time_steps);
00299         }
00300 
00301     }
00302 
00303     if (mOutputDirectory=="")
00304     {
00305         EXCEPTION("OutputDirectory not set");
00306     }
00307 
00308     double time_now = p_simulation_time->GetTime();
00309     std::ostringstream time_string;
00310     time_string << time_now;
00311 
00312     std::string results_directory = mOutputDirectory +"/results_from_time_" + time_string.str();
00313     mSimulationOutputDirectory = results_directory;
00314 
00315     // Set up simulation
00316 
00317     // Create output files for the visualizer
00318     OutputFileHandler output_file_handler(results_directory+"/", true);
00319 
00320     mrCellPopulation.CreateOutputFiles(results_directory+"/", false);
00321 
00322     mpVizSetupFile = output_file_handler.OpenOutputFile("results.vizsetup");
00323 
00324     SetupSolve();
00325 
00326     // Age the cells to the correct time. Note that cells are created with
00327     // negative birth times so that some are initially almost ready to divide.
00328     LOG(1, "Setting up cells...");
00329     for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = mrCellPopulation.Begin();
00330          cell_iter != mrCellPopulation.End();
00331          ++cell_iter)
00332     {
00333         // We don't use the result; this call is just to force the cells to age
00334         // to the current time running their cell-cycle models to get there
00335         cell_iter->ReadyToDivide();
00336     }
00337     LOG(1, "\tdone\n");
00338 
00339     // Write initial conditions to file for the visualizer
00340     WriteVisualizerSetupFile();
00341 
00342     *mpVizSetupFile << std::flush;
00343 
00344     mrCellPopulation.WriteResultsToFiles();
00345 
00346     OutputSimulationSetup();
00347 
00348     CellBasedEventHandler::EndEvent(CellBasedEventHandler::SETUP);
00349 
00350     // Enter main time loop
00351     while (!( p_simulation_time->IsFinished() || StoppingEventHasOccurred() ) )
00352     {
00353         LOG(1, "--TIME = " << p_simulation_time->GetTime() << "\n");
00354 
00355         // This function calls DoCellRemoval(), DoCellBirth() and CellPopulation::Update()
00356         UpdateCellPopulation();
00357 
00358         // Update cell locations and topology
00359         UpdateCellLocationsAndTopology();
00360 
00361         // Call PostSolve(), which may be implemented by child classes (eg to solve PDEs)
00362         PostSolve();
00363 
00364         // Increment simulation time here, so results files look sensible
00365         p_simulation_time->IncrementTimeOneStep();
00366 
00367         // Output current results to file
00368         CellBasedEventHandler::BeginEvent(CellBasedEventHandler::OUTPUT);
00369         if (p_simulation_time->GetTimeStepsElapsed()%mSamplingTimestepMultiple == 0)
00370         {
00371             mrCellPopulation.WriteResultsToFiles();
00372         }
00373         CellBasedEventHandler::EndEvent(CellBasedEventHandler::OUTPUT);
00374     }
00375 
00376     LOG(1, "--END TIME = " << p_simulation_time->GetTime() << "\n");
00377 
00378     // Carry out a final update so that cell population is coherent with new cell positions.
00379     // NB cell birth/death still need to be checked because they may be spatially-dependent.
00380     UpdateCellPopulation();
00381 
00382     AfterSolve();
00383 
00384     CellBasedEventHandler::BeginEvent(CellBasedEventHandler::OUTPUT);
00385 
00386     mrCellPopulation.CloseOutputFiles();
00387 
00388     *mpVizSetupFile << "Complete\n";
00389     mpVizSetupFile->close();
00390 
00391     CellBasedEventHandler::EndEvent(CellBasedEventHandler::OUTPUT);
00392     CellBasedEventHandler::EndEvent(CellBasedEventHandler::EVERYTHING);
00393 }
00394 
00395 template<unsigned DIM>
00396 bool AbstractCellBasedSimulation<DIM>::StoppingEventHasOccurred()
00397 {
00398     return false;
00399 }
00400 
00401 template<unsigned DIM>
00402 void AbstractCellBasedSimulation<DIM>::UpdateCellPopulation()
00403 {
00404     // Remove dead cells
00405     CellBasedEventHandler::BeginEvent(CellBasedEventHandler::DEATH);
00406     unsigned deaths_this_step = DoCellRemoval();
00407     mNumDeaths += deaths_this_step;
00408     LOG(1, "\tNum deaths = " << mNumDeaths << "\n");
00409     CellBasedEventHandler::EndEvent(CellBasedEventHandler::DEATH);
00410 
00411     // Divide cells
00412     CellBasedEventHandler::BeginEvent(CellBasedEventHandler::BIRTH);
00413     unsigned births_this_step = DoCellBirth();
00414     mNumBirths += births_this_step;
00415     LOG(1, "\tNum births = " << mNumBirths << "\n");
00416     CellBasedEventHandler::EndEvent(CellBasedEventHandler::BIRTH);
00417 
00418     // This allows NodeBasedCellPopulation::Update() to do the minimum amount of work
00419     bool births_or_death_occurred = ((births_this_step>0) || (deaths_this_step>0));
00420 
00421     // Update topology of cell population
00422     CellBasedEventHandler::BeginEvent(CellBasedEventHandler::UPDATECELLPOPULATION);
00423     if (mUpdateCellPopulation)
00424     {
00425         LOG(1, "\tUpdating cell population...");
00426         mrCellPopulation.Update(births_or_death_occurred);
00427         LOG(1, "\tdone.\n");
00428     }
00429     else if (births_or_death_occurred)
00430     {
00431         EXCEPTION("CellPopulation has had births or deaths but mUpdateCellPopulation is set to false, please set it to true.");
00432     }
00433     CellBasedEventHandler::EndEvent(CellBasedEventHandler::UPDATECELLPOPULATION);
00434 }
00435 
00436 template<unsigned DIM>
00437 void AbstractCellBasedSimulation<DIM>::OutputSimulationSetup()
00438 {
00439     OutputFileHandler output_file_handler(this->mSimulationOutputDirectory + "/", false);
00440 
00441     // Output machine information
00442     ExecutableSupport::WriteMachineInfoFile(this->mSimulationOutputDirectory + "/system_info");
00443 
00444     // Output Chaste provenance information
00445     out_stream build_info_file = output_file_handler.OpenOutputFile("build.info");
00446     ExecutableSupport::WriteLibraryInfo(build_info_file);
00447     build_info_file->close();
00448 
00449     // Output simulation parameter and setup details
00450     out_stream parameter_file = output_file_handler.OpenOutputFile("results.parameters");
00451 
00452     // Output simulation details
00453     std::string simulation_type = GetIdentifier();
00454 
00455     *parameter_file << "<Chaste>\n";
00456     *parameter_file << "\n\t<" << simulation_type << ">\n";
00457     OutputSimulationParameters(parameter_file);
00458     *parameter_file << "\t</" << simulation_type << ">\n";
00459     *parameter_file << "\n";
00460 
00461     // Output cell population details (includes cell-cycle model details)
00462     mrCellPopulation.OutputCellPopulationInfo(parameter_file);
00463 
00464     // Loop over cell killers
00465     *parameter_file << "\n\t<CellKillers>\n";
00466     for (typename std::vector<boost::shared_ptr<AbstractCellKiller<DIM> > >::iterator iter = mCellKillers.begin();
00467          iter != mCellKillers.end();
00468          ++iter)
00469     {
00470         // Output cell killer details
00471         (*iter)->OutputCellKillerInfo(parameter_file);
00472     }
00473     *parameter_file << "\t</CellKillers>\n";
00474 
00475     // This is used to output information about subclasses
00476     OutputAdditionalSimulationSetup(parameter_file);
00477 
00478     *parameter_file << "\n</Chaste>\n";
00479     parameter_file->close();
00480 }
00481 
00482 template<unsigned DIM>
00483 void AbstractCellBasedSimulation<DIM>::OutputSimulationParameters(out_stream& rParamsFile)
00484 {
00485     if (mpCellBasedPdeHandler != NULL)
00486     {
00487         mpCellBasedPdeHandler->OutputParameters(rParamsFile);
00488     }
00489 
00490     *rParamsFile << "\t\t<Dt>" << mDt << "</Dt>\n";
00491     *rParamsFile << "\t\t<EndTime>" << mEndTime << "</EndTime>\n";
00492     *rParamsFile << "\t\t<SamplingTimestepMultiple>" << mSamplingTimestepMultiple << "</SamplingTimestepMultiple>\n";
00493 }
00494 
00496 // Explicit instantiation
00498 
00499 template class AbstractCellBasedSimulation<1>;
00500 template class AbstractCellBasedSimulation<2>;
00501 template class AbstractCellBasedSimulation<3>;
Generated on Thu Dec 22 13:00:05 2011 for Chaste by  doxygen 1.6.3