|
Packit |
67cb25 |
/* ode-initval2/driver.c
|
|
Packit |
67cb25 |
*
|
|
Packit |
67cb25 |
* Copyright (C) 2009, 2010 Tuomo Keskitalo
|
|
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 |
/* Driver routine for odeiv2. This is a wrapper for low level GSL
|
|
Packit |
67cb25 |
functions that allows a simple interface to step, control and
|
|
Packit |
67cb25 |
evolve layers.
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
#include <config.h>
|
|
Packit |
67cb25 |
#include <math.h>
|
|
Packit |
67cb25 |
#include <gsl/gsl_errno.h>
|
|
Packit |
67cb25 |
#include <gsl/gsl_odeiv2.h>
|
|
Packit |
67cb25 |
#include <gsl/gsl_machine.h>
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
static gsl_odeiv2_driver *
|
|
Packit |
67cb25 |
driver_alloc (const gsl_odeiv2_system * sys, const double hstart,
|
|
Packit |
67cb25 |
const gsl_odeiv2_step_type * T)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
/* Allocates and initializes an ODE driver system. Step and evolve
|
|
Packit |
67cb25 |
objects are allocated here, but control object is allocated in
|
|
Packit |
67cb25 |
another function.
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_odeiv2_driver *state;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (sys == NULL)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR_NULL ("gsl_odeiv2_system must be defined", GSL_EINVAL);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
state = (gsl_odeiv2_driver *) calloc (1, sizeof (gsl_odeiv2_driver));
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (state == NULL)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR_NULL ("failed to allocate space for driver state",
|
|
Packit |
67cb25 |
GSL_ENOMEM);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
const size_t dim = sys->dimension;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (dim == 0)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
gsl_odeiv2_driver_free(state);
|
|
Packit |
67cb25 |
GSL_ERROR_NULL
|
|
Packit |
67cb25 |
("gsl_odeiv2_system dimension must be a positive integer",
|
|
Packit |
67cb25 |
GSL_EINVAL);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
state->sys = sys;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
state->s = gsl_odeiv2_step_alloc (T, dim);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (state->s == NULL)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
gsl_odeiv2_driver_free(state);
|
|
Packit |
67cb25 |
GSL_ERROR_NULL ("failed to allocate step object", GSL_ENOMEM);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
state->e = gsl_odeiv2_evolve_alloc (dim);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (state->e == NULL)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
gsl_odeiv2_driver_free(state);
|
|
Packit |
67cb25 |
GSL_ERROR_NULL ("failed to allocate evolve object", GSL_ENOMEM);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (hstart > 0.0 || hstart < 0.0)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
state->h = hstart;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
gsl_odeiv2_driver_free(state);
|
|
Packit |
67cb25 |
GSL_ERROR_NULL ("invalid hstart", GSL_EINVAL);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
state->h = hstart;
|
|
Packit |
67cb25 |
state->hmin = 0.0;
|
|
Packit |
67cb25 |
state->hmax = GSL_DBL_MAX;
|
|
Packit |
67cb25 |
state->nmax = 0;
|
|
Packit |
67cb25 |
state->n = 0;
|
|
Packit |
67cb25 |
state->c = NULL;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return state;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
gsl_odeiv2_driver_set_hmin (gsl_odeiv2_driver * d, const double hmin)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
/* Sets minimum allowed step size fabs(hmin) for driver. It is
|
|
Packit |
67cb25 |
required that hmin <= fabs(h) <= hmax. */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if ((fabs (hmin) > fabs (d->h)) || (fabs (hmin) > d->hmax))
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR_NULL ("hmin <= fabs(h) <= hmax required", GSL_EINVAL);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
d->hmin = fabs (hmin);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return GSL_SUCCESS;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
gsl_odeiv2_driver_set_hmax (gsl_odeiv2_driver * d, const double hmax)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
/* Sets maximum allowed step size fabs(hmax) for driver. It is
|
|
Packit |
67cb25 |
required that hmin <= fabs(h) <= hmax. */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if ((fabs (hmax) < fabs (d->h)) || (fabs (hmax) < d->hmin))
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR_NULL ("hmin <= fabs(h) <= hmax required", GSL_EINVAL);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (hmax > 0.0 || hmax < 0.0)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
d->hmax = fabs (hmax);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR_NULL ("invalid hmax", GSL_EINVAL);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return GSL_SUCCESS;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
gsl_odeiv2_driver_set_nmax (gsl_odeiv2_driver * d,
|
|
Packit |
67cb25 |
const unsigned long int nmax)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
/* Sets maximum number of allowed steps (nmax) for driver */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
d->nmax = nmax;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return GSL_SUCCESS;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_odeiv2_driver *
|
|
Packit |
67cb25 |
gsl_odeiv2_driver_alloc_y_new (const gsl_odeiv2_system * sys,
|
|
Packit |
67cb25 |
const gsl_odeiv2_step_type * T,
|
|
Packit |
67cb25 |
const double hstart,
|
|
Packit |
67cb25 |
const double epsabs, const double epsrel)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
/* Initializes an ODE driver system with control object of type y_new. */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_odeiv2_driver *state = driver_alloc (sys, hstart, T);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (state == NULL)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR_NULL ("failed to allocate driver object", GSL_ENOMEM);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (epsabs >= 0.0 && epsrel >= 0.0)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
state->c = gsl_odeiv2_control_y_new (epsabs, epsrel);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (state->c == NULL)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
gsl_odeiv2_driver_free (state);
|
|
Packit |
67cb25 |
GSL_ERROR_NULL ("failed to allocate control object", GSL_ENOMEM);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
gsl_odeiv2_driver_free (state);
|
|
Packit |
67cb25 |
GSL_ERROR_NULL ("epsabs and epsrel must be positive", GSL_EINVAL);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Distribute pointer to driver object */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_odeiv2_step_set_driver (state->s, state);
|
|
Packit |
67cb25 |
gsl_odeiv2_evolve_set_driver (state->e, state);
|
|
Packit |
67cb25 |
gsl_odeiv2_control_set_driver (state->c, state);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return state;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_odeiv2_driver *
|
|
Packit |
67cb25 |
gsl_odeiv2_driver_alloc_yp_new (const gsl_odeiv2_system * sys,
|
|
Packit |
67cb25 |
const gsl_odeiv2_step_type * T,
|
|
Packit |
67cb25 |
const double hstart,
|
|
Packit |
67cb25 |
const double epsabs, const double epsrel)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
/* Initializes an ODE driver system with control object of type yp_new. */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_odeiv2_driver *state = driver_alloc (sys, hstart, T);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (state == NULL)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR_NULL ("failed to allocate driver object", GSL_ENOMEM);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (epsabs >= 0.0 && epsrel >= 0.0)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
state->c = gsl_odeiv2_control_yp_new (epsabs, epsrel);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (state->c == NULL)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
gsl_odeiv2_driver_free (state);
|
|
Packit |
67cb25 |
GSL_ERROR_NULL ("failed to allocate control object", GSL_ENOMEM);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
gsl_odeiv2_driver_free (state);
|
|
Packit |
67cb25 |
GSL_ERROR_NULL ("epsabs and epsrel must be positive", GSL_EINVAL);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Distribute pointer to driver object */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_odeiv2_step_set_driver (state->s, state);
|
|
Packit |
67cb25 |
gsl_odeiv2_evolve_set_driver (state->e, state);
|
|
Packit |
67cb25 |
gsl_odeiv2_control_set_driver (state->c, state);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return state;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_odeiv2_driver *
|
|
Packit |
67cb25 |
gsl_odeiv2_driver_alloc_standard_new (const gsl_odeiv2_system * sys,
|
|
Packit |
67cb25 |
const gsl_odeiv2_step_type * T,
|
|
Packit |
67cb25 |
const double hstart,
|
|
Packit |
67cb25 |
const double epsabs,
|
|
Packit |
67cb25 |
const double epsrel, const double a_y,
|
|
Packit |
67cb25 |
const double a_dydt)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
/* Initializes an ODE driver system with control object of type
|
|
Packit |
67cb25 |
standard_new.
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_odeiv2_driver *state = driver_alloc (sys, hstart, T);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (state == NULL)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR_NULL ("failed to allocate driver object", GSL_ENOMEM);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (epsabs >= 0.0 && epsrel >= 0.0)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
state->c =
|
|
Packit |
67cb25 |
gsl_odeiv2_control_standard_new (epsabs, epsrel, a_y, a_dydt);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (state->c == NULL)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
gsl_odeiv2_driver_free (state);
|
|
Packit |
67cb25 |
GSL_ERROR_NULL ("failed to allocate control object", GSL_ENOMEM);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
gsl_odeiv2_driver_free (state);
|
|
Packit |
67cb25 |
GSL_ERROR_NULL ("epsabs and epsrel must be positive", GSL_EINVAL);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Distribute pointer to driver object */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_odeiv2_step_set_driver (state->s, state);
|
|
Packit |
67cb25 |
gsl_odeiv2_evolve_set_driver (state->e, state);
|
|
Packit |
67cb25 |
gsl_odeiv2_control_set_driver (state->c, state);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return state;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_odeiv2_driver *
|
|
Packit |
67cb25 |
gsl_odeiv2_driver_alloc_scaled_new (const gsl_odeiv2_system * sys,
|
|
Packit |
67cb25 |
const gsl_odeiv2_step_type * T,
|
|
Packit |
67cb25 |
const double hstart,
|
|
Packit |
67cb25 |
const double epsabs, const double epsrel,
|
|
Packit |
67cb25 |
const double a_y, const double a_dydt,
|
|
Packit |
67cb25 |
const double scale_abs[])
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
/* Initializes an ODE driver system with control object of type
|
|
Packit |
67cb25 |
scaled_new.
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_odeiv2_driver *state = driver_alloc (sys, hstart, T);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (state == NULL)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR_NULL ("failed to allocate driver object", GSL_ENOMEM);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (epsabs >= 0.0 && epsrel >= 0.0)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
state->c = gsl_odeiv2_control_scaled_new (epsabs, epsrel, a_y, a_dydt,
|
|
Packit |
67cb25 |
scale_abs, sys->dimension);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (state->c == NULL)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
gsl_odeiv2_driver_free (state);
|
|
Packit |
67cb25 |
GSL_ERROR_NULL ("failed to allocate control object", GSL_ENOMEM);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
gsl_odeiv2_driver_free (state);
|
|
Packit |
67cb25 |
GSL_ERROR_NULL ("epsabs and epsrel must be positive", GSL_EINVAL);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Distribute pointer to driver object */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_odeiv2_step_set_driver (state->s, state);
|
|
Packit |
67cb25 |
gsl_odeiv2_evolve_set_driver (state->e, state);
|
|
Packit |
67cb25 |
gsl_odeiv2_control_set_driver (state->c, state);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return state;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
gsl_odeiv2_driver_apply (gsl_odeiv2_driver * d, double *t,
|
|
Packit |
67cb25 |
const double t1, double y[])
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
/* Main driver function that evolves the system from t to t1. In
|
|
Packit |
67cb25 |
beginning vector y contains the values of dependent variables at
|
|
Packit |
67cb25 |
t. This function returns values at t=t1 in y. In case of
|
|
Packit |
67cb25 |
unrecoverable error, y and t contains the values after the last
|
|
Packit |
67cb25 |
successful step.
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
int sign = 0;
|
|
Packit |
67cb25 |
d->n = 0;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Determine integration direction sign */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (d->h > 0.0)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
sign = 1;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
sign = -1;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Check that t, t1 and step direction are sensible */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (sign * (t1 - *t) < 0.0)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR_NULL
|
|
Packit |
67cb25 |
("integration limits and/or step direction not consistent",
|
|
Packit |
67cb25 |
GSL_EINVAL);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Evolution loop */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
while (sign * (t1 - *t) > 0.0)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
int s = gsl_odeiv2_evolve_apply (d->e, d->c, d->s, d->sys,
|
|
Packit |
67cb25 |
t, t1, &(d->h), y);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (s != GSL_SUCCESS)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
return s;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Check for maximum allowed steps */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if ((d->nmax > 0) && (d->n > d->nmax))
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
return GSL_EMAXITER;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Set step size if maximum size is exceeded */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (fabs (d->h) > d->hmax)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
d->h = sign * d->hmax;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Check for too small step size */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (fabs (d->h) < d->hmin)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
return GSL_ENOPROG;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
d->n++;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return GSL_SUCCESS;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
gsl_odeiv2_driver_apply_fixed_step (gsl_odeiv2_driver * d, double *t,
|
|
Packit |
67cb25 |
const double h, const unsigned long int n,
|
|
Packit |
67cb25 |
double y[])
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
/* Alternative driver function that evolves the system from t using
|
|
Packit |
67cb25 |
* n steps of size h. In the beginning vector y contains the values
|
|
Packit |
67cb25 |
* of dependent variables at t. This function returns values at t =
|
|
Packit |
67cb25 |
* t + n * h in y. In case of an unrecoverable error, y and t
|
|
Packit |
67cb25 |
* contains the values after the last successful step.
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
unsigned long int i;
|
|
Packit |
67cb25 |
d->n = 0;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Evolution loop */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for (i = 0; i < n; i++)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
int s = gsl_odeiv2_evolve_apply_fixed_step (d->e, d->c, d->s, d->sys,
|
|
Packit |
67cb25 |
t, h, y);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (s != GSL_SUCCESS)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
return s;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
d->n++;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return GSL_SUCCESS;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
gsl_odeiv2_driver_reset (gsl_odeiv2_driver * d)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
/* Reset the driver. Resets evolve and step objects. */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
int s = gsl_odeiv2_evolve_reset (d->e);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (s != GSL_SUCCESS)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
return s;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
int s = gsl_odeiv2_step_reset (d->s);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (s != GSL_SUCCESS)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
return s;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return GSL_SUCCESS;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
gsl_odeiv2_driver_reset_hstart (gsl_odeiv2_driver * d, const double hstart)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
/* Resets current driver and sets initial step size to hstart */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_odeiv2_driver_reset (d);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if ((d->hmin > fabs (hstart)) || (fabs (hstart) > d->hmax))
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR_NULL ("hmin <= fabs(h) <= hmax required", GSL_EINVAL);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (hstart > 0.0 || hstart < 0.0)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
d->h = hstart;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR_NULL ("invalid hstart", GSL_EINVAL);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return GSL_SUCCESS;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
void
|
|
Packit |
67cb25 |
gsl_odeiv2_driver_free (gsl_odeiv2_driver * state)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
if (state->c)
|
|
Packit |
67cb25 |
gsl_odeiv2_control_free (state->c);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (state->e)
|
|
Packit |
67cb25 |
gsl_odeiv2_evolve_free (state->e);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (state->s)
|
|
Packit |
67cb25 |
gsl_odeiv2_step_free (state->s);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
free (state);
|
|
Packit |
67cb25 |
}
|