OffLatticeSimulation.cpp
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
00029 #include "OffLatticeSimulation.hpp"
00030 #include "AbstractCentreBasedCellPopulation.hpp"
00031 #include "VertexBasedCellPopulation.hpp"
00032
00033 #include "Cylindrical2dMesh.hpp"
00034 #include "Cylindrical2dVertexMesh.hpp"
00035
00036 #include "AbstractTwoBodyInteractionForce.hpp"
00037 #include "CellBasedEventHandler.hpp"
00038 #include "LogFile.hpp"
00039 #include "Version.hpp"
00040 #include "ExecutableSupport.hpp"
00041
00042 template<unsigned DIM>
00043 OffLatticeSimulation<DIM>::OffLatticeSimulation(AbstractCellPopulation<DIM>& rCellPopulation,
00044 bool deleteCellPopulationInDestructor,
00045 bool initialiseCells)
00046 : AbstractCellBasedSimulation<DIM>(rCellPopulation, deleteCellPopulationInDestructor, initialiseCells),
00047 mOutputNodeVelocities(false)
00048 {
00049 if (!dynamic_cast<AbstractOffLatticeCellPopulation<DIM>*>(&rCellPopulation))
00050 {
00051 EXCEPTION("OffLatticeSimulations require a subclass of AbstractOffLatticeCellPopulation.");
00052 }
00053
00054
00055 if (dynamic_cast<AbstractCentreBasedCellPopulation<DIM>*>(&rCellPopulation))
00056 {
00057 this->mDt = 1.0/120.0;
00058 }
00059 else
00060 {
00061 assert (dynamic_cast<VertexBasedCellPopulation<DIM>*>(&rCellPopulation));
00062 this->mDt = 0.002;
00063 }
00064 }
00065
00066 template<unsigned DIM>
00067 void OffLatticeSimulation<DIM>::AddForce(boost::shared_ptr<AbstractForce<DIM> > pForce)
00068 {
00069 mForceCollection.push_back(pForce);
00070 }
00071
00072 template<unsigned DIM>
00073 void OffLatticeSimulation<DIM>::AddCellPopulationBoundaryCondition(boost::shared_ptr<AbstractCellPopulationBoundaryCondition<DIM> > pBoundaryCondition)
00074 {
00075 mBoundaryConditions.push_back(pBoundaryCondition);
00076 }
00077
00078 template<unsigned DIM>
00079 void OffLatticeSimulation<DIM>::UpdateCellLocationsAndTopology()
00080 {
00081
00082 CellBasedEventHandler::BeginEvent(CellBasedEventHandler::FORCE);
00083
00084
00085 std::vector<c_vector<double, DIM> > forces(this->mrCellPopulation.GetNumNodes(), zero_vector<double>(DIM));
00086
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103 for (typename std::vector<boost::shared_ptr<AbstractForce<DIM> > >::iterator iter = mForceCollection.begin();
00104 iter != mForceCollection.end();
00105 ++iter)
00106 {
00107 (*iter)->AddForceContribution(forces, this->mrCellPopulation);
00108 }
00109 CellBasedEventHandler::EndEvent(CellBasedEventHandler::FORCE);
00110
00111
00112 CellBasedEventHandler::BeginEvent(CellBasedEventHandler::POSITION);
00113 UpdateNodePositions(forces);
00114 CellBasedEventHandler::EndEvent(CellBasedEventHandler::POSITION);
00115 }
00116
00117 template<unsigned DIM>
00118 c_vector<double, DIM> OffLatticeSimulation<DIM>::CalculateCellDivisionVector(CellPtr pParentCell)
00119 {
00125 if (dynamic_cast<AbstractCentreBasedCellPopulation<DIM>*>(&(this->mrCellPopulation)))
00126 {
00127
00128 c_vector<double, DIM> parent_coords = this->mrCellPopulation.GetLocationOfCellCentre(pParentCell);
00129 c_vector<double, DIM> daughter_coords;
00130
00131
00132 double separation = static_cast<AbstractCentreBasedCellPopulation<DIM>*>(&(this->mrCellPopulation))->GetMeinekeDivisionSeparation();
00133
00134
00135 c_vector<double, DIM> random_vector;
00136
00137
00138
00139
00140
00141
00142 switch (DIM)
00143 {
00144 case 1:
00145 {
00146 double random_direction = -1.0 + 2.0*(RandomNumberGenerator::Instance()->ranf() < 0.5);
00147
00148 random_vector(0) = 0.5*separation*random_direction;
00149 break;
00150 }
00151 case 2:
00152 {
00153 double random_angle = 2.0*M_PI*RandomNumberGenerator::Instance()->ranf();
00154
00155 random_vector(0) = 0.5*separation*cos(random_angle);
00156 random_vector(1) = 0.5*separation*sin(random_angle);
00157 break;
00158 }
00159 case 3:
00160 {
00161 double random_zenith_angle = M_PI*RandomNumberGenerator::Instance()->ranf();
00162 double random_azimuth_angle = 2*M_PI*RandomNumberGenerator::Instance()->ranf();
00163
00164 random_vector(0) = 0.5*separation*cos(random_azimuth_angle)*sin(random_zenith_angle);
00165 random_vector(1) = 0.5*separation*sin(random_azimuth_angle)*sin(random_zenith_angle);
00166 random_vector(2) = 0.5*separation*cos(random_zenith_angle);
00167 break;
00168 }
00169 default:
00170
00171 NEVER_REACHED;
00172 }
00173
00174 parent_coords = parent_coords - random_vector;
00175 daughter_coords = parent_coords + random_vector;
00176
00177
00178 ChastePoint<DIM> parent_coords_point(parent_coords);
00179 unsigned node_index = this->mrCellPopulation.GetLocationIndexUsingCell(pParentCell);
00180 this->mrCellPopulation.SetNode(node_index, parent_coords_point);
00181
00182 return daughter_coords;
00183 }
00184 else
00185 {
00187 return zero_vector<double>(DIM);
00188 }
00189 }
00190
00191 template<unsigned DIM>
00192 void OffLatticeSimulation<DIM>::WriteVisualizerSetupFile()
00193 {
00194 for (unsigned i=0; i<this->mForceCollection.size(); i++)
00195 {
00196 boost::shared_ptr<AbstractForce<DIM> > p_force = this->mForceCollection[i];
00197 if (boost::dynamic_pointer_cast<AbstractTwoBodyInteractionForce<DIM> >(p_force))
00198 {
00199 double cutoff = (boost::static_pointer_cast<AbstractTwoBodyInteractionForce<DIM> >(p_force))->GetCutOffLength();
00200 *(this->mpVizSetupFile) << "Cutoff\t" << cutoff << "\n";
00201 }
00202 }
00203
00204
00205 if (dynamic_cast<MeshBasedCellPopulation<DIM>*>(&this->mrCellPopulation))
00206 {
00207 if (dynamic_cast<Cylindrical2dMesh*>(&(dynamic_cast<MeshBasedCellPopulation<DIM>*>(&(this->mrCellPopulation))->rGetMesh())))
00208 {
00209 *this->mpVizSetupFile << "MeshWidth\t" << this->mrCellPopulation.GetWidth(0) << "\n";
00210 }
00211 }
00212 else if (dynamic_cast<VertexBasedCellPopulation<DIM>*>(&this->mrCellPopulation))
00213 {
00214 if (dynamic_cast<Cylindrical2dVertexMesh*>(&(dynamic_cast<VertexBasedCellPopulation<DIM>*>(&(this->mrCellPopulation))->rGetMesh())))
00215 {
00216 *this->mpVizSetupFile << "MeshWidth\t" << this->mrCellPopulation.GetWidth(0) << "\n";
00217 }
00218 }
00219
00220 }
00221
00222 template<unsigned DIM>
00223 void OffLatticeSimulation<DIM>::UpdateNodePositions(const std::vector< c_vector<double, DIM> >& rNodeForces)
00224 {
00225 unsigned num_nodes = this->mrCellPopulation.GetNumNodes();
00226
00227
00228
00229
00230
00231 std::vector<c_vector<double, DIM> > old_node_locations;
00232 old_node_locations.reserve(num_nodes);
00233 for (unsigned node_index=0; node_index<num_nodes; node_index++)
00234 {
00235 old_node_locations[node_index] = this->mrCellPopulation.GetNode(node_index)->rGetLocation();
00236 }
00237
00238
00239 static_cast<AbstractOffLatticeCellPopulation<DIM>*>(&(this->mrCellPopulation))->UpdateNodeLocations(rNodeForces, this->mDt);
00240
00241
00242 for (typename std::vector<boost::shared_ptr<AbstractCellPopulationBoundaryCondition<DIM> > >::iterator bcs_iter = mBoundaryConditions.begin();
00243 bcs_iter != mBoundaryConditions.end();
00244 ++bcs_iter)
00245 {
00246 (*bcs_iter)->ImposeBoundaryCondition(old_node_locations);
00247 }
00248
00249
00250 for (typename std::vector<boost::shared_ptr<AbstractCellPopulationBoundaryCondition<DIM> > >::iterator bcs_iter = mBoundaryConditions.begin();
00251 bcs_iter != mBoundaryConditions.end();
00252 ++bcs_iter)
00253 {
00254 if (!((*bcs_iter)->VerifyBoundaryCondition()))
00255 {
00256 EXCEPTION("The cell population boundary conditions are incompatible.");
00257 }
00258 }
00259
00260
00261 if (mOutputNodeVelocities)
00262 {
00263 if (SimulationTime::Instance()->GetTimeStepsElapsed()%this->mSamplingTimestepMultiple == 0)
00264 {
00265 *mpNodeVelocitiesFile << SimulationTime::Instance()->GetTime() << "\t";
00266 for (unsigned node_index=0; node_index<num_nodes; node_index++)
00267 {
00268
00269 assert(!this->mrCellPopulation.GetNode(node_index)->IsDeleted());
00270
00271
00272 bool is_real_node = true;
00273
00274 if (dynamic_cast<AbstractCentreBasedCellPopulation<DIM>*>(&this->mrCellPopulation))
00275 {
00276 if (static_cast<AbstractCentreBasedCellPopulation<DIM>*>(&(this->mrCellPopulation))->IsGhostNode(node_index))
00277 {
00278
00279 is_real_node = false;
00280 }
00281 else
00282 {
00283
00284 assert(!this->mrCellPopulation.GetCellUsingLocationIndex(node_index)->IsDead());
00285 }
00286 }
00287
00288
00289 if (is_real_node)
00290 {
00291 const c_vector<double,DIM>& position = this->mrCellPopulation.GetNode(node_index)->rGetLocation();
00292 double damping_constant = static_cast<AbstractOffLatticeCellPopulation<DIM>*>(&(this->mrCellPopulation))->GetDampingConstant(node_index);
00293 c_vector<double, DIM> velocity = this->mDt * rNodeForces[node_index] / damping_constant;
00294
00295 *mpNodeVelocitiesFile << node_index << " ";
00296 for (unsigned i=0; i<DIM; i++)
00297 {
00298 *mpNodeVelocitiesFile << position[i] << " ";
00299 }
00300 for (unsigned i=0; i<DIM; i++)
00301 {
00302 *mpNodeVelocitiesFile << velocity[i] << " ";
00303 }
00304 }
00305 }
00306 *mpNodeVelocitiesFile << "\n";
00307 }
00308 }
00309 }
00310
00311 template<unsigned DIM>
00312 void OffLatticeSimulation<DIM>::SetupSolve()
00313 {
00314
00315 AbstractCellBasedSimulation<DIM>::SetupSolve();
00316
00317 if (mOutputNodeVelocities)
00318 {
00319 OutputFileHandler output_file_handler2(this->mSimulationOutputDirectory+"/", false);
00320 mpNodeVelocitiesFile = output_file_handler2.OpenOutputFile("nodevelocities.dat");
00321 }
00322 }
00323
00324 template<unsigned DIM>
00325 void OffLatticeSimulation<DIM>::AfterSolve()
00326 {
00327
00328 AbstractCellBasedSimulation<DIM>::AfterSolve();
00329
00330 if (mOutputNodeVelocities)
00331 {
00332 mpNodeVelocitiesFile->close();
00333 }
00334 }
00335
00336 template<unsigned DIM>
00337 void OffLatticeSimulation<DIM>::OutputAdditionalSimulationSetup(out_stream& rParamsFile)
00338 {
00339
00340 *rParamsFile << "\n\t<Forces>\n";
00341 for (typename std::vector<boost::shared_ptr<AbstractForce<DIM> > >::iterator iter = mForceCollection.begin();
00342 iter != mForceCollection.end();
00343 ++iter)
00344 {
00345
00346 (*iter)->OutputForceInfo(rParamsFile);
00347 }
00348 *rParamsFile << "\t</Forces>\n";
00349
00350
00351 *rParamsFile << "\n\t<CellPopulationBoundaryConditions>\n";
00352 for (typename std::vector<boost::shared_ptr<AbstractCellPopulationBoundaryCondition<DIM> > >::iterator iter = mBoundaryConditions.begin();
00353 iter != mBoundaryConditions.end();
00354 ++iter)
00355 {
00356
00357 (*iter)->OutputCellPopulationBoundaryConditionInfo(rParamsFile);
00358 }
00359 *rParamsFile << "\t</CellPopulationBoundaryConditions>\n";
00360 }
00361
00362 template<unsigned DIM>
00363 bool OffLatticeSimulation<DIM>::GetOutputNodeVelocities()
00364 {
00365 return mOutputNodeVelocities;
00366 }
00367
00368 template<unsigned DIM>
00369 void OffLatticeSimulation<DIM>::SetOutputNodeVelocities(bool outputNodeVelocities)
00370 {
00371 mOutputNodeVelocities = outputNodeVelocities;
00372 }
00373
00374 template<unsigned DIM>
00375 void OffLatticeSimulation<DIM>::OutputSimulationParameters(out_stream& rParamsFile)
00376 {
00377 *rParamsFile << "\t\t<OutputNodeVelocities>" << mOutputNodeVelocities << "</OutputNodeVelocities>\n";
00378
00379
00380 AbstractCellBasedSimulation<DIM>::OutputSimulationParameters(rParamsFile);
00381 }
00382
00384
00386
00387 template class OffLatticeSimulation<1>;
00388 template class OffLatticeSimulation<2>;
00389 template class OffLatticeSimulation<3>;
00390
00391
00392 #include "SerializationExportWrapperForCpp.hpp"
00393 EXPORT_TEMPLATE_CLASS_SAME_DIMS(OffLatticeSimulation)