root/lang/cplusplus/boost-supplement/branches/numeric-ode/libs/numeric/ode/test_runge_kutta_rk4.cpp @ 6875

Revision 6875, 3.3 kB (checked in by mrkn, 5 years ago)

lang/cplusplus/boost-supplement/branches/numeric-ode/: A numerical integrator for ordinal differential equation.

  • Property svn:keywords set to Id
Line 
1/* $Id$ */
2
3#define BOOST_TEST_MAIN
4#include <boost/test/unit_test.hpp>
5
6#include <boost_supplement/numeric/ode/runge_kutta.hpp>
7
8#include <boost/test/floating_point_comparison.hpp>
9#include <boost/tuple/tuple.hpp>
10
11typedef boost::numeric::ublas::vector<double> dvector;
12typedef boost::numeric::ublas::matrix<double> dmatrix;
13
14namespace bs = boost_supplement;
15
16namespace {
17
18void
19nr_rk4(double y[], double dydx[], int n, double x, double h, double yout[],
20       void (*derivs)(double, double[], double[]))
21{
22  int i;
23  double xh, hh, h6, *dym, *dyt, *yt;
24  dym = new double[n+1];
25  dyt = new double[n+1];
26  yt  = new double[n+1];
27  hh = h*0.5;
28  h6 = h/6.0;
29  xh = x+hh;
30  for (i = 1; i <= n; i++) yt[i] = y[i]+hh*dydx[i];
31  (*derivs)(xh, yt, dyt);
32  for (i = 1; i <= n; i++) yt[i] = y[i]+hh*dyt[i];
33  (*derivs)(xh, yt, dym);
34  for (i = 1; i <= n; i++) {
35    yt[i] = y[i] + h*dym[i];
36    dym[i] += dyt[i];
37  }
38  (*derivs)(x+h, yt, dyt);
39  for (i = 1; i <= n; i++)
40    yout[i] = y[i] + h6*(dydx[i]+dyt[i]+2.0*dym[i]);
41  delete[] yt;
42  delete[] dyt;
43  delete[] dym;
44}
45
46void
47nr_rkdumb(double vstart[], int nvar, double x1, double x2, int nstep,
48          double* xx, double* y,
49          void (*derivs)(double, double[], double[]))
50{
51  int i, k;
52  double x, h;
53  double *v, *vout, *dv;
54
55  v = new double[nvar+1];
56  vout = new double[nvar+1];
57  dv = new double[nvar+1];
58  for (i = 1; i <= nvar; i++) {
59    v[i] = vstart[i];
60    y[i*(nstep+2) + 1] = v[i];
61  }
62  xx[1] = x1;
63  x = x1;
64  h = (x2 - x1)/nstep;
65  for (k = 1; k <= nstep; k++) {
66    (*derivs)(x, v, dv);
67    nr_rk4(v, dv, nvar, x, h, vout, derivs);
68    if ((double)(x+h) == x)
69      throw "Step size too small in routine rkdumb";
70    x += h;
71    xx[k+1] = x;
72    for (i = 1; i <= nvar; i++) {
73      v[i] = vout[i];
74      y[i*(nstep+2) + k+1] = v[i];
75    }
76  }
77
78  delete[] dv;
79  delete[] vout;
80  delete[] v;
81}
82
83void
84nr_derivative(double x, double y[], double dy[])
85{
86  dy[1] = y[2];
87  dy[2] = y[3];
88  dy[3] = y[1];
89}
90
91}
92
93dvector
94test_derivative(double x, dvector y)
95{
96  BOOST_ASSERT(3 == y.size());
97
98  dvector dy(3);
99  dy[0] = y[1];
100  dy[1] = y[2];
101  dy[2] = y[0];
102
103  return dy;
104}
105
106BOOST_AUTO_TEST_CASE(test_rk4)
107{
108  dvector y0(3);
109  y0[0] = y0[1] = y0[2] = 1.0;
110  dvector dydx0(test_derivative(0.0, y0));
111
112  double nr_y0[4] = { 0.0, 1.0, 1.0, 1.0 };
113  double nr_dydx0[4];
114  nr_derivative(0.0, nr_y0, nr_dydx0);
115
116  BOOST_CHECK_CLOSE(nr_dydx0[1], dydx0[0], 1e-13);
117  BOOST_CHECK_CLOSE(nr_dydx0[2], dydx0[1], 1e-13);
118  BOOST_CHECK_CLOSE(nr_dydx0[3], dydx0[2], 1e-13);
119
120  BOOST_CHECK_CLOSE(1.0, y0[0], 1e-13);
121  dvector y(bs::numeric::ode::rk4(y0, dydx0, 0.0, 0.1, test_derivative));
122
123  double nr_y[4];
124  nr_rk4(nr_y0, nr_dydx0, 3, 0.0, 0.1, nr_y, nr_derivative);
125
126  BOOST_CHECK_CLOSE(1.105170833333333, y[0], 1e-13);
127  BOOST_CHECK_CLOSE(nr_y[1], y[0], 1e-13);
128}
129
130BOOST_AUTO_TEST_CASE(test_rkdumb)
131{
132  dvector y0(3);
133  y0[0] = y0[1] = y0[2] = 1.0;
134
135  double nr_y0[4] = { 0.0, 1.0, 1.0, 1.0 };
136
137  dvector x;
138  dmatrix y;
139  boost::tie(x, y) = bs::numeric::ode::rkdumb(y0, 0.0, 1.0, 10, test_derivative);
140
141  double nr_y[4*12];
142  double nr_xx[11];
143  nr_rkdumb(nr_y0, 3, 0.0, 1.0, 10, nr_xx, nr_y, nr_derivative);
144
145  BOOST_CHECK_EQUAL(11, y.size1());
146  BOOST_CHECK_EQUAL(3, y.size2());
147
148  BOOST_CHECK_CLOSE(nr_y[1*12 + 11], y(10, 0), 1e-13);
149}
150
151/*
152 * Local Variables:
153 * coding: utf-8
154 * mode: c++
155 * c-basic-offset: 2
156 * indent-tabs-mode: nil
157 * End:
158 */
Note: See TracBrowser for help on using the browser.