changeset 22594:b8d525710075 stable

cleanup ode solvers * changed scripts/ode/ode{23,45}.m : remove references to deleted functions in help * scripts/ode/private/integrate_const.m : remove file * scripts/ode/private/integrate_n_steps.m : remove file * scripts/ode/private/ode_struct_value_check.m : remove file * scripts/ode/module.mk : unlist removed files and list added ones * scripts/ode/private/odedefaults.m : new file * scripts/ode/private/odemergeopts.m : new file
author Carlo de Falco <carlo.defalco@polimi.it>
date Thu, 06 Oct 2016 07:13:24 +0200
parents dba5074bdc79
children acfb81e6992a 8d3a2d1af389
files scripts/ode/module.mk scripts/ode/ode23.m scripts/ode/ode45.m scripts/ode/private/integrate_adaptive.m scripts/ode/private/integrate_const.m scripts/ode/private/integrate_n_steps.m scripts/ode/private/ode_struct_value_check.m scripts/ode/private/odedefaults.m scripts/ode/private/odemergeopts.m
diffstat 9 files changed, 147 insertions(+), 815 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/ode/module.mk	Thu Oct 06 06:54:32 2016 +0200
+++ b/scripts/ode/module.mk	Thu Oct 06 07:13:24 2016 +0200
@@ -5,12 +5,11 @@
 scripts_ode_PRIVATE_FCN_FILES = \
   scripts/ode/private/AbsRel_Norm.m \
   scripts/ode/private/integrate_adaptive.m \
-  scripts/ode/private/integrate_const.m \
-  scripts/ode/private/integrate_n_steps.m \
   scripts/ode/private/kahan.m \
   scripts/ode/private/known_option_names.m \
+  scripts/ode/private/odedefaults.m \
+  scripts/ode/private/odemergeopts.m \
   scripts/ode/private/ode_event_handler.m \
-  scripts/ode/private/ode_struct_value_check.m \
   scripts/ode/private/runge_kutta_23.m \
   scripts/ode/private/runge_kutta_45_dorpri.m \
   scripts/ode/private/runge_kutta_interpolate.m \
--- a/scripts/ode/ode23.m	Thu Oct 06 06:54:32 2016 +0200
+++ b/scripts/ode/ode23.m	Thu Oct 06 07:13:24 2016 +0200
@@ -22,7 +22,6 @@
 ## -*- texinfo -*-
 ## @deftypefn  {} {[@var{t}, @var{y}] =} ode23 (@var{fun}, @var{trange}, @var{init})
 ## @deftypefnx {} {[@var{t}, @var{y}] =} ode23 (@var{fun}, @var{trange}, @var{init}, @var{ode_opt})
-## @deftypefnx {} {[@var{t}, @var{y}] =} ode23 (@dots{}, @var{par1}, @var{par2}, @dots{})
 ## @deftypefnx {} {[@var{t}, @var{y}, @var{te}, @var{ye}, @var{ie}] =} ode23 (@dots{})
 ## @deftypefnx {} {@var{solution} =} ode23 (@dots{})
 ##
@@ -40,13 +39,12 @@
 ## evaluated.  Typically, it is a two-element vector specifying the initial and
 ## final times (@code{[tinit, tfinal]}).  If there are more than two elements
 ## then the solution will also be evaluated at these intermediate time
-## instances unless the integrate function specified is
-## @code{integrate_n_steps}.
+## instances.
 ##
 ## By default, @code{ode23} uses an adaptive timestep with the
 ## @code{integrate_adaptive} algorithm.  The tolerance for the timestep
-## computation may be changed by using the option @qcode{"Tau"}, that has a
-## default value of @math{1e-6}. 
+## computation may be changed by using the options @qcode{"RelTol"},
+## and @qcode{"AbsTol"},. 
 ##
 ## @var{init} contains the initial value for the unknowns.  If it is a row
 ## vector then the solution @var{y} will be a matrix in which each column is
--- a/scripts/ode/ode45.m	Thu Oct 06 06:54:32 2016 +0200
+++ b/scripts/ode/ode45.m	Thu Oct 06 07:13:24 2016 +0200
@@ -22,7 +22,6 @@
 ## -*- texinfo -*-
 ## @deftypefn  {} {[@var{t}, @var{y}] =} ode45 (@var{fun}, @var{trange}, @var{init})
 ## @deftypefnx {} {[@var{t}, @var{y}] =} ode45 (@var{fun}, @var{trange}, @var{init}, @var{ode_opt})
-## @deftypefnx {} {[@var{t}, @var{y}] =} ode45 (@dots{}, @var{par1}, @var{par2}, @dots{})
 ## @deftypefnx {} {[@var{t}, @var{y}, @var{te}, @var{ye}, @var{ie}] =} ode45 (@dots{})
 ## @deftypefnx {} {@var{solution} =} ode45 (@dots{})
 ##
@@ -38,13 +37,12 @@
 ## evaluated.  Typically, it is a two-element vector specifying the initial and
 ## final times (@code{[tinit, tfinal]}).  If there are more than two elements
 ## then the solution will also be evaluated at these intermediate time
-## instances unless the integrate function specified is
-## @code{integrate_n_steps}.
+## instances.
 ##
 ## By default, @code{ode45} uses an adaptive timestep with the
 ## @code{integrate_adaptive} algorithm.  The tolerance for the timestep
-## computation may be changed by using the option @qcode{"Tau"}, that has a
-## default value of @math{1e-6}.
+## computation may be changed by using the options @qcode{"RelTol"},
+## and @qcode{"AbsTol"}.
 ##
 ## @var{init} contains the initial value for the unknowns.  If it is a row
 ## vector then the solution @var{y} will be a matrix in which each column is
--- a/scripts/ode/private/integrate_adaptive.m	Thu Oct 06 06:54:32 2016 +0200
+++ b/scripts/ode/private/integrate_adaptive.m	Thu Oct 06 07:13:24 2016 +0200
@@ -62,7 +62,7 @@
 ##
 ## @end deftypefn
 ##
-## @seealso{integrate_const, integrate_n_steps}
+## @seealso{ode45, ode23}
 
 function solution = integrate_adaptive (stepper, order, func, tspan, x0,
                                         options)
--- a/scripts/ode/private/integrate_const.m	Thu Oct 06 06:54:32 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,284 +0,0 @@
-## Copyright (C) 2013-2016 Roberto Porcu' <roberto.porcu@polimi.it>
-##
-## This file is part of Octave.
-##
-## Octave 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.
-##
-## Octave 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 Octave; see the file COPYING.  If not, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {} {@var{solution} =} integrate_const (@var{@@stepper}, @var{@@func}, @var{tspan}, @var{x0}, @var{dt}, @var{options})
-##
-## This function file can be called by an ODE solver function in order to
-## integrate the set of ODEs on the interval @var{[t0,t1]} with a constant
-## timestep @var{dt}.
-##
-## The function returns a structure @var{solution} with two fieldss: @var{t}
-## and @var{y}.  @var{t} is a column vector and contains the time stamps.
-## @var{y} is a matrix in which each column refers to a different unknown
-## of the problem and the row number is the same as the @var{t} row number.
-## Thus, each row of the matrix @var{y} contains the values of all unknowns at
-## the time value contained in the corresponding row in @var{t}.
-##
-## The first input argument must be a function handle or inline function
-## representing the stepper, i.e., the function responsible for step-by-step
-## integration.  This function discriminates one method from the others.
-##
-## The second input argument is the order of the stepper.  It is needed to
-## compute the adaptive timesteps.
-##
-## The third input argument is a function handle or inline function that
-## defines the ODE:
-##
-## @ifhtml
-##
-## @example
-## @math{y' = f(t,y)}
-## @end example
-##
-## @end ifhtml
-## @ifnothtml
-## @math{y' = f(t,y)}.
-## @end ifnothtml
-##
-## The fourth input argument is the time vector which defines the integration
-## interval, i.e., @var{[tspan(1), tspan(end)]} and all intermediate elements
-## are taken as times at which the solution is required.
-##
-## The fourth argument contains the initial conditions for the ODEs.
-##
-## The fifth input argument represents the fixed timestep and the last input
-## argument contains some options that may be needed for the stepper.
-## @end deftypefn
-##
-## @seealso{integrate_adaptive, integrate_n_steps}
-
-function solution = integrate_const (stepper, func, tspan, x0, dt, options)
-
-  solution = struct ();
-
-  ## first values for time and solution
-  t = tspan(1);
-  x = x0(:);
-
-  direction = odeget (options, "direction", [], "fast");
-  if (sign (dt) != direction)
-    error ("Octave:invalid-input-arg",
-           "option 'InitialStep' has a wrong sign");
-  endif
-
-  ## setting parameters
-  k = length (tspan);
-  counter = 2;
-  comp = 0.0;
-  tk = tspan(1);
-  options.comp = comp;
-
-  ## Initialize the OutputFcn
-  if (options.haveoutputfunction)
-    if (options.haveoutputselection)
-      solution.retout = x(options.OutputSel,end);
-    else
-      solution.retout = x;
-    endif
-    feval (options.OutputFcn, tspan, solution.retout, "init",
-           options.funarguments{:});
-  endif
-
-  ## Initialize the EventFcn
-  if (options.haveeventfunction)
-    ode_event_handler (options.Events, t(end), x, "init",
-                         options.funarguments{:});
-  endif
-
-  solution.cntloop = 2;
-  solution.cntcycles = 1;
-  cntiter = 0;
-  solution.unhandledtermination = true;
-  solution.cntsave = 2;
-
-  z = t;
-  u = x;
-  k_vals = feval (func, t , x, options.funarguments{:});
-
-  while (counter <= k)
-    ## computing the integration step from t to t+dt
-    [s, y, ~, k_vals] = stepper (func, z(end), u(:,end), dt, options, k_vals);
-
-    [tk, comp] = kahan (tk,comp, dt);
-    options.comp = comp;
-    s(end) = tk;
-
-    if (options.havenonnegative)
-      x(options.NonNegative,end) = abs (x(options.NonNegative,end));
-      y(options.NonNegative,end) = abs (y(options.NonNegative,end));
-      y_est(options.NonNegative,end) = abs (y_est(options.NonNegative,end));
-    endif
-
-    if (options.haveoutputfunction && options.haverefine)
-      SaveVUForRefine = u(:,end);
-    endif
-
-    ## values on this interval for time and solution
-    z = [t(end);s];
-    u = [x(:,end),y];
-
-    ## if next tspan value is caught, update counter
-    if ((z(end) == tspan(counter))
-        || (abs (z(end) - tspan(counter)) /
-            (max (abs (z(end)), abs (tspan(counter)))) < 8*eps) )
-      counter += 1;
-
-    ## if there is an element in time vector at which the solution is required
-    ## the program must compute this solution before going on with next steps
-    elseif (direction * z(end) > direction * tspan(counter) )
-      ## initializing counter for the following cycle
-      i = 2;
-      while (i <= length (z))
-
-        ## if next tspan value is caught, update counter
-        if ((counter <= k)
-            && (((z(i) == tspan(counter))
-                 || (abs (z(i) - tspan(counter)) /
-                     (max (abs (z(i)), abs (tspan(counter)))) < 8*eps))) )
-          counter += 1;
-        endif
-        ## else, loop until there are requested values inside this subinterval
-        while ((counter <= k)
-               && direction * z(i) > direction * tspan(counter) )
-          ## add the interpolated value of the solution
-          u = [u(:,1:i-1),u(:,i-1) + (tspan(counter)-z(i-1))/(z(i)-z(i-1))* ...
-              (u(:,i)-u(:,i-1)),u(:,i:end)];
-          ## add the time requested
-          z = [z(1:i-1);tspan(counter);z(i:end)];
-
-          ## update counters
-          counter += 1;
-          i += 1;
-        endwhile
-
-        ## if new time requested is not out of this interval
-        if (counter <= k && direction * z(end) > direction * tspan(counter))
-          ## update the counter
-          i += 1;
-        else
-          ## else, stop the cycle and go on with the next iteration
-          i = length (z)+1;
-        endif
-
-      endwhile
-    endif
-
-    x = [x,u(:,2:end)];
-    t = [t;z(2:end)];
-    solution.cntsave += 1;
-    solution.cntloop += 1;
-    cntiter = 0;
-
-    ## Call OutputFcn only if a valid result has been found.
-    ## Stop integration if function returns false.
-    if (options.haveoutputfunction)
-      for cnt = 0:options.Refine  # Approximation between told and t
-        if (options.haverefine)   # Do interpolation
-          approxtime = (cnt + 1) / (options.Refine + 2);
-          approxvals = (1 - approxtime) * SaveVUForRefine ...
-                        + (approxtime) * y(:,end);
-          approxtime = s(end) + approxtime*dt;
-        else
-          approxvals = x(:,end);
-          approxtime = t(end);
-        endif
-        if (options.haveoutputselection)
-          approxvals = approxvals(options.OutputSel);
-        endif
-        pltret = feval (options.OutputFcn, approxtime, approxvals, [],
-                         options.funarguments{:});
-        if (pltret)  # Leave refinement loop
-          break;
-        endif
-      endfor
-      if (pltret)  # Leave main loop
-        solution.unhandledtermination = false;
-        break;
-      endif
-    endif
-
-    ## Call Events function only if a valid result has been found.
-    ## Stop integration if eventbreak is true.
-    if (options.haveeventfunction)
-      solution.event = ode_event_handler (options.Events, t(end), x(:,end),
-                                             [], options.funarguments{:});
-      if (! isempty (solution.event{1}) && solution.event{1} == 1)
-        t(solution.cntloop-1,:) = solution.event{3}(end,:);
-        x(:,solution.cntloop-1) = solution.event{4}(end,:)';
-        solution.unhandledtermination = false;
-        break;
-      endif
-    endif
-
-    ## Update counters that count the number of iteration cycles
-    solution.cntcycles += 1;  # Needed for cost statistics
-    cntiter += 1;             # Needed to find iteration problems
-
-    ## Stop solving because, in the last 5,000 steps, no successful valid
-    ## value has been found
-    if (cntiter >= 5_000)
-      error (["integrate_const: Solving was not successful. ", ...
-              " The iterative integration loop exited at time", ...
-              " t = %f before the endpoint at tend = %f was reached. ", ...
-              " This happened because the iterative integration loop", ...
-              " did not find a valid solution at this time stamp. ", ...
-              " Try to reduce the value of 'InitialStep' and/or", ...
-              " 'MaxStep' with the command 'odeset'."],
-             s(end), tspan(end));
-    endif
-
-    ## if this is the last iteration, save the length of last interval
-    if (counter > k)
-      j = length (z);
-    endif
-
-  endwhile
-
-  ## Check if integration of the ode has been successful
-  if (direction * z(end) < direction * tspan(end))
-    if (solution.unhandledtermination == true)
-      error ("integrate_const:unexpected_termination",
-             [" Solving was not successful. ", ...
-              " The iterative integration loop exited at time", ...
-              " t = %f before the endpoint at tend = %f was reached. ", ...
-              " This may happen if the stepsize becomes too small. ", ...
-              " Try to reduce the value of 'InitialStep'", ...
-              " and/or 'MaxStep' with the command 'odeset'."],
-             z(end), tspan(end));
-    else
-      warning ("integrate_const:unexpected_termination",
-               ["Solver was stopped by a call of 'break'", ...
-                " in the main iteration loop at time", ...
-                " t = %f before the endpoint at tend = %f was reached. ", ...
-                " This may happen because the @odeplot function", ...
-                " returned 'true' or the @event function returned 'true'."],
-               z(end), tspan(end));
-    endif
-  endif
-
-  ## compute how many values are out of time inerval
-  d = direction * t((end-(j-1)):end) > direction * tspan(end) * ones (j, 1);
-  f = sum (d);
-
-  ## remove not-requested values of time and solution
-  solution.t = t(1:end-f);
-  solution.x = x(:,1:end-f)';
-
-endfunction
-
--- a/scripts/ode/private/integrate_n_steps.m	Thu Oct 06 06:54:32 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,223 +0,0 @@
-## Copyright (C) 2013-2016 Roberto Porcu' <roberto.porcu@polimi.it>
-##
-## This file is part of Octave.
-##
-## Octave 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.
-##
-## Octave 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 Octave; see the file COPYING.  If not, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {} {@var{solution} =} integrate_n_steps (@var{@@stepper}, @var{@@func}, @var{t0}, @var{x0}, @var{dt}, @var{n}, @var{options})
-##
-## This function file can be called by an ODE solver function in order to
-## integrate the set of ODEs on the interval @var{[t0,t0 + n*dt]} with a
-## constant timestep dt and on a fixed number of steps.
-##
-## The function returns a structure @var{solution} with two fieldss: @var{t}
-## and @var{y}.  @var{t} is a column vector and contains the time stamps.
-## @var{y} is a matrix in which each column refers to a different unknown
-## of the problem and the row number is the same as the @var{t} row number.
-## Thus, each row of the matrix @var{y} contains the values of all unknowns at
-## the time value contained in the corresponding row in @var{t}.
-##
-## The first input argument must be a function handle or inline function
-## representing the stepper, i.e., the function responsible for step-by-step
-## integration.  This function discriminates one method from the others.
-##
-## The second input argument is the order of the stepper.  It is needed to
-## compute the adaptive timesteps.
-##
-## The third input argument is a function handle or inline function that
-## defines the ODE:
-##
-## @ifhtml
-##
-## @example
-## @math{y' = f(t,y)}
-## @end example
-##
-## @end ifhtml
-## @ifnothtml
-## @math{y' = f(t,y)}.
-## @end ifnothtml
-##
-## The third input argument is the starting point for the integration.
-##
-## The fourth argument contains the initial conditions for the ODEs.
-##
-## The fifth input argument represents the fixed timestep while the sixth
-## contains the number of integration steps.
-##
-## The last argument is a struct with the options that may be needed by the
-## stepper.
-## @end deftypefn
-##
-## @seealso{integrate_adaptive, integrate_const}
-
-function solution = integrate_n_steps (stepper, func, t0, x0, dt, n, options)
-
-  solution = struct ();
-
-  ## first values for time and solution
-  x = x0(:);
-  t = t0;
-
-  direction = odeget (options, "direction", [], "fast");
-  if (sign (dt) != direction)
-    error ("Octave:invalid-input-arg", "option 'InitialStep' has a wrong sign");
-  endif
-
-  comp = 0.0;
-  tk = t0;
-  options.comp = comp;
-
-  ## Initialize the OutputFcn
-  if (options.haveoutputfunction)
-    if (options.haveoutputselection)
-      solution.retout = x(options.OutputSel,end);
-    else
-      solution.retout = x;
-    endif
-    feval (options.OutputFcn, tspan, solution.retout, "init",
-           options.funarguments{:});
-  endif
-
-  ## Initialize the EventFcn
-  if (options.haveeventfunction)
-    ode_event_handler (options.Events, t(end), x, "init",
-                         options.funarguments{:});
-  endif
-
-  solution.cntloop = 2;
-  solution.cntcycles = 1;
-  cntiter = 0;
-  solution.unhandledtermination = true;
-  solution.cntsave = 2;
-
-  z = t;
-  u = x;
-  k_vals = feval (func, t , x, options.funarguments{:});
-
-  for i = 1:n
-    ## Compute the integration step from t to t+dt
-    [s, y, ~, k_vals] = stepper (func, z(end), u(:,end), dt, options, k_vals);
-
-    [tk, comp] = kahan (tk, comp, dt);
-    options.comp = comp;
-    s(end) = tk;
-
-    if (options.havenonnegative)
-      x(options.NonNegative,end) = abs (x(options.NonNegative,end));
-      y(options.NonNegative,end) = abs (y(options.NonNegative,end));
-    endif
-
-    if (options.haveoutputfunction && options.haverefine)
-      SaveVUForRefine = u(:,end);
-    endif
-
-    ## values on this interval for time and solution
-    z = [t(end);s];
-    u = [x(:,end),y];
-
-    x = [x,u(:,2:end)];
-    t = [t;z(2:end)];
-    solution.cntsave += 1;
-    solution.cntloop += 1;
-    cntiter = 0;
-
-    ## Call OutputFcn only if a valid result has been found.
-    ## Stop integration if function returns false.
-    if (options.haveoutputfunction)
-      for cnt = 0:options.Refine  # Approximation between told and t
-        if (options.haverefine)   # Do interpolation
-          approxtime = (cnt + 1) / (options.Refine + 2);
-          approxvals = (1 - approxtime) * SaveVUForRefine ...
-                        + (approxtime) * y(:,end);
-          approxtime = s(end) + approxtime*dt;
-        else
-          approxvals = x(:,end);
-          approxtime = t(end);
-        endif
-        if (options.haveoutputselection)
-          approxvals = approxvals(options.OutputSel);
-        endif
-        pltret = feval (options.OutputFcn, approxtime, approxvals, [],
-                        options.funarguments{:});
-        if (pltret)  # Leave refinement loop
-          break;
-        endif
-      endfor
-      if (pltret)  # Leave main loop
-        solution.unhandledtermination = false;
-        break;
-      endif
-    endif
-
-    ## Call Events function only if a valid result has been found.
-    ## Stop integration if eventbreak is true.
-    if (options.haveeventfunction)
-      solution.event = ode_event_handler (options.Events, t(end), x(:,end),
-                                             [], options.funarguments{:});
-      if (! isempty (solution.event{1}) && solution.event{1} == 1)
-        t(solution.cntloop-1,:) = solution.event{3}(end,:);
-        x(:,solution.cntloop-1) = solution.event{4}(end,:)';
-        solution.unhandledtermination = false;
-        break;
-      endif
-    endif
-
-    ## Update counters that count the number of iteration cycles
-    solution.cntcycles += 1;  # Needed for cost statistics
-    cntiter += 1;             # Needed to find iteration problems
-
-    ## Stop solving because, in the last 5,000 steps, no successful valid
-    ## value has been found
-    if (cntiter >= 5_000)
-      error (["integrate_n_steps: Solving was not successful. ", ...
-              " The iterative integration loop exited at time", ...
-              " t = %f before the endpoint at tend = %f was reached. ", ...
-              " This happened because the iterative integration loop", ...
-              " did not find a valid solution at this time stamp. ", ...
-              " Try to reduce the value of 'InitialStep' and/or", ...
-              " 'MaxStep' with the command 'odeset'."],
-             s(end), tspan(end));
-    endif
-  endfor
-
-  ## Check if integration of the ode has been successful
-  #if (direction * z(end) < direction * tspan(end))
-  #  if (solution.unhandledtermination == true)
-  #   error ("integrate_n_steps:unexpected_termination",
-  #          [" Solving was not successful. ", ...
-  #           " The iterative integration loop exited at time", ...
-  #           " t = %f before the endpoint at tend = %f was reached. ", ...
-  #           " This may happen if the stepsize becomes too small. ", ...
-  #           " Try to reduce the value of 'InitialStep'", ...
-  #           " and/or 'MaxStep' with the command 'odeset'."],
-  #           z(end), tspan(end));
-  #  else
-  #   warning ("integrate_n_steps:unexpected_termination",
-  #            ["Solver was stopped by a call of 'break'", ...
-  #             " in the main iteration loop at time", ...
-  #             " t = %f before the endpoint at tend = %f was reached. ", ...
-  #             " This may happen because the @odeplot function", ...
-  #             " returned 'true' or the @event function returned 'true'."],
-  #             z(end), tspan(end));
-  #  endif
-  #endif
-
-  solution.t = t;
-  solution.x = x';
-
-endfunction
-
--- a/scripts/ode/private/ode_struct_value_check.m	Thu Oct 06 06:54:32 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,294 +0,0 @@
-## Copyright (C) 2013-2016 Roberto Porcu' <roberto.porcu@polimi.it>
-## Copyright (C) 2006-2012 Thomas Treichl <treichl@users.sourceforge.net>
-##
-## This file is part of Octave.
-##
-## Octave 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.
-##
-## Octave 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 Octave; see the file COPYING.  If not, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn  {} {} ode_struct_value_check (@var{"caller"}, @var{ode_struct})
-## @deftypefnx {} {} ode_struct_value_check (@var{"caller"), @var{ode_struct}, @var{"solver"})
-## @deftypefnx {} {@var{ode_struct} =} ode_struct_value_check (@dots{})
-##
-## Validate the fields and values in the ODE options structure
-## @var{ode_struct}.
-##
-## The first argument @var{caller} is a string with the name of the calling
-## function so that warning and error messages properly display the source
-## of any problems.
-##
-## The second argument @var{ode_struct} is a structure with fields and values
-## that configure the ODE solvers (@pxref{XREFodeset,,odeset}).
-##
-## The optional third argument @var{"solver"} is a string with the name of a
-## specific ODE solver.  This extra information can enable more extensive value
-## validation for certain options.
-##
-## The function does not modify any of the field names or field values, but
-## terminates with an error if an invalid value is found.
-##
-## Normally the function is called with no output.  However, the input struct
-## is passed unmodified to the output for certain solvers which expect to
-## receive the validated ODE structure returned.
-## @end deftypefn
-##
-## @seealso{odeset, odeget}
-
-function ode_struct = ode_struct_value_check (caller, ode_struct, solver = "")
-
-  for [val, opt] = ode_struct  # Cycle over all fields
-
-    switch (opt)
-
-      case "AbsTol"
-        if (! isempty (val))
-          if (! isnumeric (val) || ! isreal (val)
-              || ! isvector (val) || any (val <= 0))
-            error ("Octave:invalid-input-arg",
-                   [caller ": invalid value assigned to field '%s'"], opt);
-          endif
-        endif
-
-      case "BDF"
-        if (! isempty (val))
-          if (! strcmp (val, "on") && ! strcmp (val, "off"))
-            error ("Octave:invalid-input-arg",
-                   [caller ": invalid value assigned to field '%s'"], opt);
-          endif
-        endif
-
-      case "Events"
-        if (! isempty (val))
-          if (! isa (val, "function_handle"))
-            error ("Octave:invalid-input-arg",
-                   [caller ": invalid value assigned to field '%s'"], opt);
-          endif
-        endif
-
-      case "InitialSlope"
-        if (! isempty (val))
-          if (! ischar (val)
-              && (! isnumeric (val) || (! isvector (val) && ! isreal (val))))
-            error ("Octave:invalid-input-arg",
-                   [caller ": invalid value assigned to field '%s'"], opt);
-          endif
-        endif
-
-      case "InitialStep"
-        if (! isempty (val))
-          if (! isnumeric (val) || ! isreal (val) || ! isscalar (val)
-              || val <= 0)
-            error ("Octave:invalid-input-arg",
-                   [caller ": invalid value assigned to field '%s'"], opt);
-          endif
-        endif
-
-      case "Jacobian"
-        if (! isempty (val))
-          if (! isnumeric (val))
-            if (! isa (val, "function_handle") && ! iscell (val))
-              error ("Octave:invalid-input-arg",
-                     [caller ": invalid value assigned to field '%s'"], opt);
-            endif
-          endif
-        endif
-
-      case "JConstant"
-        if (! isempty (val))
-          if (! strcmp (val, "on") && ! strcmp (val, "off"))
-            error ("Octave:invalid-input-arg",
-                   [caller ": invalid value assigned to field '%s'"], opt);
-          endif
-        endif
-
-      case "JPattern"
-        if (! isempty (val))
-          if (! isnumeric (val) && ! isvector (val))
-            error ("Octave:invalid-input-arg",
-                   [caller ": invalid value assigned to field '%s'"], opt);
-          endif
-        endif
-
-      case "Mass"
-        if (! isempty (val))
-          if ((! isnumeric (val) || ! ismatrix (val))
-              && ! isa (val, "function_handle"))
-            error ("Octave:invalid-input-arg",
-                   [caller ": invalid value assigned to field '%s'"], opt);
-          endif
-        endif
-
-      case "MassConstant"
-        if (! isempty (val))
-          if (! strcmp (val, "on") && ! strcmp (val, "off"))
-            error ("Octave:invalid-input-arg",
-                   [caller ": invalid value assigned to field '%s'"], opt);
-          endif
-        endif
-
-      case "MassSingular"
-        if (! isempty (val))
-          if (! any (strcmp (val, {"yes", "no", "maybe"})))
-            error ("Octave:invalid-input-arg",
-                   [caller ": invalid value assigned to field '%s'"], opt);
-          endif
-        endif
-
-      case "MaxOrder"
-        if (! isempty (val))
-          if (! isnumeric (val)
-              || val != fix (val) || val <= 0 || val >= 8)
-            error ("Octave:invalid-input-arg",
-                   [caller ": invalid value assigned to field '%s'"], opt);
-          endif
-        endif
-
-      case "MaxStep"
-        if (! isempty (val))
-          if (! isnumeric (val) || ! isscalar (val) || val <= 0)
-            error ("Octave:invalid-input-arg",
-                   [caller ": invalid value assigned to field '%s'"], opt);
-          endif
-        endif
-
-      case "MStateDependence"
-        if (! isempty (val))
-          if (! any (strcmp (val, {"none", "weak", "strong"})))
-            error ("Octave:invalid-input-arg",
-                   [caller ": invalid value assigned to field '%s'"], opt);
-          endif
-        endif
-
-      case "MvPattern"
-        if (! isempty (val))
-          if (! isnumeric (val) && ! isvector (val))
-            error ("Octave:invalid-input-arg",
-                   [caller ": invalid value assigned to field '%s'"], opt);
-          endif
-        endif
-
-      case "NonNegative"
-        if (! isempty (val))
-          if (! isnumeric (val) || ! isvector (val)
-              || any (val <= 0) || any (val != fix (val)))
-            error ("Octave:invalid-input-arg",
-                   [caller ": invalid value assigned to field '%s'"], opt);
-          endif
-        endif
-
-      case "NormControl"
-        if (! isempty (val))
-          if (! strcmp (val, "on") && ! strcmp (val, "off"))
-            error ("Octave:invalid-input-arg",
-                   [caller ": invalid value assigned to field '%s'"], opt);
-          endif
-        endif
-
-      case "OutputFcn"
-        if (! isempty (val))
-          if (! isa (val, "function_handle"))
-            error ("Octave:invalid-input-arg",
-                   [caller ": invalid value assigned to field '%s'"], opt);
-          endif
-        endif
-
-      case "OutputSel"
-        if (! isempty (val))
-          if (! isnumeric (val) || ! isvector (val))
-            error ("Octave:invalid-input-arg",
-                   [caller ": invalid value assigned to field '%s'"], opt);
-          endif
-        endif
-
-      case "Refine"
-        if (! isempty (val))
-          if (! isnumeric (val) || ! isscalar (val)
-              || val != fix (val)  || val < 0 || val > 5)
-            error ("Octave:invalid-input-arg",
-                   [caller ": invalid value assigned to field '%s'"], opt);
-          endif
-        endif
-
-      case "RelTol"
-        if (! isempty (val))
-          if (! isnumeric (val) || ! isreal (val) || any (val <= 0))
-            error ("Octave:invalid-input-arg",
-                   [caller ": invalid value assigned to field '%s'"], opt);
-          endif
-          if (any (strcmp (solver, {"ode23", "ode23d", "ode45", "ode45d",
-                                    "ode54", "ode54d", "ode78", "ode78d"})))
-            if (! isscalar (val))
-              error ("Octave:invalid-input-arg",
-                     [caller ": invalid value assigned to field '%s'"], opt);
-            endif
-          endif
-        endif
-
-      case "Stats"
-        if (! isempty (val))
-          if (! strcmp (val, "on") && ! strcmp (val, "off"))
-            error ("Octave:invalid-input-arg",
-                   [caller ": invalid value assigned to field '%s'"], opt);
-          endif
-        endif
-
-      case "Vectorized"
-        if (! isempty (val))
-          if (! strcmp (val, "on") && ! strcmp (val, "off"))
-            error ("Octave:invalid-input-arg",
-                   [caller ": invalid value assigned to field '%s'"], opt);
-          endif
-        endif
-
-      case "TimeStepSize"
-        if (! isempty (val))
-         if (! isscalar (val))
-              error ("Octave:invalid-input-arg",
-                     [caller ": invalid value assigned to field '%s'"], opt);
-         endif
-        endif
-
-      case "TimeStepNumber"
-        if (! isempty (val))
-          if (! isscalar (val))
-            error ("Octave:invalid-input-arg",
-                   [caller ": invalid value assigned to field '%s'"], opt);
-          endif
-        endif
-
-      otherwise
-        warning ("Octave:invalid-input-arg",
-                 [caller ": unknown field '%s' in ODE options\n"], opt);
-    endswitch
-  endfor
-
-endfunction
-
-
-%!demo
-%! # Return the checked ODE options structure that is created by
-%! # the command odeset.
-%!
-%! ode_struct_value_check (odeset);
-
-%!demo
-%! # Create the ODE options structure A with odeset and check it
-%! # with ode_struct_value_check.  This actually is unnecessary
-%! # because odeset automatically calls ode_struct_value_check before
-%! # returning.
-%!
-%! A = odeset ();
-%! ode_struct_value_check (A);
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/ode/private/odedefaults.m	Thu Oct 06 07:13:24 2016 +0200
@@ -0,0 +1,96 @@
+## Copyright (C) 2016, Francesco Faccio <francesco.faccio@mail.polimi.it>
+##
+## This file is part of Octave.
+##
+## Octave 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.
+##
+## Octave 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 Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+function [defaults, classes, attributes] = odedefaults (n, t0, tf)
+
+defaults = odeset ('AbsTol', 1e-6,
+                   'BDF', 'off',
+                   'Events', [],
+                   'InitialSlope', zeros(n,1),
+                   'InitialStep', [],
+                   'Jacobian', [],
+                   'JConstant', 'off',
+                   'JPattern', [],
+                   'Mass', [],
+                   'MassConstant', 'off',
+                   'MassSingular', 'maybe',
+                   'MaxOrder', 5,
+                   'MaxStep', 0.1*abs(t0-tf),
+                   'MStateDependence', 'weak',
+                   'MvPattern', [],
+                   'NonNegative', [],
+                   'NormControl', 'off',
+                   'OutputFcn', [],
+                   'OutputSel', [],
+                   'Refine', 1,  
+                   'RelTol', 1e-3,
+                   'Stats', 'off',
+                   'Vectorized', 'off');
+ 
+classes = odeset ('Abstol', {"float"},
+                  'BDF', "char",
+                  'Events', {"function_handle"},
+                  'InitialSlope', {"float"},
+                  'InitialStep', {"float"},
+                  'Jacobian', {"float", "function_handle", "cell"},
+                  'JConstant', "char",
+                  'JPattern', {"float"},
+                  'Mass', {"float", "function_handle"},
+                  'MassConstant', "char",
+                  'MassSingular', "char",
+                  'MaxOrder', {"float"},
+                  'MaxStep', {"float"},
+                  'MStateDependence', "char",
+                  'MvPattern', {"float"},
+                  'NonNegative', {"float"},
+                  'NormControl', "char",
+                  'OutputFcn', {"function_handle"},
+                  'OutputSel', {"float"},
+                  'Refine', {"float"},
+                  'RelTol', {"float"},
+                  'Stats', "char",
+                  'Vectorized', "char");
+
+
+##FIXME: How can I check Jacobian where it's a cell????? Maybe it's better to check it inside the solver
+##FIXME: Vectorized can be a cell of stings
+attributes = odeset ('AbsTol', {"real", "vector", "positive"},
+                     'BDF', {"on", "off"},
+                     'Events', {},
+                     'InitialSlope', {"real", "vector", "numel", n},
+                     'InitialStep', {"positive", "scalar"},
+                     'Jacobian', {},
+                     'JConstant', {"on", "off"},
+                     'JPattern', {"vector"},
+                     'Mass', {},
+                     'MassConstant', {"on", "off"},
+                     'MassSingular', {"no", "maybe", "yes"},
+                     'MaxOrder', {">=", 0, "<=", 5, "integer"},
+                     'MaxStep', {"positive", "scalar", "real"},
+                     'MStateDependence', {"weak", "strong", "none"},
+                     'MvPattern', {"vector"},
+                     'NonNegative', {"vector", "integer", "positive"},
+                     'NormControl', {"on", "off"},
+                     'OutputFcn', {},
+                     'OutputSel', {"vector", "integer", "positive",...
+                                   ">", 0, "<=", n},
+                     'Refine', {"scalar", ">", 0, "integer"},
+                     'RelTol', {"scalar", "positive", "real"},
+                     'Stats', {"on", "off"},
+                     'Vectorized', {"on", "off"});
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/ode/private/odemergeopts.m	Thu Oct 06 07:13:24 2016 +0200
@@ -0,0 +1,42 @@
+## Copyright (C) 2016, Francesco Faccio <francesco.faccio@mail.polimi.it>
+##
+## This file is part of Octave.
+##
+## Octave 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.
+##
+## Octave 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 Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+function options = odemergeopts  (useroptions, options, classes,
+                                  attributes, fun_name);
+
+  for [value, key] = options;
+
+    if (isfield (useroptions, key) && ! isempty (useroptions.(key)))
+
+      if (! strcmp (classes.(key), "char"))
+        validateattributes (useroptions.(key), classes.(key),
+                            attributes.(key), fun_name, key);
+
+      elseif (ischar (useroptions.(key)))
+        validatestring (useroptions.(key), attributes.(key), fun_name, key);
+
+      else
+        error ("Octave:invalid-input-arg",
+                [fun_name ": invalid value assigned to field '%s'"], key);
+      endif
+      
+    options.(key) = useroptions.(key);
+    
+    endif
+  endfor
+endfunction