85 if (tlen > 0 && tmp(0).is_defined ())
87 if (! warned_fcn_imaginary && tmp(0).is_complex_type ())
89 warning (
"dassl: ignoring imaginary part returned from user-supplied function");
90 warned_fcn_imaginary =
true;
96 ires = tmp(1).int_value ();
134 if (tlen > 0 && tmp(0).is_defined ())
136 if (! warned_jac_imaginary && tmp(0).is_complex_type ())
138 warning (
"dassl: ignoring imaginary part returned from user-supplied jacobian function");
139 warned_jac_imaginary =
true;
142 retval = tmp(0).matrix_value ();
154 #define DASSL_ABORT() \
157 #define DASSL_ABORT1(msg) \
160 ::error ("dassl: " msg); \
165 #define DASSL_ABORT2(fmt, arg) \
168 ::error ("dassl: " fmt, arg); \
173 DEFUN (dassl, args, nargout,
175 @deftypefn {Built-in Function} {[@var{x}, @var{xdot}, @var{istate}, @var{msg}] =} dassl (@var{fcn}, @var{x_0}, @var{xdot_0}, @var{t}, @var{t_crit})\n\
176 Solve the set of differential-algebraic equations\n\
178 $$ 0 = f (x, \\dot{x}, t) $$\n\
180 $$ x(t_0) = x_0, \\dot{x}(t_0) = \\dot{x}_0 $$\n\
185 0 = f (x, xdot, t)\n\
192 x(t_0) = x_0, xdot(t_0) = xdot_0\n\
196 The solution is returned in the matrices @var{x} and @var{xdot},\n\
197 with each row in the result matrices corresponding to one of the\n\
198 elements in the vector @var{t}. The first element of @var{t}\n\
199 should be @math{t_0} and correspond to the initial state of the\n\
200 system @var{x_0} and its derivative @var{xdot_0}, so that the first\n\
201 row of the output @var{x} is @var{x_0} and the first row\n\
202 of the output @var{xdot} is @var{xdot_0}.\n\
204 The first argument, @var{fcn}, is a string, inline, or function handle\n\
205 that names the function @math{f} to call to compute the vector of\n\
206 residuals for the set of equations. It must have the form\n\
209 @var{res} = f (@var{x}, @var{xdot}, @var{t})\n\
213 in which @var{x}, @var{xdot}, and @var{res} are vectors, and @var{t} is a\n\
216 If @var{fcn} is a two-element string array or a two-element cell array\n\
217 of strings, inline functions, or function handles, the first element names\n\
218 the function @math{f} described above, and the second element names a\n\
219 function to compute the modified Jacobian\n\
223 J = {\\partial f \\over \\partial x}\n\
224 + c {\\partial f \\over \\partial \\dot{x}}\n\
232 jac = -- + c ------\n\
239 The modified Jacobian function must have the form\n\
244 @var{jac} = j (@var{x}, @var{xdot}, @var{t}, @var{c})\n\
249 The second and third arguments to @code{dassl} specify the initial\n\
250 condition of the states and their derivatives, and the fourth argument\n\
251 specifies a vector of output times at which the solution is desired,\n\
252 including the time corresponding to the initial condition.\n\
254 The set of initial states and derivatives are not strictly required to\n\
255 be consistent. In practice, however, @sc{dassl} is not very good at\n\
256 determining a consistent set for you, so it is best if you ensure that\n\
257 the initial values result in the function evaluating to zero.\n\
259 The fifth argument is optional, and may be used to specify a set of\n\
260 times that the DAE 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\n\
265 greater than zero (consistent with the Fortran version of @sc{dassl}).\n\
267 If the computation is not successful, the value of @var{istate} will be\n\
268 less than zero and @var{msg} will contain additional information.\n\
270 You can use the function @code{dassl_options} to set optional\n\
271 parameters for @code{dassl}.\n\
272 @seealso{daspk, dasrt, lsode}\n\
277 warned_fcn_imaginary =
false;
278 warned_jac_imaginary =
false;
288 int nargin = args.length ();
290 if (nargin > 3 && nargin < 6 && nargout < 5)
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 dassl_fcn = c(0).function_value ();
310 fname =
"function y = ";
311 fname.append (fcn_name);
312 fname.append (
" (x, xdot, t) y = ");
319 if (c(1).is_function_handle () || c(1).is_inline_function ())
320 dassl_jac = c(1).function_value ();
324 jname =
"function jac = ";
325 jname.append (jac_name);
326 jname.append (
" (x, xdot, t, cj) jac = ");
328 jname,
"; endfunction");
332 if (fcn_name.length ())
340 DASSL_ABORT1 (
"incorrect number of elements in cell array");
343 if (!dassl_fcn && ! f_arg.
is_cell ())
349 switch (f_arg.
rows ())
355 fname =
"function y = ";
356 fname.append (fcn_name);
357 fname.append (
" (x, xdot, t) y = ");
359 fname,
"; endfunction");
371 fname =
"function y = ";
372 fname.append (fcn_name);
373 fname.append (
" (x, xdot, t) y = ");
375 fname,
"; endfunction");
380 jname =
"function jac = ";
381 jname.append (jac_name);
382 jname.append (
" (x, xdot, t, cj) jac = ");
389 if (fcn_name.length ())
406 DASSL_ABORT1 (
"expecting state vector as second argument");
411 DASSL_ABORT1 (
"expecting derivative vector as third argument");
416 DASSL_ABORT1 (
"expecting output time vector as fourth argument");
419 int crit_times_set = 0;
425 DASSL_ABORT1 (
"expecting critical time vector as fifth argument");
433 double tzero = out_times (0);
439 DASSL dae (state, deriv, tzero, func);
447 output = dae.
integrate (out_times, deriv_output, crit_times);
449 output = dae.
integrate (out_times, deriv_output);
451 if (fcn_name.length ())
453 if (jac_name.length ())
465 retval(1) = deriv_output;
474 error (
"dassl: %s", msg.c_str ());