From eef117428de40d564ab97eb1aafbc2d2a67e851d Mon Sep 17 00:00:00 2001
From: Sergey B Kirpichev <skirpichev@gmail.com>
Date: Sat, 24 Jul 2010 18:11:14 +0400
Subject: [PATCH] Fixed step size control object

---
 doc/ode-initval.texi    |   10 +++++-
 ode-initval/Makefile.am |    2 +-
 ode-initval/cfxd.c      |   81 +++++++++++++++++++++++++++++++++++++++++++++++
 ode-initval/gsl_odeiv.h |    4 ++
 4 files changed, 94 insertions(+), 3 deletions(-)
 create mode 100644 ode-initval/cfxd.c

diff --git a/doc/ode-initval.texi b/doc/ode-initval.texi
index 17af7af..2584db0 100644
--- a/doc/ode-initval.texi
+++ b/doc/ode-initval.texi
@@ -336,6 +336,11 @@ where @math{s_i} is the @math{i}-th component of the array @var{scale_abs}.
 The same error control heuristic is used by the Matlab @sc{ode} suite. 
 @end deftypefun
 
+@deftypefun {gsl_odeiv_control *} gsl_odeiv_control_fixed_new ()
+This function creates a new control object which will keep the step
+size fixed.
+@end deftypefun
+
 @deftypefun {gsl_odeiv_control *} gsl_odeiv_control_alloc (const gsl_odeiv_control_type * @var{T})
 This function returns a pointer to a newly allocated instance of a
 control function of type @var{T}.  This function is only needed for
@@ -554,8 +559,9 @@ Note that arbitrary values of @math{t_i} can be used for each stage of
 the integration.  The equally spaced points in this example are just
 used as an illustration.
 
-It is also possible to work with a non-adaptive integrator, using only
-the stepping function itself.  The following program uses the @code{rk4}
+It is also possible to work with a non-adaptive integrator (control
+object which keeps step size fixed) or using only the stepping
+function itself.  The following program uses the @code{rk4}
 fourth-order Runge-Kutta stepping function with a fixed stepsize of
 0.01,
 
diff --git a/ode-initval/Makefile.am b/ode-initval/Makefile.am
index e5e38be..b0dac93 100644
--- a/ode-initval/Makefile.am
+++ b/ode-initval/Makefile.am
@@ -4,7 +4,7 @@ pkginclude_HEADERS = gsl_odeiv.h
 
 INCLUDES = -I$(top_srcdir)
 
-libgslodeiv_la_SOURCES = control.c cstd.c cscal.c evolve.c step.c rk2.c rk2imp.c rk2simp.c rk4.c rk4imp.c rkf45.c rk8pd.c rkck.c bsimp.c gear1.c gear2.c
+libgslodeiv_la_SOURCES = control.c cstd.c cscal.c cfxd.c evolve.c step.c rk2.c rk2imp.c rk2simp.c rk4.c rk4imp.c rkf45.c rk8pd.c rkck.c bsimp.c gear1.c gear2.c
 
 noinst_HEADERS = odeiv_util.h
 
diff --git a/ode-initval/cfxd.c b/ode-initval/cfxd.c
new file mode 100644
index 0000000..211b4d6
--- /dev/null
+++ b/ode-initval/cfxd.c
@@ -0,0 +1,81 @@
+/* ode-initval/cfxd.c
+ * 
+ * Copyright (C) 2010 Sergey B Kirpichev
+ * 
+ * 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 3 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.
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <gsl/gsl_errno.h>
+#include <gsl/gsl_math.h>
+#include <gsl/gsl_odeiv.h>
+
+static void *
+fc_control_alloc (void)
+{
+  char * s = (char *) malloc (1); /* stub stuff */
+
+  if (s == 0)
+    {
+      GSL_ERROR_NULL ("failed to allocate space", GSL_ENOMEM);
+    }
+
+  return s;
+}
+
+static int
+fc_control_init (void * vstate, double eps_abs,
+                 double eps_rel, double a_y, double a_dydt)
+{
+  return GSL_SUCCESS;
+}
+
+static int
+fc_control_hadjust (void * vstate, size_t dim, unsigned int ord,
+                    const double y[], const double yerr[],
+                    const double yp[], double * h)
+{
+  return GSL_ODEIV_HADJ_NIL; /* never change step size */
+}
+
+static void
+fc_control_free (void * vstate)
+{
+  char *state = (char *) vstate;
+
+  free (state);
+}
+
+static const gsl_odeiv_control_type fc_control_type = {
+  "fixed", /* name */
+  &fc_control_alloc,
+  &fc_control_init,
+  &fc_control_hadjust,
+  &fc_control_free
+};
+
+const gsl_odeiv_control_type *gsl_odeiv_control_fixed = &fc_control_type;
+
+gsl_odeiv_control *
+gsl_odeiv_control_fixed_new (void)
+{
+  gsl_odeiv_control * c = gsl_odeiv_control_alloc (gsl_odeiv_control_fixed);
+
+  return c;
+}
diff --git a/ode-initval/gsl_odeiv.h b/ode-initval/gsl_odeiv.h
index d70f150..ce1542a 100644
--- a/ode-initval/gsl_odeiv.h
+++ b/ode-initval/gsl_odeiv.h
@@ -203,6 +203,10 @@ gsl_odeiv_control * gsl_odeiv_control_yp_new(double eps_abs, double eps_rel);
  */
 gsl_odeiv_control * gsl_odeiv_control_scaled_new(double eps_abs, double eps_rel, double a_y, double a_dydt, const double scale_abs[], size_t dim);
 
+/* This controller forces using fixed step size
+ */
+gsl_odeiv_control * gsl_odeiv_control_fixed_new ();
+
 /* General evolution object.
  */
 typedef struct {
-- 
1.5.6.5

