3 * Copyright (C) 1996, 1997, 1998, 1999, 2000 Gerard Jungman
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or (at
8 * your option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 #include <gsl/gsl_errno.h>
24 #include <gsl/gsl_math.h>
25 #include <gsl/gsl_odeiv.h>
37 std_control_alloc (void)
39 std_control_state_t * s =
40 (std_control_state_t *) malloc (sizeof(std_control_state_t));
44 GSL_ERROR_NULL ("failed to allocate space for std_control_state",
52 std_control_init (void * vstate,
53 double eps_abs, double eps_rel, double a_y, double a_dydt)
55 std_control_state_t * s = (std_control_state_t *) vstate;
59 GSL_ERROR ("eps_abs is negative", GSL_EINVAL);
63 GSL_ERROR ("eps_rel is negative", GSL_EINVAL);
67 GSL_ERROR ("a_y is negative", GSL_EINVAL);
71 GSL_ERROR ("a_dydt is negative", GSL_EINVAL);
83 std_control_hadjust(void * vstate, size_t dim, unsigned int ord, const double y[], const double yerr[], const double yp[], double * h)
85 std_control_state_t *state = (std_control_state_t *) vstate;
87 const double eps_abs = state->eps_abs;
88 const double eps_rel = state->eps_rel;
89 const double a_y = state->a_y;
90 const double a_dydt = state->a_dydt;
93 const double h_old = *h;
95 double rmax = DBL_MIN;
98 for(i=0; i<dim; i++) {
100 eps_rel * (a_y * fabs(y[i]) + a_dydt * fabs(h_old * yp[i])) + eps_abs;
101 const double r = fabs(yerr[i]) / fabs(D0);
102 rmax = GSL_MAX_DBL(r, rmax);
106 /* decrease step, no more than factor of 5, but a fraction S more
107 than scaling suggests (for better accuracy) */
108 double r = S / pow(rmax, 1.0/ord);
115 return GSL_ODEIV_HADJ_DEC;
117 else if(rmax < 0.5) {
118 /* increase step, no more than factor of 5 */
119 double r = S / pow(rmax, 1.0/(ord+1.0));
124 if (r < 1.0) /* don't allow any decrease caused by S<1 */
129 return GSL_ODEIV_HADJ_INC;
133 return GSL_ODEIV_HADJ_NIL;
139 std_control_free (void * vstate)
141 std_control_state_t *state = (std_control_state_t *) vstate;
145 static const gsl_odeiv_control_type std_control_type =
146 {"standard", /* name */
149 &std_control_hadjust,
152 const gsl_odeiv_control_type *gsl_odeiv_control_standard = &std_control_type;
156 gsl_odeiv_control_standard_new(double eps_abs, double eps_rel,
157 double a_y, double a_dydt)
159 gsl_odeiv_control * c =
160 gsl_odeiv_control_alloc (gsl_odeiv_control_standard);
162 int status = gsl_odeiv_control_init (c, eps_abs, eps_rel, a_y, a_dydt);
164 if (status != GSL_SUCCESS)
166 gsl_odeiv_control_free (c);
167 GSL_ERROR_NULL ("error trying to initialize control", status);
174 gsl_odeiv_control_y_new(double eps_abs, double eps_rel)
176 return gsl_odeiv_control_standard_new(eps_abs, eps_rel, 1.0, 0.0);
181 gsl_odeiv_control_yp_new(double eps_abs, double eps_rel)
183 return gsl_odeiv_control_standard_new(eps_abs, eps_rel, 0.0, 1.0);