Blame ode-initval/bsimp.c

Packit 67cb25
/* ode-initval/bsimp.c
Packit 67cb25
 * 
Packit 67cb25
 * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2004 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
/* Bulirsch-Stoer Implicit */
Packit 67cb25
Packit 67cb25
/* Author:  G. Jungman
Packit 67cb25
 */
Packit 67cb25
/* Bader-Deuflhard implicit extrapolative stepper.
Packit 67cb25
 * [Numer. Math., 41, 373 (1983)]
Packit 67cb25
 */
Packit 67cb25
#include <config.h>
Packit 67cb25
#include <stdlib.h>
Packit 67cb25
#include <string.h>
Packit 67cb25
#include <gsl/gsl_math.h>
Packit 67cb25
#include <gsl/gsl_errno.h>
Packit 67cb25
#include <gsl/gsl_linalg.h>
Packit 67cb25
#include <gsl/gsl_odeiv.h>
Packit 67cb25
Packit 67cb25
#include "odeiv_util.h"
Packit 67cb25
Packit 67cb25
#define SEQUENCE_COUNT 8
Packit 67cb25
#define SEQUENCE_MAX   7
Packit 67cb25
Packit 67cb25
/* Bader-Deuflhard extrapolation sequence */
Packit 67cb25
static const int bd_sequence[SEQUENCE_COUNT] =
Packit 67cb25
  { 2, 6, 10, 14, 22, 34, 50, 70 };
Packit 67cb25
Packit 67cb25
typedef struct
Packit 67cb25
{
Packit 67cb25
  gsl_matrix *d;                /* workspace for extrapolation         */
Packit 67cb25
  gsl_matrix *a_mat;            /* workspace for linear system matrix  */
Packit 67cb25
  gsl_permutation *p_vec;       /* workspace for LU permutation        */
Packit 67cb25
Packit 67cb25
  double x[SEQUENCE_MAX];       /* workspace for extrapolation */
Packit 67cb25
Packit 67cb25
  /* state info */
Packit 67cb25
  size_t k_current;
Packit 67cb25
  size_t k_choice;
Packit 67cb25
  double h_next;
Packit 67cb25
  double eps;
Packit 67cb25
Packit 67cb25
  /* workspace for extrapolation step */
Packit 67cb25
  double *yp;
Packit 67cb25
  double *y_save;
Packit 67cb25
  double *yerr_save;
Packit 67cb25
  double *y_extrap_save;
Packit 67cb25
  double *y_extrap_sequence;
Packit 67cb25
  double *extrap_work;
Packit 67cb25
  double *dfdt;
Packit 67cb25
  double *y_temp;
Packit 67cb25
  double *delta_temp;
Packit 67cb25
  double *weight;
Packit 67cb25
  gsl_matrix *dfdy;
Packit 67cb25
Packit 67cb25
  /* workspace for the basic stepper */
Packit 67cb25
  double *rhs_temp;
Packit 67cb25
  double *delta;
Packit 67cb25
Packit 67cb25
  /* order of last step */
Packit 67cb25
  size_t order;
Packit 67cb25
}
Packit 67cb25
bsimp_state_t;
Packit 67cb25
Packit 67cb25
/* Compute weighting factor */
Packit 67cb25
Packit 67cb25
static void
Packit 67cb25
compute_weights (const double y[], double w[], size_t dim)
Packit 67cb25
{
Packit 67cb25
  size_t i;
Packit 67cb25
  for (i = 0; i < dim; i++)
Packit 67cb25
    {
Packit 67cb25
      double u = fabs(y[i]);
Packit 67cb25
      w[i] = (u > 0.0) ? u : 1.0;
Packit 67cb25
    }
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
/* Calculate a choice for the "order" of the method, using the
Packit 67cb25
 * Deuflhard criteria.  
Packit 67cb25
 */
Packit 67cb25
Packit 67cb25
static size_t
Packit 67cb25
bsimp_deuf_kchoice (double eps, size_t dimension)
Packit 67cb25
{
Packit 67cb25
  const double safety_f = 0.25;
Packit 67cb25
  const double small_eps = safety_f * eps;
Packit 67cb25
Packit 67cb25
  double a_work[SEQUENCE_COUNT];
Packit 67cb25
  double alpha[SEQUENCE_MAX][SEQUENCE_MAX];
Packit 67cb25
Packit 67cb25
  int i, k;
Packit 67cb25
Packit 67cb25
  a_work[0] = bd_sequence[0] + 1.0;
Packit 67cb25
Packit 67cb25
  for (k = 0; k < SEQUENCE_MAX; k++)
Packit 67cb25
    {
Packit 67cb25
      a_work[k + 1] = a_work[k] + bd_sequence[k + 1];
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  for (i = 0; i < SEQUENCE_MAX; i++)
Packit 67cb25
    {
Packit 67cb25
      alpha[i][i] = 1.0;
Packit 67cb25
      for (k = 0; k < i; k++)
Packit 67cb25
        {
Packit 67cb25
          const double tmp1 = a_work[k + 1] - a_work[i + 1];
Packit 67cb25
          const double tmp2 = (a_work[i + 1] - a_work[0] + 1.0) * (2 * k + 1);
Packit 67cb25
          alpha[k][i] = pow (small_eps, tmp1 / tmp2);
Packit 67cb25
        }
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  a_work[0] += dimension;
Packit 67cb25
Packit 67cb25
  for (k = 0; k < SEQUENCE_MAX; k++)
Packit 67cb25
    {
Packit 67cb25
      a_work[k + 1] = a_work[k] + bd_sequence[k + 1];
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  for (k = 0; k < SEQUENCE_MAX - 1; k++)
Packit 67cb25
    {
Packit 67cb25
      if (a_work[k + 2] > a_work[k + 1] * alpha[k][k + 1])
Packit 67cb25
        break;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  return k;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
static void
Packit 67cb25
poly_extrap (gsl_matrix * d,
Packit 67cb25
             const double x[],
Packit 67cb25
             const unsigned int i_step,
Packit 67cb25
             const double x_i,
Packit 67cb25
             const double y_i[],
Packit 67cb25
             double y_0[], double y_0_err[], double work[], const size_t dim)
Packit 67cb25
{
Packit 67cb25
  size_t j, k;
Packit 67cb25
Packit 67cb25
  DBL_MEMCPY (y_0_err, y_i, dim);
Packit 67cb25
  DBL_MEMCPY (y_0, y_i, dim);
Packit 67cb25
Packit 67cb25
  if (i_step == 0)
Packit 67cb25
    {
Packit 67cb25
      for (j = 0; j < dim; j++)
Packit 67cb25
        {
Packit 67cb25
          gsl_matrix_set (d, 0, j, y_i[j]);
Packit 67cb25
        }
Packit 67cb25
    }
Packit 67cb25
  else
Packit 67cb25
    {
Packit 67cb25
      DBL_MEMCPY (work, y_i, dim);
Packit 67cb25
Packit 67cb25
      for (k = 0; k < i_step; k++)
Packit 67cb25
        {
Packit 67cb25
          double delta = 1.0 / (x[i_step - k - 1] - x_i);
Packit 67cb25
          const double f1 = delta * x_i;
Packit 67cb25
          const double f2 = delta * x[i_step - k - 1];
Packit 67cb25
Packit 67cb25
          for (j = 0; j < dim; j++)
Packit 67cb25
            {
Packit 67cb25
              const double q_kj = gsl_matrix_get (d, k, j);
Packit 67cb25
              gsl_matrix_set (d, k, j, y_0_err[j]);
Packit 67cb25
              delta = work[j] - q_kj;
Packit 67cb25
              y_0_err[j] = f1 * delta;
Packit 67cb25
              work[j] = f2 * delta;
Packit 67cb25
              y_0[j] += y_0_err[j];
Packit 67cb25
            }
Packit 67cb25
        }
Packit 67cb25
Packit 67cb25
      for (j = 0; j < dim; j++)
Packit 67cb25
        {
Packit 67cb25
          gsl_matrix_set (d, i_step, j, y_0_err[j]);
Packit 67cb25
        }
Packit 67cb25
    }
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
/* Basic implicit Bulirsch-Stoer step.  Divide the step h_total into
Packit 67cb25
 * n_step smaller steps and do the Bader-Deuflhard semi-implicit
Packit 67cb25
 * iteration.  */
Packit 67cb25
Packit 67cb25
static int
Packit 67cb25
bsimp_step_local (void *vstate,
Packit 67cb25
                  size_t dim,
Packit 67cb25
                  const double t0,
Packit 67cb25
                  const double h_total,
Packit 67cb25
                  const unsigned int n_step,
Packit 67cb25
                  const double y[],
Packit 67cb25
                  const double yp[],
Packit 67cb25
                  const double dfdt[],
Packit 67cb25
                  const gsl_matrix * dfdy,
Packit 67cb25
                  double y_out[], 
Packit 67cb25
                  const gsl_odeiv_system * sys)
Packit 67cb25
{
Packit 67cb25
  bsimp_state_t *state = (bsimp_state_t *) vstate;
Packit 67cb25
Packit 67cb25
  gsl_matrix *const a_mat = state->a_mat;
Packit 67cb25
  gsl_permutation *const p_vec = state->p_vec;
Packit 67cb25
Packit 67cb25
  double *const delta = state->delta;
Packit 67cb25
  double *const y_temp = state->y_temp;
Packit 67cb25
  double *const delta_temp = state->delta_temp;
Packit 67cb25
  double *const rhs_temp = state->rhs_temp;
Packit 67cb25
  double *const w = state->weight;
Packit 67cb25
Packit 67cb25
  gsl_vector_view y_temp_vec = gsl_vector_view_array (y_temp, dim);
Packit 67cb25
  gsl_vector_view delta_temp_vec = gsl_vector_view_array (delta_temp, dim);
Packit 67cb25
  gsl_vector_view rhs_temp_vec = gsl_vector_view_array (rhs_temp, dim);
Packit 67cb25
Packit 67cb25
  const double h = h_total / n_step;
Packit 67cb25
  double t = t0 + h;
Packit 67cb25
Packit 67cb25
  double sum;
Packit 67cb25
Packit 67cb25
  /* This is the factor sigma referred to in equation 3.4 of the
Packit 67cb25
     paper.  A relative change in y exceeding sigma indicates a
Packit 67cb25
     runaway behavior. According to the authors suitable values for
Packit 67cb25
     sigma are >>1.  I have chosen a value of 100*dim. BJG */
Packit 67cb25
Packit 67cb25
  const double max_sum = 100.0 * dim;
Packit 67cb25
Packit 67cb25
  int signum, status;
Packit 67cb25
  size_t i, j;
Packit 67cb25
  size_t n_inter;
Packit 67cb25
Packit 67cb25
  /* Calculate the matrix for the linear system. */
Packit 67cb25
  for (i = 0; i < dim; i++)
Packit 67cb25
    {
Packit 67cb25
      for (j = 0; j < dim; j++)
Packit 67cb25
        {
Packit 67cb25
          gsl_matrix_set (a_mat, i, j, -h * gsl_matrix_get (dfdy, i, j));
Packit 67cb25
        }
Packit 67cb25
      gsl_matrix_set (a_mat, i, i, gsl_matrix_get (a_mat, i, i) + 1.0);
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  /* LU decomposition for the linear system. */
Packit 67cb25
Packit 67cb25
  gsl_linalg_LU_decomp (a_mat, p_vec, &signum);
Packit 67cb25
Packit 67cb25
  /* Compute weighting factors */
Packit 67cb25
Packit 67cb25
  compute_weights (y, w, dim);
Packit 67cb25
Packit 67cb25
  /* Initial step. */
Packit 67cb25
Packit 67cb25
  for (i = 0; i < dim; i++)
Packit 67cb25
    {
Packit 67cb25
      y_temp[i] = h * (yp[i] + h * dfdt[i]);
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  gsl_linalg_LU_solve (a_mat, p_vec, &y_temp_vec.vector, &delta_temp_vec.vector);
Packit 67cb25
Packit 67cb25
  sum = 0.0;
Packit 67cb25
Packit 67cb25
  for (i = 0; i < dim; i++)
Packit 67cb25
    {
Packit 67cb25
      const double di = delta_temp[i];
Packit 67cb25
      delta[i] = di;
Packit 67cb25
      y_temp[i] = y[i] + di;
Packit 67cb25
      sum += fabs(di) / w[i];
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  if (sum > max_sum) 
Packit 67cb25
    {
Packit 67cb25
      return GSL_EFAILED ;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  /* Intermediate steps. */
Packit 67cb25
Packit 67cb25
  status = GSL_ODEIV_FN_EVAL (sys, t, y_temp, y_out);
Packit 67cb25
Packit 67cb25
  if (status)
Packit 67cb25
    {
Packit 67cb25
      return status;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  for (n_inter = 1; n_inter < n_step; n_inter++)
Packit 67cb25
    {
Packit 67cb25
      for (i = 0; i < dim; i++)
Packit 67cb25
        {
Packit 67cb25
          rhs_temp[i] = h * y_out[i] - delta[i];
Packit 67cb25
        }
Packit 67cb25
Packit 67cb25
      gsl_linalg_LU_solve (a_mat, p_vec, &rhs_temp_vec.vector, &delta_temp_vec.vector);
Packit 67cb25
Packit 67cb25
      sum = 0.0;
Packit 67cb25
Packit 67cb25
      for (i = 0; i < dim; i++)
Packit 67cb25
        {
Packit 67cb25
          delta[i] += 2.0 * delta_temp[i];
Packit 67cb25
          y_temp[i] += delta[i];
Packit 67cb25
          sum += fabs(delta[i]) / w[i];
Packit 67cb25
        }
Packit 67cb25
Packit 67cb25
      if (sum > max_sum) 
Packit 67cb25
        {
Packit 67cb25
          return GSL_EFAILED ;
Packit 67cb25
        }
Packit 67cb25
Packit 67cb25
      t += h;
Packit 67cb25
Packit 67cb25
      status = GSL_ODEIV_FN_EVAL (sys, t, y_temp, y_out);
Packit 67cb25
Packit 67cb25
      if (status)
Packit 67cb25
        {
Packit 67cb25
          return status;
Packit 67cb25
        }
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
Packit 67cb25
  /* Final step. */
Packit 67cb25
Packit 67cb25
  for (i = 0; i < dim; i++)
Packit 67cb25
    {
Packit 67cb25
      rhs_temp[i] = h * y_out[i] - delta[i];
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  gsl_linalg_LU_solve (a_mat, p_vec, &rhs_temp_vec.vector, &delta_temp_vec.vector);
Packit 67cb25
Packit 67cb25
  sum = 0.0;
Packit 67cb25
Packit 67cb25
  for (i = 0; i < dim; i++)
Packit 67cb25
    {
Packit 67cb25
      y_out[i] = y_temp[i] + delta_temp[i];
Packit 67cb25
      sum += fabs(delta_temp[i]) / w[i];
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  if (sum > max_sum) 
Packit 67cb25
    {
Packit 67cb25
      return GSL_EFAILED ;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  return GSL_SUCCESS;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
Packit 67cb25
static void *
Packit 67cb25
bsimp_alloc (size_t dim)
Packit 67cb25
{
Packit 67cb25
  bsimp_state_t *state = (bsimp_state_t *) malloc (sizeof (bsimp_state_t));
Packit 67cb25
Packit 67cb25
  state->d = gsl_matrix_alloc (SEQUENCE_MAX, dim);
Packit 67cb25
  state->a_mat = gsl_matrix_alloc (dim, dim);
Packit 67cb25
  state->p_vec = gsl_permutation_alloc (dim);
Packit 67cb25
Packit 67cb25
  state->yp = (double *) malloc (dim * sizeof (double));
Packit 67cb25
  state->y_save = (double *) malloc (dim * sizeof (double));
Packit 67cb25
  state->yerr_save = (double *) malloc (dim * sizeof (double));
Packit 67cb25
  state->y_extrap_save = (double *) malloc (dim * sizeof (double));
Packit 67cb25
  state->y_extrap_sequence = (double *) malloc (dim * sizeof (double));
Packit 67cb25
  state->extrap_work = (double *) malloc (dim * sizeof (double));
Packit 67cb25
  state->dfdt = (double *) malloc (dim * sizeof (double));
Packit 67cb25
  state->y_temp = (double *) malloc (dim * sizeof (double));
Packit 67cb25
  state->delta_temp = (double *) malloc (dim * sizeof(double));
Packit 67cb25
  state->weight = (double *) malloc (dim * sizeof(double));
Packit 67cb25
Packit 67cb25
  state->dfdy = gsl_matrix_alloc (dim, dim);
Packit 67cb25
Packit 67cb25
  state->rhs_temp = (double *) malloc (dim * sizeof(double));
Packit 67cb25
  state->delta = (double *) malloc (dim * sizeof (double));
Packit 67cb25
Packit 67cb25
  {
Packit 67cb25
    size_t k_choice = bsimp_deuf_kchoice (GSL_SQRT_DBL_EPSILON, dim); /*FIXME: choice of epsilon? */
Packit 67cb25
    state->k_choice = k_choice;
Packit 67cb25
    state->k_current = k_choice;
Packit 67cb25
    state->order = 2 * k_choice;
Packit 67cb25
  }
Packit 67cb25
Packit 67cb25
  state->h_next = -GSL_SQRT_DBL_MAX;
Packit 67cb25
Packit 67cb25
  return state;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
/* Perform the basic semi-implicit extrapolation
Packit 67cb25
 * step, of size h, at a Deuflhard determined order.
Packit 67cb25
 */
Packit 67cb25
static int
Packit 67cb25
bsimp_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[], 
Packit 67cb25
             const gsl_odeiv_system * sys)
Packit 67cb25
{
Packit 67cb25
  bsimp_state_t *state = (bsimp_state_t *) vstate;
Packit 67cb25
Packit 67cb25
  double *const x = state->x;
Packit 67cb25
  double *const yp = state->yp;
Packit 67cb25
  double *const y_save = state->y_save;
Packit 67cb25
  double *const yerr_save = state->yerr_save;
Packit 67cb25
  double *const y_extrap_sequence = state->y_extrap_sequence;
Packit 67cb25
  double *const y_extrap_save = state->y_extrap_save;
Packit 67cb25
  double *const extrap_work = state->extrap_work;
Packit 67cb25
  double *const dfdt = state->dfdt;
Packit 67cb25
  gsl_matrix *d = state->d;
Packit 67cb25
  gsl_matrix *dfdy = state->dfdy;
Packit 67cb25
Packit 67cb25
  const double t_local = t;
Packit 67cb25
  size_t i, k;
Packit 67cb25
Packit 67cb25
  if (h + t_local == t_local)
Packit 67cb25
    {
Packit 67cb25
      return GSL_EUNDRFLW;      /* FIXME: error condition */
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  DBL_MEMCPY (y_extrap_save, y, dim);
Packit 67cb25
Packit 67cb25
  /* Save inputs */
Packit 67cb25
  DBL_MEMCPY (y_save, y, dim);
Packit 67cb25
  DBL_MEMCPY (yerr_save, yerr, dim);
Packit 67cb25
  
Packit 67cb25
  /* Evaluate the derivative. */
Packit 67cb25
  if (dydt_in != NULL)
Packit 67cb25
    {
Packit 67cb25
      DBL_MEMCPY (yp, dydt_in, dim);
Packit 67cb25
    }
Packit 67cb25
  else
Packit 67cb25
    {
Packit 67cb25
      int s = GSL_ODEIV_FN_EVAL (sys, t_local, y, yp);
Packit 67cb25
Packit 67cb25
      if (s != GSL_SUCCESS)
Packit 67cb25
	{
Packit 67cb25
          return s;
Packit 67cb25
	}
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  /* Evaluate the Jacobian for the system. */
Packit 67cb25
  {
Packit 67cb25
    int s = GSL_ODEIV_JA_EVAL (sys, t_local, y, dfdy->data, dfdt);
Packit 67cb25
  
Packit 67cb25
    if (s != GSL_SUCCESS)
Packit 67cb25
      {
Packit 67cb25
        return s;
Packit 67cb25
      }
Packit 67cb25
  }
Packit 67cb25
Packit 67cb25
  /* Make a series of refined extrapolations,
Packit 67cb25
   * up to the specified maximum order, which
Packit 67cb25
   * was calculated based on the Deuflhard
Packit 67cb25
   * criterion upon state initialization.  */
Packit 67cb25
  for (k = 0; k <= state->k_current; k++)
Packit 67cb25
    {
Packit 67cb25
      const unsigned int N = bd_sequence[k];
Packit 67cb25
      const double r = (h / N);
Packit 67cb25
      const double x_k = r * r;
Packit 67cb25
Packit 67cb25
      int status = bsimp_step_local (state,
Packit 67cb25
                                     dim, t_local, h, N,
Packit 67cb25
                                     y_extrap_save, yp,
Packit 67cb25
                                     dfdt, dfdy,
Packit 67cb25
                                     y_extrap_sequence, 
Packit 67cb25
                                     sys);
Packit 67cb25
Packit 67cb25
      if (status == GSL_EFAILED)
Packit 67cb25
        {
Packit 67cb25
          /* If the local step fails, set the error to infinity in
Packit 67cb25
             order to force a reduction in the step size */
Packit 67cb25
	  
Packit 67cb25
          for (i = 0; i < dim; i++)
Packit 67cb25
            {
Packit 67cb25
              yerr[i] = GSL_POSINF;
Packit 67cb25
            }
Packit 67cb25
Packit 67cb25
          break;
Packit 67cb25
        }
Packit 67cb25
      
Packit 67cb25
      else if (status != GSL_SUCCESS)
Packit 67cb25
	{
Packit 67cb25
	  return status;
Packit 67cb25
	}
Packit 67cb25
      
Packit 67cb25
      x[k] = x_k;
Packit 67cb25
Packit 67cb25
      poly_extrap (d, x, k, x_k, y_extrap_sequence, y, yerr, extrap_work, dim);
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
          DBL_MEMCPY (y, y_save, dim);
Packit 67cb25
          DBL_MEMCPY (yerr, yerr_save, dim);
Packit 67cb25
          return s;
Packit 67cb25
        }
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  return GSL_SUCCESS;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
static unsigned int
Packit 67cb25
bsimp_order (void *vstate)
Packit 67cb25
{
Packit 67cb25
  bsimp_state_t *state = (bsimp_state_t *) vstate;
Packit 67cb25
  return state->order;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
static int
Packit 67cb25
bsimp_reset (void *vstate, size_t dim)
Packit 67cb25
{
Packit 67cb25
  bsimp_state_t *state = (bsimp_state_t *) vstate;
Packit 67cb25
Packit 67cb25
  state->h_next = 0;
Packit 67cb25
Packit 67cb25
  DBL_ZERO_MEMSET (state->yp, dim);
Packit 67cb25
Packit 67cb25
  return GSL_SUCCESS;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
Packit 67cb25
static void
Packit 67cb25
bsimp_free (void * vstate)
Packit 67cb25
{
Packit 67cb25
  bsimp_state_t *state = (bsimp_state_t *) vstate;
Packit 67cb25
Packit 67cb25
  free (state->delta);
Packit 67cb25
  free (state->rhs_temp);
Packit 67cb25
Packit 67cb25
  gsl_matrix_free (state->dfdy);
Packit 67cb25
Packit 67cb25
  free (state->weight);
Packit 67cb25
  free (state->delta_temp);
Packit 67cb25
  free (state->y_temp);
Packit 67cb25
  free (state->dfdt);
Packit 67cb25
  free (state->extrap_work);
Packit 67cb25
  free (state->y_extrap_sequence);
Packit 67cb25
  free (state->y_extrap_save);
Packit 67cb25
  free (state->y_save);
Packit 67cb25
  free (state->yerr_save);
Packit 67cb25
  free (state->yp);
Packit 67cb25
Packit 67cb25
  gsl_permutation_free (state->p_vec);
Packit 67cb25
  gsl_matrix_free (state->a_mat);
Packit 67cb25
  gsl_matrix_free (state->d);
Packit 67cb25
  free (state);
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
static const gsl_odeiv_step_type bsimp_type = { 
Packit 67cb25
  "bsimp",                      /* name */
Packit 67cb25
  1,                            /* can use dydt_in */
Packit 67cb25
  1,                            /* gives exact dydt_out */
Packit 67cb25
  &bsimp_alloc,
Packit 67cb25
  &bsimp_apply,
Packit 67cb25
  &bsimp_reset,
Packit 67cb25
  &bsimp_order,
Packit 67cb25
  &bsimp_free
Packit 67cb25
};
Packit 67cb25
Packit 67cb25
const gsl_odeiv_step_type *gsl_odeiv_step_bsimp = &bsimp_type;