CellBasedSimulation.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 #include <cmath>
00029 #include <ctime>
00030 #include <iostream>
00031 #include <fstream>
00032 #include <set>
00033 
00034 #include "CellBasedSimulation.hpp"
00035 #include "AbstractCentreBasedCellPopulation.hpp"
00036 #include "CellBasedEventHandler.hpp"
00037 #include "LogFile.hpp"
00038 #include "Version.hpp"
00039 #include "ExecutableSupport.hpp"
00040 
00041 #include <typeinfo>
00042 
00043 template<unsigned DIM>
00044 CellBasedSimulation<DIM>::CellBasedSimulation(AbstractCellPopulation<DIM>& rCellPopulation,
00045                                               bool deleteCellPopulationAndForcesAndBCsInDestructor,
00046                                               bool initialiseCells)
00047     : mEndTime(0.0),  // hours - this is set later on
00048       mrCellPopulation(rCellPopulation),
00049       mDeleteCellPopulationAndForcesAndBCsInDestructor(deleteCellPopulationAndForcesAndBCsInDestructor),
00050       mInitialiseCells(initialiseCells),
00051       mNoBirth(false),
00052       mUpdateCellPopulation(true),
00053       mOutputDirectory(""),
00054       mSimulationOutputDirectory(mOutputDirectory),
00055       mNumBirths(0),
00056       mNumDeaths(0),
00057       mSamplingTimestepMultiple(1),
00058       mOutputNodeVelocities(false)
00059 {
00060     // This line sets a random seed of 0 if it wasn't specified earlier.
00061     mpRandomGenerator = RandomNumberGenerator::Instance();
00062 
00063     // Different time steps are used for cell-centre and vertex-based simulations
00064     if (dynamic_cast<AbstractCentreBasedCellPopulation<DIM>*>(&rCellPopulation))
00065     {
00066         mDt = 1.0/120.0; // 30 seconds
00067     }
00068     else
00069     {
00070         mDt = 0.002; // smaller time step required for convergence/stability
00071     }
00072 
00073     if (mInitialiseCells)
00074     {
00075         mrCellPopulation.InitialiseCells();
00076     }
00077 }
00078 
00079 
00080 template<unsigned DIM>
00081 CellBasedSimulation<DIM>::~CellBasedSimulation()
00082 {
00083     if (mDeleteCellPopulationAndForcesAndBCsInDestructor)
00084     {
00085         for (typename std::vector<AbstractForce<DIM>*>::iterator force_iter = mForceCollection.begin();
00086              force_iter != mForceCollection.end();
00087              ++force_iter)
00088         {
00089             delete *force_iter;
00090         }
00091 
00092         for (typename std::vector<AbstractCellKiller<DIM>*>::iterator it=mCellKillers.begin();
00093              it != mCellKillers.end();
00094              ++it)
00095         {
00096             delete *it;
00097         }
00098 
00099         for (typename std::vector<AbstractCellPopulationBoundaryCondition<DIM>*>::iterator it=mBoundaryConditions.begin();
00100              it != mBoundaryConditions.end();
00101              ++it)
00102         {
00103             delete *it;
00104         }
00105 
00106         delete &mrCellPopulation;
00107     }
00108 }
00109 
00110 
00111 template<unsigned DIM>
00112 unsigned CellBasedSimulation<DIM>::DoCellBirth()
00113 {
00114     if (mNoBirth)
00115     {
00116         return 0;
00117     }
00118 
00119     unsigned num_births_this_step = 0;
00120 
00121     // Iterate over all cells, seeing if each one can be divided
00122     for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = mrCellPopulation.Begin();
00123          cell_iter != mrCellPopulation.End();
00124          ++cell_iter)
00125     {
00126         // Check if this cell is ready to divide - if so create a new cell etc.
00127         if (cell_iter->GetAge() > 0.0)
00128         {
00129             if (cell_iter->ReadyToDivide())
00130             {
00131                 // Create a new cell
00132                 CellPtr p_new_cell = cell_iter->Divide();
00133 
00134                 // Call method that determines how cell division occurs and returns a vector
00135                 c_vector<double, DIM> new_location = CalculateCellDivisionVector(*cell_iter);
00136 
00137                 // Add new cell to the cell population
00138                 mrCellPopulation.AddCell(p_new_cell, new_location, *cell_iter);
00139 
00140                 // Update counter
00141                 num_births_this_step++;
00142             }
00143         }
00144     }
00145     return num_births_this_step;
00146 }
00147 
00148 
00149 template<unsigned DIM>
00150 unsigned CellBasedSimulation<DIM>::DoCellRemoval()
00151 {
00152     unsigned num_deaths_this_step = 0;
00153 
00154     // This labels cells as dead or apoptosing. It does not actually remove the cells,
00155     // mrCellPopulation.RemoveDeadCells() needs to be called for this.
00156     for (typename std::vector<AbstractCellKiller<DIM>*>::iterator killer_iter = mCellKillers.begin();
00157          killer_iter != mCellKillers.end();
00158          ++killer_iter)
00159     {
00160         (*killer_iter)->TestAndLabelCellsForApoptosisOrDeath();
00161     }
00162 
00163     num_deaths_this_step += mrCellPopulation.RemoveDeadCells();
00164 
00165     return num_deaths_this_step;
00166 }
00167 
00168 
00169 template<unsigned DIM>
00170 c_vector<double, DIM> CellBasedSimulation<DIM>::CalculateCellDivisionVector(CellPtr pParentCell)
00171 {
00177     if (dynamic_cast<AbstractCentreBasedCellPopulation<DIM>*>(&mrCellPopulation))
00178     {
00179         // Location of parent and daughter cells
00180         c_vector<double, DIM> parent_coords = mrCellPopulation.GetLocationOfCellCentre(pParentCell);
00181         c_vector<double, DIM> daughter_coords;
00182 
00183         // Get separation parameter
00184         double separation = static_cast<AbstractCentreBasedCellPopulation<DIM>*>(&mrCellPopulation)->GetMeinekeDivisionSeparation();
00185 
00186         // Make a random direction vector of the required length
00187         c_vector<double, DIM> random_vector;
00188 
00189         /*
00190          * Pick a random direction and move the parent cell backwards by 0.5*separation
00191          * in that direction and return the position of the daughter cell 0.5*separation
00192          * forwards in that direction.
00193          */
00194         switch (DIM)
00195         {
00196             case 1:
00197             {
00198                 double random_direction = -1.0 + 2.0*(RandomNumberGenerator::Instance()->ranf() < 0.5);
00199 
00200                 random_vector(0) = 0.5*separation*random_direction;
00201                 break;
00202             }
00203             case 2:
00204             {
00205                 double random_angle = 2.0*M_PI*RandomNumberGenerator::Instance()->ranf();
00206 
00207                 random_vector(0) = 0.5*separation*cos(random_angle);
00208                 random_vector(1) = 0.5*separation*sin(random_angle);
00209                 break;
00210             }
00211             case 3:
00212             {
00213                 double random_zenith_angle = M_PI*RandomNumberGenerator::Instance()->ranf(); // phi
00214                 double random_azimuth_angle = 2*M_PI*RandomNumberGenerator::Instance()->ranf(); // theta
00215 
00216                 random_vector(0) = 0.5*separation*cos(random_azimuth_angle)*sin(random_zenith_angle);
00217                 random_vector(1) = 0.5*separation*sin(random_azimuth_angle)*sin(random_zenith_angle);
00218                 random_vector(2) = 0.5*separation*cos(random_zenith_angle);
00219                 break;
00220             }
00221             default:
00222                 // This can't happen
00223                 NEVER_REACHED;
00224         }
00225 
00226         parent_coords = parent_coords - random_vector;
00227         daughter_coords = parent_coords + random_vector;
00228 
00229         // Set the parent to use this location
00230         ChastePoint<DIM> parent_coords_point(parent_coords);
00231         unsigned node_index = mrCellPopulation.GetLocationIndexUsingCell(pParentCell);
00232         mrCellPopulation.SetNode(node_index, parent_coords_point);
00233 
00234         return daughter_coords;
00235     }
00236     else
00237     {
00238         // Do something for Vertex / Potts Models here
00239         return zero_vector<double>(DIM);
00240     }
00241 }
00242 
00243 
00244 template<unsigned DIM>
00245 void CellBasedSimulation<DIM>::UpdateNodePositions(const std::vector< c_vector<double, DIM> >& rNodeForces)
00246 {
00247     unsigned num_nodes = mrCellPopulation.GetNumNodes();
00248 
00249     /*
00250      * Get the previous node positions (these may be needed when applying boundary conditions,
00251      * e.g. in the case of immotile cells)
00252      */
00253     std::vector<c_vector<double, DIM> > old_node_locations;
00254     old_node_locations.reserve(num_nodes);
00255     for (unsigned node_index=0; node_index<num_nodes; node_index++)
00256     {
00257         old_node_locations[node_index] = mrCellPopulation.GetNode(node_index)->rGetLocation();
00258     }
00259 
00260     // Update node locations
00261     mrCellPopulation.UpdateNodeLocations(rNodeForces, mDt);
00262 
00263     // Apply any boundary conditions
00264     for (typename std::vector<AbstractCellPopulationBoundaryCondition<DIM>*>::iterator bcs_iter = mBoundaryConditions.begin();
00265          bcs_iter != mBoundaryConditions.end();
00266          ++bcs_iter)
00267     {
00268         (*bcs_iter)->ImposeBoundaryCondition();
00269     }
00270 
00271     // Verify that each boundary condition is now satisfied
00272     for (typename std::vector<AbstractCellPopulationBoundaryCondition<DIM>*>::iterator bcs_iter = mBoundaryConditions.begin();
00273          bcs_iter != mBoundaryConditions.end();
00274          ++bcs_iter)
00275     {
00276         if (!((*bcs_iter)->VerifyBoundaryCondition()))
00277         {
00278             EXCEPTION("The cell population boundary conditions are incompatible.");
00279         }
00280     }
00281 
00283     ApplyCellPopulationBoundaryConditions(old_node_locations);
00284 
00285     // Write node velocities to file if required
00286     if (mOutputNodeVelocities)
00287     {
00288         if (SimulationTime::Instance()->GetTimeStepsElapsed()%mSamplingTimestepMultiple == 0)
00289         {
00290             *mpNodeVelocitiesFile << SimulationTime::Instance()->GetTime() << "\t";
00291             for (unsigned node_index=0; node_index<num_nodes; node_index++)
00292             {
00293                 // We should never encounter deleted nodes due to where this method is called by Solve()
00294                 assert(!mrCellPopulation.GetNode(node_index)->IsDeleted());
00295 
00296                 // Check that results should be written for this node
00297                 bool is_real_node = true;
00298                 if (dynamic_cast<AbstractCentreBasedCellPopulation<DIM>*>(&mrCellPopulation))
00299                 {
00300                     if (static_cast<AbstractCentreBasedCellPopulation<DIM>*>(&mrCellPopulation)->IsGhostNode(node_index))
00301                     {
00302                         // If this node is a ghost node then don't record its velocity
00303                         is_real_node = false;
00304                     }
00305                     else
00306                     {
00307                         // We should never encounter nodes associated with dead cells due to where this method is called by Solve()
00308                         assert(!mrCellPopulation.GetCellUsingLocationIndex(node_index)->IsDead());
00309                     }
00310                 }
00311 
00312                 // Write node data to file
00313                 if (is_real_node)
00314                 {
00315                     const c_vector<double,DIM>& position = mrCellPopulation.GetNode(node_index)->rGetLocation();
00316                     c_vector<double, 2> velocity = this->mDt * rNodeForces[node_index] / this->mrCellPopulation.GetDampingConstant(node_index);
00317 
00318                     *mpNodeVelocitiesFile << node_index  << " ";
00319                     for (unsigned i=0; i<DIM; i++)
00320                     {
00321                         *mpNodeVelocitiesFile << position[i] << " ";
00322                     }
00323                     for (unsigned i=0; i<DIM; i++)
00324                     {
00325                         *mpNodeVelocitiesFile << velocity[i] << " ";
00326                     }
00327                 }
00328             }
00329             *mpNodeVelocitiesFile << "\n";
00330         }
00331     }
00332 }
00333 
00334 
00335 template<unsigned DIM>
00336 void CellBasedSimulation<DIM>::SetDt(double dt)
00337 {
00338     assert(dt > 0);
00339     mDt = dt;
00340 }
00341 
00342 
00343 template<unsigned DIM>
00344 double CellBasedSimulation<DIM>::GetDt()
00345 {
00346     return mDt;
00347 }
00348 
00349 
00350 template<unsigned DIM>
00351 unsigned CellBasedSimulation<DIM>::GetNumBirths()
00352 {
00353     return mNumBirths;
00354 }
00355 
00356 
00357 template<unsigned DIM>
00358 unsigned CellBasedSimulation<DIM>::GetNumDeaths()
00359 {
00360     return mNumDeaths;
00361 }
00362 
00363 
00364 template<unsigned DIM>
00365 void CellBasedSimulation<DIM>::SetEndTime(double endTime)
00366 {
00367     assert(endTime > 0);
00368     mEndTime = endTime;
00369 }
00370 
00371 
00372 template<unsigned DIM>
00373 void CellBasedSimulation<DIM>::SetOutputDirectory(std::string outputDirectory)
00374 {
00375     mOutputDirectory = outputDirectory;
00376     mSimulationOutputDirectory = mOutputDirectory;
00377 }
00378 
00379 
00380 template<unsigned DIM>
00381 std::string CellBasedSimulation<DIM>::GetOutputDirectory()
00382 {
00383     return mOutputDirectory;
00384 }
00385 
00386 template<unsigned DIM>
00387 void CellBasedSimulation<DIM>::SetSamplingTimestepMultiple(unsigned samplingTimestepMultiple)
00388 {
00389     assert(samplingTimestepMultiple > 0);
00390     mSamplingTimestepMultiple = samplingTimestepMultiple;
00391 }
00392 
00393 
00394 template<unsigned DIM>
00395 AbstractCellPopulation<DIM>& CellBasedSimulation<DIM>::rGetCellPopulation()
00396 {
00397     return mrCellPopulation;
00398 }
00399 
00400 
00401 template<unsigned DIM>
00402 const AbstractCellPopulation<DIM>& CellBasedSimulation<DIM>::rGetCellPopulation() const
00403 {
00404     return mrCellPopulation;
00405 }
00406 
00407 
00408 template<unsigned DIM>
00409 void CellBasedSimulation<DIM>::SetUpdateCellPopulationRule(bool updateCellPopulation)
00410 {
00411     mUpdateCellPopulation = updateCellPopulation;
00412 }
00413 
00414 
00415 template<unsigned DIM>
00416 void CellBasedSimulation<DIM>::SetNoBirth(bool noBirth)
00417 {
00418     mNoBirth = noBirth;
00419 }
00420 
00421 
00422 template<unsigned DIM>
00423 void CellBasedSimulation<DIM>::AddCellKiller(AbstractCellKiller<DIM>* pCellKiller)
00424 {
00425     mCellKillers.push_back(pCellKiller);
00426 }
00427 
00428 template<unsigned DIM>
00429 void CellBasedSimulation<DIM>::AddForce(AbstractForce<DIM>* pForce)
00430 {
00431     mForceCollection.push_back(pForce);
00432 }
00433 
00434 template<unsigned DIM>
00435 void CellBasedSimulation<DIM>::AddCellPopulationBoundaryCondition(AbstractCellPopulationBoundaryCondition<DIM>* pBoundaryCondition)
00436 {
00437     mBoundaryConditions.push_back(pBoundaryCondition);
00438 }
00439 
00440 
00441 template<unsigned DIM>
00442 std::vector<double> CellBasedSimulation<DIM>::GetNodeLocation(const unsigned& rNodeIndex)
00443 {
00444     std::vector<double> location;
00445     for (unsigned i=0; i<DIM; i++)
00446     {
00447         location.push_back(mrCellPopulation.GetNode(rNodeIndex)->rGetLocation()[i]);
00448     }
00449     return location;
00450 }
00451 
00452 
00453 template<unsigned DIM>
00454 void CellBasedSimulation<DIM>::Solve()
00455 {
00456     CellBasedEventHandler::BeginEvent(CellBasedEventHandler::EVERYTHING);
00457     CellBasedEventHandler::BeginEvent(CellBasedEventHandler::SETUP);
00458 
00459     // Set up the simulation time
00460     SimulationTime* p_simulation_time = SimulationTime::Instance();
00461     double current_time = p_simulation_time->GetTime();
00462 
00463     unsigned num_time_steps = (unsigned) ((mEndTime-current_time)/mDt+0.5);
00464 
00465     if (current_time > 0) // use the reset function if necessary
00466     {
00467         p_simulation_time->ResetEndTimeAndNumberOfTimeSteps(mEndTime, num_time_steps);
00468     }
00469     else
00470     {
00471         p_simulation_time->SetEndTimeAndNumberOfTimeSteps(mEndTime, num_time_steps);
00472     }
00473 
00474     if (mOutputDirectory=="")
00475     {
00476         EXCEPTION("OutputDirectory not set");
00477     }
00478 
00479     double time_now = p_simulation_time->GetTime();
00480     std::ostringstream time_string;
00481     time_string << time_now;
00482 
00483     std::string results_directory = mOutputDirectory +"/results_from_time_" + time_string.str();
00484     mSimulationOutputDirectory = results_directory;
00485 
00487     // Set up Simulation
00489 
00490     // Create output files for the visualizer
00491     OutputFileHandler output_file_handler(results_directory+"/", true);
00492 
00493     mrCellPopulation.CreateOutputFiles(results_directory+"/", false);
00494 
00495     mpVizSetupFile = output_file_handler.OpenOutputFile("results.vizsetup");
00496 
00497     if (mOutputNodeVelocities)
00498     {
00499         OutputFileHandler output_file_handler2(results_directory+"/", false);
00500         mpNodeVelocitiesFile = output_file_handler2.OpenOutputFile("nodevelocities.dat");
00501     }
00502 
00503     SetupSolve();
00504 
00505     // Age the cells to the correct time. Note that cells are created with
00506     // negative birth times so that some are initially almost ready to divide.
00507     LOG(1, "Setting up cells...");
00508     for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = mrCellPopulation.Begin();
00509          cell_iter != mrCellPopulation.End();
00510          ++cell_iter)
00511     {
00512         // We don't use the result; this call is just to force the cells to age
00513         // to the current time running their cell-cycle models to get there
00514         cell_iter->ReadyToDivide();
00515     }
00516     LOG(1, "\tdone\n");
00517 
00518     // Write initial conditions to file for the visualizer
00519     WriteVisualizerSetupFile();
00520 
00521     *mpVizSetupFile << std::flush;
00522 
00523     mrCellPopulation.WriteResultsToFiles();
00524 
00525     OutputSimulationSetup();
00526 
00527     CellBasedEventHandler::EndEvent(CellBasedEventHandler::SETUP);
00528 
00529     // Initialise a vector of forces on node
00530     std::vector<c_vector<double, DIM> > forces(mrCellPopulation.GetNumNodes(), zero_vector<double>(DIM));
00531 
00533     // Main time loop
00535 
00536     while ((p_simulation_time->GetTimeStepsElapsed() < num_time_steps) && !(StoppingEventHasOccurred()) )
00537     {
00538         LOG(1, "--TIME = " << p_simulation_time->GetTime() << "\n");
00539 
00546         UpdateCellPopulation();
00547 
00549         // Calculate Forces
00551         CellBasedEventHandler::BeginEvent(CellBasedEventHandler::FORCE);
00552 
00553         // First set all the forces to zero
00554         for (unsigned i=0; i<forces.size(); i++)
00555         {
00556              forces[i].clear();
00557         }
00558 
00559         // Then resize the std::vector if the number of cells has increased or decreased
00560         // (note this should be done after the above zeroing)
00561         unsigned num_nodes = mrCellPopulation.GetNumNodes();
00562         if (num_nodes != forces.size())
00563         {
00564             forces.resize(num_nodes, zero_vector<double>(DIM));
00565         }
00566 
00567         // Now add force contributions from each AbstractForce
00568         for (typename std::vector<AbstractForce<DIM>*>::iterator iter = mForceCollection.begin();
00569              iter != mForceCollection.end();
00570              ++iter)
00571         {
00572             (*iter)->AddForceContribution(forces, mrCellPopulation);
00573         }
00574         CellBasedEventHandler::EndEvent(CellBasedEventHandler::FORCE);
00575 
00577         // Update node positions
00579         CellBasedEventHandler::BeginEvent(CellBasedEventHandler::POSITION);
00580         UpdateNodePositions(forces);
00581         CellBasedEventHandler::EndEvent(CellBasedEventHandler::POSITION);
00582 
00584         // PostSolve, which may be implemented by
00585         // child classes (e.g. to solve PDEs)
00587         PostSolve();
00588 
00589         // Increment simulation time here, so results files look sensible
00590         p_simulation_time->IncrementTimeOneStep();
00591 
00593         // Output current results
00595         CellBasedEventHandler::BeginEvent(CellBasedEventHandler::OUTPUT);
00596 
00597         // Write results to file
00598         if (p_simulation_time->GetTimeStepsElapsed()%mSamplingTimestepMultiple == 0)
00599         {
00600             mrCellPopulation.WriteResultsToFiles();
00601         }
00602 
00603         CellBasedEventHandler::EndEvent(CellBasedEventHandler::OUTPUT);
00604     }
00605 
00606     LOG(1, "--END TIME = " << SimulationTime::Instance()->GetTime() << "\n");
00607     /* Carry out a final update so that cell population is coherent with new cell positions.
00608      * NB cell birth/death still need to be checked because they may be spatially-dependent.*/
00609     UpdateCellPopulation();
00610 
00611     AfterSolve();
00612 
00613     CellBasedEventHandler::BeginEvent(CellBasedEventHandler::OUTPUT);
00614 
00615     mrCellPopulation.CloseOutputFiles();
00616 
00617     if (mOutputNodeVelocities)
00618     {
00619         mpNodeVelocitiesFile->close();
00620     }
00621 
00622     *mpVizSetupFile << "Complete\n";
00623     mpVizSetupFile->close();
00624 
00625     CellBasedEventHandler::EndEvent(CellBasedEventHandler::OUTPUT);
00626 
00627     CellBasedEventHandler::EndEvent(CellBasedEventHandler::EVERYTHING);
00628 }
00629 
00630 
00631 template<unsigned DIM>
00632 bool CellBasedSimulation<DIM>::StoppingEventHasOccurred()
00633 {
00634     return false;
00635 }
00636 
00637 
00638 template<unsigned DIM>
00639 void CellBasedSimulation<DIM>::UpdateCellPopulation()
00640 {
00642     // Remove dead cells
00644     CellBasedEventHandler::BeginEvent(CellBasedEventHandler::DEATH);
00645     unsigned deaths_this_step = DoCellRemoval();
00646     mNumDeaths += deaths_this_step;
00647     LOG(1, "\tNum deaths = " << mNumDeaths << "\n");
00648     CellBasedEventHandler::EndEvent(CellBasedEventHandler::DEATH);
00649 
00651     // Divide cells
00653     CellBasedEventHandler::BeginEvent(CellBasedEventHandler::BIRTH);
00654     unsigned births_this_step = DoCellBirth();
00655     mNumBirths += births_this_step;
00656     LOG(1, "\tNum births = " << mNumBirths << "\n");
00657     CellBasedEventHandler::EndEvent(CellBasedEventHandler::BIRTH);
00658 
00659     // This allows NodeBasedCellPopulation::Update() to do the minimum amount of work
00660     bool births_or_death_occurred = ((births_this_step>0) || (deaths_this_step>0));
00661 
00663     // Update topology of cell population
00665     CellBasedEventHandler::BeginEvent(CellBasedEventHandler::UPDATECELLPOPULATION);
00666     if (mUpdateCellPopulation)
00667     {
00668         LOG(1, "\tUpdating cell population...");
00669         mrCellPopulation.Update(births_or_death_occurred);
00670         LOG(1, "\tdone.\n");
00671     }
00672     else if (births_or_death_occurred)
00673     {
00674         EXCEPTION("CellPopulation has had births or deaths but mUpdateCellPopulation is set to false, please set it to true.");
00675     }
00676     CellBasedEventHandler::EndEvent(CellBasedEventHandler::UPDATECELLPOPULATION);
00677 }
00678 
00679 template<unsigned DIM>
00680 void CellBasedSimulation<DIM>::OutputSimulationSetup()
00681 {
00682     OutputFileHandler output_file_handler(this->mSimulationOutputDirectory + "/", false);
00683 
00684     // Output machine information
00685     ExecutableSupport::WriteMachineInfoFile(this->mSimulationOutputDirectory + "/system_info");
00686 
00687     // Output Chaste provenance information
00688     out_stream build_info_file = output_file_handler.OpenOutputFile("build.info");
00689     ExecutableSupport::WriteLibraryInfo(build_info_file);
00690     build_info_file->close();
00691 
00692     // Output simulation parameter and setup details
00693     out_stream parameter_file = output_file_handler.OpenOutputFile("results.parameters");
00694 
00695     // Output simulation details
00696     std::string simulation_type = GetIdentifier();
00697 
00698     *parameter_file << "<Chaste>\n";
00699     *parameter_file << "\n\t<" << simulation_type << ">\n";
00700     OutputSimulationParameters(parameter_file);
00701     *parameter_file << "\t</" << simulation_type << ">\n";
00702     *parameter_file << "\n";
00703 
00704     // Output cell population details (includes cell-cycle model details)
00705     mrCellPopulation.OutputCellPopulationInfo(parameter_file);
00706 
00707     // Loop over forces
00708     *parameter_file << "\n\t<Forces>\n";
00709     for (typename std::vector<AbstractForce<DIM>*>::iterator iter = mForceCollection.begin();
00710          iter != mForceCollection.end();
00711          ++iter)
00712     {
00713         // Output force details
00714         (*iter)->OutputForceInfo(parameter_file);
00715     }
00716     *parameter_file << "\t</Forces>\n";
00717 
00718     // Loop over cell killers
00719     *parameter_file << "\n\t<CellKillers>\n";
00720     for (typename std::vector<AbstractCellKiller<DIM>*>::iterator iter = mCellKillers.begin();
00721          iter != mCellKillers.end();
00722          ++iter)
00723     {
00724         // Output cell killer details
00725         (*iter)->OutputCellKillerInfo(parameter_file);
00726     }
00727     *parameter_file << "\t</CellKillers>\n";
00728 
00729     // Loop over cell population boundary conditions
00730     *parameter_file << "\n\t<CellPopulationBoundaryConditions>\n";
00731     for (typename std::vector<AbstractCellPopulationBoundaryCondition<DIM>*>::iterator iter = mBoundaryConditions.begin();
00732          iter != mBoundaryConditions.end();
00733          ++iter)
00734     {
00735         // Output cell killer details
00736         (*iter)->OutputCellPopulationBoundaryConditionInfo(parameter_file);
00737     }
00738     *parameter_file << "\t</CellPopulationBoundaryConditions>\n";
00739 
00740     *parameter_file << "\n</Chaste>\n";
00741     parameter_file->close();
00742 }
00743 
00744 template<unsigned DIM>
00745 bool CellBasedSimulation<DIM>::GetOutputNodeVelocities()
00746 {
00747     return mOutputNodeVelocities;
00748 }
00749 
00750 template<unsigned DIM>
00751 void CellBasedSimulation<DIM>::SetOutputNodeVelocities(bool outputNodeVelocities)
00752 {
00753     mOutputNodeVelocities = outputNodeVelocities;
00754 }
00755 
00756 template<unsigned DIM>
00757 void CellBasedSimulation<DIM>::OutputSimulationParameters(out_stream& rParamsFile)
00758 {
00759     *rParamsFile << "\t\t<Dt>" << mDt << "</Dt>\n";
00760     *rParamsFile << "\t\t<EndTime>" << mEndTime << "</EndTime>\n";
00761     *rParamsFile << "\t\t<SamplingTimestepMultiple>" << mSamplingTimestepMultiple << "</SamplingTimestepMultiple>\n";
00762     *rParamsFile << "\t\t<OutputNodeVelocities>" << mOutputNodeVelocities << "</OutputNodeVelocities>\n";
00763 }
00764 
00765 
00766 // Serialization for Boost >= 1.36
00767 #include "SerializationExportWrapperForCpp.hpp"
00768 EXPORT_TEMPLATE_CLASS_SAME_DIMS(CellBasedSimulation)
00769 
00770 
00771 // Explicit instantiation
00773 
00774 template class CellBasedSimulation<1>;
00775 template class CellBasedSimulation<2>;
00776 template class CellBasedSimulation<3>;

Generated on Tue May 31 14:31:41 2011 for Chaste by  doxygen 1.5.5