comparison 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
comparison
equal deleted inserted replaced
20567:2480bbcd1333 20568:fcb792acab9b
1 ## Copyright (C) 2013, Roberto Porcu' <roberto.porcu@polimi.it>
2 ## Copyright (C) 2006-2012, Thomas Treichl <treichl@users.sourceforge.net>
3 ##
4 ## This file is part of Octave.
5 ##
6 ## Octave is free software; you can redistribute it and/or modify it
7 ## under the terms of the GNU General Public License as published by
8 ## the Free Software Foundation; either version 3 of the License, or (at
9 ## your option) any later version.
10 ##
11 ## Octave is distributed in the hope that it will be useful, but
12 ## WITHOUT ANY WARRANTY; without even the implied warranty of
13 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 ## General Public License for more details.
15 ##
16 ## You should have received a copy of the GNU General Public License
17 ## along with Octave; see the file COPYING. If not, see
18 ## <http://www.gnu.org/licenses/>.
19
20
21 ## -*- texinfo -*-
22 ## @deftypefn {Function File} {[@var{}] =} odeset ()
23 ## @deftypefnx {Function File} {[@var{odestruct}] =} odeset (@var{"field1"}, @var{value1}, @var{"field2"}, @var{value2}, @dots{})
24 ## @deftypefnx {Function File} {[@var{odestruct}] =} odeset (@var{oldstruct}, @var{"field1"}, @var{value1}, @var{"field2"}, @var{value2}, @dots{})
25 ## @deftypefnx {Function File} {[@var{odestruct}] =} odeset (@var{oldstruct},
26 ## @var{newstruct})
27 ##
28 ## If this function is called without an input argument then return a new
29 ## ODE options structure array that contains all the necessary fields and
30 ## sets the values of all fields to default values.
31 ##
32 ## If this function is called with string input arguments @var{"field1"},
33 ## @var{"field2"}, @dots{} identifying valid ODE options then return a
34 ## new ODE options structure with all necessary fields and set the values
35 ## of the fields @var{"field1"}, @var{"field2"}, @dots{} to the values
36 ## @var{value1}, @var{value2}, @dots{}
37 ##
38 ## If this function is called with a first input argument @var{oldstruct}
39 ## of type structure array then overwrite all values of the options
40 ## @var{"field1"}, @var{"field2"}, @dots{} of the structure @var{oldstruct}
41 ## with new values @var{value1}, @var{value2}, @dots{} and return the
42 ## modified structure array.
43 ##
44 ## If this function is called with two input arguments @var{oldstruct}
45 ## and @var{newstruct} of type structure array then overwrite all values
46 ## in the fields from the structure @var{oldstruct} with new values of the
47 ## fields from the structure @var{newstruct}. Empty values of @var{newstruct}
48 ## will not overwrite values in @var{oldstruct}.
49 ## @end deftypefn
50 ##
51
52 function opt = odeset (varargin)
53
54 ## Check number and types of all input arguments
55 if ((nargin == 0)
56 && (nargout == 0))
57 print_options;
58 return
59 endif
60
61 ## Creating a vector of OdePkg possible fields
62 fields = ["AbsTol"; "Algorithm"; "BDF"; "Choice"; "Eta"; "Events";
63 "Explicit"; "InexactSolver"; "InitialSlope"; "InitialStep";
64 "Jacobian";"JConstant";"JPattern";"Mass"; "MassConstant";
65 "MassSingular"; "MaxNewtonIterations"; "MaxOrder"; "MaxStep";
66 "MStateDependence"; "MvPattern"; "NewtonTol"; "NonNegative";
67 "NormControl"; "OutputFcn"; "OutputSave"; "OutputSel";
68 "PolynomialDegree"; "QuadratureOrder"; "Refine"; "RelTol";
69 "Restart"; "Stats"; "TimeStepNumber"; "TimeStepSize";
70 "UseJacobian"; "Vectorized"];
71
72 fields_nb = size (fields, 1);
73
74 ## initialize output
75 opt = [];
76 for i = 1:1:fields_nb
77 opt.(deblank (fields(i,:))) = [];
78 endfor
79
80 opt.Refine = 0;
81 opt.OutputSave = 1;
82
83 if ((nargin == 0)
84 && (nargout == 1))
85 return
86 endif
87
88 ode_fields = fieldnames (opt);
89
90 if (isstruct (varargin{1}))
91 ode_struct_value_check (varargin{1});
92
93 optA_fields = fieldnames (varargin{1});
94 optA_f_nb = length (optA_fields);
95
96 ## loop on first struct options for updating
97 for i = 1:optA_f_nb
98 name = lower (deblank (optA_fields{i}));
99
100 while (1)
101 pos = fuzzy_compare (name, fields);
102 if (size (pos, 1) == 0)
103 warning ("OdePkg:InvalidArgument",
104 "no property found with name ''%s''", name);
105 endif
106
107 if (size (pos, 1) == 1)
108 if (! strcmp (lower (deblank (name)),
109 lower (deblank (fields(pos,:)))))
110 warning ("OdePkg:InvalidArgument", "no exact matching for ",
111 "''%s''. Assuming you were intending ''%s''",
112 name, deblank (fields(pos,:)));
113 endif
114
115 opt.(deblank (fields(pos,:))) = varargin{1}.(optA_fields{i});
116 break
117 endif
118
119 ## if there are more matching, ask the user to be more precise
120 warning ("OdePkg:InvalidArgument",
121 "no exact matching for ''%s''. %d possible fields were found",
122 name, size(pos, 1));
123 for j = 1:(size (pos, 1))
124 fprintf ("%s\n", deblank (fields(pos(j),:)));
125 endfor
126 do
127 fprintf ("Please insert field name again\n");
128 name = input ("New field name: ");
129 until (ischar (name))
130 endwhile
131 endfor
132
133 if ((nargin == 2)
134 && (isstruct (varargin{2})))
135 ode_struct_value_check (varargin{2});
136
137 optB_fields = fieldnames (varargin{2});
138 optB_f_nb = length (optB_fields);
139
140 ## update the first struct with the values in the second one
141 for i = 1:optB_f_nb
142 name = lower (deblank (optB_fields{i}));
143 while (1)
144 pos = fuzzy_compare (name, fields);
145
146 if (size (pos, 1) == 0)
147 warning ("OdePkg:InvalidArgument", ...
148 "no property found with name ''%s''", name);
149 endif
150
151 if (size(pos, 1) == 1)
152 if (! strcmp (lower (deblank (name)), lower (deblank (fields(pos,:)))))
153 warning ("OdePkg:InvalidArgument", "no exact matching for ",
154 "''%s''. Assuming you were intending ''%s''",
155 name, deblank (fields(pos,:)));
156 endif
157 opt.(deblank (fields(pos,:))) = varargin{2}.(optB_fields{i});
158 break
159 endif
160
161 ## if there are more matching, ask the user to be more precise
162 warning ("OdePkg:InvalidArgument", "no exact matching for ''%s''. ",
163 "%d possible fields were found",
164 name, size (pos, 1));
165 for j = 1:(size (pos, 1))
166 fprintf ("%s\n", deblank (fields(pos(j),:)));
167 endfor
168 do
169 fprintf ("Please insert field name again\n");
170 name = input ("New field name: ");
171 until (ischar (name))
172 endwhile
173 endfor
174 return
175 endif
176
177 ## if the second argument is not a struct,
178 ## pass new values of the OdePkg options to the first struct
179 if (mod (nargin, 2) != 1)
180 error ("OdePkg:InvalidArgument",
181 "odeset expects an odd number of input arguments",
182 " when the first is a ODE_STRUCT");
183 endif
184
185 ## loop on the input arguments
186 for i = 2:2:(nargin - 1)
187
188 if (! ischar(varargin{i}))
189 error ("OdePkg:InvalidArgument",
190 "not all odd input arguments are strings");
191 endif
192
193 name = varargin{i};
194
195 while (1)
196 pos = fuzzy_compare (name, fields);
197
198 if (size (pos, 1) == 0)
199 error ("OdePkg:InvalidArgument",
200 "no property found with name ''%s''", name);
201 endif
202
203 if (size (pos, 1) == 1)
204 if (! strcmp (lower (deblank (name)), lower (deblank (fields(pos,:)))))
205 warning ("OdePkg:InvalidArgument", "no exact matching for ''%s''. ",
206 "%d possible fields were found",
207 name, size (pos, 1));
208 endif
209 opt.(deblank (fields(pos,:))) = varargin{i+1};
210 break
211 endif
212
213 ## if there are more matching, ask the user to be more precise
214 warning ("OdePkg:InvalidArgument", "no exact matching for ''%s''. ",
215 "%d possible fields were found",
216 name, size (pos, 1));
217 for j = 1:(size (pos, 1))
218 fprintf ("%s\n", deblank (fields(pos(j),:)));
219 endfor
220 do
221 fprintf ("Please insert field name again\n");
222 name = input ("New field name: ");
223 until (ischar (name))
224 endwhile
225 endfor
226
227 ## check if all has been done gives a valid OdePkg struct
228 ode_struct_value_check (opt);
229 return
230 endif
231
232 ## first input argument was not a struct
233 if (mod (nargin, 2) != 0)
234 error ("OdePkg:InvalidArgument", "odeset expects an even number ",
235 "of input arguments when the first is a string");
236 endif
237
238 for i = 1:2:(nargin-1)
239 if (! ischar (varargin{i}))
240 error ("OdePkg:InvalidArgument",
241 "not all even input arguments are strings");
242 endif
243
244 name = varargin{i};
245
246 while (1)
247 pos = fuzzy_compare (name, fields);
248
249 if (size (pos, 1) == 0)
250 error ("OdePkg:InvalidArgument",
251 "invalid property. No property found with name ''%s''", name);
252 endif
253
254 if (size (pos, 1) == 1)
255 if (! strcmp (lower (deblank (name)),
256 lower (deblank (fields(pos,:)))))
257 warning ("OdePkg:InvalidArgument", "no exact matching for ",
258 "''%s''. Assuming you were intending ''%s''",
259 name, deblank (fields(pos,:)));
260 endif
261 opt.(deblank (fields(pos,:))) = varargin{i+1};
262 break
263 endif
264
265 ## if there are more matching, ask the user to be more precise
266 warning ("OdePkg:InvalidArgument", "no exact matching for ''%s''. ",
267 "%d possible fields were found",
268 name, size (pos, 1));
269 for j = 1:(size (pos, 1))
270 fprintf ("%s\n", deblank (fields(pos(j),:)));
271 endfor
272 do
273 fprintf ("Please insert field name again\n");
274 name = input ("New field name: ");
275 until (ischar (name))
276 endwhile
277 endfor
278
279 ## check if all has been done gives a valid OdePkg struct
280 ode_struct_value_check (opt);
281 endfunction
282
283 ## function useful to print all the possible options
284 function print_options ()
285
286 fprintf ("These following are all possible options.\n",
287 "Default values are put in square brackets.\n\n");
288
289 disp (" AbsTol: scalar or vector, >0, [1.e-6]");
290 disp (" Algorithm: string, {[''gmres''], ''pcg'', ''bicgstab''}");
291 disp (" BDF: binary, {''on'', [''off'']}");
292 disp (" Choice: switch, {[1], 2}");
293 disp (" Eta: scalar, >=0, <1, [0.5]");
294 disp (" Events: function_handle, []");
295 disp (" Explicit: binary, {''yes'', [''no'']}");
296 disp (" InexactSolver: string, {''inexact_newton'', ''fsolve'', []}");
297 disp (" InitialSlope: vector, []");
298 disp (" InitialStep: scalar, >0, []");
299 disp (" Jacobian: matrix or function_handle, []");
300 disp (" JConstant: binary, {''on'', [''off'']}");
301 disp (" JPattern: sparse matrix, []");
302 disp (" Mass: matrix or function_handle, []");
303 disp (" MassConstant: binary, {''on'', [''off'']}");
304 disp (" MassSingular: switch, {''yes'', [''maybe''], ''no''}");
305 disp ("MaxNewtonIterations: scalar, integer, >0, [1.e3]");
306 disp (" MaxOrder: switch, {1, 2, 3, 4, [5]}");
307 disp (" MaxStep: scalar, >0, []");
308 disp (" MStateDependence: switch, {''none'', [''weak''], ''strong''}");
309 disp (" MvPattern: sparse matrix, []");
310 disp (" NewtonTol: scalar or vector, >0, []");
311 disp (" NonNegative: vector of integers, []");
312 disp (" NormControl: binary, {''on'', [''off'']}");
313 disp (" OutputFcn: function_handle, []");
314 disp (" OutputSave: scalar, integer, >0, []");
315 disp (" OutputSel: scalar or vector, []");
316 disp (" PolynomialDegree: scalar, integer, >0, []");
317 disp (" QuadratureOrder: scalar, integer, >0, []");
318 disp (" Refine: scalar, integer, >0, []");
319 disp (" RelTol: scalar, >0, [1.e-3]");
320 disp (" Restart: scalar, integer, >0, [20]");
321 disp (" Stats: binary, {''on'', [''off'']}");
322 disp (" TimeStepNumber: scalar, integer, >0, []");
323 disp (" TimeStepSize: scalar, >0, []");
324 disp (" UseJacobian: binary, {''yes'', [''no'']}");
325 disp (" Vectorized: binary, {''on'', [''off'']}");
326
327 endfunction
328
329 ## All tests that are needed to check if a correct resp. valid option
330 ## has been set are implemented in ode_struct_value_check.m.
331 %! ## Turn off output of warning messages for all tests, turn them on
332 %! ## again if the last test is called
333 %! warning ('off', 'OdePkg:InvalidArgument');
334 %!test odeoptA = odeset ();
335 %!test odeoptB = odeset ('AbsTol', 1e-2, 'RelTol', 1e-1);
336 %! if (odeoptB.AbsTol != 1e-2), error; endif
337 %! if (odeoptB.RelTol != 1e-1), error; endif
338 %!test odeoptB = odeset ('AbsTol', 1e-2, 'RelTol', 1e-1);
339 %! odeoptC = odeset (odeoptB, 'NormControl', 'on');
340 %!test odeoptB = odeset ('AbsTol', 1e-2, 'RelTol', 1e-1);
341 %! odeoptC = odeset (odeoptB, 'NormControl', 'on');
342 %! odeoptD = odeset (odeoptC, odeoptB);
343 %!
344 %! warning ('on', 'OdePkg:InvalidArgument');
345
346 %!demo
347 %! # A new OdePkg options structure with default values is created.
348 %!
349 %! odeoptA = odeset ();
350 %!
351 %!demo
352 %! # A new OdePkg options structure with manually set options
353 %! # "AbsTol" and "RelTol" is created.
354 %!
355 %! odeoptB = odeset ('AbsTol', 1e-2, 'RelTol', 1e-1);
356 %!
357 %!demo
358 %! # A new OdePkg options structure from odeoptB is created with
359 %! # a modified value for option "NormControl".
360 %!
361 %! odeoptB = odeset ('AbsTol', 1e-2, 'RelTol', 1e-1);
362 %! odeoptC = odeset (odeoptB, 'NormControl', 'on');
363
364 ## Local Variables: ***
365 ## mode: octave ***
366 ## End: ***