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

Generated on Mon Apr 18 11:35:28 2011 for Chaste by  doxygen 1.5.5