diff scripts/ode/odeset.m @ 20568:fcb792acab9b

Moving ode45, odeset, odeget, and levenshtein from odepkg to core. * libinterp/corefcn/levenshtein.cc: move function from odepkg into core * libinterp/corefcn/module.mk: include levenshtein.cc * scripts/ode: move ode45, odeset, odeget, and all dependencies from odepkg into core * scripts/module.mk: include them * doc/interpreter/diffeq.txi: add documentation for ode45, odeset, odeget * NEWS: announce functions included with this changeset * scripts/help/__unimplemented__.m: removed new functions
author jcorno <jacopo.corno@gmail.com>
date Thu, 24 Sep 2015 12:58:46 +0200
parents
children 25623ef2ff4f
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/ode/odeset.m	Thu Sep 24 12:58:46 2015 +0200
@@ -0,0 +1,366 @@
+## Copyright (C) 2013, 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  {Function File} {[@var{}] =} odeset ()
+## @deftypefnx {Function File}  {[@var{odestruct}] =} odeset (@var{"field1"}, @var{value1}, @var{"field2"}, @var{value2}, @dots{})
+## @deftypefnx {Function File}  {[@var{odestruct}] =} odeset (@var{oldstruct}, @var{"field1"}, @var{value1}, @var{"field2"}, @var{value2}, @dots{})
+## @deftypefnx {Function File}  {[@var{odestruct}] =} odeset (@var{oldstruct},
+## @var{newstruct})
+##
+## If this function is called without an input argument then return a new
+## ODE options structure array that contains all the necessary fields and
+## sets the values of all fields to default values.
+##
+## If this function is called with string input arguments @var{"field1"},
+## @var{"field2"}, @dots{} identifying valid ODE options then return a
+## new ODE options structure with all necessary fields and set the values
+## of the fields @var{"field1"}, @var{"field2"}, @dots{} to the values
+## @var{value1}, @var{value2}, @dots{}
+##
+## If this function is called with a first input argument @var{oldstruct}
+## of type structure array then overwrite all values of the options
+## @var{"field1"}, @var{"field2"}, @dots{} of the structure @var{oldstruct}
+## with new values @var{value1}, @var{value2}, @dots{} and return the
+## modified structure array.
+##
+## If this function is called with two input arguments @var{oldstruct}
+## and @var{newstruct} of type structure array then overwrite all values
+## in the fields from the structure @var{oldstruct} with new values of the
+## fields from the structure @var{newstruct}. Empty values of @var{newstruct}
+## will not overwrite values in @var{oldstruct}.
+## @end deftypefn
+##
+
+function opt = odeset (varargin)
+
+  ## Check number and types of all input arguments
+  if ((nargin == 0)
+      && (nargout == 0))
+    print_options;
+    return
+  endif
+
+  ## Creating a vector of OdePkg possible fields
+  fields = ["AbsTol"; "Algorithm"; "BDF"; "Choice"; "Eta"; "Events";
+            "Explicit"; "InexactSolver"; "InitialSlope"; "InitialStep";
+            "Jacobian";"JConstant";"JPattern";"Mass"; "MassConstant";
+            "MassSingular"; "MaxNewtonIterations"; "MaxOrder"; "MaxStep";
+            "MStateDependence"; "MvPattern"; "NewtonTol"; "NonNegative";
+            "NormControl"; "OutputFcn"; "OutputSave"; "OutputSel";
+            "PolynomialDegree"; "QuadratureOrder"; "Refine"; "RelTol";
+            "Restart"; "Stats"; "TimeStepNumber"; "TimeStepSize";
+            "UseJacobian"; "Vectorized"];
+
+  fields_nb = size (fields, 1);
+
+  ## initialize output
+  opt = [];
+  for i = 1:1:fields_nb
+    opt.(deblank (fields(i,:))) = [];
+  endfor
+
+  opt.Refine = 0;
+  opt.OutputSave = 1;
+
+  if ((nargin == 0)
+      && (nargout == 1))
+    return
+  endif
+
+  ode_fields = fieldnames (opt);
+  
+  if (isstruct (varargin{1}))
+    ode_struct_value_check (varargin{1});
+
+    optA_fields = fieldnames (varargin{1});
+    optA_f_nb = length (optA_fields);
+
+    ## loop on first struct options for updating
+    for i = 1:optA_f_nb
+      name = lower (deblank (optA_fields{i}));
+
+      while (1)
+        pos = fuzzy_compare (name, fields);
+        if (size (pos, 1) == 0)
+          warning ("OdePkg:InvalidArgument",
+                   "no property found with name ''%s''", name);
+        endif
+
+        if (size (pos, 1) == 1)
+          if (! strcmp (lower (deblank (name)),
+                        lower (deblank (fields(pos,:)))))
+            warning ("OdePkg:InvalidArgument", "no exact matching for ",
+                     "''%s''. Assuming you were intending ''%s''",
+                     name, deblank (fields(pos,:)));
+          endif
+
+          opt.(deblank (fields(pos,:))) = varargin{1}.(optA_fields{i});
+          break
+        endif
+
+        ## if there are more matching, ask the user to be more precise
+        warning ("OdePkg:InvalidArgument",
+                 "no exact matching for ''%s''. %d possible fields were found",
+                 name, size(pos, 1));
+        for j = 1:(size (pos, 1))
+          fprintf ("%s\n", deblank (fields(pos(j),:)));
+        endfor
+        do
+          fprintf ("Please insert field name again\n");
+          name = input ("New field name: ");
+        until (ischar (name))
+      endwhile
+    endfor
+
+    if ((nargin == 2)
+        && (isstruct (varargin{2})))
+      ode_struct_value_check (varargin{2});
+
+      optB_fields = fieldnames (varargin{2});
+      optB_f_nb = length (optB_fields);
+
+      ## update the first struct with the values in the second one
+      for i = 1:optB_f_nb
+        name = lower (deblank (optB_fields{i}));
+        while (1)
+          pos = fuzzy_compare (name, fields);
+
+          if (size (pos, 1) == 0)
+            warning ("OdePkg:InvalidArgument", ...
+                     "no property found with name ''%s''", name);
+          endif
+
+          if (size(pos, 1) == 1)
+            if (! strcmp (lower (deblank (name)), lower (deblank (fields(pos,:)))))
+              warning ("OdePkg:InvalidArgument", "no exact matching for ",
+                       "''%s''. Assuming you were intending ''%s''",
+                        name, deblank (fields(pos,:)));
+            endif
+            opt.(deblank (fields(pos,:))) = varargin{2}.(optB_fields{i});
+            break
+          endif
+
+          ## if there are more matching, ask the user to be more precise
+          warning ("OdePkg:InvalidArgument", "no exact matching for ''%s''. ",
+                   "%d possible fields were found",
+                   name, size (pos, 1));
+          for j = 1:(size (pos, 1))
+            fprintf ("%s\n", deblank (fields(pos(j),:)));
+          endfor
+          do
+            fprintf ("Please insert field name again\n");
+            name = input ("New field name: ");
+          until (ischar (name))
+        endwhile
+      endfor
+      return
+    endif
+
+    ## if the second argument is not a struct,
+    ## pass new values of the OdePkg options to the first struct
+    if (mod (nargin, 2) != 1)
+      error ("OdePkg:InvalidArgument",
+             "odeset expects an odd number of input arguments",
+             " when the first is a ODE_STRUCT");
+    endif
+
+    ## loop on the input arguments
+    for i = 2:2:(nargin - 1)
+
+      if (! ischar(varargin{i}))
+        error ("OdePkg:InvalidArgument",
+               "not all odd input arguments are strings");
+      endif
+
+      name = varargin{i};
+
+      while (1)
+        pos = fuzzy_compare (name, fields);
+
+        if (size (pos, 1) == 0)
+          error ("OdePkg:InvalidArgument",
+                 "no property found with name ''%s''", name);
+        endif
+
+        if (size (pos, 1) == 1)
+          if (! strcmp (lower (deblank (name)), lower (deblank (fields(pos,:)))))
+            warning ("OdePkg:InvalidArgument", "no exact matching for ''%s''. ",
+                     "%d possible fields were found",
+                     name, size (pos, 1));
+          endif
+          opt.(deblank (fields(pos,:))) = varargin{i+1};
+          break
+        endif
+
+        ## if there are more matching, ask the user to be more precise
+        warning ("OdePkg:InvalidArgument", "no exact matching for ''%s''. ",
+                 "%d possible fields were found",
+                 name, size (pos, 1));
+        for j = 1:(size (pos, 1))
+          fprintf ("%s\n", deblank (fields(pos(j),:)));
+        endfor
+        do
+          fprintf ("Please insert field name again\n");
+          name = input ("New field name: ");
+        until (ischar (name))
+      endwhile
+    endfor
+
+    ## check if all has been done gives a valid OdePkg struct
+    ode_struct_value_check (opt);
+    return
+  endif
+
+  ## first input argument was not a struct
+  if (mod (nargin, 2) != 0)
+    error ("OdePkg:InvalidArgument", "odeset expects an even number ",
+           "of input arguments when the first is a string");
+  endif
+
+  for i = 1:2:(nargin-1)
+    if (! ischar (varargin{i}))
+      error ("OdePkg:InvalidArgument",
+             "not all even input arguments are strings");
+    endif
+
+    name = varargin{i};
+
+    while (1)
+      pos = fuzzy_compare (name, fields);
+
+      if (size (pos, 1) == 0)
+        error ("OdePkg:InvalidArgument",
+               "invalid property. No property found with name ''%s''", name);
+      endif
+
+      if (size (pos, 1) == 1)
+        if (! strcmp (lower (deblank (name)),
+                      lower (deblank (fields(pos,:)))))
+          warning ("OdePkg:InvalidArgument", "no exact matching for ",
+                   "''%s''. Assuming you were intending ''%s''",
+                   name, deblank (fields(pos,:)));
+        endif
+        opt.(deblank (fields(pos,:))) = varargin{i+1};
+        break
+      endif
+
+      ## if there are more matching, ask the user to be more precise
+      warning ("OdePkg:InvalidArgument", "no exact matching for ''%s''. ",
+               "%d possible fields were found",
+               name, size (pos, 1));
+      for j = 1:(size (pos, 1))
+        fprintf ("%s\n", deblank (fields(pos(j),:)));
+      endfor
+      do
+        fprintf ("Please insert field name again\n");
+        name = input ("New field name: ");
+      until (ischar (name))
+    endwhile
+  endfor
+
+  ## check if all has been done gives a valid OdePkg struct
+  ode_struct_value_check (opt);
+endfunction
+
+## function useful to print all the possible options
+function print_options ()
+  
+  fprintf ("These following are all possible options.\n",
+           "Default values are put in square brackets.\n\n");
+  
+  disp ("             AbsTol:  scalar or vector, >0, [1.e-6]");
+  disp ("          Algorithm:  string, {[''gmres''], ''pcg'', ''bicgstab''}");
+  disp ("                BDF:  binary, {''on'', [''off'']}");
+  disp ("             Choice:  switch, {[1], 2}");
+  disp ("                Eta:  scalar, >=0, <1, [0.5]");
+  disp ("             Events:  function_handle, []");
+  disp ("           Explicit:  binary, {''yes'', [''no'']}");
+  disp ("      InexactSolver:  string, {''inexact_newton'', ''fsolve'', []}");
+  disp ("       InitialSlope:  vector, []");
+  disp ("        InitialStep:  scalar, >0, []");
+  disp ("           Jacobian:  matrix or function_handle, []");
+  disp ("          JConstant:  binary, {''on'', [''off'']}");
+  disp ("           JPattern:  sparse matrix, []");
+  disp ("               Mass:  matrix or function_handle, []");
+  disp ("       MassConstant:  binary, {''on'', [''off'']}");
+  disp ("       MassSingular:  switch, {''yes'', [''maybe''], ''no''}");
+  disp ("MaxNewtonIterations:  scalar, integer, >0, [1.e3]");
+  disp ("           MaxOrder:  switch, {1, 2, 3, 4, [5]}");
+  disp ("            MaxStep:  scalar, >0, []");
+  disp ("   MStateDependence:  switch, {''none'', [''weak''], ''strong''}");
+  disp ("          MvPattern:  sparse matrix, []");
+  disp ("          NewtonTol:  scalar or vector, >0, []");
+  disp ("        NonNegative:  vector of integers, []");
+  disp ("        NormControl:  binary, {''on'', [''off'']}");
+  disp ("          OutputFcn:  function_handle, []");
+  disp ("         OutputSave:  scalar, integer, >0, []");
+  disp ("          OutputSel:  scalar or vector, []");
+  disp ("   PolynomialDegree:  scalar, integer, >0, []");
+  disp ("    QuadratureOrder:  scalar, integer, >0, []");
+  disp ("             Refine:  scalar, integer, >0, []");
+  disp ("             RelTol:  scalar, >0, [1.e-3]");
+  disp ("            Restart:  scalar, integer, >0, [20]");
+  disp ("              Stats:  binary, {''on'', [''off'']}");
+  disp ("     TimeStepNumber:  scalar, integer, >0, []");
+  disp ("       TimeStepSize:  scalar, >0, []");
+  disp ("        UseJacobian:  binary, {''yes'', [''no'']}");
+  disp ("         Vectorized:  binary, {''on'', [''off'']}");
+
+endfunction
+
+## All tests that are needed to check if a correct resp. valid option
+## has been set are implemented in ode_struct_value_check.m.
+%! ## Turn off output of warning messages for all tests, turn them on
+%! ## again if the last test is called
+%!  warning ('off', 'OdePkg:InvalidArgument');
+%!test odeoptA = odeset ();
+%!test odeoptB = odeset ('AbsTol', 1e-2, 'RelTol', 1e-1);
+%!     if (odeoptB.AbsTol != 1e-2), error; endif
+%!     if (odeoptB.RelTol != 1e-1), error; endif
+%!test odeoptB = odeset ('AbsTol', 1e-2, 'RelTol', 1e-1);
+%!     odeoptC = odeset (odeoptB, 'NormControl', 'on');
+%!test odeoptB = odeset ('AbsTol', 1e-2, 'RelTol', 1e-1);
+%!     odeoptC = odeset (odeoptB, 'NormControl', 'on');
+%!     odeoptD = odeset (odeoptC, odeoptB);
+%!
+%!  warning ('on', 'OdePkg:InvalidArgument');
+
+%!demo
+%! # A new OdePkg options structure with default values is created.
+%!
+%! odeoptA = odeset ();
+%!
+%!demo
+%! # A new OdePkg options structure with manually set options 
+%! # "AbsTol" and "RelTol" is created.
+%!
+%! odeoptB = odeset ('AbsTol', 1e-2, 'RelTol', 1e-1);
+%!
+%!demo
+%! # A new OdePkg options structure from odeoptB is created with
+%! # a modified value for option "NormControl".
+%!
+%! odeoptB = odeset ('AbsTol', 1e-2, 'RelTol', 1e-1);
+%! odeoptC = odeset (odeoptB, 'NormControl', 'on');
+
+## Local Variables: ***
+## mode: octave ***
+## End: ***