81 if (tmp.
length () > 0 && tmp(0).is_defined ())
83 if (! warned_fcn_imaginary && tmp(0).is_complex_type ())
85 warning (
"lsode: ignoring imaginary part returned from user-supplied function");
86 warned_fcn_imaginary =
true;
120 if (tmp.
length () > 0 && tmp(0).is_defined ())
122 if (! warned_jac_imaginary && tmp(0).is_complex_type ())
124 warning (
"lsode: ignoring imaginary part returned from user-supplied jacobian function");
125 warned_jac_imaginary =
true;
128 retval = tmp(0).matrix_value ();
140 #define LSODE_ABORT() \
143 #define LSODE_ABORT1(msg) \
146 ::error ("lsode: " msg); \
151 #define LSODE_ABORT2(fmt, arg) \
154 ::error ("lsode: " fmt, arg); \
159 DEFUN (lsode, args, nargout,
161 @deftypefn {Built-in Function} {[@var{x}, @var{istate}, @var{msg}] =} lsode (@var{fcn}, @var{x_0}, @var{t})\n\
162 @deftypefnx {Built-in Function} {[@var{x}, @var{istate}, @var{msg}] =} lsode (@var{fcn}, @var{x_0}, @var{t}, @var{t_crit})\n\
163 Solve the set of differential equations\n\
165 $$ {dx \\over dt} = f (x, t) $$\n\
167 $$ x(t_0) = x_0 $$\n\
187 The solution is returned in the matrix @var{x}, with each row\n\
188 corresponding to an element of the vector @var{t}. The first element\n\
189 of @var{t} should be @math{t_0} and should correspond to the initial\n\
190 state of the system @var{x_0}, so that the first row of the output\n\
193 The first argument, @var{fcn}, is a string, inline, or function handle\n\
194 that names the function @math{f} to call to compute the vector of right\n\
195 hand sides for the set of equations. The function must have the form\n\
198 @var{xdot} = f (@var{x}, @var{t})\n\
202 in which @var{xdot} and @var{x} are vectors and @var{t} is a scalar.\n\
204 If @var{fcn} is a two-element string array or a two-element cell array\n\
205 of strings, inline functions, or function handles, the first element names\n\
206 the function @math{f} described above, and the second element names a\n\
207 function to compute the Jacobian of @math{f}. The Jacobian function\n\
208 must have the form\n\
211 @var{jac} = j (@var{x}, @var{t})\n\
215 in which @var{jac} is the matrix of partial derivatives\n\
217 $$ J = {\\partial f_i \\over \\partial x_j} = \\left[\\matrix{\n\
218 {\\partial f_1 \\over \\partial x_1}\n\
219 & {\\partial f_1 \\over \\partial x_2}\n\
221 & {\\partial f_1 \\over \\partial x_N} \\cr\n\
222 {\\partial f_2 \\over \\partial x_1}\n\
223 & {\\partial f_2 \\over \\partial x_2}\n\
225 & {\\partial f_2 \\over \\partial x_N} \\cr\n\
226 \\vdots & \\vdots & \\ddots & \\vdots \\cr\n\
227 {\\partial f_3 \\over \\partial x_1}\n\
228 & {\\partial f_3 \\over \\partial x_2}\n\
230 & {\\partial f_3 \\over \\partial x_N} \\cr}\\right]$$\n\
236 | df_1 df_1 df_1 |\n\
237 | ---- ---- ... ---- |\n\
238 | dx_1 dx_2 dx_N |\n\
240 | df_2 df_2 df_2 |\n\
241 | ---- ---- ... ---- |\n\
242 df_i | dx_1 dx_2 dx_N |\n\
248 | df_N df_N df_N |\n\
249 | ---- ---- ... ---- |\n\
250 | dx_1 dx_2 dx_N |\n\
256 The second and third arguments specify the initial state of the system,\n\
257 @math{x_0}, and the initial value of the independent variable @math{t_0}.\n\
259 The fourth argument is optional, and may be used to specify a set of\n\
260 times that the ODE solver should not integrate past. It is useful for\n\
261 avoiding difficulties with singularities and points where there is a\n\
262 discontinuity in the derivative.\n\
264 After a successful computation, the value of @var{istate} will be 2\n\
265 (consistent with the Fortran version of @sc{lsode}).\n\
267 If the computation is not successful, @var{istate} will be something\n\
268 other than 2 and @var{msg} will contain additional information.\n\
270 You can use the function @code{lsode_options} to set optional\n\
271 parameters for @code{lsode}.\n\
272 @seealso{daspk, dassl, dasrt}\n\
277 warned_fcn_imaginary =
false;
278 warned_jac_imaginary =
false;
288 int nargin = args.length ();
290 if (nargin > 2 && nargin < 5 && nargout < 4)
292 std::string fcn_name, fname, jac_name, jname;
303 else if (c.
length () == 2)
305 if (c(0).is_function_handle () || c(0).is_inline_function ())
306 lsode_fcn = c(0).function_value ();
310 fname =
"function y = ";
311 fname.append (fcn_name);
312 fname.append (
" (x, t) y = ");
319 if (c(1).is_function_handle () || c(1).is_inline_function ())
320 lsode_jac = c(1).function_value ();
324 jname =
"function jac = ";
325 jname.append (jac_name);
326 jname.append (
" (x, t) jac = ");
328 jname,
"; endfunction");
332 if (fcn_name.length ())
340 LSODE_ABORT1 (
"incorrect number of elements in cell array");
343 if (!lsode_fcn && ! f_arg.
is_cell ())
349 switch (f_arg.
rows ())
355 fname =
"function y = ";
356 fname.append (fcn_name);
357 fname.append (
" (x, t) y = ");
359 fname,
"; endfunction");
371 fname =
"function y = ";
372 fname.append (fcn_name);
373 fname.append (
" (x, t) y = ");
375 fname,
"; endfunction");
380 jname =
"function jac = ";
381 jname.append (jac_name);
382 jname.append (
" (x, t) jac = ");
389 if (fcn_name.length ())
400 (
"first arg should be a string or 2-element string array");
411 LSODE_ABORT1 (
"expecting state vector as second argument");
416 LSODE_ABORT1 (
"expecting output time vector as third argument");
420 int crit_times_set = 0;
426 LSODE_ABORT1 (
"expecting critical time vector as fourth argument");
431 double tzero = out_times (0);
437 LSODE ode (state, tzero, func);
443 output = ode.
integrate (out_times, crit_times);
447 if (fcn_name.length ())
449 if (jac_name.length ())
466 error (
"lsode: %s", msg.c_str ());