Computing solution after a fixed time
For long-time integration we recommend to use ITimeMap. It has almost the same interface as its nonrigorous version DTimeMap - see Long-time integration.
In order to compute trajectory after a given time we have to
- define an instance of ODE solver
This class is used to represent a map .
Definition: Map.h:125
int order
Definition: tayltst.cpp:31
capd::dynsys::OdeSolver< capd::IMap > IOdeSolver
Definition: typedefs.h:19
- define an instance of ITimeMap
TimeMap class provides methods for transport of sets (or points) by a given flow over some time inter...
Definition: TimeMap.h:34
- specify initial condition
capd::dynset::C0DoubletonSet< capd::IMatrix, C0Rect2Policies > C0Rect2Set
Definition: typedefs.h:46
intervals::DoubleInterval interval
Definition: DoubleInterval.h:36
- and integrate
IVector y = timeMap(finalTime,set);
Below is an example of integration of the Planar Restricted Circular Three Body Problem.
See also an example of integration of the Rossler system: Integration of an ordinary differential equation
Complete example (from examples/odesrig/ITimeMapExample.cpp):
#include <iostream>
void pcr3bpVectorField(Node , Node in[],
int , Node out[],
int , Node params[],
int )
{
Node mj = 1-params[0];
Node xMu = in[0] + params[0];
Node xMj = in[0] - mj;
Node xMuSquare = xMu^2;
Node xMjSquare = xMj^2;
Node ySquare = in[1]^2;
Node factor1 = mj*((xMuSquare+ySquare)^-1.5);
Node factor2 = params[0]*((xMjSquare+ySquare)^-1.5);
out[0] = in[2];
out[1] = in[3];
out[2] = in[0] - xMu*factor1 - xMj*factor2 + 2*in[3];
out[3] = in[1]*(1 - factor1 - factor2) - 2*in[2];
}
cout.precision(17);
int dim=4, noParam=1;
vf.setParameter(0, mu);
L1[0] = 0.9208034913207400196;
L1[3] =
sqrt(
sqr(L1[0]) + 2.*(mj/
abs(L1[0]+mu) + mu/
abs(L1[0]-mj)) + mu*mj - JacobiConstant);
cout << "T=0\n" << L1 << endl;
interval finalTime1 = 3.082119126376508;
interval finalTime2 = 3.082119126392904;
cout << "T=" << finalTime1 << "\n" << timeMap(finalTime1,set1) << endl;
cout << "T=" << finalTime2 << "\n" << timeMap(finalTime2,set2) << endl;
return 0;
}
double sqr(double x)
Definition: power.h:42
T abs(const T &x)
Definition: minmax.h:54
capd::dynset::C0HOSet< capd::C0TripletonSet > C0HOTripletonSet
Definition: typedefs.h:49
capd::dynset::C0TripletonSet< capd::IMatrix, C0Rect2Policies > C0TripletonSet
Definition: typedefs.h:47
int main(int argc, char *argv[])
Definition: argdemo.cpp:81
Interval< T_Bound, T_Rnd > sqrt(const Interval< T_Bound, T_Rnd > &x)
square root of x
Definition: Interval_Fun.hpp:290
void pcr3bpVectorField(Node, Node in[], int, Node out[], int, Node params[], int)
Definition: mapExample.cpp:16
Definition: ApplicationDesc.h:23
Definition: NodeType.h:192
Enclosure of trajectory between time steps.
Long time integration can be stopped after each step made and then resumed. It is enough to set flag
timeMap.stopAfterStep(true);
and integrate an ODE in a while loop
do{
timeMap(finalTime,set);
}while(!timeMap.completed());
After each step one can extract from the solver what time step has been made and get enclosure of trajectory for this time range.
Details are shown in the example bellow (see also another example Enclosure for a trajectory between time steps).
Complete example (from examples/odesrig/ITimeMapEncloseTrajectoryExample.cpp):
#include <iostream>
cout.precision(17);
IMap pendulum(
"time:t;par:omega;var:x,dx;fun:dx,sin(omega*t)-sin(x);");
pendulum.setParameter("omega",1.);
u[0] = 1.;
u[1] = 2.;
timeMap.stopAfterStep(true);
do{
timeMap(finalTime,set);
cout << "currentTime: " << set.getCurrentTime() << endl;
cout <<
"x(t) = " << (
IVector)set << endl;
cout << "enclosure over last time step: " << set.getLastEnclosure() << endl << endl;
}while(!timeMap.completed());
return 0;
}
capd::dynset::C0HOSet< capd::C0Rect2Set > C0HORect2Set
Definition: typedefs.h:48
capd::vectalg::Vector< capd::DInterval, CAPD_DEFAULT_DIMENSION > IVector
Definition: typedefs.h:33
Solutions to IVPs as functions
Class ITimeMap provides methods for computing solutions to IVPs that behave like regular functions. This mechanism is written in the spirit of functional programming. Using this method you will get a function solution that represents solution to IVP and you will be able to evaluate this function at any intermediate time
without additional integration of ODE.
This method is recommended if you
- do not know exact time t at which you will need the solution
- you need solution values for many intermediate times t
In order to obtain solution curve you have to
- define an instance of SolutionCurve - this is type defined in class ITimeMap
Definition: SolutionCurve.h:131
- specify initial condition and call your timeMap integrator
timeMap(finalTime,set,solution);
After the last line the object solution becomes a function that you can evaluate at given time. We will describe details in the sequel.
The type ITimeMap::SolutionCurve provides (in particular) methods for
- obtaining the domain at which this curve is defined - this should be interval [initialTime,finalTime]
double L = solution.getLeftDomain();
double R = solution.getRightDomain();
- evaluating the function. For one can compute which is guaranteed bound for the solution to the IVP at time t (it can be interval).
- Note
- An exception is thrown when the argument t in call to
solution(t)
is out of the domain
Complete example (from examples/odesrig/ITimeMapSolutionCurveExample.cpp):
#include <iostream>
cout.precision(17);
IMap pendulum(
"time:t;par:omega;var:x,dx;fun:dx,sin(omega*t)-sin(x);");
pendulum.setParameter("omega",1.);
u[0] = 1.;
u[1] = 2.;
double initTime = 4;
double finalTime = 10;
timeMap(finalTime,set,solution);
cout << "domain = [" << solution.getLeftDomain() << "," << solution.getRightDomain() << "]\n";
cout << "solution(4) =" << solution(4) << endl;
cout <<
"solution(5.,5.125) = " << solution(
interval(5,5.125)) << endl;
cout <<
"solution(7,8) =" << solution(
interval(7,8)) << endl;
cout << "solution(10)=" << solution(10) << endl;
return 0;
}