Boost giving strange result for ode integration - c++

I ran the following code which solves a simple differential equation. The result seems to depend on tsteps. The result I get for tsteps = 100 is 9.688438503116524e-15, but for tsteps = 1000 the answer is 7.124585369895499e-218 much closer to the expected result.
#include <iostream>
#include <iomanip>
#include <boost/numeric/odeint.hpp> // odeint function definitions
using namespace std;
using namespace boost::numeric::odeint;
typedef std::vector< double> state_type;
int tsize = 1;
void my_observer( const state_type &x, const double t );
void initarrays(state_type &x)
{
x[0]=1.0e0;
}
void my_system( const state_type &x , state_type &dxdt , const double t )
{
dxdt[0]=-x[0];
}
void my_observer( const state_type &x, const double t )
{
std::cout<<t<<" ";
for(int i=0;i<tsize;i++)
{
std::cout<<x[i]<<" ";
}
std::cout<<std::endl;
}
int main()
{
std::cout.setf ( std::ios::scientific, std::ios::floatfield );
std::cout.precision(15);
int size=tsize;
state_type x0(size);
double err_abs = 1.0e-12;
double err_rel = 1.0e-12;
double a_x = 1.0;
double a_dxdt = 1.0;
initarrays(x0);
double t0 = 0.0e0;
int tsteps = 1000;
double t1 = 500.0e0;
double dt = (t1-t0)/((double)tsteps);
typedef runge_kutta_fehlberg78< state_type > solver;
typedef controlled_runge_kutta< solver > controller;
my_observer(x0,t0);
for(int ts=0;ts<tsteps;ts++)
{
integrate_adaptive( make_controlled( err_abs , err_rel , solver() ), my_system, x0 , t0+ts*dt , t0+(1+ts)*dt , dt);
my_observer(x0,t0+(1+ts)*dt);
}
}

Related

odeint c++ do_step openmp

I'm trying to use solve my ode system and use openmp. When I try stepper.do_step with:
typedef runge_kutta_dopri5< state_type , double , state_type , double , openmp_range_algebra > stepper;
I define my state_type as std::vector
And I compile I get:
error: expected unqualified-id before '.' token stepper.do_step(c , Y , t, dt );
Is it a problem of my typedef or I can't use do_step with openmp?
#include <boost/numeric/odeint.hpp>
#include<omp.h>
#include <boost/numeric/odeint/external/openmp/openmp.hpp>
typedef std::vector< double > state_type;
struct T
{
double m_param1;
double m_param2;
};
class sys
{
struct T T1;
public:
sys(struct T G) : T1(G) {}
void operator() ( state_type const& Y , state_type& dY , double t )
{
const size_t N = Y.size();
#pragma omp parallel for schedule(runtime)
for (size_t aux = 0; aux <= N; aux++) {
mdlfnt(Y,dY,t,T1.m_currents,T1.m_stim); //Here is my ode system
}
}
};
struct T T2;
state_type Y(45); // initial conditions
void main()
{
typedef runge_kutta_dopri5< state_type , double , state_type , double , openmp_range_algebra , default_operations , never_resizer > stepper;
int number_threads = 1;
omp_set_num_threads(number_threads);
int chunk_size = omp_get_max_threads();
omp_set_schedule( omp_sched_static , chunk_size );
for(int i=0;i<nd;i++){
sys c(T2);
stepperdo_step(c , Y , t, dt );
}
}

Passing a matrix as a parameter by function call operator overloading

As I know function call operator overloading is used to pass arbitrary number of parameter to a function inside a class. Is it also possible to pass a 2-Dimensional array ?
something like this in the following code:Edited
class harm_osc {
vector< vector<double> >& m_gam;
public:
harm_osc( vector< vector<double> > &gam ) : m_gam(gam) { }
void operator() ( const state_type &x , state_type &dxdt , const double /* t */ )
{
dxdt[0] = m_gam[0][0]*x[1];
dxdt[1] = m_gam[1][0]*x[0] - m_gam[1][1]*x[1];
}
};
When we have a large system of equations there are a lot of parameters.
Here an example from odeint library with some modification, with a single parameter:Edited
#include <iostream>
#include <vector>
#include <boost/numeric/odeint.hpp>
using namespace std;
/* The type of container used to hold the state vector */
typedef vector< double > state_type;
/* The rhs of x' = f(x) defined as a class */
class harm_osc {
vector< vector<double> >& m_gam;
public:
harm_osc( vector< vector<double> > &gam ) : m_gam(gam) { }
void operator() ( const state_type &x , state_type &dxdt , const double /* t */ )
{
dxdt[0] = m_gam[0][0]*x[1];
dxdt[1] = m_gam[1][0]*x[0] - m_gam[2][2]*x[1];
}
};
int main(int /* argc */ , char** /* argv */ )
{
using namespace boost::numeric::odeint;
//[ state_initialization
state_type x(2);
x[0] = 1.0; // start at x=1.0, p=0.0
x[1] = 0.0;
//]
//[ integration_class
vector< vector<double> > par {{1.,0.},{-1.,0.15}};
harm_osc ho(par);
size_t steps = integrate( ho ,
x , 0.0 , 10.0 , 0.1);
//]
}
Thanks for any guide or comment.

ODEINT output to txt file instead of console

Is there a way to write the outputs of t and x of this example to a txt file instead of the console. Thanks!
This is the example I copied from Odeint website.
#include <iostream>
#include <boost/numeric/odeint.hpp>
using namespace std;
using namespace boost::numeric::odeint;
/* we solve the simple ODE x' = 3/(2t^2) + x/(2t)
* with initial condition x(1) = 0.
* Analytic solution is x(t) = sqrt(t) - 1/t
*/
void rhs( const double x , double &dxdt , const double t )
{
dxdt = 3.0/(2.0*t*t) + x/(2.0*t);
}
void write_cout( const double &x , const double t )
{
cout << t << '\t' << x << endl;
}
// state_type = double
typedef runge_kutta_dopri5< double > stepper_type;
int main()
{
double x = 0.0;
integrate_adaptive( make_controlled( 1E-12 , 1E-12 , stepper_type() ) ,
rhs , x , 1.0 , 10.0 , 0.1 , write_cout );
}
you can simply pipe the output of this example into a text file
$ ./lorenz > data.txt
Otherwise you can use a C++ ofstreams to write the output directly into a file, e.g. described there: http://www.cplusplus.com/doc/tutorial/files/
just replace cout with object of ofstream.
#include <iostream>
#include <fstream>
#include <boost/numeric/odeint.hpp>
using namespace std;
using namespace boost::numeric::odeint;
ofstream data("data.txt");
/* we solve the simple ODE x' = 3/(2t^2) + x/(2t)
* with initial condition x(1) = 0.
* Analytic solution is x(t) = sqrt(t) - 1/t
*/
void rhs(const double x, double &dxdt, const double t)
{
dxdt = 3.0 / (2.0*t*t) + x / (2.0*t);
}
void write_cout(const double &x, const double t)
{
data << t << '\t' << x << endl;
}
// state_type = double
typedef runge_kutta_dopri5< double > stepper_type;
int main()
{
double x = 0.0;
integrate_adaptive(make_controlled(1E-12, 1E-12, stepper_type()),
rhs, x, 1.0, 10.0, 0.1, write_cout);
}

Define custom stepper for dynamic array in boost

How would I whip up a custom stepper for the ODE integrator in boost? I know how to do that for an array whose size is known at compile time. A simple implementation is like this
#include <boost/array.hpp>
#include <boost/numeric/odeint.hpp>
using namespace std;
using namespace boost::numeric::odeint;
typedef boost::array<double, 2> state_type;
template <size_t N>
class euler_stepper {
public:
typedef double value_type;
typedef double time_type;
typedef unsigned short order_type;
typedef boost::numeric::odeint::stepper_tag stepper_category;
static order_type order(void) { return(1); }
template<class System>
void do_step(System system, state_type &x, time_type t, time_type dt) const {
state_type der;
system(x , der);
for(size_t i=0 ; i<x.size(); i++) {
x[i] += dt*der[i];
}
}
};
struct rhs {
void operator()(const state_type &x, state_type &dxdt) const {
for(int i=0; i < x.size(); i++) dxdt[i] = -x[i];
}
};
struct observer {
void operator()(const state_type &x , double t) const {
for(int i=0; i < x.size(); i++) cout << x[i] << '\t';
cout << endl;
}
};
int main(int argc , char **argv) {
double dt = 0.01;
state_type x = {{2.0, 1.0}};
integrate_const(euler_stepper<2>(), rhs(), x, 0.0, 0.1, dt, observer());
return 0;
}
But how should I change the implementation, if I wanted to work with a state_type like this
typedef vector<complex<double>> state_type;
Basically, I would like to pass the size of the state vector as an argument to main.
Thanks,
Zoltán
Try this:
template < typename State >
class euler_stepper {
public:
using state_type = State;
using value_type = typename state_type::value_type;
using time_type = value_type;
using order_type = unsigned short;
using stepper_category = boost::numeric::odeint::stepper_tag;
static order_type order(void) { return(1); }
template<class System>
void do_step( System system , state_type &x , time_type t , time_type dt ) const
{
state_type der;
system(x , der);
for(size_t i=0 ; i<x.size(); i++) {
x[i] += dt*der[i];
}
}
};
You can also fix the state type for your solver, for example:
class euler_stepper
{
public:
using state_type = vector< complex< double > >;
using value_type = double;
using time_type = double;
// ...
};

GSL: Solving ODEs with time-dependent coefficients

I have an ODE of type:
x'(t) = a(t)x+g(t)
Which I am trying to solve. The only GSL ODE example isn't very helpful because the only coefficient (\mu) is not time dependent.
This question has been answered on the GSL mailing list however the answer is very unclear - g(t) is ignored and it has not been explained how to incorporate a(t) into func ( should it be passed in *params?).
Is there any example I can see where such an ODE is solved using GSL?
UPDATE: As has been pointed out below, this has been answered on the GSL mailing list. Here is a full example program of how this is done:
#include <stdio.h>
#include <math.h>
#include "gsl/gsl_errno.h"
#include "gsl/gsl_matrix.h"
#include "gsl/gsl_odeiv2.h"
int func(double t, const double y[], double f[], void *params) {
f[0] = -t* y[0];
return GSL_SUCCESS;
}
int jac(double t, const double y[], double *dfdy, double dfdt[], void
*params) {
gsl_matrix_view dfdy_mat = gsl_matrix_view_array(dfdy, 1, 1);
gsl_matrix * m = &dfdy_mat.matrix;
gsl_matrix_set(m, 0, 0, -t);
dfdt[0] = -1;
return GSL_SUCCESS;
}
int main(void) {
double mu = 0;
gsl_odeiv2_system sys = { func, jac, 1, &mu };
gsl_odeiv2_driver * d = gsl_odeiv2_driver_alloc_y_new(&sys,
gsl_odeiv2_step_rk1imp, 1e-7, 1e-7, 0.0);
int i;
double t = 0.0, t1 = 2.0;
const double x0 = 1.0;
double y[1] = {x0};
const int N = 100;
printf("time\t \tapprox solution \t exact solution\n");
for (i = 0; i <= N; i++) {
double ti = i * (t1 / N);
int status = gsl_odeiv2_driver_apply(d, &t, ti, y);
if (status != GSL_SUCCESS) {
printf("error, return value=%d\n", status);
break;
}
printf("%.5e\t%.5e\t\t%.5e\n", t, y[0], x0*exp(-0.5*t*t));
}
gsl_odeiv2_driver_free(d);
printf("\n...and done!\n");
return 0;
}
If you are not restricted to the GSL and/or C you can use http://odeint.com - a modern C++ library for ODEs. Odeint is part of boost, so it might be already installed on your system or can easily be installed be most of the package managers for Linux distributions.
You can simply define your coefficients and the ODE and use for example the RK4 method:
double coef_a( double t ) { /* return a(t) */ };
double coef_g( double t ) { /* return b(t) */ };
typedef std::array< double , 1 > state_type;
double ode( state_type const &x , state_type &dxdt , double )
{
dxdt[0] = coef_a( t ) * x[0] + coef_g( t );
}
state_type x;
double t_state , t_end , dt;
// initialize x
integrate_const( runge_kutta< state_type >() , ode , x , t_start , dt , t_end );