Chaste Release::3.1
|
00001 /* 00002 00003 Copyright (c) 2005-2012, University of Oxford. 00004 All rights reserved. 00005 00006 University of Oxford means the Chancellor, Masters and Scholars of the 00007 University of Oxford, having an administrative office at Wellington 00008 Square, Oxford OX1 2JD, UK. 00009 00010 This file is part of Chaste. 00011 00012 Redistribution and use in source and binary forms, with or without 00013 modification, are permitted provided that the following conditions are met: 00014 * Redistributions of source code must retain the above copyright notice, 00015 this list of conditions and the following disclaimer. 00016 * Redistributions in binary form must reproduce the above copyright notice, 00017 this list of conditions and the following disclaimer in the documentation 00018 and/or other materials provided with the distribution. 00019 * Neither the name of the University of Oxford nor the names of its 00020 contributors may be used to endorse or promote products derived from this 00021 software without specific prior written permission. 00022 00023 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00024 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00025 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00026 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 00027 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00028 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 00029 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00030 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00031 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 00032 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00033 00034 */ 00035 00036 #include <cmath> 00037 #include <ctime> 00038 #include <iostream> 00039 #include <fstream> 00040 #include <set> 00041 00042 #include "AbstractCellBasedSimulation.hpp" 00043 #include "CellBasedEventHandler.hpp" 00044 #include "LogFile.hpp" 00045 #include "Version.hpp" 00046 #include "ExecutableSupport.hpp" 00047 #include "Exception.hpp" 00048 #include <typeinfo> 00049 00050 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00051 AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::AbstractCellBasedSimulation(AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>& rCellPopulation, 00052 bool deleteCellPopulationInDestructor, 00053 bool initialiseCells) 00054 : mDt(DOUBLE_UNSET), 00055 mEndTime(DOUBLE_UNSET), // hours - this is set later on 00056 mrCellPopulation(rCellPopulation), 00057 mDeleteCellPopulationInDestructor(deleteCellPopulationInDestructor), 00058 mInitialiseCells(initialiseCells), 00059 mNoBirth(false), 00060 mUpdateCellPopulation(true), 00061 mOutputDirectory(""), 00062 mSimulationOutputDirectory(mOutputDirectory), 00063 mNumBirths(0), 00064 mNumDeaths(0), 00065 mOutputDivisionLocations(false), 00066 mSamplingTimestepMultiple(1), 00067 mpCellBasedPdeHandler(NULL) 00068 { 00069 // Set a random seed of 0 if it wasn't specified earlier 00070 RandomNumberGenerator::Instance(); 00071 00072 if (mInitialiseCells) 00073 { 00074 mrCellPopulation.InitialiseCells(); 00075 } 00076 } 00077 00078 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00079 AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::~AbstractCellBasedSimulation() 00080 { 00081 if (mDeleteCellPopulationInDestructor) 00082 { 00083 delete &mrCellPopulation; 00084 delete mpCellBasedPdeHandler; 00085 } 00086 } 00087 00088 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00089 void AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::SetCellBasedPdeHandler(CellBasedPdeHandler<SPACE_DIM>* pCellBasedPdeHandler) 00090 { 00091 mpCellBasedPdeHandler = pCellBasedPdeHandler; 00092 } 00093 00094 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00095 CellBasedPdeHandler<SPACE_DIM>* AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::GetCellBasedPdeHandler() 00096 { 00097 return mpCellBasedPdeHandler; 00098 } 00099 00100 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00101 unsigned AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::DoCellBirth() 00102 { 00103 if (mNoBirth) 00104 { 00105 return 0; 00106 } 00107 00108 unsigned num_births_this_step = 0; 00109 00110 // Iterate over all cells, seeing if each one can be divided 00111 for (typename AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>::Iterator cell_iter = mrCellPopulation.Begin(); 00112 cell_iter != mrCellPopulation.End(); 00113 ++cell_iter) 00114 { 00115 // Check if this cell is ready to divide - if so create a new cell etc. 00116 if (cell_iter->GetAge() > 0.0) 00117 { 00118 if (cell_iter->ReadyToDivide()) 00119 { 00120 try 00121 { 00122 // Store age before division 00123 double cell_age =cell_iter->GetAge(); 00124 00125 // Create a new cell 00126 CellPtr p_new_cell = cell_iter->Divide(); 00127 00128 // Call method that determines how cell division occurs and returns a vector 00129 c_vector<double, SPACE_DIM> new_location = CalculateCellDivisionVector(*cell_iter); 00130 00131 // If required, output this location to file 00132 if (mOutputDivisionLocations) 00133 { 00134 *mpDivisionLocationFile << SimulationTime::Instance()->GetTime() << "\t"; 00135 for (unsigned i=0; i<SPACE_DIM; i++) 00136 { 00137 *mpDivisionLocationFile << new_location[i] << "\t"; 00138 } 00139 *mpDivisionLocationFile << "\t" << cell_age << "\n"; 00140 } 00141 00142 // Add new cell to the cell population 00143 mrCellPopulation.AddCell(p_new_cell, new_location, *cell_iter); 00144 00145 // Update counter 00146 num_births_this_step++; 00147 } 00148 catch (Exception& e) 00149 { 00150 if (!(e.GetShortMessage()=="No free space to divide.")) 00151 { 00152 NEVER_REACHED; 00153 // If you do reach here, then uncomment the following line to see why. 00154 //throw e; 00155 } 00156 } 00157 } 00158 } 00159 } 00160 return num_births_this_step; 00161 } 00162 00163 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00164 unsigned AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::DoCellRemoval() 00165 { 00166 unsigned num_deaths_this_step = 0; 00167 00168 /* 00169 * This labels cells as dead or apoptosing. It does not actually remove the cells, 00170 * mrCellPopulation.RemoveDeadCells() needs to be called for this. 00171 */ 00172 for (typename std::vector<boost::shared_ptr<AbstractCellKiller<SPACE_DIM> > >::iterator killer_iter = mCellKillers.begin(); 00173 killer_iter != mCellKillers.end(); 00174 ++killer_iter) 00175 { 00176 (*killer_iter)->CheckAndLabelCellsForApoptosisOrDeath(); 00177 } 00178 00179 num_deaths_this_step += mrCellPopulation.RemoveDeadCells(); 00180 00181 return num_deaths_this_step; 00182 } 00183 00184 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00185 void AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::SetDt(double dt) 00186 { 00187 assert(dt > 0); 00188 mDt = dt; 00189 } 00190 00191 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00192 double AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::GetDt() 00193 { 00194 return mDt; 00195 } 00196 00197 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00198 unsigned AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::GetNumBirths() 00199 { 00200 return mNumBirths; 00201 } 00202 00203 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00204 unsigned AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::GetNumDeaths() 00205 { 00206 return mNumDeaths; 00207 } 00208 00209 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00210 void AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::SetEndTime(double endTime) 00211 { 00212 assert(endTime > 0); 00213 mEndTime = endTime; 00214 } 00215 00216 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00217 void AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::SetOutputDirectory(std::string outputDirectory) 00218 { 00219 mOutputDirectory = outputDirectory; 00220 mSimulationOutputDirectory = mOutputDirectory; 00221 } 00222 00223 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00224 std::string AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::GetOutputDirectory() 00225 { 00226 return mOutputDirectory; 00227 } 00228 00229 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00230 void AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::SetSamplingTimestepMultiple(unsigned samplingTimestepMultiple) 00231 { 00232 assert(samplingTimestepMultiple > 0); 00233 mSamplingTimestepMultiple = samplingTimestepMultiple; 00234 } 00235 00236 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00237 AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>& AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::rGetCellPopulation() 00238 { 00239 return mrCellPopulation; 00240 } 00241 00242 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00243 const AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>& AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::rGetCellPopulation() const 00244 { 00245 return mrCellPopulation; 00246 } 00247 00248 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00249 void AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::SetUpdateCellPopulationRule(bool updateCellPopulation) 00250 { 00251 mUpdateCellPopulation = updateCellPopulation; 00252 } 00253 00254 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00255 void AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::SetNoBirth(bool noBirth) 00256 { 00257 mNoBirth = noBirth; 00258 } 00259 00260 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00261 void AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::AddCellKiller(boost::shared_ptr<AbstractCellKiller<SPACE_DIM> > pCellKiller) 00262 { 00263 mCellKillers.push_back(pCellKiller); 00264 } 00265 00266 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00267 void AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::RemoveAllCellKillers() 00268 { 00269 mCellKillers.clear(); 00270 } 00271 00272 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00273 std::vector<double> AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::GetNodeLocation(const unsigned& rNodeIndex) 00274 { 00275 std::vector<double> location; 00276 for (unsigned i=0; i<SPACE_DIM; i++) 00277 { 00278 location.push_back(mrCellPopulation.GetNode(rNodeIndex)->rGetLocation()[i]); 00279 } 00280 return location; 00281 } 00282 00283 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00284 void AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::Solve() 00285 { 00286 CellBasedEventHandler::BeginEvent(CellBasedEventHandler::EVERYTHING); 00287 CellBasedEventHandler::BeginEvent(CellBasedEventHandler::SETUP); 00288 00289 // Set up the simulation time 00290 SimulationTime* p_simulation_time = SimulationTime::Instance(); 00291 double current_time = p_simulation_time->GetTime(); 00292 00293 assert(mDt != DOUBLE_UNSET); //Subclass constructors take care of this 00294 00295 if (mEndTime == DOUBLE_UNSET) 00296 { 00297 EXCEPTION("SetEndTime has not yet been called."); 00298 } 00299 00300 /*Note that mDt is used here for "ideal time step". If this step doesn't divide the time remaining then 00301 * a *different* time step will be taken by the time-stepper. The real time-step (used in the SimulationTime 00302 * singleton is currently not available to this class! 00303 * Should we over-write the value of mDt, or should we change this behaviour? \todo #2159 00304 */ 00305 unsigned num_time_steps = (unsigned) ((mEndTime-current_time)/mDt+0.5); 00306 if (current_time > 0) // use the reset function if necessary 00307 { 00308 p_simulation_time->ResetEndTimeAndNumberOfTimeSteps(mEndTime, num_time_steps); 00309 } 00310 else 00311 { 00312 if (p_simulation_time->IsEndTimeAndNumberOfTimeStepsSetUp()) 00313 { 00314 EXCEPTION("End time and number of timesteps already setup. You should not use SimulationTime::SetEndTimeAndNumberOfTimeSteps in cell-based tests."); 00315 } 00316 else 00317 { 00318 p_simulation_time->SetEndTimeAndNumberOfTimeSteps(mEndTime, num_time_steps); 00319 } 00320 } 00321 00322 if (mOutputDirectory == "") 00323 { 00324 EXCEPTION("OutputDirectory not set"); 00325 } 00326 00327 double time_now = p_simulation_time->GetTime(); 00328 std::ostringstream time_string; 00329 time_string << time_now; 00330 00331 std::string results_directory = mOutputDirectory +"/results_from_time_" + time_string.str(); 00332 mSimulationOutputDirectory = results_directory; 00333 00334 // Set up simulation 00335 00336 // Create output files for the visualizer 00337 OutputFileHandler output_file_handler(results_directory+"/", true); 00338 00339 mrCellPopulation.CreateOutputFiles(results_directory+"/", false); 00340 00341 if (mOutputDivisionLocations) 00342 { 00343 mpDivisionLocationFile = output_file_handler.OpenOutputFile("divisions.dat"); 00344 } 00345 00346 if (PetscTools::AmMaster()) 00347 { 00348 mpVizSetupFile = output_file_handler.OpenOutputFile("results.vizsetup"); 00349 } 00350 00351 // If any PDEs have been defined, set up results files to store their solution 00352 if (mpCellBasedPdeHandler != NULL) 00353 { 00354 mpCellBasedPdeHandler->OpenResultsFiles(this->mSimulationOutputDirectory); 00355 if (PetscTools::AmMaster()) 00356 { 00357 *this->mpVizSetupFile << "PDE \n"; 00358 } 00359 } 00360 00361 SetupSolve(); 00362 00363 // Age the cells to the correct time. Note that cells are created with 00364 // negative birth times so that some are initially almost ready to divide. 00365 LOG(1, "Setting up cells..."); 00366 for (typename AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>::Iterator cell_iter = mrCellPopulation.Begin(); 00367 cell_iter != mrCellPopulation.End(); 00368 ++cell_iter) 00369 { 00370 // We don't use the result; this call is just to force the cells to age 00371 // to the current time running their cell-cycle models to get there 00372 cell_iter->ReadyToDivide(); 00373 } 00374 LOG(1, "\tdone\n"); 00375 00376 // Write initial conditions to file for the visualizer 00377 WriteVisualizerSetupFile(); 00378 00379 if (PetscTools::AmMaster()) 00380 { 00381 *mpVizSetupFile << std::flush; 00382 } 00383 00384 mrCellPopulation.WriteResultsToFiles(); 00385 00386 OutputSimulationSetup(); 00387 00388 CellBasedEventHandler::EndEvent(CellBasedEventHandler::SETUP); 00389 00390 00391 // Enter main time loop 00392 while (!( p_simulation_time->IsFinished() || StoppingEventHasOccurred() ) ) 00393 { 00394 LOG(1, "--TIME = " << p_simulation_time->GetTime() << "\n"); 00395 00396 // This function calls DoCellRemoval(), DoCellBirth() and CellPopulation::Update() 00397 UpdateCellPopulation(); 00398 00399 // Update cell locations and topology 00400 UpdateCellLocationsAndTopology(); 00401 00402 // If any PDEs have been defined, solve them and store their solution in results files 00403 if (mpCellBasedPdeHandler != NULL) 00404 { 00405 CellBasedEventHandler::BeginEvent(CellBasedEventHandler::PDE); 00406 mpCellBasedPdeHandler->SolvePdeAndWriteResultsToFile(this->mSamplingTimestepMultiple); 00407 CellBasedEventHandler::EndEvent(CellBasedEventHandler::PDE); 00408 } 00409 00410 // Call UpdateAtEndOfTimeStep(), which may be implemented by child classes 00411 CellBasedEventHandler::BeginEvent(CellBasedEventHandler::UPDATESIMULATION); 00412 UpdateAtEndOfTimeStep(); 00413 CellBasedEventHandler::EndEvent(CellBasedEventHandler::UPDATESIMULATION); 00414 00415 // Increment simulation time here, so results files look sensible 00416 p_simulation_time->IncrementTimeOneStep(); 00417 00418 // Output current results to file 00419 CellBasedEventHandler::BeginEvent(CellBasedEventHandler::OUTPUT); 00420 if (p_simulation_time->GetTimeStepsElapsed()%mSamplingTimestepMultiple == 0) 00421 { 00422 mrCellPopulation.WriteResultsToFiles(); 00423 } 00424 CellBasedEventHandler::EndEvent(CellBasedEventHandler::OUTPUT); 00425 } 00426 00427 LOG(1, "--END TIME = " << p_simulation_time->GetTime() << "\n"); 00428 00429 // Carry out a final update so that cell population is coherent with new cell positions. 00430 // NB cell birth/death still need to be checked because they may be spatially-dependent. 00431 UpdateCellPopulation(); 00432 00433 // If any PDEs have been defined, close the results files storing their solution 00434 if (mpCellBasedPdeHandler != NULL) 00435 { 00436 mpCellBasedPdeHandler->CloseResultsFiles(); 00437 } 00438 00439 CellBasedEventHandler::BeginEvent(CellBasedEventHandler::UPDATESIMULATION); 00440 UpdateAtEndOfSolve(); 00441 CellBasedEventHandler::EndEvent(CellBasedEventHandler::UPDATESIMULATION); 00442 00443 CellBasedEventHandler::BeginEvent(CellBasedEventHandler::OUTPUT); 00444 00445 mrCellPopulation.CloseOutputFiles(); 00446 00447 if (mOutputDivisionLocations) 00448 { 00449 mpDivisionLocationFile->close(); 00450 } 00451 00452 if (PetscTools::AmMaster()) 00453 { 00454 *mpVizSetupFile << "Complete\n"; 00455 mpVizSetupFile->close(); 00456 } 00457 00458 CellBasedEventHandler::EndEvent(CellBasedEventHandler::OUTPUT); 00459 CellBasedEventHandler::EndEvent(CellBasedEventHandler::EVERYTHING); 00460 } 00461 00462 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00463 bool AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::StoppingEventHasOccurred() 00464 { 00465 return false; 00466 } 00467 00468 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00469 void AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::UpdateCellPopulation() 00470 { 00471 // Remove dead cells 00472 CellBasedEventHandler::BeginEvent(CellBasedEventHandler::DEATH); 00473 unsigned deaths_this_step = DoCellRemoval(); 00474 mNumDeaths += deaths_this_step; 00475 LOG(1, "\tNum deaths = " << mNumDeaths << "\n"); 00476 CellBasedEventHandler::EndEvent(CellBasedEventHandler::DEATH); 00477 00478 // Divide cells 00479 CellBasedEventHandler::BeginEvent(CellBasedEventHandler::BIRTH); 00480 unsigned births_this_step = DoCellBirth(); 00481 mNumBirths += births_this_step; 00482 LOG(1, "\tNum births = " << mNumBirths << "\n"); 00483 CellBasedEventHandler::EndEvent(CellBasedEventHandler::BIRTH); 00484 00485 // This allows NodeBasedCellPopulation::Update() to do the minimum amount of work 00486 bool births_or_death_occurred = ((births_this_step>0) || (deaths_this_step>0)); 00487 00488 // Update topology of cell population 00489 CellBasedEventHandler::BeginEvent(CellBasedEventHandler::UPDATECELLPOPULATION); 00490 if (mUpdateCellPopulation) 00491 { 00492 LOG(1, "\tUpdating cell population..."); 00493 mrCellPopulation.Update(births_or_death_occurred); 00494 LOG(1, "\tdone.\n"); 00495 } 00496 else if (births_or_death_occurred) 00497 { 00498 EXCEPTION("CellPopulation has had births or deaths but mUpdateCellPopulation is set to false, please set it to true."); 00499 } 00500 CellBasedEventHandler::EndEvent(CellBasedEventHandler::UPDATECELLPOPULATION); 00501 } 00502 00503 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00504 bool AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::GetOutputDivisionLocations() 00505 { 00506 return mOutputDivisionLocations; 00507 } 00508 00509 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00510 void AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::SetOutputDivisionLocations(bool outputDivisionLocations) 00511 { 00512 mOutputDivisionLocations = outputDivisionLocations; 00513 } 00514 00515 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00516 void AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::OutputSimulationSetup() 00517 { 00518 OutputFileHandler output_file_handler(this->mSimulationOutputDirectory + "/", false); 00519 00520 // Output machine information 00521 ExecutableSupport::WriteMachineInfoFile(this->mSimulationOutputDirectory + "/system_info"); 00522 00523 // Output Chaste provenance information 00524 out_stream build_info_file = output_file_handler.OpenOutputFile("build.info"); 00525 ExecutableSupport::WriteLibraryInfo(build_info_file); 00526 build_info_file->close(); 00527 00528 // Output simulation parameter and setup details 00529 out_stream parameter_file = output_file_handler.OpenOutputFile("results.parameters"); 00530 00531 // Output simulation details 00532 std::string simulation_type = GetIdentifier(); 00533 00534 *parameter_file << "<Chaste>\n"; 00535 *parameter_file << "\n\t<" << simulation_type << ">\n"; 00536 OutputSimulationParameters(parameter_file); 00537 *parameter_file << "\t</" << simulation_type << ">\n"; 00538 *parameter_file << "\n"; 00539 00540 // Output cell population details (includes cell-cycle model details) 00541 mrCellPopulation.OutputCellPopulationInfo(parameter_file); 00542 00543 // Loop over cell killers 00544 *parameter_file << "\n\t<CellKillers>\n"; 00545 for (typename std::vector<boost::shared_ptr<AbstractCellKiller<SPACE_DIM> > >::iterator iter = mCellKillers.begin(); 00546 iter != mCellKillers.end(); 00547 ++iter) 00548 { 00549 // Output cell killer details 00550 (*iter)->OutputCellKillerInfo(parameter_file); 00551 } 00552 *parameter_file << "\t</CellKillers>\n"; 00553 00554 // This is used to output information about subclasses 00555 OutputAdditionalSimulationSetup(parameter_file); 00556 00557 *parameter_file << "\n</Chaste>\n"; 00558 parameter_file->close(); 00559 } 00560 00561 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00562 void AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::OutputSimulationParameters(out_stream& rParamsFile) 00563 { 00564 if (mpCellBasedPdeHandler != NULL) 00565 { 00566 mpCellBasedPdeHandler->OutputParameters(rParamsFile); 00567 } 00568 00569 *rParamsFile << "\t\t<Dt>" << mDt << "</Dt>\n"; 00570 *rParamsFile << "\t\t<EndTime>" << mEndTime << "</EndTime>\n"; 00571 *rParamsFile << "\t\t<SamplingTimestepMultiple>" << mSamplingTimestepMultiple << "</SamplingTimestepMultiple>\n"; 00572 *rParamsFile << "\t\t<OutputDivisionLocations>" << mOutputDivisionLocations << "</OutputDivisionLocations>\n"; 00573 } 00574 00576 // Explicit instantiation 00578 00579 template class AbstractCellBasedSimulation<1,1>; 00580 template class AbstractCellBasedSimulation<1,2>; 00581 template class AbstractCellBasedSimulation<2,2>; 00582 template class AbstractCellBasedSimulation<1,3>; 00583 template class AbstractCellBasedSimulation<2,3>; 00584 template class AbstractCellBasedSimulation<3,3>;