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
00030
00031
00032
00033
00034
00035
00036 #include "OffLatticeSimulation.hpp"
00037 #include "AbstractCentreBasedCellPopulation.hpp"
00038 #include "VertexBasedCellPopulation.hpp"
00039 #include "T2SwapCellKiller.hpp"
00040 #include "AbstractVertexBasedDivisionRule.hpp"
00041 #include "Cylindrical2dMesh.hpp"
00042 #include "Cylindrical2dVertexMesh.hpp"
00043 #include "AbstractTwoBodyInteractionForce.hpp"
00044 #include "CellBasedEventHandler.hpp"
00045 #include "LogFile.hpp"
00046 #include "Version.hpp"
00047 #include "ExecutableSupport.hpp"
00048
00049 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00050 OffLatticeSimulation<ELEMENT_DIM,SPACE_DIM>::OffLatticeSimulation(AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>& rCellPopulation,
00051 bool deleteCellPopulationInDestructor,
00052 bool initialiseCells)
00053 : AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>(rCellPopulation, deleteCellPopulationInDestructor, initialiseCells)
00054 {
00055 if (!dynamic_cast<AbstractOffLatticeCellPopulation<ELEMENT_DIM,SPACE_DIM>*>(&rCellPopulation))
00056 {
00057 EXCEPTION("OffLatticeSimulations require a subclass of AbstractOffLatticeCellPopulation.");
00058 }
00059
00060
00061 if (dynamic_cast<AbstractCentreBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>*>(&rCellPopulation))
00062 {
00063 this->mDt = 1.0/120.0;
00064 }
00065 else
00066 {
00067 assert(dynamic_cast<VertexBasedCellPopulation<SPACE_DIM>*>(&rCellPopulation));
00068 this->mDt = 0.002;
00069
00070
00071
00072 VertexBasedCellPopulation<SPACE_DIM>* p_vertex_based_cell_population = dynamic_cast<VertexBasedCellPopulation<SPACE_DIM>*>(&rCellPopulation);
00073 MAKE_PTR_ARGS(T2SwapCellKiller<SPACE_DIM>, T2_swap_cell_killer, (p_vertex_based_cell_population));
00074 this->AddCellKiller(T2_swap_cell_killer);
00075 }
00076 }
00077
00078 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00079 void OffLatticeSimulation<ELEMENT_DIM,SPACE_DIM>::AddForce(boost::shared_ptr<AbstractForce<ELEMENT_DIM,SPACE_DIM> > pForce)
00080 {
00081 mForceCollection.push_back(pForce);
00082 }
00083
00084 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00085 void OffLatticeSimulation<ELEMENT_DIM,SPACE_DIM>::RemoveAllForces()
00086 {
00087 mForceCollection.clear();
00088 }
00089
00090 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00091 void OffLatticeSimulation<ELEMENT_DIM,SPACE_DIM>::AddCellPopulationBoundaryCondition(boost::shared_ptr<AbstractCellPopulationBoundaryCondition<ELEMENT_DIM,SPACE_DIM> > pBoundaryCondition)
00092 {
00093 mBoundaryConditions.push_back(pBoundaryCondition);
00094 }
00095
00096 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00097 void OffLatticeSimulation<ELEMENT_DIM,SPACE_DIM>::RemoveAllCellPopulationBoundaryConditions()
00098 {
00099 mBoundaryConditions.clear();
00100 }
00101
00102 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00103 void OffLatticeSimulation<ELEMENT_DIM,SPACE_DIM>::UpdateCellLocationsAndTopology()
00104 {
00105
00106 CellBasedEventHandler::BeginEvent(CellBasedEventHandler::FORCE);
00107
00108
00109 for (typename AbstractMesh<ELEMENT_DIM, SPACE_DIM>::NodeIterator node_iter = this->mrCellPopulation.rGetMesh().GetNodeIteratorBegin();
00110 node_iter != this->mrCellPopulation.rGetMesh().GetNodeIteratorEnd();
00111 ++node_iter)
00112 {
00113 node_iter->ClearAppliedForce();
00114 }
00115
00116
00117 for (typename std::vector<boost::shared_ptr<AbstractForce<ELEMENT_DIM, SPACE_DIM> > >::iterator iter = mForceCollection.begin();
00118 iter != mForceCollection.end();
00119 ++iter)
00120 {
00121 (*iter)->AddForceContribution(this->mrCellPopulation);
00122 }
00123 CellBasedEventHandler::EndEvent(CellBasedEventHandler::FORCE);
00124
00125
00126 CellBasedEventHandler::BeginEvent(CellBasedEventHandler::POSITION);
00127 UpdateNodePositions();
00128 CellBasedEventHandler::EndEvent(CellBasedEventHandler::POSITION);
00129 }
00130
00131 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00132 c_vector<double, SPACE_DIM> OffLatticeSimulation<ELEMENT_DIM,SPACE_DIM>::CalculateCellDivisionVector(CellPtr pParentCell)
00133 {
00139
00140 if (dynamic_cast<AbstractCentreBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>*>(&(this->mrCellPopulation)))
00141 {
00142
00143 c_vector<double, SPACE_DIM> parent_coords = this->mrCellPopulation.GetLocationOfCellCentre(pParentCell);
00144 c_vector<double, SPACE_DIM> daughter_coords;
00145
00146
00147 double separation = static_cast<AbstractCentreBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>*>(&(this->mrCellPopulation))->GetMeinekeDivisionSeparation();
00148
00149
00150 c_vector<double, SPACE_DIM> random_vector;
00151
00152
00153
00154
00155
00156
00157 switch (SPACE_DIM)
00158 {
00159 case 1:
00160 {
00161 double random_direction = -1.0 + 2.0*(RandomNumberGenerator::Instance()->ranf() < 0.5);
00162
00163 random_vector(0) = 0.5*separation*random_direction;
00164 break;
00165 }
00166 case 2:
00167 {
00168 double random_angle = 2.0*M_PI*RandomNumberGenerator::Instance()->ranf();
00169
00170 random_vector(0) = 0.5*separation*cos(random_angle);
00171 random_vector(1) = 0.5*separation*sin(random_angle);
00172 break;
00173 }
00174 case 3:
00175 {
00176
00177
00178
00179
00180
00181
00182 double u = RandomNumberGenerator::Instance()->ranf();
00183 double v = RandomNumberGenerator::Instance()->ranf();
00184
00185 double random_azimuth_angle = 2*M_PI*u;
00186 double random_zenith_angle = std::acos(2*v - 1);
00187
00188 random_vector(0) = 0.5*separation*cos(random_azimuth_angle)*sin(random_zenith_angle);
00189 random_vector(1) = 0.5*separation*sin(random_azimuth_angle)*sin(random_zenith_angle);
00190 random_vector(2) = 0.5*separation*cos(random_zenith_angle);
00191 break;
00192 }
00193 default:
00194
00195 NEVER_REACHED;
00196 }
00197
00198 parent_coords = parent_coords - random_vector;
00199 daughter_coords = parent_coords + random_vector;
00200
00201
00202 ChastePoint<SPACE_DIM> parent_coords_point(parent_coords);
00203 unsigned node_index = this->mrCellPopulation.GetLocationIndexUsingCell(pParentCell);
00204 this->mrCellPopulation.SetNode(node_index, parent_coords_point);
00205
00206 return daughter_coords;
00207 }
00208 else
00209 {
00210
00211 assert(dynamic_cast<VertexBasedCellPopulation<SPACE_DIM>*>(&(this->mrCellPopulation)));
00212
00213 VertexBasedCellPopulation<SPACE_DIM>* p_vertex_population = dynamic_cast<VertexBasedCellPopulation<SPACE_DIM>*>(&(this->mrCellPopulation));
00214 boost::shared_ptr<AbstractVertexBasedDivisionRule<SPACE_DIM> > p_division_rule = p_vertex_population->GetVertexBasedDivisionRule();
00215
00216 return p_division_rule->CalculateCellDivisionVector(pParentCell, *p_vertex_population);
00217 }
00218 }
00219
00220 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00221 void OffLatticeSimulation<ELEMENT_DIM,SPACE_DIM>::WriteVisualizerSetupFile()
00222 {
00223 if (PetscTools::AmMaster())
00224 {
00225 for (unsigned i=0; i<this->mForceCollection.size(); i++)
00226 {
00227
00229
00230 boost::shared_ptr<AbstractForce<ELEMENT_DIM,SPACE_DIM> > p_force = this->mForceCollection[i];
00231 if (boost::dynamic_pointer_cast<AbstractTwoBodyInteractionForce<ELEMENT_DIM,SPACE_DIM> >(p_force))
00232 {
00233 double cutoff = (boost::static_pointer_cast<AbstractTwoBodyInteractionForce<ELEMENT_DIM,SPACE_DIM> >(p_force))->GetCutOffLength();
00234 *(this->mpVizSetupFile) << "Cutoff\t" << cutoff << "\n";
00235 }
00236 }
00237
00238
00239 if (dynamic_cast<MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>*>(&this->mrCellPopulation))
00240 {
00241 if (dynamic_cast<Cylindrical2dMesh*>(&(dynamic_cast<MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>*>(&(this->mrCellPopulation))->rGetMesh())))
00242 {
00243 *this->mpVizSetupFile << "MeshWidth\t" << this->mrCellPopulation.GetWidth(0) << "\n";
00244 }
00245 }
00246 else if (dynamic_cast<VertexBasedCellPopulation<SPACE_DIM>*>(&this->mrCellPopulation))
00247 {
00248 if (dynamic_cast<Cylindrical2dVertexMesh*>(&(dynamic_cast<VertexBasedCellPopulation<SPACE_DIM>*>(&(this->mrCellPopulation))->rGetMesh())))
00249 {
00250 *this->mpVizSetupFile << "MeshWidth\t" << this->mrCellPopulation.GetWidth(0) << "\n";
00251 }
00252 }
00253 }
00254 }
00255
00256 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00257 void OffLatticeSimulation<ELEMENT_DIM,SPACE_DIM>::UpdateNodePositions()
00258 {
00259
00260
00261
00262
00263 std::map<Node<SPACE_DIM>*, c_vector<double, SPACE_DIM> > old_node_locations;
00264 for (typename AbstractMesh<ELEMENT_DIM, SPACE_DIM>::NodeIterator node_iter = this->mrCellPopulation.rGetMesh().GetNodeIteratorBegin();
00265 node_iter != this->mrCellPopulation.rGetMesh().GetNodeIteratorEnd();
00266 ++node_iter)
00267 {
00268 old_node_locations[&(*node_iter)] = (node_iter)->rGetLocation();
00269 }
00270
00271
00272 static_cast<AbstractOffLatticeCellPopulation<ELEMENT_DIM,SPACE_DIM>*>(&(this->mrCellPopulation))->UpdateNodeLocations(this->mDt);
00273
00274
00275 for (typename std::vector<boost::shared_ptr<AbstractCellPopulationBoundaryCondition<ELEMENT_DIM,SPACE_DIM> > >::iterator bcs_iter = mBoundaryConditions.begin();
00276 bcs_iter != mBoundaryConditions.end();
00277 ++bcs_iter)
00278 {
00279 (*bcs_iter)->ImposeBoundaryCondition(old_node_locations);
00280 }
00281
00282
00283 for (typename std::vector<boost::shared_ptr<AbstractCellPopulationBoundaryCondition<ELEMENT_DIM,SPACE_DIM> > >::iterator bcs_iter = mBoundaryConditions.begin();
00284 bcs_iter != mBoundaryConditions.end();
00285 ++bcs_iter)
00286 {
00287 if (!((*bcs_iter)->VerifyBoundaryCondition()))
00288 {
00289 EXCEPTION("The cell population boundary conditions are incompatible.");
00290 }
00291 }
00292 }
00293
00294 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00295 void OffLatticeSimulation<ELEMENT_DIM,SPACE_DIM>::SetupSolve()
00296 {
00297
00298 for (typename AbstractMesh<ELEMENT_DIM, SPACE_DIM>::NodeIterator node_iter = this->mrCellPopulation.rGetMesh().GetNodeIteratorBegin();
00299 node_iter != this->mrCellPopulation.rGetMesh().GetNodeIteratorEnd();
00300 ++node_iter)
00301 {
00302 node_iter->ClearAppliedForce();
00303 }
00304 }
00305
00306
00307 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00308 void OffLatticeSimulation<ELEMENT_DIM,SPACE_DIM>::OutputAdditionalSimulationSetup(out_stream& rParamsFile)
00309 {
00310
00311 *rParamsFile << "\n\t<Forces>\n";
00312 for (typename std::vector<boost::shared_ptr<AbstractForce<ELEMENT_DIM,SPACE_DIM> > >::iterator iter = mForceCollection.begin();
00313 iter != mForceCollection.end();
00314 ++iter)
00315 {
00316
00317 (*iter)->OutputForceInfo(rParamsFile);
00318 }
00319 *rParamsFile << "\t</Forces>\n";
00320
00321
00322 *rParamsFile << "\n\t<CellPopulationBoundaryConditions>\n";
00323 for (typename std::vector<boost::shared_ptr<AbstractCellPopulationBoundaryCondition<ELEMENT_DIM,SPACE_DIM> > >::iterator iter = mBoundaryConditions.begin();
00324 iter != mBoundaryConditions.end();
00325 ++iter)
00326 {
00327
00328 (*iter)->OutputCellPopulationBoundaryConditionInfo(rParamsFile);
00329 }
00330 *rParamsFile << "\t</CellPopulationBoundaryConditions>\n";
00331 }
00332
00333 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00334 void OffLatticeSimulation<ELEMENT_DIM,SPACE_DIM>::OutputSimulationParameters(out_stream& rParamsFile)
00335 {
00336
00337 AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::OutputSimulationParameters(rParamsFile);
00338 }
00339
00341
00343
00344 template class OffLatticeSimulation<1,1>;
00345 template class OffLatticeSimulation<1,2>;
00346 template class OffLatticeSimulation<2,2>;
00347 template class OffLatticeSimulation<1,3>;
00348 template class OffLatticeSimulation<2,3>;
00349 template class OffLatticeSimulation<3,3>;
00350
00351
00352 #include "SerializationExportWrapperForCpp.hpp"
00353 EXPORT_TEMPLATE_CLASS_ALL_DIMS(OffLatticeSimulation)