CellBasedSimulation.cpp

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

Generated on Mon Nov 1 12:35:16 2010 for Chaste by  doxygen 1.5.5