* New ODE methods: Euler, Improved Euler, Adams-Bashford-Moulton
@ 2004-06-06 22:58 alfonso_acosta_mail
2004-06-07 8:09 ` alfonso_acosta_mail
2004-06-07 16:38 ` New ODE methods: Euler, Improved Euler, Adams-Bashford-Moulton Brian Gough
0 siblings, 2 replies; 6+ messages in thread
From: alfonso_acosta_mail @ 2004-06-06 22:58 UTC (permalink / raw)
To: gsl-discuss
[-- Attachment #1: Type: text/plain, Size: 614 bytes --]
Hi:
We needed those methods for a college project and we implemented them
with GSL, I know Euler and Improved Euler are merely didactic methods
but maybe some students (like us) could avoid reinventing the wheel.
On the other hand, 4 step Adams-Bashford-Moulton method could be usable
in a real application. We used Runge-Kutta to obtain the remainig three
initial steps.
I attached the 3 files just in case you want to include them in the GSL
distribution
Cheers
Alfonso Acosta
PS: The three methods were tested without step control, so we are not
sure wether the error we provide is correct or not.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: abm.c --]
[-- Type: text/x-csrc; name="abm.c", Size: 8498 bytes --]
/* abm.c
*
* Copyright (C) 1996, 1997, 1998, 1999, 2000 Gerard Jungman
* Copyright (C) 2004 Daniel Rodríguez
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* Adams-Bashford-Moulton */
/* Authors: Daniel Rodríguez
*/
#include <gsl/gsl_errno.h>
#include <gsl/gsl_odeiv.h>
#include "odeiv_util.h"
#define FALSE 0
#define TRUE !FALSE
typedef struct
{
double valueT;
double * valueY;
double * valueF;
} node_t;
typedef struct
{
node_t * TY;
int inicializado;
} abm_state_t;
static void *
abm_alloc (size_t dim)
{
abm_state_t *state = (abm_state_t *) malloc (sizeof (abm_state_t));
if (state == NULL) {
GSL_ERROR_NULL ("failed to allocate space for abm_state", GSL_ENOMEM);
}
state->inicializado = 3;
state->TY = (node_t*) malloc (4 * sizeof (node_t));
if (state->TY == NULL) {
free(state);
GSL_ERROR_NULL("failed to allocate space for valueY", GSL_ENOMEM);
}
state->TY[0].valueY = (double*) malloc (dim * sizeof (double));
if (state->TY[0].valueY == NULL) {
free(state);
GSL_ERROR_NULL("failed to allocate space for valueY", GSL_ENOMEM);
}
state->TY[1].valueY = (double*) malloc (dim * sizeof (double));
if (state->TY[1].valueY == NULL) {
free(state->TY[0].valueY);
free(state);
GSL_ERROR_NULL("failed to allocate space for valueY", GSL_ENOMEM);
}
state->TY[2].valueY = (double*) malloc (dim * sizeof (double));
if (state->TY[2].valueY == NULL) {
free(state->TY[1].valueY);
free(state->TY[0].valueY);
free(state);
GSL_ERROR_NULL("failed to allocate space for valueY", GSL_ENOMEM);
}
state->TY[3].valueY = (double*) malloc (dim * sizeof (double));
if (state->TY[3].valueY == NULL) {
free(state->TY[2].valueY);
free(state->TY[1].valueY);
free(state->TY[0].valueY);
free(state);
GSL_ERROR_NULL("failed to allocate space for valueY", GSL_ENOMEM);
}
state->TY[0].valueF = (double*) malloc (dim * sizeof (double));
if (state->TY[0].valueF == NULL) {
free(state->TY[3].valueY);
free(state->TY[2].valueY);
free(state->TY[1].valueY);
free(state->TY[0].valueY);
free(state);
GSL_ERROR_NULL("failed to allocate space for valueY", GSL_ENOMEM);
}
state->TY[1].valueF = (double*) malloc (dim * sizeof (double));
if (state->TY[1].valueF == NULL) {
free(state->TY[0].valueF);
free(state->TY[3].valueY);
free(state->TY[2].valueY);
free(state->TY[1].valueY);
free(state->TY[0].valueY);
free(state);
GSL_ERROR_NULL("failed to allocate space for valueY", GSL_ENOMEM);
}
state->TY[2].valueF = (double*) malloc (dim * sizeof (double));
if (state->TY[2].valueF == NULL) {
free(state->TY[1].valueF);
free(state->TY[0].valueF);
free(state->TY[3].valueY);
free(state->TY[2].valueY);
free(state->TY[1].valueY);
free(state->TY[0].valueY);
free(state);
GSL_ERROR_NULL("failed to allocate space for valueY", GSL_ENOMEM);
}
state->TY[3].valueF = (double*) malloc (dim * sizeof (double));
if (state->TY[3].valueF == NULL) {
free(state->TY[2].valueF);
free(state->TY[1].valueF);
free(state->TY[0].valueF);
free(state->TY[3].valueY);
free(state->TY[2].valueY);
free(state->TY[1].valueY);
free(state->TY[0].valueY);
free(state);
GSL_ERROR_NULL("failed to allocate space for valueY", GSL_ENOMEM);
}
return state;
}
static int
abm_apply (void *vstate,
size_t dim,
double t,
double h,
double y[],
double yerr[],
const double dydt_in[],
double dydt_out[],
const gsl_odeiv_system * sys)
{
abm_state_t *state = (abm_state_t *) vstate;
int * inicializado = &(state->inicializado);
double temp, proxt;
size_t i;
int status = 0;
int s;
double * p = (double*) malloc(dim * sizeof(double));
double * Ftmp = (double*) malloc(dim * sizeof(double));
node_t *TY = state->TY;
if (*inicializado) { /* Estamos en el primer paso, hacemos RK4 manualmente */
TY[3-*inicializado].valueT = t;
DBL_MEMCPY (TY[3-*inicializado].valueY, y, dim);
s = GSL_ODEIV_FN_EVAL
(sys, t, TY[3-*inicializado].valueY, TY[3-*inicializado].valueF);
GSL_STATUS_UPDATE (&status, s);
const gsl_odeiv_step_type * T = gsl_odeiv_step_rk4;
gsl_odeiv_step * step = gsl_odeiv_step_alloc(T, dim);
gsl_odeiv_evolve * e = gsl_odeiv_evolve_alloc(dim);
int s2 = gsl_odeiv_evolve_apply(e, NULL, step, sys, &t, t+4*h, &h, y);
GSL_STATUS_UPDATE (&status, s2);
DBL_MEMCPY(TY[3-*inicializado+1].valueY, y, dim);
TY[3-*inicializado+1].valueT = t;
s = GSL_ODEIV_FN_EVAL
(sys, t, TY[3-*inicializado+1].valueY, TY[3-*inicializado+1].valueF);
GSL_STATUS_UPDATE (&status, s);
for (i=0; i<dim; i++) {
yerr[i] = h * TY[3-*inicializado+1].valueF[i];
if (dydt_out != NULL)
dydt_out[i] = TY[3-*inicializado+1].valueF[i];
}
(*inicializado)--;
} else {
for (i=0; i<dim; i++) {
p[i] =
TY[3].valueY[i] + (h/24)*(-9*TY[0].valueF[i]+37*TY[1].valueF[i]-
59*TY[2].valueF[i]+55*TY[3].valueF[i]);
}
proxt = TY[3].valueT + h;
GSL_ODEIV_FN_EVAL (sys, proxt, p, Ftmp);
GSL_STATUS_UPDATE (&status, s);
for (i=0; i<dim; i++) {
temp = (h/24)*(TY[1].valueF[i]-5*TY[2].valueF[i]+
19*TY[3].valueF[i]+9*Ftmp[i]);
p[i] = TY[3].valueY[i] + temp;
yerr[i] = h * temp;
if (dydt_out != NULL)
dydt_out[i] = temp;
}
DBL_MEMCPY(TY[0].valueY, TY[1].valueY, dim);
DBL_MEMCPY(TY[1].valueY, TY[2].valueY, dim);
DBL_MEMCPY(TY[2].valueY, TY[3].valueY, dim);
DBL_MEMCPY(TY[3].valueY, p, dim);
TY[0].valueT = TY[1].valueT;
TY[1].valueT = TY[2].valueT;
TY[2].valueT = TY[3].valueT;
TY[3].valueT = proxt;
DBL_MEMCPY(TY[0].valueF, TY[1].valueF, dim);
DBL_MEMCPY(TY[1].valueF, TY[2].valueF, dim);
DBL_MEMCPY(TY[2].valueF, TY[3].valueF, dim);
GSL_ODEIV_FN_EVAL (sys, proxt, TY[3].valueY, Ftmp);
GSL_STATUS_UPDATE (&status, s);
DBL_MEMCPY(TY[3].valueF, Ftmp, dim);
DBL_MEMCPY(y, TY[3].valueY, dim);
}
return status;
}
static int
abm_reset (void *vstate, size_t dim)
{
abm_state_t *state = (abm_state_t *) vstate;
DBL_ZERO_MEMSET (state->TY[0].valueY, dim);
DBL_ZERO_MEMSET (state->TY[1].valueY, dim);
DBL_ZERO_MEMSET (state->TY[2].valueY, dim);
DBL_ZERO_MEMSET (state->TY[3].valueY, dim);
DBL_ZERO_MEMSET (state->TY[0].valueF, dim);
DBL_ZERO_MEMSET (state->TY[1].valueF, dim);
DBL_ZERO_MEMSET (state->TY[2].valueF, dim);
DBL_ZERO_MEMSET (state->TY[3].valueF, dim);
state->TY[0].valueT = 0;
state->TY[1].valueT = 0;
state->TY[2].valueT = 0;
state->TY[3].valueT = 0;
state->inicializado = 3;
return GSL_SUCCESS;
}
static unsigned int
abm_order (void *vstate)
{
abm_state_t *state = (abm_state_t *) vstate;
state = 0; /* prevent warnings about unused parameters */
return 4;
}
static void
abm_free (void *vstate)
{
abm_state_t *state = (abm_state_t *) vstate;
free (state->TY[0].valueY);
free (state->TY[1].valueY);
free (state->TY[2].valueY);
free (state->TY[3].valueY);
free (state->TY[0].valueF);
free (state->TY[1].valueF);
free (state->TY[2].valueF);
free (state->TY[3].valueF);
free (state->TY);
free (state);
}
static const gsl_odeiv_step_type abm_type = { "abm", /* name */
0, /* can use dydt_in */
0, /* gives exact dydt_out */
&abm_alloc,
&abm_apply,
&abm_reset,
&abm_order,
&abm_free
};
const gsl_odeiv_step_type *gsl_odeiv_step_abm = &abm_type;
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: euler.c --]
[-- Type: text/x-csrc; name="euler.c", Size: 3204 bytes --]
/* euler.c
*
* Copyright (C) 1996, 1997, 1998, 1999, 2000 Gerard Jungman
* Copyright (C) 2004 Alfonso Acosta & Daniel Rodríguez
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* Euler Method*/
/* Authors: Alfonso Acosta & Daniel Rodríguez
*/
#include <gsl/gsl_errno.h>
#include <gsl/gsl_odeiv.h>
#include "odeiv_util.h"
typedef struct
{
double *k;
}
euler_state_t;
static void *
euler_alloc (size_t dim)
{
euler_state_t *state = (euler_state_t *) malloc (sizeof (euler_state_t));
if (state == 0)
{
GSL_ERROR_NULL ("failed to allocate space for euler_state", GSL_ENOMEM);
}
state->k = (double *) malloc (dim * sizeof (double));
if (state->k == 0)
{
free (state);
GSL_ERROR_NULL ("failed to allocate space for k", GSL_ENOMEM);
}
return state;
}
static int
euler_apply (void *vstate,
size_t dim,
double t,
double h,
double y[],
double yerr[],
const double dydt_in[],
double dydt_out[],
const gsl_odeiv_system * sys)
{
euler_state_t *state = (euler_state_t *) vstate;
double temp;
size_t i;
int status = 0;
double *const k = state->k;
if (dydt_in != NULL)
{
DBL_MEMCPY (k, dydt_in, dim);
}
else
{
int s = GSL_ODEIV_FN_EVAL (sys, t, y, k);
GSL_STATUS_UPDATE (&status, s);
}
for (i = 0; i < dim; i++)
{
temp = y[i]; /* save y[i] */
y[i] = h * k[i];
yerr[i] = h * y[i];
y[i] += temp;
if (dydt_out != NULL)
dydt_out[i] = k[i];
}
return status;
}
static int
euler_reset (void *vstate, size_t dim)
{
euler_state_t *state = (euler_state_t *) vstate;
DBL_ZERO_MEMSET (state->k, dim);
return GSL_SUCCESS;
}
static unsigned int
euler_order (void *vstate)
{
euler_state_t *state = (euler_state_t *) vstate;
state = 0; /* prevent warnings about unused parameters */
return 1;
}
static void
euler_free (void *vstate)
{
euler_state_t *state = (euler_state_t *) vstate;
free (state->k);
free (state);
}
static const gsl_odeiv_step_type euler_type = { "euler", /* name */
1, /* can use dydt_in */
0, /* gives exact dydt_out */
&euler_alloc,
&euler_apply,
&euler_reset,
&euler_order,
&euler_free
};
const gsl_odeiv_step_type *gsl_odeiv_step_euler = &euler_type;
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #4: eulerplus.c --]
[-- Type: text/x-csrc; name="eulerplus.c", Size: 4260 bytes --]
/* eulerplus.c
*
* Copyright (C) 1996, 1997, 1998, 1999, 2000 Gerard Jungman
* Copyright (C) 2004 Alfonso Acosta & Daniel Rodríguez
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* Improved Euler Method */
/* Authors: Alfonso Acosta & Daniel Rodríguez
*/
#include <gsl/gsl_errno.h>
#include <gsl/gsl_odeiv.h>
#include "odeiv_util.h"
typedef struct
{
double *k1;
double *k2;
double *ytmp;
}
eulerplus_state_t;
static void *
eulerplus_alloc (size_t dim)
{
eulerplus_state_t *state =
(eulerplus_state_t *) malloc (sizeof (eulerplus_state_t));
if (state == 0)
{
GSL_ERROR_NULL ("failed to allocate space for eulerplus_state",
GSL_ENOMEM);
}
state->k1 = (double *) malloc (dim * sizeof (double));
if (state->k1 == 0)
{
free (state);
GSL_ERROR_NULL ("failed to allocate space for k1", GSL_ENOMEM);
}
state->k2 = (double *) malloc (dim * sizeof (double));
if (state->k2 == 0)
{
free (state->k1);
free (state);
GSL_ERROR_NULL ("failed to allocate space for k2", GSL_ENOMEM);
}
state->ytmp = (double *) malloc (dim * sizeof (double));
if (state->ytmp == 0)
{
free (state->k2);
free (state->k1);
free (state);
GSL_ERROR_NULL ("failed to allocate space for ytmp", GSL_ENOMEM);
}
return state;
}
static int
eulerplus_apply (void *vstate,
size_t dim,
double t,
double h,
double y[],
double yerr[],
const double dydt_in[],
double dydt_out[],
const gsl_odeiv_system * sys)
{
eulerplus_state_t *state = (eulerplus_state_t *) vstate;
double temp;
size_t i;
int status = 0;
double *const k1 = state->k1;
double *const k2 = state->k2;
double *const ytmp = state->ytmp;
if (dydt_in != NULL)
{
DBL_MEMCPY (k1, dydt_in, dim);
}
else
{
int s = GSL_ODEIV_FN_EVAL (sys, t, y, k1);
GSL_STATUS_UPDATE (&status, s);
}
/* aplicamos euler */
for (i = 0; i < dim; i++)
{
ytmp[i] = y[i] + h * k1[i] ;
}
{
int s = GSL_ODEIV_FN_EVAL (sys, t+h, ytmp, k2);
GSL_STATUS_UPDATE (&status, s);
}
for (i = 0; i < dim; i++)
{
temp = (k1[i]+k2[i]) / 2; /* la pendiente en x + h */
if (dydt_out != NULL)
dydt_out[i] = temp;
yerr[i] = h * temp;
y[i] += h*temp;
}
return status;
}
static int
eulerplus_reset (void *vstate, size_t dim)
{
eulerplus_state_t *state = (eulerplus_state_t *) vstate;
DBL_ZERO_MEMSET (state->k1, dim);
DBL_ZERO_MEMSET (state->k2, dim);
DBL_ZERO_MEMSET (state->ytmp, dim);
return GSL_SUCCESS;
}
static unsigned int
eulerplus_order (void *vstate)
{
eulerplus_state_t *state = (eulerplus_state_t *) vstate;
state = 0; /* prevent warnings about unused parameters */
return 2;
}
static void
eulerplus_free (void *vstate)
{
eulerplus_state_t *state = (eulerplus_state_t *) vstate;
free (state->k1);
free (state->k2);
free (state->ytmp);
free (state);
}
static const gsl_odeiv_step_type eulerplus_type = { "eulerplus", /* name */
1, /* can use dydt_in */
0, /* gives exact dydt_out */
&eulerplus_alloc,
&eulerplus_apply,
&eulerplus_reset,
&eulerplus_order,
&eulerplus_free
};
const gsl_odeiv_step_type *gsl_odeiv_step_eulerplus = &eulerplus_type;
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: New ODE methods: Euler, Improved Euler, Adams-Bashford-Moulton
2004-06-06 22:58 New ODE methods: Euler, Improved Euler, Adams-Bashford-Moulton alfonso_acosta_mail
@ 2004-06-07 8:09 ` alfonso_acosta_mail
2004-09-03 13:40 ` gsl_root_test_residual(double f, double epsabs) Karsten Howes
2004-06-07 16:38 ` New ODE methods: Euler, Improved Euler, Adams-Bashford-Moulton Brian Gough
1 sibling, 1 reply; 6+ messages in thread
From: alfonso_acosta_mail @ 2004-06-07 8:09 UTC (permalink / raw)
To: gsl-discuss
[-- Attachment #1: Type: text/plain, Size: 66 bytes --]
Sorry, I forgot to correct some comments in spanish from abm.c
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: abm.c --]
[-- Type: text/x-csrc; name="abm.c", Size: 8473 bytes --]
/* abm.c
*
* Copyright (C) 1996, 1997, 1998, 1999, 2000 Gerard Jungman
* Copyright (C) 2004 Daniel Rodríguez
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* 4 step Adams-Bashford-Moulton */
/* Authors: Daniel Rodríguez
*/
#include <gsl/gsl_errno.h>
#include <gsl/gsl_odeiv.h>
#include "odeiv_util.h"
#define FALSE 0
#define TRUE !FALSE
typedef struct
{
double valueT;
double * valueY;
double * valueF;
} node_t;
typedef struct
{
node_t * TY;
int initialized;
} abm_state_t;
static void *
abm_alloc (size_t dim)
{
abm_state_t *state = (abm_state_t *) malloc (sizeof (abm_state_t));
if (state == NULL) {
GSL_ERROR_NULL ("failed to allocate space for abm_state", GSL_ENOMEM);
}
state->initialized = 3;
state->TY = (node_t*) malloc (4 * sizeof (node_t));
if (state->TY == NULL) {
free(state);
GSL_ERROR_NULL("failed to allocate space for valueY", GSL_ENOMEM);
}
state->TY[0].valueY = (double*) malloc (dim * sizeof (double));
if (state->TY[0].valueY == NULL) {
free(state);
GSL_ERROR_NULL("failed to allocate space for valueY", GSL_ENOMEM);
}
state->TY[1].valueY = (double*) malloc (dim * sizeof (double));
if (state->TY[1].valueY == NULL) {
free(state->TY[0].valueY);
free(state);
GSL_ERROR_NULL("failed to allocate space for valueY", GSL_ENOMEM);
}
state->TY[2].valueY = (double*) malloc (dim * sizeof (double));
if (state->TY[2].valueY == NULL) {
free(state->TY[1].valueY);
free(state->TY[0].valueY);
free(state);
GSL_ERROR_NULL("failed to allocate space for valueY", GSL_ENOMEM);
}
state->TY[3].valueY = (double*) malloc (dim * sizeof (double));
if (state->TY[3].valueY == NULL) {
free(state->TY[2].valueY);
free(state->TY[1].valueY);
free(state->TY[0].valueY);
free(state);
GSL_ERROR_NULL("failed to allocate space for valueY", GSL_ENOMEM);
}
state->TY[0].valueF = (double*) malloc (dim * sizeof (double));
if (state->TY[0].valueF == NULL) {
free(state->TY[3].valueY);
free(state->TY[2].valueY);
free(state->TY[1].valueY);
free(state->TY[0].valueY);
free(state);
GSL_ERROR_NULL("failed to allocate space for valueY", GSL_ENOMEM);
}
state->TY[1].valueF = (double*) malloc (dim * sizeof (double));
if (state->TY[1].valueF == NULL) {
free(state->TY[0].valueF);
free(state->TY[3].valueY);
free(state->TY[2].valueY);
free(state->TY[1].valueY);
free(state->TY[0].valueY);
free(state);
GSL_ERROR_NULL("failed to allocate space for valueY", GSL_ENOMEM);
}
state->TY[2].valueF = (double*) malloc (dim * sizeof (double));
if (state->TY[2].valueF == NULL) {
free(state->TY[1].valueF);
free(state->TY[0].valueF);
free(state->TY[3].valueY);
free(state->TY[2].valueY);
free(state->TY[1].valueY);
free(state->TY[0].valueY);
free(state);
GSL_ERROR_NULL("failed to allocate space for valueY", GSL_ENOMEM);
}
state->TY[3].valueF = (double*) malloc (dim * sizeof (double));
if (state->TY[3].valueF == NULL) {
free(state->TY[2].valueF);
free(state->TY[1].valueF);
free(state->TY[0].valueF);
free(state->TY[3].valueY);
free(state->TY[2].valueY);
free(state->TY[1].valueY);
free(state->TY[0].valueY);
free(state);
GSL_ERROR_NULL("failed to allocate space for valueY", GSL_ENOMEM);
}
return state;
}
static int
abm_apply (void *vstate,
size_t dim,
double t,
double h,
double y[],
double yerr[],
const double dydt_in[],
double dydt_out[],
const gsl_odeiv_system * sys)
{
abm_state_t *state = (abm_state_t *) vstate;
int * initialized = &(state->initialized);
double temp, proxt;
size_t i;
int status = 0;
int s;
double * p = (double*) malloc(dim * sizeof(double));
double * Ftmp = (double*) malloc(dim * sizeof(double));
node_t *TY = state->TY;
if (*initialized) { /* obtain the first 3 steps with RK4 */
TY[3-*initialized].valueT = t;
DBL_MEMCPY (TY[3-*initialized].valueY, y, dim);
s = GSL_ODEIV_FN_EVAL
(sys, t, TY[3-*initialized].valueY, TY[3-*initialized].valueF);
GSL_STATUS_UPDATE (&status, s);
const gsl_odeiv_step_type * T = gsl_odeiv_step_rk4;
gsl_odeiv_step * step = gsl_odeiv_step_alloc(T, dim);
gsl_odeiv_evolve * e = gsl_odeiv_evolve_alloc(dim);
int s2 = gsl_odeiv_evolve_apply(e, NULL, step, sys, &t, t+4*h, &h, y);
GSL_STATUS_UPDATE (&status, s2);
DBL_MEMCPY(TY[3-*initialized+1].valueY, y, dim);
TY[3-*initialized+1].valueT = t;
s = GSL_ODEIV_FN_EVAL
(sys, t, TY[3-*initialized+1].valueY, TY[3-*initialized+1].valueF);
GSL_STATUS_UPDATE (&status, s);
for (i=0; i<dim; i++) {
yerr[i] = h * TY[3-*initialized+1].valueF[i];
if (dydt_out != NULL)
dydt_out[i] = TY[3-*initialized+1].valueF[i];
}
(*initialized)--;
} else {
for (i=0; i<dim; i++) {
p[i] =
TY[3].valueY[i] + (h/24)*(-9*TY[0].valueF[i]+37*TY[1].valueF[i]-
59*TY[2].valueF[i]+55*TY[3].valueF[i]);
}
proxt = TY[3].valueT + h;
GSL_ODEIV_FN_EVAL (sys, proxt, p, Ftmp);
GSL_STATUS_UPDATE (&status, s);
for (i=0; i<dim; i++) {
temp = (h/24)*(TY[1].valueF[i]-5*TY[2].valueF[i]+
19*TY[3].valueF[i]+9*Ftmp[i]);
p[i] = TY[3].valueY[i] + temp;
yerr[i] = h * temp;
if (dydt_out != NULL)
dydt_out[i] = temp;
}
DBL_MEMCPY(TY[0].valueY, TY[1].valueY, dim);
DBL_MEMCPY(TY[1].valueY, TY[2].valueY, dim);
DBL_MEMCPY(TY[2].valueY, TY[3].valueY, dim);
DBL_MEMCPY(TY[3].valueY, p, dim);
TY[0].valueT = TY[1].valueT;
TY[1].valueT = TY[2].valueT;
TY[2].valueT = TY[3].valueT;
TY[3].valueT = proxt;
DBL_MEMCPY(TY[0].valueF, TY[1].valueF, dim);
DBL_MEMCPY(TY[1].valueF, TY[2].valueF, dim);
DBL_MEMCPY(TY[2].valueF, TY[3].valueF, dim);
GSL_ODEIV_FN_EVAL (sys, proxt, TY[3].valueY, Ftmp);
GSL_STATUS_UPDATE (&status, s);
DBL_MEMCPY(TY[3].valueF, Ftmp, dim);
DBL_MEMCPY(y, TY[3].valueY, dim);
}
return status;
}
static int
abm_reset (void *vstate, size_t dim)
{
abm_state_t *state = (abm_state_t *) vstate;
DBL_ZERO_MEMSET (state->TY[0].valueY, dim);
DBL_ZERO_MEMSET (state->TY[1].valueY, dim);
DBL_ZERO_MEMSET (state->TY[2].valueY, dim);
DBL_ZERO_MEMSET (state->TY[3].valueY, dim);
DBL_ZERO_MEMSET (state->TY[0].valueF, dim);
DBL_ZERO_MEMSET (state->TY[1].valueF, dim);
DBL_ZERO_MEMSET (state->TY[2].valueF, dim);
DBL_ZERO_MEMSET (state->TY[3].valueF, dim);
state->TY[0].valueT = 0;
state->TY[1].valueT = 0;
state->TY[2].valueT = 0;
state->TY[3].valueT = 0;
state->initialized = 3;
return GSL_SUCCESS;
}
static unsigned int
abm_order (void *vstate)
{
abm_state_t *state = (abm_state_t *) vstate;
state = 0; /* prevent warnings about unused parameters */
return 4;
}
static void
abm_free (void *vstate)
{
abm_state_t *state = (abm_state_t *) vstate;
free (state->TY[0].valueY);
free (state->TY[1].valueY);
free (state->TY[2].valueY);
free (state->TY[3].valueY);
free (state->TY[0].valueF);
free (state->TY[1].valueF);
free (state->TY[2].valueF);
free (state->TY[3].valueF);
free (state->TY);
free (state);
}
static const gsl_odeiv_step_type abm_type = { "abm", /* name */
0, /* can use dydt_in */
0, /* gives exact dydt_out */
&abm_alloc,
&abm_apply,
&abm_reset,
&abm_order,
&abm_free
};
const gsl_odeiv_step_type *gsl_odeiv_step_abm = &abm_type;
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: New ODE methods: Euler, Improved Euler, Adams-Bashford-Moulton
2004-06-06 22:58 New ODE methods: Euler, Improved Euler, Adams-Bashford-Moulton alfonso_acosta_mail
2004-06-07 8:09 ` alfonso_acosta_mail
@ 2004-06-07 16:38 ` Brian Gough
1 sibling, 0 replies; 6+ messages in thread
From: Brian Gough @ 2004-06-07 16:38 UTC (permalink / raw)
To: alfonso_acosta_mail; +Cc: gsl-discuss
alfonso_acosta_mail@yahoo.es writes:
> We needed those methods for a college project and we implemented them
> with GSL, I know Euler and Improved Euler are merely didactic methods
> but maybe some students (like us) could avoid reinventing the wheel.
>
> On the other hand, 4 step Adams-Bashford-Moulton method could be usable
> in a real application. We used Runge-Kutta to obtain the remainig three
> initial steps.
>
> I attached the 3 files just in case you want to include them in the GSL
> distribution
Thanks, I will take a look at them.
--
Brian Gough
^ permalink raw reply [flat|nested] 6+ messages in thread
* gsl_root_test_residual(double f, double epsabs)
2004-06-07 8:09 ` alfonso_acosta_mail
@ 2004-09-03 13:40 ` Karsten Howes
2004-09-09 8:00 ` Brian Gough
0 siblings, 1 reply; 6+ messages in thread
From: Karsten Howes @ 2004-09-03 13:40 UTC (permalink / raw)
To: gsl-discuss
Hi,
I am working with the 1D root finder framework and I am trying to figure
out how to get the value of my function at the current best root estimate
(without re-evaluating my function of course). I need it because I want
to stop when the function is sufficiently close to zero and I dont
actually care about the exact location of the root. The information does
not appear to be in the solver state:
typedef struct
{
const gsl_root_fsolver_type * type;
gsl_function * function ;
double root ;
double x_lower;
double x_upper;
void *state;
}
gsl_root_fsolver;
How do I use the function gsl_root_test_residual?
If it doesn't work, one possibility is for me to maintain a map x->f for
all previous valuations of f and then just look up f in the map using the
current best root. Sorry if I'm missing something obvious.
Thanks for a great library Brian et al.
Best regards,
Karsten
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: gsl_root_test_residual(double f, double epsabs)
2004-09-03 13:40 ` gsl_root_test_residual(double f, double epsabs) Karsten Howes
@ 2004-09-09 8:00 ` Brian Gough
2004-09-09 12:35 ` Karsten Howes
0 siblings, 1 reply; 6+ messages in thread
From: Brian Gough @ 2004-09-09 8:00 UTC (permalink / raw)
To: Karsten Howes; +Cc: gsl-discuss
Karsten Howes writes:
> I am working with the 1D root finder framework and I am trying to figure
> out how to get the value of my function at the current best root estimate
> (without re-evaluating my function of course).
You do need to evaluate the function f(root). Depending on the
algorithm it may not be a reevaluation (see e.g. bisection).
--
Brian Gough
Network Theory Ltd,
Commercial support for GSL --- http://www.network-theory.co.uk/gsl/
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: gsl_root_test_residual(double f, double epsabs)
2004-09-09 8:00 ` Brian Gough
@ 2004-09-09 12:35 ` Karsten Howes
0 siblings, 0 replies; 6+ messages in thread
From: Karsten Howes @ 2004-09-09 12:35 UTC (permalink / raw)
To: Brian Gough; +Cc: gsl-discuss
OK, thanks Brian. I am using Brent's method which appears always to have
valued the function at the root. I solved the problem by storing a map
root->value inside my function. I have included the code below. It's a
C++/stl/boost wrapper for the brent solver, which will be of no interest
to those who are hard core C programmers. And, it has a few pointers of
overhead, etc, which doesnt matter to me in my applications. It does have
the advantage of being able to find roots of member functions though
(using e.g. boost::bind).
Best regards,
Karsten
//params for gsl root finder. Includes the function
struct DoubleGslBoostFuncWrapper {
boost::function<double (double)> f;
std::map<double, double> f_map;
};
static double doubleGslFunc(double x, void *boostFunc){
double f = ((DoubleGslBoostFuncWrapper *) boostFunc)->f(x);
((DoubleGslBoostFuncWrapper *) boostFunc)->f_map[x] = f;
return f;
}
//Finds root of f with error of tolerance
int brent(boost::function<double (double)> &f,
double x_lo, double x_hi, double tolerance, double &root){
int status;
int iter = 0, max_iter = 20;
const gsl_root_fsolver_type *T;
gsl_root_fsolver *s;
gsl_function F;
DoubleGslBoostFuncWrapper gslBoostFuncWrapper;
gslBoostFuncWrapper.f = f;
F.function = &doubleGslFunc;
F.params = &gslBoostFuncWrapper;
T = gsl_root_fsolver_brent;
s = gsl_root_fsolver_alloc (T);
gsl_root_fsolver_set (s, &F, x_lo, x_hi);
printf ("using %s method\n",
gsl_root_fsolver_name (s));
printf ("%5s [%9s, %9s] %9s %10s %9s\n",
"iter", "lower", "upper", "root",
"err", "err(est)");
do
{
iter++;
status = gsl_root_fsolver_iterate (s);
root = gsl_root_fsolver_root (s);
x_lo = gsl_root_fsolver_x_lower (s);
x_hi = gsl_root_fsolver_x_upper (s);
//status = gsl_root_test_interval (x_lo, x_hi, 0, 0.001);
double residual = gslBoostFuncWrapper.f_map[root];
status = gsl_root_test_residual (residual, tolerance);
if (status == GSL_SUCCESS)
printf ("Converged:\n");
printf ("%5d [%.7f, %.7f] %.7f %.7f, f=%.7f\n",
iter, x_lo, x_hi, root, x_hi - x_lo, residual);
}
while (status == GSL_CONTINUE && iter < max_iter);
return status;
}
On Wed, 08 Sep 2004 18:26:59 +0100, Brian Gough <bjg@network-theory.co.uk>
wrote:
> Karsten Howes writes:
> > I am working with the 1D root finder framework and I am trying to
> figure
> > out how to get the value of my function at the current best root
> estimate
> > (without re-evaluating my function of course).
>
> You do need to evaluate the function f(root). Depending on the
> algorithm it may not be a reevaluation (see e.g. bisection).
>
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2004-09-09 12:35 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-06-06 22:58 New ODE methods: Euler, Improved Euler, Adams-Bashford-Moulton alfonso_acosta_mail
2004-06-07 8:09 ` alfonso_acosta_mail
2004-09-03 13:40 ` gsl_root_test_residual(double f, double epsabs) Karsten Howes
2004-09-09 8:00 ` Brian Gough
2004-09-09 12:35 ` Karsten Howes
2004-06-07 16:38 ` New ODE methods: Euler, Improved Euler, Adams-Bashford-Moulton Brian Gough
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).