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 "TissueSimulation.hpp"
00035 #include "AbstractCellCentreBasedTissue.hpp"
00036 #include "CancerEventHandler.hpp"
00037 #include "LogFile.hpp"
00038
00039 template<unsigned DIM>
00040 TissueSimulation<DIM>::TissueSimulation(AbstractTissue<DIM>& rTissue,
00041 std::vector<AbstractForce<DIM>*> forceCollection,
00042 bool deleteTissueAndForceCollection,
00043 bool initialiseCells)
00044 : mDt(1.0/120.0),
00045 mEndTime(0.0),
00046 mrTissue(rTissue),
00047 mDeleteTissue(deleteTissueAndForceCollection),
00048 mAllocatedMemoryForForceCollection(deleteTissueAndForceCollection),
00049 mInitialiseCells(initialiseCells),
00050 mNoBirth(false),
00051 mUpdateTissue(true),
00052 mOutputDirectory(""),
00053 mSimulationOutputDirectory(mOutputDirectory),
00054 mNumBirths(0),
00055 mNumDeaths(0),
00056 mSamplingTimestepMultiple(1),
00057 mForceCollection(forceCollection)
00058 {
00059 mpConfig = TissueConfig::Instance();
00060
00061
00062 mpRandomGenerator = RandomNumberGenerator::Instance();
00063
00064 if (mInitialiseCells)
00065 {
00066 mrTissue.InitialiseCells();
00067 }
00068 }
00069
00070
00071 template<unsigned DIM>
00072 TissueSimulation<DIM>::~TissueSimulation()
00073 {
00074 if (mAllocatedMemoryForForceCollection)
00075 {
00076 for (typename std::vector<AbstractForce<DIM>*>::iterator force_iter = mForceCollection.begin();
00077 force_iter != mForceCollection.end();
00078 ++force_iter)
00079 {
00080 delete *force_iter;
00081 }
00082 }
00083
00084 if (mDeleteTissue)
00085 {
00086 for (typename std::vector<AbstractCellKiller<DIM>*>::iterator it=mCellKillers.begin();
00087 it != mCellKillers.end();
00088 ++it)
00089 {
00090 delete *it;
00091 }
00092 delete &mrTissue;
00093 }
00094 }
00095
00096
00097 template<unsigned DIM>
00098 unsigned TissueSimulation<DIM>::DoCellBirth()
00099 {
00100 if (mNoBirth)
00101 {
00102 return 0;
00103 }
00104
00105 unsigned num_births_this_step = 0;
00106
00107
00108 for (typename AbstractTissue<DIM>::Iterator cell_iter = mrTissue.Begin();
00109 cell_iter != mrTissue.End();
00110 ++cell_iter)
00111 {
00112
00113 if (cell_iter->GetAge() > 0.0)
00114 {
00115 if (cell_iter->ReadyToDivide())
00116 {
00117
00118 TissueCell new_cell = cell_iter->Divide();
00119
00121 c_vector<double, DIM> new_location = zero_vector<double>(DIM);
00122 if (dynamic_cast<AbstractCellCentreBasedTissue<DIM>*>(&mrTissue))
00123 {
00124 new_location = CalculateDividingCellCentreLocations(&(*cell_iter));
00125 }
00126
00127
00128 mrTissue.AddCell(new_cell, new_location, &(*cell_iter));
00129
00130
00131 num_births_this_step++;
00132 }
00133 }
00134 }
00135 return num_births_this_step;
00136 }
00137
00138
00139 template<unsigned DIM>
00140 unsigned TissueSimulation<DIM>::DoCellRemoval()
00141 {
00142 unsigned num_deaths_this_step = 0;
00143
00144
00145
00146 for (typename std::vector<AbstractCellKiller<DIM>*>::iterator killer_iter = mCellKillers.begin();
00147 killer_iter != mCellKillers.end();
00148 ++killer_iter)
00149 {
00150 (*killer_iter)->TestAndLabelCellsForApoptosisOrDeath();
00151 }
00152
00153 num_deaths_this_step += mrTissue.RemoveDeadCells();
00154
00155 return num_deaths_this_step;
00156 }
00157
00158
00159 template<unsigned DIM>
00160 const std::vector<AbstractForce<DIM>*> TissueSimulation<DIM>::rGetForceCollection() const
00161 {
00162 return mForceCollection;
00163 }
00164
00165
00166 template<unsigned DIM>
00167 c_vector<double, DIM> TissueSimulation<DIM>::CalculateDividingCellCentreLocations(TissueCell* pParentCell)
00168 {
00169
00170 c_vector<double, DIM> parent_coords = mrTissue.GetLocationOfCellCentre(pParentCell);
00171 c_vector<double, DIM> daughter_coords;
00172
00173
00174 double separation = TissueConfig::Instance()->GetDivisionSeparation();
00175
00176
00177 c_vector<double, DIM> random_vector;
00178
00179
00180
00181
00182
00183
00184 switch (DIM)
00185 {
00186 case 1:
00187 {
00188 double random_direction = -1.0 + 2.0*(RandomNumberGenerator::Instance()->ranf() < 0.5);
00189
00190 random_vector(0) = 0.5*separation*random_direction;
00191 break;
00192 }
00193 case 2:
00194 {
00195 double random_angle = 2.0*M_PI*RandomNumberGenerator::Instance()->ranf();
00196
00197 random_vector(0) = 0.5*separation*cos(random_angle);
00198 random_vector(1) = 0.5*separation*sin(random_angle);
00199 break;
00200 }
00201 case 3:
00202 {
00203 double random_zenith_angle = M_PI*RandomNumberGenerator::Instance()->ranf();
00204 double random_azimuth_angle = 2*M_PI*RandomNumberGenerator::Instance()->ranf();
00205
00206 random_vector(0) = 0.5*separation*cos(random_azimuth_angle)*sin(random_zenith_angle);
00207 random_vector(1) = 0.5*separation*sin(random_azimuth_angle)*sin(random_zenith_angle);
00208 random_vector(2) = 0.5*separation*cos(random_zenith_angle);
00209 break;
00210 }
00211 default:
00212
00213 NEVER_REACHED;
00214 }
00215
00216 parent_coords = parent_coords - random_vector;
00217 daughter_coords = parent_coords + random_vector;
00218
00219
00220 ChastePoint<DIM> parent_coords_point(parent_coords);
00221 unsigned node_index = mrTissue.GetLocationIndexUsingCell(pParentCell);
00222 mrTissue.SetNode(node_index, parent_coords_point);
00223
00224 return daughter_coords;
00225 }
00226
00227
00228 template<unsigned DIM>
00229 void TissueSimulation<DIM>::UpdateNodePositions(const std::vector< c_vector<double, DIM> >& rNodeForces)
00230 {
00231
00232
00233
00234 std::vector<c_vector<double, DIM> > old_node_locations;
00235 old_node_locations.reserve(mrTissue.GetNumNodes());
00236 for (unsigned node_index=0; node_index<mrTissue.GetNumNodes(); node_index++)
00237 {
00238 old_node_locations[node_index] = mrTissue.GetNode(node_index)->rGetLocation();
00239 }
00240
00241
00242 mrTissue.UpdateNodeLocations(rNodeForces, mDt);
00243
00244
00245 ApplyTissueBoundaryConditions(old_node_locations);
00246 }
00247
00248
00249 template<unsigned DIM>
00250 void TissueSimulation<DIM>::SetDt(double dt)
00251 {
00252 assert(dt > 0);
00253 mDt = dt;
00254 }
00255
00256
00257 template<unsigned DIM>
00258 double TissueSimulation<DIM>::GetDt()
00259 {
00260 return mDt;
00261 }
00262
00263
00264 template<unsigned DIM>
00265 unsigned TissueSimulation<DIM>::GetNumBirths()
00266 {
00267 return mNumBirths;
00268 }
00269
00270
00271 template<unsigned DIM>
00272 unsigned TissueSimulation<DIM>::GetNumDeaths()
00273 {
00274 return mNumDeaths;
00275 }
00276
00277
00278 template<unsigned DIM>
00279 void TissueSimulation<DIM>::SetEndTime(double endTime)
00280 {
00281 assert(endTime > 0);
00282 mEndTime = endTime;
00283 }
00284
00285
00286 template<unsigned DIM>
00287 void TissueSimulation<DIM>::SetOutputDirectory(std::string outputDirectory)
00288 {
00289 mOutputDirectory = outputDirectory;
00290 mSimulationOutputDirectory = mOutputDirectory;
00291 }
00292
00293
00294 template<unsigned DIM>
00295 std::string TissueSimulation<DIM>::GetOutputDirectory()
00296 {
00297 return mOutputDirectory;
00298 }
00299
00300
00301 template<unsigned DIM>
00302 void TissueSimulation<DIM>::SetSamplingTimestepMultiple(unsigned samplingTimestepMultiple)
00303 {
00304 assert(samplingTimestepMultiple > 0);
00305 mSamplingTimestepMultiple = samplingTimestepMultiple;
00306 }
00307
00308
00309 template<unsigned DIM>
00310 AbstractTissue<DIM>& TissueSimulation<DIM>::rGetTissue()
00311 {
00312 return mrTissue;
00313 }
00314
00315
00316 template<unsigned DIM>
00317 const AbstractTissue<DIM>& TissueSimulation<DIM>::rGetTissue() const
00318 {
00319 return mrTissue;
00320 }
00321
00322
00323 template<unsigned DIM>
00324 void TissueSimulation<DIM>::SetUpdateTissueRule(bool updateTissue)
00325 {
00326 mUpdateTissue = updateTissue;
00327 }
00328
00329
00330 template<unsigned DIM>
00331 void TissueSimulation<DIM>::SetNoBirth(bool noBirth)
00332 {
00333 mNoBirth = noBirth;
00334 }
00335
00336
00337 template<unsigned DIM>
00338 void TissueSimulation<DIM>::AddCellKiller(AbstractCellKiller<DIM>* pCellKiller)
00339 {
00340 mCellKillers.push_back(pCellKiller);
00341 }
00342
00343
00344 template<unsigned DIM>
00345 std::vector<double> TissueSimulation<DIM>::GetNodeLocation(const unsigned& rNodeIndex)
00346 {
00347 std::vector<double> location;
00348 for (unsigned i=0; i<DIM; i++)
00349 {
00350 location.push_back( mrTissue.GetNode(rNodeIndex)->rGetLocation()[i] );
00351 }
00352 return location;
00353 }
00354
00355
00356 template<unsigned DIM>
00357 void TissueSimulation<DIM>::Solve()
00358 {
00359 CancerEventHandler::BeginEvent(CancerEventHandler::EVERYTHING);
00360 CancerEventHandler::BeginEvent(CancerEventHandler::SETUP);
00361
00362
00363 SimulationTime *p_simulation_time = SimulationTime::Instance();
00364 double current_time = p_simulation_time->GetTime();
00365
00366 unsigned num_time_steps = (unsigned) ((mEndTime-current_time)/mDt+0.5);
00367
00368 if (current_time > 0)
00369 {
00370 p_simulation_time->ResetEndTimeAndNumberOfTimeSteps(mEndTime, num_time_steps);
00371 }
00372 else
00373 {
00374 p_simulation_time->SetEndTimeAndNumberOfTimeSteps(mEndTime, num_time_steps);
00375 }
00376
00377 if (mOutputDirectory=="")
00378 {
00379 EXCEPTION("OutputDirectory not set");
00380 }
00381
00382 double time_now = p_simulation_time->GetTime();
00383 std::ostringstream time_string;
00384 time_string << time_now;
00385
00386 std::string results_directory = mOutputDirectory +"/results_from_time_" + time_string.str();
00387 mSimulationOutputDirectory = results_directory;
00388
00390
00392
00393
00394 OutputFileHandler output_file_handler(results_directory+"/", true);
00395
00396 mrTissue.CreateOutputFiles(results_directory+"/", false);
00397
00398 mpSetupFile = output_file_handler.OpenOutputFile("results.vizsetup");
00399
00400 SetupSolve();
00401
00402
00403
00404 LOG(1, "Setting up cells...");
00405 for (typename AbstractTissue<DIM>::Iterator cell_iter = mrTissue.Begin();
00406 cell_iter != mrTissue.End();
00407 ++cell_iter)
00408 {
00409
00410
00411 cell_iter->ReadyToDivide();
00412 }
00413 LOG(1, "\tdone\n");
00414
00415
00416 if (DIM==2)
00417 {
00418 WriteVisualizerSetupFile();
00419 }
00420 *mpSetupFile << std::flush;
00421
00422 mrTissue.WriteResultsToFiles();
00423
00424 CancerEventHandler::EndEvent(CancerEventHandler::SETUP);
00425
00426
00427 std::vector<c_vector<double, DIM> > forces(mrTissue.GetNumNodes(),zero_vector<double>(DIM));
00428
00430
00432
00433 while ((p_simulation_time->GetTimeStepsElapsed() < num_time_steps) && !(StoppingEventHasOccurred()) )
00434 {
00435 LOG(1, "--TIME = " << p_simulation_time->GetTime() << "\n");
00436
00443 UpdateTissue();
00444
00446
00448 CancerEventHandler::BeginEvent(CancerEventHandler::FORCE);
00449
00450
00451 for (unsigned i=0; i<forces.size(); i++)
00452 {
00453 forces[i].clear();
00454 }
00455
00456
00457
00458 if (mrTissue.GetNumNodes()!=forces.size())
00459 {
00460 forces.resize(mrTissue.GetNumNodes(), zero_vector<double>(DIM));
00461 }
00462
00463
00464 for (typename std::vector<AbstractForce<DIM>*>::iterator iter = mForceCollection.begin();
00465 iter !=mForceCollection.end();
00466 iter++)
00467 {
00468 (*iter)->AddForceContribution(forces, mrTissue);
00469 }
00470 CancerEventHandler::EndEvent(CancerEventHandler::FORCE);
00471
00473
00475 CancerEventHandler::BeginEvent(CancerEventHandler::POSITION);
00476 UpdateNodePositions(forces);
00477 CancerEventHandler::EndEvent(CancerEventHandler::POSITION);
00478
00480
00481
00483 PostSolve();
00484
00485
00486 p_simulation_time->IncrementTimeOneStep();
00487
00489
00491 CancerEventHandler::BeginEvent(CancerEventHandler::OUTPUT);
00492
00493
00494 if (p_simulation_time->GetTimeStepsElapsed()%mSamplingTimestepMultiple==0)
00495 {
00496 mrTissue.WriteResultsToFiles();
00497 }
00498
00499 CancerEventHandler::EndEvent(CancerEventHandler::OUTPUT);
00500 }
00501
00502 LOG(1, "--END TIME = " << SimulationTime::Instance()->GetTime() << "\n");
00503
00504
00505 UpdateTissue();
00506
00507 AfterSolve();
00508
00509 CancerEventHandler::BeginEvent(CancerEventHandler::OUTPUT);
00510 mrTissue.CloseOutputFiles();
00511
00512 *mpSetupFile << "Complete\n";
00513 mpSetupFile->close();
00514
00515 CancerEventHandler::EndEvent(CancerEventHandler::OUTPUT);
00516
00517 CancerEventHandler::EndEvent(CancerEventHandler::EVERYTHING);
00518 }
00519
00520
00521 template<unsigned DIM>
00522 bool TissueSimulation<DIM>::StoppingEventHasOccurred()
00523 {
00524 return false;
00525 }
00526
00527
00528 template<unsigned DIM>
00529 void TissueSimulation<DIM>::UpdateTissue()
00530 {
00532
00534 CancerEventHandler::BeginEvent(CancerEventHandler::DEATH);
00535 unsigned deaths_this_step = DoCellRemoval();
00536 mNumDeaths += deaths_this_step;
00537 LOG(1, "\tNum deaths = " << mNumDeaths << "\n");
00538 CancerEventHandler::EndEvent(CancerEventHandler::DEATH);
00539
00541
00543 CancerEventHandler::BeginEvent(CancerEventHandler::BIRTH);
00544 unsigned births_this_step = DoCellBirth();
00545 mNumBirths += births_this_step;
00546 LOG(1, "\tNum births = " << mNumBirths << "\n");
00547 CancerEventHandler::EndEvent(CancerEventHandler::BIRTH);
00548
00549
00550 bool births_or_death_occurred = ((births_this_step>0) || (deaths_this_step>0));
00551
00553
00555 CancerEventHandler::BeginEvent(CancerEventHandler::UPDATETISSUE);
00556 if (mUpdateTissue)
00557 {
00558 LOG(1, "\tUpdating tissue...");
00559 mrTissue.Update(births_or_death_occurred);
00560 LOG(1, "\tdone.\n");
00561 }
00562 else if (births_or_death_occurred)
00563 {
00564 EXCEPTION("Tissue has had births or deaths but mUpdateTissue is set to false, please set it to true.");
00565 }
00566 CancerEventHandler::EndEvent(CancerEventHandler::UPDATETISSUE);
00567 }
00568
00570
00572
00573
00574 template class TissueSimulation<1>;
00575 template class TissueSimulation<2>;
00576 template class TissueSimulation<3>;