Solutions to IVPs as functions
Class [L]DTimeMap 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, say 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 or
- 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 [L]DTimeMap
double initialTime = ....;
- specify initial condition and call your timeMap integrator
double finalTime = ...;
timeMap(finalTime,u,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 DTimeMap::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 you can compute which is an approximate solution to IVP at time
t
. - Note
- An exception is thrown when the argument
t
in call to solution(t)
is out of the domain
Complete example (from examples/odes/DTimeMapSolutionCurveExample.cpp):
#include <iostream>
#include "capd/capdlib.h"
using namespace std;
cout.precision(21);
LDMap 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.;
long double initTime = 4;
long double finalTime = 10;
timeMap(finalTime,u,solution);
cout << "domain = [" << solution.getLeftDomain() << "," << solution.getRightDomain() << "]\n";
cout << "solution(4) =" << solution(4) << endl;
cout << "solution(7) =" << solution(7) << endl;
cout << "solution(10)=" << solution(10) << endl;
return 0;
}
First order variational equations - functional approach
As in the case of solving IVPs (see Solutions to IVPs as functions) one can obtain solution to variational equation as a functional object that can be evaluated at any intermediate time. In principle there are two differences:
- We can specify initial condition for variational equations. This argument (initMatrix in the example below) is optional. If it is skipped then the Identity matrix will be chosen as an initial condition for variational equations.
- We have to send an additional argument to operator that receives monodromy matrix at the end of trajectory and indicates that we intend to integrate variational equations.
Complete example (from examples/odes/DTimeMapMonodromyMatrixCurveExample.cpp):
#include <iostream>
#include "capd/capdlib.h"
using namespace std;
LDMap 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.;
long double initTime = 4;
long double finalTime = 10;
long double data[] = {1,1,3,4};
timeMap(finalTime,u,initMatrix,monodromyMatrix,solution);
cout.precision(21);
cout << "domain = [" << solution.getLeftDomain() << "," << solution.getRightDomain() << "]\n";
cout << "solution(4) =" << solution(4) << endl;
cout << "solution(7) =" << solution(7) << endl;
cout << "solution(10)=" << solution(10) << endl;
cout << "monodromyMatrix(4)=" << solution.derivative(4) << endl;
cout << "monodromyMatrix(7)=" << solution.derivative(7) << endl;
cout << "monodromyMatrix(10)=" << solution.derivative(10) << endl;
cout << monodromyMatrix << endl;
return 0;
}
Second order variational equations - functional approach
As in the case of solving IVPs (see Solutions to IVPs as functions) one can obtain solution to first and second order variational equation as a functional object that can be evaluated at any intermediate time. In principle there are two differences:
- We can specify initial condition for first and second order variational equations. These arguments (initMatrix and initHessian in the example below) are optional. If both of them are skipped then the Identity matrix will be chosen for first order variational equations and zero for the second order variational equations.
- We have to send two additional arguments to the operator that computes trajectory. These arguments receive monodromy matrix and normalized hassian at the end of trajectory, respectively. Moreover, they indicate that we intend to integrate second order variational equations.
Complete example (from examples/odes/DTimeMapHessianCurveExample.cpp):
#include <iostream>
#include "capd/capdlib.h"
using namespace std;
cout << "hessian(" << t << ")={";
cout << " " << h(i,j,c);
cout << " }\n";
}
LDMap 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.;
long double initTime = 4;
long double finalTime = 10;
long double initDerData[] = {1,1,3,4};
long double initHessData[] = {1,3,3,0,2,1};
timeMap(finalTime,u,initMatrix,initHessian,D,H,solution);
cout.precision(21);
cout << "domain = [" << solution.getLeftDomain() << "," << solution.getRightDomain() << "]\n";
cout << "solution(4) =" << solution(4) << endl;
cout << "solution(7) =" << solution(7) << endl;
cout << "solution(10)=" << solution(10) << endl;
cout << "monodromyMatrix(4)=" << solution.derivative(4) << endl;
cout << "monodromyMatrix(7)=" << solution.derivative(7) << endl;
cout << "monodromyMatrix(10)=" << solution.derivative(10) << endl;
cout << D << endl;
print(solution.hessian(4),4);
print(solution.hessian(7),7);
print(solution.hessian(10),10);
return 0;
}
Higher order variational equations - functional approach
The class [L]DCnTimeMap can compute solutions to higher order variational equations as a functional objects that can be evaluated at any intermediate time. In principle there are two differences:
- We can specify initial condition for all variational equations. This argument (initJet in the example below) is optional. If it is skipped then the Identity matrix will be chosen for first order variational equations and zero for higher order variational equations.
- We have to send one additional arguments to the operator that computes trajectory. This argument receives jet of solution and indicates that we intend to integrate higher order variational equations.
Complete example (from examples/odes/DTimeMapJetCurveExample.cpp):
#include <iostream>
#include "capd/capdlib.h"
const int degree = 4;
DMap pendulum(
"time:t;par:omega;var:x,dx;fun:dx,sin(omega*t)-sin(x);",degree);
pendulum.setParameter("omega",1.);
double initTime = 4;
double finalTime = 10;
initJet(0) = 1; initJet(1) = 2;
initJet(0,0) = 1; initJet(0,1) = 1; initJet(1,0) = 3; initJet(1,1) = 4;
initJet(0,0,0) = 1; initJet(0,0,1) = 3; initJet(0,1,1) = 3; initJet(1,0,0) = 0; initJet(1,0,1) = 2; initJet(1,1,1) = 1;
timeMap(finalTime,initJet,J,solution);
std::cout << "solution(7)=" << solution.jet(7).toString() << std::endl;
std::cout << "solution(10)="<< J.toString() << std::endl;
return 0;
}