18#ifndef _BOOST_ODEINT_INTEGRATOR_H_
19#define _BOOST_ODEINT_INTEGRATOR_H_
21#include "root_finding_integrator.h"
22#include <mbsim/dynamic_system_solver.h>
23#include <mbsim/utils/eps.h>
24#include <boost/numeric/odeint/util/is_resizeable.hpp>
25#include <boost/numeric/odeint/stepper/stepper_categories.hpp>
26#include <boost/numeric/ublas/matrix.hpp>
27#include <boost/numeric/ublas/matrix_proxy.hpp>
34 struct is_resizeable<fmatvec::Vec> {
35 typedef boost::true_type type;
36 static const bool value=
true;
42 inline int size(
const fmatvec::Vec& v) {
49 namespace BoostOdeintHelper {
55 inline void assign(fmatvec::Vec &d,
const fmatvec::Vec &s) {
56 if(d.size()!=s.size()) d.resize(s.size(),fmatvec::NONINIT);
59 template<
typename Dst,
typename Src>
60 inline void assign(Dst &d,
const Src &s) {
61 if(
static_cast<size_t>(d.size())!=
static_cast<size_t>(s.size()))
63 std::copy(s.begin(), s.end(), d.begin());
74 template<
class SystemCategory,
class ZdFunc,
class JacFunc>
77 template<
class ZdFunc,
class JacFunc>
81 const ZdFunc& operator()()
const {
return zdFunc_; }
83 const ZdFunc& zdFunc_;
86 template<
class ZdFunc,
class JacFunc>
89 BoostOdeintSystem(
const ZdFunc& zdFunc__,
const JacFunc& jacFunc__) : implFunc_(make_pair(zdFunc__, jacFunc__)) {}
90 const std::pair<ZdFunc, JacFunc>& operator()()
const {
return implFunc_; }
92 const std::pair<ZdFunc, JacFunc> implFunc_;
102 template<
typename DOS>
106 static constexpr bool isControlled{std::is_base_of<boost::numeric::odeint::controlled_stepper_tag,
107 typename DOS::UnderlayingStepperCategory>::value};
110 using EnableIfControlled=
typename std::enable_if<std::is_base_of<boost::numeric::odeint::controlled_stepper_tag,
111 typename H::UnderlayingStepperCategory>::value>::type;
115 void preIntegrate()
override;
116 void subIntegrate(
double tSamplePoint)
override;
117 void postIntegrate()
override;
123 template<
typename H=DOS,
typename=EnableIfControlled<H>>
127 template<
typename H=DOS,
typename=EnableIfControlled<H>>
131 template<
typename H=DOS,
typename=EnableIfControlled<H>>
137 void zd(
const typename DOS::state_type &z,
typename DOS::state_type &zd,
const double t);
139 void jac(
const typename DOS::state_type &z, boost::numeric::ublas::matrix<double> &jac,
const double t,
140 typename DOS::state_type &ft);
142 const std::function<void(
const typename DOS::state_type&,
typename DOS::state_type&,
const double)> zdFunc
145 const std::function<void(
const typename DOS::state_type&, boost::numeric::ublas::matrix<double>&c,
const double,
146 typename DOS::state_type&)> jacFunc
147 {bind(&BoostOdeintDOS<DOS>::jac,
this, std::placeholders::_1, std::placeholders::_2,
148 std::placeholders::_3, std::placeholders::_4)};
151 const BoostOdeintHelper::BoostOdeintSystem<
typename DOS::SystemCategory,
decltype(zdFunc),
decltype(jacFunc)>
152 boostOdeintSystem{zdFunc, jacFunc};
155 std::unique_ptr<DOS> dos;
166 typename DOS::state_type zTemp;
169 fmatvec::Vec zDisturbed;
183 template<
typename DOS>
184 void BoostOdeintDOS<DOS>::zd(
const typename DOS::state_type &z,
typename DOS::state_type &zd,
const double t) {
188 BoostOdeintHelper::assign(system->getState(), z);
189 system->resetUpToDate();
190 BoostOdeintHelper::assign(zd, system->evalzd());
195 template<
typename DOS>
196 void BoostOdeintDOS<DOS>::jac(
const typename DOS::state_type &z, boost::numeric::ublas::matrix<double> &jac,
const double t,
197 typename DOS::state_type &ft) {
200 if(
static_cast<size_t>(z.size())!=
static_cast<size_t>(jac.size1()) ||
201 static_cast<size_t>(z.size())!=
static_cast<size_t>(jac.size2()))
202 jac.resize(z.size(), z.size());
204 BoostOdeintHelper::assign(system->getState(), z);
205 system->resetUpToDate();
206 BoostOdeintHelper::assign(zDisturbed, z);
207 fmatvec::Vec zd0=system->evalzd();
209 for(
size_t i=0; i<static_cast<size_t>(z.size()); ++i) {
210 double delta=sqrt(macheps*std::max(1.e-5,abs(zDisturbed(i))));
211 double zDisturbediSave=zDisturbed(i);
212 zDisturbed(i)+=delta;
213 system->setState(zDisturbed);
214 system->resetUpToDate();
215 auto col=boost::numeric::ublas::column(jac, i);
216 auto zd=(system->evalzd()-zd0)/delta;
217 std::copy(zd.begin(), zd.end(), col.begin());
218 zDisturbed(i)=zDisturbediSave;
221 system->setTime(t+MBSim::epsroot);
222 system->setState(zDisturbed);
223 system->resetUpToDate();
224 BoostOdeintHelper::assign(ft, (system->evalzd()-zd0)*MBSim::epsrootInv);
227 template<
typename DOS>
234 template<
typename DOS>
246 system->setTime(tStart);
250 if(z0.size()!=system->getzSize()+system->getisSize())
251 throwError(
"BoostOdeintDOS:: size of z0 does not match, must be " + std::to_string(system->getzSize()+system->getisSize()));
252 BoostOdeintHelper::assign(zTemp, z0(fmatvec::RangeV(0,system->getzSize()-1)));
253 system->setInternalState(z0(fmatvec::RangeV(system->getzSize(),z0.size()-1)));
256 BoostOdeintHelper::assign(zTemp, system->evalz0());
258 BoostOdeintHelper::assign(system->getState(), zTemp);
259 system->resetUpToDate();
260 system->computeInitialCondition();
264 tPlot=tStart+plotSample*dtPlot;
266 svLast <<= system->evalsv();
267 BoostOdeintHelper::assign(zTemp, system->getState());
270 dos.reset(
new DOS(aTol, rTol, dtMax));
271 dos->initialize(zTemp, tStart, dt0);
274 template<
typename DOS>
275 void BoostOdeintDOS<DOS>::subIntegrate(
double tSamplePoint) {
277 static constexpr double oneMinusEps = 1 - std::numeric_limits<double>::epsilon();
278 while(dos->current_time()<tSamplePoint*oneMinusEps) {
281#if BOOST_VERSION >= 107100
283 dos->setDtMax(std::min(dtMax, tSamplePoint-dos->current_time()));
285 auto step=dos->do_step(boostOdeintSystem());
288 double curTimeAndState=dos->current_time();
289 system->setTime(dos->current_time());
290 BoostOdeintHelper::assign(system->getState(), dos->current_state());
291 system->resetUpToDate();
293 shift=signChangedWRTsvLast(system->evalsv());
297 double dt=step.second-step.first;
300 double tRoot=step.second-dt;
301 dos->calc_state(tRoot, zTemp);
302 curTimeAndState=tRoot;
303 system->setTime(tRoot);
304 BoostOdeintHelper::assign(system->getState(), zTemp);
305 system->resetUpToDate();
307 if(signChangedWRTsvLast(system->evalsv()))
312 dos->calc_state(step.second, zTemp);
313 curTimeAndState=step.second;
314 system->setTime(step.second);
315 BoostOdeintHelper::assign(system->getState(), zTemp);
316 system->resetUpToDate();
318 auto &sv=system->evalsv();
319 auto &jsv=system->getjsv();
320 for(
int i=0; i<sv.size(); ++i)
321 jsv(i)=svLast(i)*sv(i)<0;
326 static constexpr double onePlusEps = 1 + std::numeric_limits<double>::epsilon();
327 while(tPlot<=step.second*onePlusEps
328#
if BOOST_VERSION < 107100
329 && tPlot<=tSamplePoint*onePlusEps
332 dos->calc_state(tPlot, zTemp);
333 if(curTimeAndState!=tPlot) {
334 curTimeAndState=tPlot;
335 system->setTime(tPlot);
336 BoostOdeintHelper::assign(system->getState(), zTemp);
337 system->resetUpToDate();
342 msg(Status)<<
"t = "<<tPlot<<
", dt="<<dos->current_time_step()<<
" "<<std::flush;
343 system->updateInternalState();
345 tPlot=tStart+plotSample*dtPlot;
353 msg(Status)<<
"t = "<<step.second<<
", dt="<<dos->current_time_step()<<
" "<<std::flush;
356#if BOOST_VERSION < 107100
357 if(step.second<tSamplePoint) {
361 dos->calc_state(step.second, zTemp);
362 if(curTimeAndState!=step.second) {
363 curTimeAndState=step.second;
364 system->setTime(step.second);
365 BoostOdeintHelper::assign(system->getState(), zTemp);
366 system->resetUpToDate();
373 system->resetUpToDate();
380 svLast=system->evalsv();
382 BoostOdeintHelper::assign(zTemp, system->getState());
383 dos->initialize(zTemp, step.second, dos->current_time_step());
388 if((gMax>=0 || gdMax>=0) && curTimeAndState!=step.second) {
389 curTimeAndState=step.second;
390 system->setTime(step.second);
391 BoostOdeintHelper::assign(system->getState(), dos->current_state());
392 system->resetUpToDate();
395 bool reinitNeeded=
false;
396 if(gMax>=0 and system->positionDriftCompensationNeeded(gMax)) {
397 system->projectGeneralizedPositions(3);
398 system->projectGeneralizedVelocities(3);
401 else if(gdMax>=0 and system->velocityDriftCompensationNeeded(gdMax)) {
402 system->projectGeneralizedVelocities(3);
407 BoostOdeintHelper::assign(zTemp, system->getState());
408 dos->initialize(zTemp, step.second, dos->current_time_step());
410 system->updateStopVectorParameters();
412#if BOOST_VERSION < 107100
420 dos->calc_state(tSamplePoint, zTemp);
421 curTimeAndState=tSamplePoint;
422 system->setTime(tSamplePoint);
423 BoostOdeintHelper::assign(system->getState(), zTemp);
424 system->resetUpToDate();
425 dos->initialize(zTemp, tSamplePoint, dos->current_time_step());
426 system->updateStopVectorParameters();
430#if BOOST_VERSION >= 107100
433 if(curTimeAndState!=dos->current_time()) {
434 system->setTime(dos->current_time());
435 BoostOdeintHelper::assign(system->getState(), dos->current_state());
436 system->resetUpToDate();
439 system->updateInternalState();
443 template<
typename DOS>
444 void BoostOdeintDOS<DOS>::postIntegrate() {
445 msg(Info)<<std::endl;
446 msg(Info)<<
"Integration statistics:"<<std::endl;
447 msg(Info)<<
"nrSteps = "<<nrSteps<<std::endl;
448 msg(Info)<<
"nrRHS = "<<nrRHS<<std::endl;
449 msg(Info)<<
"nrJacs = "<<nrJacs<<std::endl;
450 msg(Info)<<
"nrPlots = "<<nrPlots<<std::endl;
451 msg(Info)<<
"nrSVs = "<<nrSVs<<std::endl;
452 msg(Info)<<
"nrRoots = "<<nrRoots<<std::endl;
453 msg(Info)<<
"nrDriftCorr = "<<nrDriftCorr<<std::endl;
458 template<
bool,
typename Self>
459 struct InitializeUsingXMLControlled;
462 template<
typename Self>
463 struct InitializeUsingXMLControlled<true, Self> {
464 static void call(Self self, xercesc::DOMElement* element) {
465 xercesc::DOMElement *e;
467 e=MBXMLUtils::E(element)->getFirstElementChildNamed(MBSIM%
"absoluteToleranceScalar");
468 if(e) self->setAbsoluteTolerance(MBXMLUtils::E(e)->getText<double>());
470 e=MBXMLUtils::E(element)->getFirstElementChildNamed(MBSIM%
"relativeToleranceScalar");
471 if(e) self->setRelativeTolerance(MBXMLUtils::E(e)->getText<double>());
473 e=MBXMLUtils::E(element)->getFirstElementChildNamed(MBSIM%
"maximumStepSize");
474 if(e) self->setMaximumStepSize(MBXMLUtils::E(e)->getText<double>());
479 template<
typename Self>
480 struct InitializeUsingXMLControlled<false, Self> {
481 static void call(Self self, xercesc::DOMElement* element) {
482 xercesc::DOMElement *e;
486 e=MBXMLUtils::E(element)->getFirstElementChildNamed(MBSIM%
"absoluteToleranceScalar");
487 if(e) self->throwError(
"absoluteToleranceScalar element used for an fixed step-size stepper.");
489 e=MBXMLUtils::E(element)->getFirstElementChildNamed(MBSIM%
"relativeToleranceScalar");
490 if(e) self->throwError(
"relativeToleranceScalar element used for an fixed step-size stepper.");
492 e=MBXMLUtils::E(element)->getFirstElementChildNamed(MBSIM%
"maximumStepSize");
493 if(e) self->throwError(
"maximumStepSize element used for an fixed step-size stepper.");
498 template<
typename DOS>
501 xercesc::DOMElement *e;
503 InitializeUsingXMLControlled<isControlled,
decltype(
this)>::call(
this, element);
505 e=MBXMLUtils::E(element)->getFirstElementChildNamed(MBSIM%
"initialStepSize");
506 if(e) setInitialStepSize(MBXMLUtils::E(e)->getText<double>());
Definition: boost_odeint_integrator.h:103
void setMaximumStepSize(double dtMax_)
Set maximum step size.
Definition: boost_odeint_integrator.h:132
void setRelativeTolerance(double rTol_)
Set relative tolerance.
Definition: boost_odeint_integrator.h:128
void setInitialStepSize(double dt0_)
Set initial step size.
Definition: boost_odeint_integrator.h:120
void integrate() override
start the integration of the system set by setSystem. Each class implemeting this function should cal...
Definition: boost_odeint_integrator.h:228
void initializeUsingXML(xercesc::DOMElement *element) override
initialize integrator
Definition: boost_odeint_integrator.h:499
void setAbsoluteTolerance(double aTol_)
Set absolute tolerance.
Definition: boost_odeint_integrator.h:124
Definition: boost_odeint_integrator.h:75
Integrator with root-finding.
Definition: root_finding_integrator.h:32
virtual void initializeUsingXML(xercesc::DOMElement *element)
initialize integrator
Definition: root_finding_integrator.cc:44
namespace MBSim
Definition: bilateral_constraint.cc:30
Definition: boost_odeint_integrator.h:67
Definition: boost_odeint_integrator.h:69