|
Packit |
67cb25 |
/* ode-initval/rk8pd.c
|
|
Packit |
67cb25 |
*
|
|
Packit |
67cb25 |
* Copyright (C) 1996, 1997, 1998, 1999, 2000 Gerard Jungman
|
|
Packit |
67cb25 |
*
|
|
Packit |
67cb25 |
* This program is free software; you can redistribute it and/or modify
|
|
Packit |
67cb25 |
* it under the terms of the GNU General Public License as published by
|
|
Packit |
67cb25 |
* the Free Software Foundation; either version 3 of the License, or (at
|
|
Packit |
67cb25 |
* your option) any later version.
|
|
Packit |
67cb25 |
*
|
|
Packit |
67cb25 |
* This program is distributed in the hope that it will be useful, but
|
|
Packit |
67cb25 |
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
67cb25 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
67cb25 |
* General Public License for more details.
|
|
Packit |
67cb25 |
*
|
|
Packit |
67cb25 |
* You should have received a copy of the GNU General Public License
|
|
Packit |
67cb25 |
* along with this program; if not, write to the Free Software
|
|
Packit |
67cb25 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Runge-Kutta 8(9), Prince-Dormand
|
|
Packit |
67cb25 |
*
|
|
Packit |
67cb25 |
* High Order Embedded Runge-Kutta Formulae
|
|
Packit |
67cb25 |
* P.J. Prince and J.R. Dormand
|
|
Packit |
67cb25 |
* J. Comp. Appl. Math.,7, pp. 67-75, 1981
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Author: G. Jungman
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
#include <config.h>
|
|
Packit |
67cb25 |
#include <stdlib.h>
|
|
Packit |
67cb25 |
#include <string.h>
|
|
Packit |
67cb25 |
#include <gsl/gsl_errno.h>
|
|
Packit |
67cb25 |
#include <gsl/gsl_odeiv.h>
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
#include "odeiv_util.h"
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Prince-Dormand constants */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
static const double Abar[] = {
|
|
Packit |
67cb25 |
14005451.0 / 335480064.0,
|
|
Packit |
67cb25 |
0.0,
|
|
Packit |
67cb25 |
0.0,
|
|
Packit |
67cb25 |
0.0,
|
|
Packit |
67cb25 |
0.0,
|
|
Packit |
67cb25 |
-59238493.0 / 1068277825.0,
|
|
Packit |
67cb25 |
181606767.0 / 758867731.0,
|
|
Packit |
67cb25 |
561292985.0 / 797845732.0,
|
|
Packit |
67cb25 |
-1041891430.0 / 1371343529.0,
|
|
Packit |
67cb25 |
760417239.0 / 1151165299.0,
|
|
Packit |
67cb25 |
118820643.0 / 751138087.0,
|
|
Packit |
67cb25 |
-528747749.0 / 2220607170.0,
|
|
Packit |
67cb25 |
1.0 / 4.0
|
|
Packit |
67cb25 |
};
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
static const double A[] = {
|
|
Packit |
67cb25 |
13451932.0 / 455176623.0,
|
|
Packit |
67cb25 |
0.0,
|
|
Packit |
67cb25 |
0.0,
|
|
Packit |
67cb25 |
0.0,
|
|
Packit |
67cb25 |
0.0,
|
|
Packit |
67cb25 |
-808719846.0 / 976000145.0,
|
|
Packit |
67cb25 |
1757004468.0 / 5645159321.0,
|
|
Packit |
67cb25 |
656045339.0 / 265891186.0,
|
|
Packit |
67cb25 |
-3867574721.0 / 1518517206.0,
|
|
Packit |
67cb25 |
465885868.0 / 322736535.0,
|
|
Packit |
67cb25 |
53011238.0 / 667516719.0,
|
|
Packit |
67cb25 |
2.0 / 45.0
|
|
Packit |
67cb25 |
};
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
static const double ah[] = {
|
|
Packit |
67cb25 |
1.0 / 18.0,
|
|
Packit |
67cb25 |
1.0 / 12.0,
|
|
Packit |
67cb25 |
1.0 / 8.0,
|
|
Packit |
67cb25 |
5.0 / 16.0,
|
|
Packit |
67cb25 |
3.0 / 8.0,
|
|
Packit |
67cb25 |
59.0 / 400.0,
|
|
Packit |
67cb25 |
93.0 / 200.0,
|
|
Packit |
67cb25 |
5490023248.0 / 9719169821.0,
|
|
Packit |
67cb25 |
13.0 / 20.0,
|
|
Packit |
67cb25 |
1201146811.0 / 1299019798.0
|
|
Packit |
67cb25 |
};
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
static const double b21 = 1.0 / 18.0;
|
|
Packit |
67cb25 |
static const double b3[] = { 1.0 / 48.0, 1.0 / 16.0 };
|
|
Packit |
67cb25 |
static const double b4[] = { 1.0 / 32.0, 0.0, 3.0 / 32.0 };
|
|
Packit |
67cb25 |
static const double b5[] = { 5.0 / 16.0, 0.0, -75.0 / 64.0, 75.0 / 64.0 };
|
|
Packit |
67cb25 |
static const double b6[] = { 3.0 / 80.0, 0.0, 0.0, 3.0 / 16.0, 3.0 / 20.0 };
|
|
Packit |
67cb25 |
static const double b7[] = {
|
|
Packit |
67cb25 |
29443841.0 / 614563906.0,
|
|
Packit |
67cb25 |
0.0,
|
|
Packit |
67cb25 |
0.0,
|
|
Packit |
67cb25 |
77736538.0 / 692538347.0,
|
|
Packit |
67cb25 |
-28693883.0 / 1125000000.0,
|
|
Packit |
67cb25 |
23124283.0 / 1800000000.0
|
|
Packit |
67cb25 |
};
|
|
Packit |
67cb25 |
static const double b8[] = {
|
|
Packit |
67cb25 |
16016141.0 / 946692911.0,
|
|
Packit |
67cb25 |
0.0,
|
|
Packit |
67cb25 |
0.0,
|
|
Packit |
67cb25 |
61564180.0 / 158732637.0,
|
|
Packit |
67cb25 |
22789713.0 / 633445777.0,
|
|
Packit |
67cb25 |
545815736.0 / 2771057229.0,
|
|
Packit |
67cb25 |
-180193667.0 / 1043307555.0
|
|
Packit |
67cb25 |
};
|
|
Packit |
67cb25 |
static const double b9[] = {
|
|
Packit |
67cb25 |
39632708.0 / 573591083.0,
|
|
Packit |
67cb25 |
0.0,
|
|
Packit |
67cb25 |
0.0,
|
|
Packit |
67cb25 |
-433636366.0 / 683701615.0,
|
|
Packit |
67cb25 |
-421739975.0 / 2616292301.0,
|
|
Packit |
67cb25 |
100302831.0 / 723423059.0,
|
|
Packit |
67cb25 |
790204164.0 / 839813087.0,
|
|
Packit |
67cb25 |
800635310.0 / 3783071287.0
|
|
Packit |
67cb25 |
};
|
|
Packit |
67cb25 |
static const double b10[] = {
|
|
Packit |
67cb25 |
246121993.0 / 1340847787.0,
|
|
Packit |
67cb25 |
0.0,
|
|
Packit |
67cb25 |
0.0,
|
|
Packit |
67cb25 |
-37695042795.0 / 15268766246.0,
|
|
Packit |
67cb25 |
-309121744.0 / 1061227803.0,
|
|
Packit |
67cb25 |
-12992083.0 / 490766935.0,
|
|
Packit |
67cb25 |
6005943493.0 / 2108947869.0,
|
|
Packit |
67cb25 |
393006217.0 / 1396673457.0,
|
|
Packit |
67cb25 |
123872331.0 / 1001029789.0
|
|
Packit |
67cb25 |
};
|
|
Packit |
67cb25 |
static const double b11[] = {
|
|
Packit |
67cb25 |
-1028468189.0 / 846180014.0,
|
|
Packit |
67cb25 |
0.0,
|
|
Packit |
67cb25 |
0.0,
|
|
Packit |
67cb25 |
8478235783.0 / 508512852.0,
|
|
Packit |
67cb25 |
1311729495.0 / 1432422823.0,
|
|
Packit |
67cb25 |
-10304129995.0 / 1701304382.0,
|
|
Packit |
67cb25 |
-48777925059.0 / 3047939560.0,
|
|
Packit |
67cb25 |
15336726248.0 / 1032824649.0,
|
|
Packit |
67cb25 |
-45442868181.0 / 3398467696.0,
|
|
Packit |
67cb25 |
3065993473.0 / 597172653.0
|
|
Packit |
67cb25 |
};
|
|
Packit |
67cb25 |
static const double b12[] = {
|
|
Packit |
67cb25 |
185892177.0 / 718116043.0,
|
|
Packit |
67cb25 |
0.0,
|
|
Packit |
67cb25 |
0.0,
|
|
Packit |
67cb25 |
-3185094517.0 / 667107341.0,
|
|
Packit |
67cb25 |
-477755414.0 / 1098053517.0,
|
|
Packit |
67cb25 |
-703635378.0 / 230739211.0,
|
|
Packit |
67cb25 |
5731566787.0 / 1027545527.0,
|
|
Packit |
67cb25 |
5232866602.0 / 850066563.0,
|
|
Packit |
67cb25 |
-4093664535.0 / 808688257.0,
|
|
Packit |
67cb25 |
3962137247.0 / 1805957418.0,
|
|
Packit |
67cb25 |
65686358.0 / 487910083.0
|
|
Packit |
67cb25 |
};
|
|
Packit |
67cb25 |
static const double b13[] = {
|
|
Packit |
67cb25 |
403863854.0 / 491063109.0,
|
|
Packit |
67cb25 |
0.0,
|
|
Packit |
67cb25 |
0.0,
|
|
Packit |
67cb25 |
-5068492393.0 / 434740067.0,
|
|
Packit |
67cb25 |
-411421997.0 / 543043805.0,
|
|
Packit |
67cb25 |
652783627.0 / 914296604.0,
|
|
Packit |
67cb25 |
11173962825.0 / 925320556.0,
|
|
Packit |
67cb25 |
-13158990841.0 / 6184727034.0,
|
|
Packit |
67cb25 |
3936647629.0 / 1978049680.0,
|
|
Packit |
67cb25 |
-160528059.0 / 685178525.0,
|
|
Packit |
67cb25 |
248638103.0 / 1413531060.0,
|
|
Packit |
67cb25 |
0.0
|
|
Packit |
67cb25 |
};
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
typedef struct
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
double *k[13];
|
|
Packit |
67cb25 |
double *ytmp;
|
|
Packit |
67cb25 |
double *y0;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
rk8pd_state_t;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
static void *
|
|
Packit |
67cb25 |
rk8pd_alloc (size_t dim)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
rk8pd_state_t *state = (rk8pd_state_t *) malloc (sizeof (rk8pd_state_t));
|
|
Packit |
67cb25 |
int i, j;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (state == 0)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR_NULL ("failed to allocate space for rk8pd_state", GSL_ENOMEM);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
state->ytmp = (double *) malloc (dim * sizeof (double));
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (state->ytmp == 0)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
free (state);
|
|
Packit |
67cb25 |
GSL_ERROR_NULL ("failed to allocate space for ytmp", GSL_ENOMEM);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
state->y0 = (double *) malloc (dim * sizeof (double));
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (state->y0 == 0)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
free (state->ytmp);
|
|
Packit |
67cb25 |
free (state);
|
|
Packit |
67cb25 |
GSL_ERROR_NULL ("failed to allocate space for y0", GSL_ENOMEM);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for (i = 0; i < 13; i++)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
state->k[i] = (double *) malloc (dim * sizeof (double));
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (state->k[i] == 0)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
for (j = 0; j < i; j++)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
free (state->k[j]);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
free (state->y0);
|
|
Packit |
67cb25 |
free (state->ytmp);
|
|
Packit |
67cb25 |
free (state);
|
|
Packit |
67cb25 |
GSL_ERROR_NULL ("failed to allocate space for k's", GSL_ENOMEM);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return state;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
static int
|
|
Packit |
67cb25 |
rk8pd_apply (void *vstate,
|
|
Packit |
67cb25 |
size_t dim,
|
|
Packit |
67cb25 |
double t,
|
|
Packit |
67cb25 |
double h,
|
|
Packit |
67cb25 |
double y[],
|
|
Packit |
67cb25 |
double yerr[],
|
|
Packit |
67cb25 |
const double dydt_in[],
|
|
Packit |
67cb25 |
double dydt_out[], const gsl_odeiv_system * sys)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
rk8pd_state_t *state = (rk8pd_state_t *) vstate;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
size_t i;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
double *const ytmp = state->ytmp;
|
|
Packit |
67cb25 |
double *const y0 = state->y0;
|
|
Packit |
67cb25 |
/* Note that k1 is stored in state->k[0] due to zero-based indexing */
|
|
Packit |
67cb25 |
double *const k1 = state->k[0];
|
|
Packit |
67cb25 |
double *const k2 = state->k[1];
|
|
Packit |
67cb25 |
double *const k3 = state->k[2];
|
|
Packit |
67cb25 |
double *const k4 = state->k[3];
|
|
Packit |
67cb25 |
double *const k5 = state->k[4];
|
|
Packit |
67cb25 |
double *const k6 = state->k[5];
|
|
Packit |
67cb25 |
double *const k7 = state->k[6];
|
|
Packit |
67cb25 |
double *const k8 = state->k[7];
|
|
Packit |
67cb25 |
double *const k9 = state->k[8];
|
|
Packit |
67cb25 |
double *const k10 = state->k[9];
|
|
Packit |
67cb25 |
double *const k11 = state->k[10];
|
|
Packit |
67cb25 |
double *const k12 = state->k[11];
|
|
Packit |
67cb25 |
double *const k13 = state->k[12];
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
DBL_MEMCPY (y0, y, dim);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* k1 step */
|
|
Packit |
67cb25 |
if (dydt_in != NULL)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
DBL_MEMCPY (k1, dydt_in, dim);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
int s = GSL_ODEIV_FN_EVAL (sys, t, y, k1);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (s != GSL_SUCCESS)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
return s;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for (i = 0; i < dim; i++)
|
|
Packit |
67cb25 |
ytmp[i] = y[i] + b21 * h * k1[i];
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* k2 step */
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
int s = GSL_ODEIV_FN_EVAL (sys, t + ah[0] * h, ytmp, k2);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (s != GSL_SUCCESS)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
return s;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for (i = 0; i < dim; i++)
|
|
Packit |
67cb25 |
ytmp[i] = y[i] + h * (b3[0] * k1[i] + b3[1] * k2[i]);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* k3 step */
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
int s = GSL_ODEIV_FN_EVAL (sys, t + ah[1] * h, ytmp, k3);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (s != GSL_SUCCESS)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
return s;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for (i = 0; i < dim; i++)
|
|
Packit |
67cb25 |
ytmp[i] = y[i] + h * (b4[0] * k1[i] + b4[2] * k3[i]);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* k4 step */
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
int s = GSL_ODEIV_FN_EVAL (sys, t + ah[2] * h, ytmp, k4);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (s != GSL_SUCCESS)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
return s;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for (i = 0; i < dim; i++)
|
|
Packit |
67cb25 |
ytmp[i] = y[i] + h * (b5[0] * k1[i] + b5[2] * k3[i] + b5[3] * k4[i]);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* k5 step */
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
int s = GSL_ODEIV_FN_EVAL (sys, t + ah[3] * h, ytmp, k5);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (s != GSL_SUCCESS)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
return s;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for (i = 0; i < dim; i++)
|
|
Packit |
67cb25 |
ytmp[i] = y[i] + h * (b6[0] * k1[i] + b6[3] * k4[i] + b6[4] * k5[i]);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* k6 step */
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
int s = GSL_ODEIV_FN_EVAL (sys, t + ah[4] * h, ytmp, k6);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (s != GSL_SUCCESS)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
return s;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for (i = 0; i < dim; i++)
|
|
Packit |
67cb25 |
ytmp[i] =
|
|
Packit |
67cb25 |
y[i] + h * (b7[0] * k1[i] + b7[3] * k4[i] + b7[4] * k5[i] +
|
|
Packit |
67cb25 |
b7[5] * k6[i]);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* k7 step */
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
int s = GSL_ODEIV_FN_EVAL (sys, t + ah[5] * h, ytmp, k7);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (s != GSL_SUCCESS)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
return s;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for (i = 0; i < dim; i++)
|
|
Packit |
67cb25 |
ytmp[i] =
|
|
Packit |
67cb25 |
y[i] + h * (b8[0] * k1[i] + b8[3] * k4[i] + b8[4] * k5[i] +
|
|
Packit |
67cb25 |
b8[5] * k6[i] + b8[6] * k7[i]);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* k8 step */
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
int s = GSL_ODEIV_FN_EVAL (sys, t + ah[6] * h, ytmp, k8);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (s != GSL_SUCCESS)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
return s;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for (i = 0; i < dim; i++)
|
|
Packit |
67cb25 |
ytmp[i] =
|
|
Packit |
67cb25 |
y[i] + h * (b9[0] * k1[i] + b9[3] * k4[i] + b9[4] * k5[i] +
|
|
Packit |
67cb25 |
b9[5] * k6[i] + b9[6] * k7[i] + b9[7] * k8[i]);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* k9 step */
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
int s = GSL_ODEIV_FN_EVAL (sys, t + ah[7] * h, ytmp, k9);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (s != GSL_SUCCESS)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
return s;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for (i = 0; i < dim; i++)
|
|
Packit |
67cb25 |
ytmp[i] =
|
|
Packit |
67cb25 |
y[i] + h * (b10[0] * k1[i] + b10[3] * k4[i] + b10[4] * k5[i] +
|
|
Packit |
67cb25 |
b10[5] * k6[i] + b10[6] * k7[i] + b10[7] * k8[i] +
|
|
Packit |
67cb25 |
b10[8] * k9[i]);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* k10 step */
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
int s = GSL_ODEIV_FN_EVAL (sys, t + ah[8] * h, ytmp, k10);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (s != GSL_SUCCESS)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
return s;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for (i = 0; i < dim; i++)
|
|
Packit |
67cb25 |
ytmp[i] =
|
|
Packit |
67cb25 |
y[i] + h * (b11[0] * k1[i] + b11[3] * k4[i] + b11[4] * k5[i] +
|
|
Packit |
67cb25 |
b11[5] * k6[i] + b11[6] * k7[i] + b11[7] * k8[i] +
|
|
Packit |
67cb25 |
b11[8] * k9[i] + b11[9] * k10[i]);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* k11 step */
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
int s = GSL_ODEIV_FN_EVAL (sys, t + ah[9] * h, ytmp, k11);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (s != GSL_SUCCESS)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
return s;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for (i = 0; i < dim; i++)
|
|
Packit |
67cb25 |
ytmp[i] =
|
|
Packit |
67cb25 |
y[i] + h * (b12[0] * k1[i] + b12[3] * k4[i] + b12[4] * k5[i] +
|
|
Packit |
67cb25 |
b12[5] * k6[i] + b12[6] * k7[i] + b12[7] * k8[i] +
|
|
Packit |
67cb25 |
b12[8] * k9[i] + b12[9] * k10[i] + b12[10] * k11[i]);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* k12 step */
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
int s = GSL_ODEIV_FN_EVAL (sys, t + h, ytmp, k12);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (s != GSL_SUCCESS)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
return s;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for (i = 0; i < dim; i++)
|
|
Packit |
67cb25 |
ytmp[i] =
|
|
Packit |
67cb25 |
y[i] + h * (b13[0] * k1[i] + b13[3] * k4[i] + b13[4] * k5[i] +
|
|
Packit |
67cb25 |
b13[5] * k6[i] + b13[6] * k7[i] + b13[7] * k8[i] +
|
|
Packit |
67cb25 |
b13[8] * k9[i] + b13[9] * k10[i] + b13[10] * k11[i] +
|
|
Packit |
67cb25 |
b13[11] * k12[i]);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* k13 step */
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
int s = GSL_ODEIV_FN_EVAL (sys, t + h, ytmp, k13);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (s != GSL_SUCCESS)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
return s;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* final sum */
|
|
Packit |
67cb25 |
for (i = 0; i < dim; i++)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
const double ksum8 =
|
|
Packit |
67cb25 |
Abar[0] * k1[i] + Abar[5] * k6[i] + Abar[6] * k7[i] +
|
|
Packit |
67cb25 |
Abar[7] * k8[i] + Abar[8] * k9[i] + Abar[9] * k10[i] +
|
|
Packit |
67cb25 |
Abar[10] * k11[i] + Abar[11] * k12[i] + Abar[12] * k13[i];
|
|
Packit |
67cb25 |
y[i] += h * ksum8;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Evaluate dydt_out[]. */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (dydt_out != NULL)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
int s = GSL_ODEIV_FN_EVAL (sys, t + h, y, dydt_out);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (s != GSL_SUCCESS)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
/* Restore initial values */
|
|
Packit |
67cb25 |
DBL_MEMCPY (y, y0, dim);
|
|
Packit |
67cb25 |
return s;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* error estimate */
|
|
Packit |
67cb25 |
for (i = 0; i < dim; i++)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
const double ksum8 =
|
|
Packit |
67cb25 |
Abar[0] * k1[i] + Abar[5] * k6[i] + Abar[6] * k7[i] +
|
|
Packit |
67cb25 |
Abar[7] * k8[i] + Abar[8] * k9[i] + Abar[9] * k10[i] +
|
|
Packit |
67cb25 |
Abar[10] * k11[i] + Abar[11] * k12[i] + Abar[12] * k13[i];
|
|
Packit |
67cb25 |
const double ksum7 =
|
|
Packit |
67cb25 |
A[0] * k1[i] + A[5] * k6[i] + A[6] * k7[i] + A[7] * k8[i] +
|
|
Packit |
67cb25 |
A[8] * k9[i] + A[9] * k10[i] + A[10] * k11[i] + A[11] * k12[i];
|
|
Packit |
67cb25 |
yerr[i] = h * (ksum7 - ksum8);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return GSL_SUCCESS;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
static int
|
|
Packit |
67cb25 |
rk8pd_reset (void *vstate, size_t dim)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
rk8pd_state_t *state = (rk8pd_state_t *) vstate;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
int i;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for (i = 0; i < 13; i++)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
DBL_ZERO_MEMSET (state->k[i], dim);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
DBL_ZERO_MEMSET (state->y0, dim);
|
|
Packit |
67cb25 |
DBL_ZERO_MEMSET (state->ytmp, dim);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return GSL_SUCCESS;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
static unsigned int
|
|
Packit |
67cb25 |
rk8pd_order (void *vstate)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
rk8pd_state_t *state = (rk8pd_state_t *) vstate;
|
|
Packit |
67cb25 |
state = 0; /* prevent warnings about unused parameters */
|
|
Packit |
67cb25 |
return 8;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
static void
|
|
Packit |
67cb25 |
rk8pd_free (void *vstate)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
rk8pd_state_t *state = (rk8pd_state_t *) vstate;
|
|
Packit |
67cb25 |
int i;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for (i = 0; i < 13; i++)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
free (state->k[i]);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
free (state->y0);
|
|
Packit |
67cb25 |
free (state->ytmp);
|
|
Packit |
67cb25 |
free (state);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
static const gsl_odeiv_step_type rk8pd_type = { "rk8pd", /* name */
|
|
Packit |
67cb25 |
1, /* can use dydt_in */
|
|
Packit |
67cb25 |
1, /* gives exact dydt_out */
|
|
Packit |
67cb25 |
&rk8pd_alloc,
|
|
Packit |
67cb25 |
&rk8pd_apply,
|
|
Packit |
67cb25 |
&rk8pd_reset,
|
|
Packit |
67cb25 |
&rk8pd_order,
|
|
Packit |
67cb25 |
&rk8pd_free
|
|
Packit |
67cb25 |
};
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
const gsl_odeiv_step_type *gsl_odeiv_step_rk8pd = &rk8pd_type;
|