⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bsimp.c

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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -