3 * Copyright (C) 2002, 2007 Brian Gough
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.
24 #include <gsl/gsl_errno.h>
25 #include <gsl/gsl_math.h>
26 #include <gsl/gsl_odeiv.h>
39 sc_control_alloc (void)
41 sc_control_state_t * s =
42 (sc_control_state_t *) malloc (sizeof(sc_control_state_t));
46 GSL_ERROR_NULL ("failed to allocate space for sc_control_state",
54 sc_control_init (void * vstate,
55 double eps_abs, double eps_rel, double a_y, double a_dydt)
57 sc_control_state_t * s = (sc_control_state_t *) vstate;
61 GSL_ERROR ("eps_abs is negative", GSL_EINVAL);
65 GSL_ERROR ("eps_rel is negative", GSL_EINVAL);
69 GSL_ERROR ("a_y is negative", GSL_EINVAL);
73 GSL_ERROR ("a_dydt is negative", GSL_EINVAL);
85 sc_control_hadjust(void * vstate, size_t dim, unsigned int ord, const double y[], const double yerr[], const double yp[], double * h)
87 sc_control_state_t *state = (sc_control_state_t *) vstate;
89 const double eps_abs = state->eps_abs;
90 const double eps_rel = state->eps_rel;
91 const double a_y = state->a_y;
92 const double a_dydt = state->a_dydt;
93 const double * scale_abs = state->scale_abs;
96 const double h_old = *h;
98 double rmax = DBL_MIN;
101 for(i=0; i<dim; i++) {
103 eps_rel * (a_y * fabs(y[i]) + a_dydt * fabs(h_old * yp[i]))
104 + eps_abs * scale_abs[i];
105 const double r = fabs(yerr[i]) / fabs(D0);
106 rmax = GSL_MAX_DBL(r, rmax);
110 /* decrease step, no more than factor of 5, but a fraction S more
111 than scaling suggests (for better accuracy) */
112 double r = S / pow(rmax, 1.0/ord);
119 return GSL_ODEIV_HADJ_DEC;
121 else if(rmax < 0.5) {
122 /* increase step, no more than factor of 5 */
123 double r = S / pow(rmax, 1.0/(ord+1.0));
128 if (r < 1.0) /* don't allow any decrease caused by S<1 */
133 return GSL_ODEIV_HADJ_INC;
137 return GSL_ODEIV_HADJ_NIL;
143 sc_control_free (void * vstate)
145 sc_control_state_t *state = (sc_control_state_t *) vstate;
146 free (state->scale_abs);
150 static const gsl_odeiv_control_type sc_control_type =
151 {"scaled", /* name */
157 const gsl_odeiv_control_type *gsl_odeiv_control_scaled = &sc_control_type;
161 gsl_odeiv_control_scaled_new(double eps_abs, double eps_rel,
162 double a_y, double a_dydt,
163 const double scale_abs[],
166 gsl_odeiv_control * c =
167 gsl_odeiv_control_alloc (gsl_odeiv_control_scaled);
169 int status = gsl_odeiv_control_init (c, eps_abs, eps_rel, a_y, a_dydt);
171 if (status != GSL_SUCCESS)
173 gsl_odeiv_control_free (c);
174 GSL_ERROR_NULL ("error trying to initialize control", status);
178 sc_control_state_t * s = (sc_control_state_t *) c->state;
180 s->scale_abs = (double *)malloc(dim * sizeof(double));
182 if (s->scale_abs == 0)
185 GSL_ERROR_NULL ("failed to allocate space for scale_abs",
189 memcpy(s->scale_abs, scale_abs, dim * sizeof(double));