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
- define an instance of ITimeMap
- specify initial condition
- 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>
#include "capd/capdlib.h"
using namespace std;
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;
IMap vf(pcr3bpVectorField,dim,dim,noParam);
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;
}
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
and integrate an ODE in a while loop
do{
timeMap(finalTime,set);
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>
#include "capd/capdlib.h"
using namespace std;
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.;
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;
return 0;
}
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
- 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>
#include "capd/capdlib.h"
using namespace std;
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;
}