36#include "OffLatticeSimulation.hpp"
38#include <boost/make_shared.hpp>
40#include "CellBasedEventHandler.hpp"
41#include "ForwardEulerNumericalMethod.hpp"
42#include "StepSizeException.hpp"
44template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
46 bool deleteCellPopulationInDestructor,
52 EXCEPTION(
"OffLatticeSimulations require a subclass of AbstractOffLatticeCellPopulation.");
56template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
59 mForceCollection.push_back(pForce);
62template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
65 mForceCollection.clear();
68template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
71 mBoundaryConditions.push_back(pBoundaryCondition);
74template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
77 mBoundaryConditions.clear();
80template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
83 mpNumericalMethod = pNumericalMethod;
86template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
89 return mpNumericalMethod;
92template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
95 return mForceCollection;
99template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
102 mMaxAdaptiveTimeSteps = maxAdaptiveTimeStep;
105template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
108 return mMaxAdaptiveTimeSteps;
113template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
118 double time_advanced_so_far = 0;
119 double target_time_step = this->mDt;
120 double present_time_step = this->mDt;
122 while (time_advanced_so_far < target_time_step)
125 std::map<Node<SPACE_DIM>*, c_vector<double, SPACE_DIM> > old_node_locations;
128 node_iter != this->mrCellPopulation.rGetMesh().GetNodeIteratorEnd();
131 old_node_locations[&(*node_iter)] = (node_iter)->rGetLocation();
137 mpNumericalMethod->UpdateAllNodePositions(present_time_step);
138 ApplyBoundaries(old_node_locations);
141 time_advanced_so_far += present_time_step;
144 if (mpNumericalMethod->HasAdaptiveTimestep())
147 double timestep_increase = 0.01;
148 present_time_step = std::min((1+timestep_increase)*present_time_step, target_time_step - time_advanced_so_far);
154 unsigned adaptive_timer = 0;
156 if (mpNumericalMethod->HasAdaptiveTimestep() && adaptive_timer < mMaxAdaptiveTimeSteps )
159 RevertToOldLocations(old_node_locations);
160 present_time_step = std::min(e.GetSuggestedNewStep(), target_time_step - time_advanced_so_far);
174template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
178 node_iter != this->mrCellPopulation.rGetMesh().GetNodeIteratorEnd();
181 (node_iter)->rGetModifiableLocation() = oldNodeLoctions[&(*node_iter)];
185template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
190 bcs_iter != mBoundaryConditions.end();
193 (*bcs_iter)->ImposeBoundaryCondition(oldNodeLoctions);
198 bcs_iter != mBoundaryConditions.end();
201 if (!((*bcs_iter)->VerifyBoundaryCondition()))
203 EXCEPTION(
"The cell population boundary conditions are incompatible.");
208template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
213 for (
unsigned i=0; i<this->mForceCollection.size(); i++)
215 this->mForceCollection[i]->WriteDataToVisualizerSetupFile(this->mpVizSetupFile);
218 this->mrCellPopulation.WriteDataToVisualizerSetupFile(this->mpVizSetupFile);
222template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
227 node_iter != this->mrCellPopulation.rGetMesh().GetNodeIteratorEnd();
230 node_iter->ClearAppliedForce();
234 if (mpNumericalMethod ==
nullptr)
236 mpNumericalMethod = boost::make_shared<ForwardEulerNumericalMethod<ELEMENT_DIM, SPACE_DIM> >();
239 mpNumericalMethod->SetForceCollection(&mForceCollection);
240 mpNumericalMethod->SetBoundaryConditions(&mBoundaryConditions);
243template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
247 *rParamsFile <<
"\n\t<Forces>\n";
249 iter != mForceCollection.end();
253 (*iter)->OutputForceInfo(rParamsFile);
255 *rParamsFile <<
"\t</Forces>\n";
258 *rParamsFile <<
"\n\t<CellPopulationBoundaryConditions>\n";
260 iter != mBoundaryConditions.end();
264 (*iter)->OutputCellPopulationBoundaryConditionInfo(rParamsFile);
266 *rParamsFile <<
"\t</CellPopulationBoundaryConditions>\n";
269 *rParamsFile <<
"\n\t<NumericalMethod>\n";
270 mpNumericalMethod->OutputNumericalMethodInfo(rParamsFile);
271 *rParamsFile <<
"\t</NumericalMethod>\n";
274template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
#define EXCEPTION(message)
#define EXPORT_TEMPLATE_CLASS_ALL_DIMS(CLASS)
virtual void OutputSimulationParameters(out_stream &rParamsFile)=0
static void BeginEvent(unsigned event)
static void EndEvent(unsigned event)
const boost::shared_ptr< AbstractNumericalMethod< ELEMENT_DIM, SPACE_DIM > > GetNumericalMethod() const
unsigned GetMaxAdaptiveTimeStep() const
virtual void UpdateCellLocationsAndTopology()
void OutputAdditionalSimulationSetup(out_stream &rParamsFile)
void RemoveAllCellPopulationBoundaryConditions()
void AddCellPopulationBoundaryCondition(boost::shared_ptr< AbstractCellPopulationBoundaryCondition< ELEMENT_DIM, SPACE_DIM > > pBoundaryCondition)
const std::vector< boost::shared_ptr< AbstractForce< ELEMENT_DIM, SPACE_DIM > > > & rGetForceCollection() const
void SetNumericalMethod(boost::shared_ptr< AbstractNumericalMethod< ELEMENT_DIM, SPACE_DIM > > pNumericalMethod)
virtual void SetupSolve()
void SetMaxAdaptiveTimeStep(const unsigned maxAdaptiveTimeStep)
void ApplyBoundaries(std::map< Node< SPACE_DIM > *, c_vector< double, SPACE_DIM > > oldNodeLoctions)
virtual void WriteVisualizerSetupFile()
virtual void OutputSimulationParameters(out_stream &rParamsFile)
void RevertToOldLocations(std::map< Node< SPACE_DIM > *, c_vector< double, SPACE_DIM > > oldNodeLoctions)
void AddForce(boost::shared_ptr< AbstractForce< ELEMENT_DIM, SPACE_DIM > > pForce)
OffLatticeSimulation(AbstractCellPopulation< ELEMENT_DIM, SPACE_DIM > &rCellPopulation, bool deleteCellPopulationInDestructor=false, bool initialiseCells=true)