00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
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),
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
00062 mpRandomGenerator = RandomNumberGenerator::Instance();
00063
00064
00065 if (dynamic_cast<AbstractCentreBasedCellPopulation<DIM>*>(&rCellPopulation))
00066 {
00067 mDt = 1.0/120.0;
00068 }
00069 else
00070 {
00071 mDt = 0.002;
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
00123 for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = mrCellPopulation.Begin();
00124 cell_iter != mrCellPopulation.End();
00125 ++cell_iter)
00126 {
00127
00128 if (cell_iter->GetAge() > 0.0)
00129 {
00130 if (cell_iter->ReadyToDivide())
00131 {
00132
00133 CellPtr p_new_cell = cell_iter->Divide();
00134
00135
00136 c_vector<double, DIM> new_location = CalculateCellDivisionVector(*cell_iter);
00137
00138
00139 mrCellPopulation.AddCell(p_new_cell, new_location, *cell_iter);
00140
00141
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
00156
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
00181 c_vector<double, DIM> parent_coords = mrCellPopulation.GetLocationOfCellCentre(pParentCell);
00182 c_vector<double, DIM> daughter_coords;
00183
00184
00185 double separation = static_cast<AbstractCentreBasedCellPopulation<DIM>*>(&mrCellPopulation)->GetMeinekeDivisionSeparation();
00186
00187
00188 c_vector<double, DIM> random_vector;
00189
00190
00191
00192
00193
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();
00215 double random_azimuth_angle = 2*M_PI*RandomNumberGenerator::Instance()->ranf();
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
00224 NEVER_REACHED;
00225 }
00226
00227 parent_coords = parent_coords - random_vector;
00228 daughter_coords = parent_coords + random_vector;
00229
00230
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
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
00252
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
00262 mrCellPopulation.UpdateNodeLocations(rNodeForces, mDt);
00263
00264
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
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
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
00295 assert(!mrCellPopulation.GetNode(node_index)->IsDeleted());
00296
00297
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
00304 is_real_node = false;
00305 }
00306 else
00307 {
00308
00309 assert(!mrCellPopulation.GetCellUsingLocationIndex(node_index)->IsDead());
00310 }
00311 }
00312
00313
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
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)
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
00490
00491
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
00507
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
00514
00515 cell_iter->ReadyToDivide();
00516 }
00517 LOG(1, "\tdone\n");
00518
00519
00520 WriteVisualizerSetupFile();
00521
00522 *mpVizSetupFile << std::flush;
00523
00524 mrCellPopulation.WriteResultsToFiles();
00525
00526 OutputSimulationSetup();
00527
00528 CellBasedEventHandler::EndEvent(CellBasedEventHandler::SETUP);
00529
00530
00531 std::vector<c_vector<double, DIM> > forces(mrCellPopulation.GetNumNodes(), zero_vector<double>(DIM));
00532
00534
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
00552 CellBasedEventHandler::BeginEvent(CellBasedEventHandler::FORCE);
00553
00554
00555 for (unsigned i=0; i<forces.size(); i++)
00556 {
00557 forces[i].clear();
00558 }
00559
00560
00561
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
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
00580 CellBasedEventHandler::BeginEvent(CellBasedEventHandler::POSITION);
00581 UpdateNodePositions(forces);
00582 CellBasedEventHandler::EndEvent(CellBasedEventHandler::POSITION);
00583
00585
00586
00588 PostSolve();
00589
00590
00591 p_simulation_time->IncrementTimeOneStep();
00592
00594
00596 CellBasedEventHandler::BeginEvent(CellBasedEventHandler::OUTPUT);
00597
00598
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
00609
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
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
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
00661 bool births_or_death_occurred = ((births_this_step>0) || (deaths_this_step>0));
00662
00664
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
00686 ExecutableSupport::WriteMachineInfoFile(this->mSimulationOutputDirectory + "/system_info");
00687
00688
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
00694 out_stream parameter_file = output_file_handler.OpenOutputFile("results.parameters");
00695
00696
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
00706 mrCellPopulation.OutputCellPopulationInfo(parameter_file);
00707
00708
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
00715 (*iter)->OutputForceInfo(parameter_file);
00716 }
00717 *parameter_file << "\t</Forces>\n";
00718
00719
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
00726 (*iter)->OutputCellKillerInfo(parameter_file);
00727 }
00728 *parameter_file << "\t</CellKillers>\n";
00729
00730
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
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
00768 #include "SerializationExportWrapperForCpp.hpp"
00769 EXPORT_TEMPLATE_CLASS_SAME_DIMS(CellBasedSimulation)
00770
00771
00772
00774
00775
00776 template class CellBasedSimulation<1>;
00777 template class CellBasedSimulation<2>;
00778 template class CellBasedSimulation<3>;