📄 test.c
字号:
/* ode-initval/test_odeiv.c * * Copyright (C) 2004 Tuomo Keskitalo * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *//* Some functions and tests based on test.c by G. Jungman.*/#include <config.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <math.h>#include <gsl/gsl_test.h>#include <gsl/gsl_errno.h>#include <gsl/gsl_math.h>#include <gsl/gsl_matrix.h>#include <gsl/gsl_linalg.h>#include <gsl/gsl_ieee_utils.h>#include <gsl/gsl_odeiv.h>#include "odeiv_util.h"/* Maximum number of ODE equations */#define MAXEQ 4/* RHS for f=2. Solution y = 2 * t + t0 */intrhs_linear (double t, const double y[], double f[], void *params){ f[0] = 2.0; return GSL_SUCCESS;}intjac_linear (double t, const double y[], double *dfdy, double dfdt[], void *params){ dfdy[0] = 0.0; dfdt[0] = 0.0; return GSL_SUCCESS;}gsl_odeiv_system rhs_func_lin = { rhs_linear, jac_linear, 1, 0};/* RHS for f=y. Equals y=exp(t) with initial value y(0)=1.0 */intrhs_exp (double t, const double y[], double f[], void *params){ f[0] = y[0]; return GSL_SUCCESS;}intjac_exp (double t, const double y[], double *dfdy, double dfdt[], void *params){ dfdy[0] = y[0]; dfdt[0] = 0.0; return GSL_SUCCESS;}gsl_odeiv_system rhs_func_exp = { rhs_exp, jac_exp, 1, 0};/* RHS for f0 = -y1, f1 = y0 equals y = [cos(t), sin(t)] with initial values [1, 0]*/intrhs_sin (double t, const double y[], double f[], void *params){ f[0] = -y[1]; f[1] = y[0]; return GSL_SUCCESS;}intjac_sin (double t, const double y[], double *dfdy, double dfdt[], void *params){ dfdy[0] = 0.0; dfdy[1] = -1.0; dfdy[2] = 1.0; dfdy[3] = 0.0; dfdt[0] = 0.0; dfdt[1] = 0.0; return GSL_SUCCESS;}gsl_odeiv_system rhs_func_sin = { rhs_sin, jac_sin, 2, 0};/* Sine/cosine with random failures */intrhs_xsin (double t, const double y[], double f[], void *params){ static int n = 0; n++; if (n > 40 && n < 65) { f[0] = GSL_NAN; f[1] = GSL_NAN; return GSL_EFAILED; } f[0] = -y[1]; f[1] = y[0]; return GSL_SUCCESS;}intjac_xsin (double t, const double y[], double *dfdy, double dfdt[], void *params){ static int n = 0; n++; if (n > 50 && n < 55) { dfdy[0] = GSL_NAN; dfdy[1] = GSL_NAN; dfdy[2] = GSL_NAN; dfdy[3] = GSL_NAN; dfdt[0] = GSL_NAN; dfdt[1] = GSL_NAN; return GSL_EFAILED; } dfdy[0] = 0.0; dfdy[1] = -1.0; dfdy[2] = 1.0; dfdy[3] = 0.0; dfdt[0] = 0.0; dfdt[1] = 0.0; return GSL_SUCCESS;}gsl_odeiv_system rhs_func_xsin = { rhs_xsin, jac_xsin, 2, 0};/* RHS for classic stiff example dy0 / dt = 998 * y0 + 1998 * y1 y0(0) = 1.0 dy1 / dt = -999 * y0 - 1999 * y1 y1(0) = 0.0 solution is y0 = 2 * exp(-t) - exp(-1000 * t) y1 = - exp(-t) + exp(-1000 * t)*/intrhs_stiff (double t, const double y[], double f[], void *params){ f[0] = 998.0 * y[0] + 1998.0 * y[1]; f[1] = -999.0 * y[0] - 1999.0 * y[1]; return GSL_SUCCESS;}intjac_stiff (double t, const double y[], double *dfdy, double dfdt[], void *params){ dfdy[0] = 998.0; dfdy[1] = 1998.0; dfdy[2] = -999.0; dfdy[3] = -1999.0; dfdt[0] = 0.0; dfdt[1] = 0.0; return GSL_SUCCESS;}gsl_odeiv_system rhs_func_stiff = { rhs_stiff, jac_stiff, 2, 0};/* van Der Pol oscillator: f0 = y1 y0(0) = 1.0 f1 = -y0 + mu * y1 * (1 - y0^2) y1(0) = 0.0*/intrhs_vanderpol (double t, const double y[], double f[], void *params){ const double mu = 10.0; f[0] = y[1]; f[1] = -y[0] + mu * y[1] * (1.0 - y[0]*y[0]); return GSL_SUCCESS;}intjac_vanderpol (double t, const double y[], double *dfdy, double dfdt[], void *params){ const double mu = 10.0; dfdy[0] = 0.0; dfdy[1] = 1.0; dfdy[2] = -2.0 * mu * y[0] * y[1] - 1.0; dfdy[3] = mu * (1.0 - y[0] * y[0]); dfdt[0] = 0.0; dfdt[1] = 0.0; return GSL_SUCCESS;}gsl_odeiv_system rhs_func_vanderpol = { rhs_vanderpol, jac_vanderpol, 2, 0};/* The Oregonator - chemical Belusov-Zhabotinskii reaction y0(0) = 1.0, y1(0) = 2.0, y2(0) = 3.0*/intrhs_oregonator (double t, const double y[], double f[], void *params){ const double c1=77.27; const double c2=8.375e-6; const double c3=0.161; f[0] = c1 * (y[1] + y[0] * (1 - c2 * y[0] - y[1])); f[1] = 1/c1 * (y[2] - y[1] * (1 + y[0])); f[2] = c3 * (y[0] - y[2]); return GSL_SUCCESS;}intjac_oregonator (double t, const double y[], double *dfdy, double dfdt[], void *params){ const double c1=77.27; const double c2=8.375e-6; const double c3=0.161; dfdy[0] = c1 * (1 - 2 * c2 * y[0] - y[1]); dfdy[1] = c1 * (1 - y[0]); dfdy[2] = 0.0; dfdy[3] = 1/c1 * (-y[1]); dfdy[4] = 1/c1 * (-1 - y[0]); dfdy[5] = 1/c1; dfdy[6] = c3; dfdy[7] = 0.0; dfdy[8] = -c3; dfdt[0] = 0.0; dfdt[1] = 0.0; dfdt[2] = 0.0; return GSL_SUCCESS;}gsl_odeiv_system rhs_func_oregonator = { rhs_oregonator, jac_oregonator, 3, 0};/* Volterra-Lotka predator-prey model f0 = (a - b * y1) * y0 y0(0) = 3.0 f1 = (-c + d * y0) * y1 y1(0) = 1.0 */intrhs_vl (double t, const double y[], double f[], void *params){ const double a = 1.0; const double b = 1.0; const double c = 1.0; const double d = 1.0; f[0] = (a - b * y[1]) * y[0]; f[1] = (-c + d * y[0]) * y[1]; return GSL_SUCCESS;}intjac_vl (double t, const double y[], double *dfdy, double dfdt[], void *params){ const double a = 1.0; const double b = 1.0; const double c = 1.0; const double d = 1.0; dfdy[0] = a - b * y[1]; dfdy[1] = -b * y[0]; dfdy[2] = d * y[1]; dfdy[3] = -c + d * y[0]; dfdt[0] = 0.0; dfdt[1] = 0.0; return GSL_SUCCESS;}gsl_odeiv_system rhs_func_vl = { rhs_vl, jac_vl, 2, 0};/* Stiff trigonometric example f0 = -50 * (y0 - cos(t)) y0(0) = 0.0 */intrhs_stifftrig (double t, const double y[], double f[], void *params){ f[0] = -50 * (y[0] - cos(t)); return GSL_SUCCESS;}intjac_stifftrig (double t, const double y[], double *dfdy, double dfdt[], void *params){ dfdy[0] = -50; dfdt[0] = -50 * sin(t); return GSL_SUCCESS;}gsl_odeiv_system rhs_func_stifftrig = { rhs_stifftrig, jac_stifftrig, 1, 0};/* E5 - a stiff badly scaled chemical problem by Enright, Hull & Lindberg (1975): Comparing numerical methods for stiff systems of ODEs. BIT, vol. 15, pp. 10-48. f0 = -a * y0 - b * y0 * y2 y0(0) = 1.76e-3 f1 = a * y0 - m * c * y1 * y2 y1(0) = 0.0 f2 = a * y0 - b * y0 * y2 - m * c * y1 * y2 + c * y3 y2(0) = 0.0 f3 = b * y0 * y2 - c * y3 y3(0) = 0.0 */intrhs_e5 (double t, const double y[], double f[], void *params){ const double a = 7.89e-10; const double b = 1.1e7; const double c = 1.13e3; const double m = 1.0e6; f[0] = -a * y[0] - b * y[0] * y[2]; f[1] = a * y[0] - m * c * y[1] * y[2]; f[3] = b * y[0] * y[2] - c * y[3]; f[2] = f[1] - f[3]; return GSL_SUCCESS;}intjac_e5 (double t, const double y[], double *dfdy, double dfdt[], void *params){ const double a = 7.89e-10; const double b = 1.1e7; const double c = 1.13e3; const double m = 1.0e6; dfdy[0] = -a - b * y[2]; dfdy[1] = 0.0; dfdy[2] = -b * y[0]; dfdy[3] = 0.0; dfdy[4] = a; dfdy[5] = -m * c * y[2]; dfdy[6] = -m * c * y[1]; dfdy[7] = 0.0; dfdy[8] = a - b * y[2]; dfdy[9] = -m * c * y[2]; dfdy[10] = -b * y[0] - m * c * y[1]; dfdy[11] = c; dfdy[12] = b * y[2]; dfdy[13] = 0.0; dfdy[14] = b * y[0]; dfdy[15] = -c; dfdt[0] = 0.0; dfdt[1] = 0.0; dfdt[2] = 0.0; dfdt[3] = 0.0; return GSL_SUCCESS;}gsl_odeiv_system rhs_func_e5 = { rhs_e5, jac_e5, 4, 0};voidtest_odeiv_stepper (const gsl_odeiv_step_type *T, const gsl_odeiv_system *sys, const double h, const double t, const char desc[], const double y0[], const double yfin[], const double relerr){ /* tests stepper T with one fixed length step advance of system sys and compares with given values yfin */ double y[MAXEQ] = {0.0}; double yerr[MAXEQ] = {0.0}; size_t ne = sys->dimension; size_t i; gsl_odeiv_step *step = gsl_odeiv_step_alloc (T, ne); DBL_MEMCPY (y, y0, MAXEQ); { int s = gsl_odeiv_step_apply (step, t, h, y, yerr, 0, 0, sys); if (s != GSL_SUCCESS) { gsl_test(s, "test_odeiv_stepper: %s step_apply returned %d", desc, s); } } for (i = 0; i < ne; i++) { gsl_test_rel (y[i], yfin[i], relerr, "%s %s step(%d)", gsl_odeiv_step_name (step), desc,i); } gsl_odeiv_step_free (step);}voidtest_stepper (const gsl_odeiv_step_type *T) { /* Tests stepper T with a step of selected systems */ double y[MAXEQ] = {0.0}; double yfin[MAXEQ] = {0.0}; /* Step length */ double h; /* Required tolerance */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -