Mercurial > octave
view libinterp/corefcn/lsode.cc @ 25438:cb1606f78f6b
prefer <istream>, <ostream>, or <iosfwd> to <iostream> where possible
Using <iostream> brings with it a static initializer for the std::cin,
std::cout, and std::cerr streams. In most cases they are not needed
and should be avoided if possible.
Files affected:
build-aux/mk-opts.pl
libgui/qterminal/libqterminal/win32/QWinTerminalImpl.cpp
libinterp/corefcn/__dsearchn__.cc
libinterp/corefcn/c-file-ptr-stream.cc
libinterp/corefcn/c-file-ptr-stream.h
libinterp/corefcn/daspk.cc
libinterp/corefcn/dasrt.cc
libinterp/corefcn/dassl.cc
libinterp/corefcn/defaults.cc
libinterp/corefcn/defun.cc
libinterp/corefcn/file-io.cc
libinterp/corefcn/ft-text-renderer.cc
libinterp/corefcn/gl-render.cc
libinterp/corefcn/help.cc
libinterp/corefcn/ls-ascii-helper.cc
libinterp/corefcn/ls-hdf5.cc
libinterp/corefcn/ls-hdf5.h
libinterp/corefcn/ls-mat-ascii.cc
libinterp/corefcn/ls-mat4.cc
libinterp/corefcn/ls-mat5.cc
libinterp/corefcn/ls-oct-binary.cc
libinterp/corefcn/ls-oct-text.cc
libinterp/corefcn/lsode.cc
libinterp/corefcn/oct-iostrm.cc
libinterp/corefcn/oct-procbuf.cc
libinterp/corefcn/oct-stdstrm.h
libinterp/corefcn/procstream.cc
libinterp/corefcn/procstream.h
libinterp/corefcn/quad.cc
libinterp/corefcn/symscope.h
libinterp/corefcn/symtab.h
libinterp/corefcn/toplev.cc
libinterp/corefcn/urlwrite.cc
libinterp/corefcn/utils.cc
libinterp/corefcn/zfstream.cc
libinterp/dldfcn/__ode15__.cc
libinterp/dldfcn/convhulln.cc
libinterp/octave-value/ov-base-diag.cc
libinterp/octave-value/ov-base-int.cc
libinterp/octave-value/ov-base-mat.cc
libinterp/octave-value/ov-base-scalar.cc
libinterp/octave-value/ov-base-sparse.cc
libinterp/octave-value/ov-base.cc
libinterp/octave-value/ov-bool-mat.cc
libinterp/octave-value/ov-bool-sparse.cc
libinterp/octave-value/ov-bool.cc
libinterp/octave-value/ov-cell.cc
libinterp/octave-value/ov-ch-mat.cc
libinterp/octave-value/ov-class.cc
libinterp/octave-value/ov-colon.cc
libinterp/octave-value/ov-complex.cc
libinterp/octave-value/ov-cs-list.cc
libinterp/octave-value/ov-cx-mat.cc
libinterp/octave-value/ov-cx-sparse.cc
libinterp/octave-value/ov-fcn-handle.cc
libinterp/octave-value/ov-fcn-inline.cc
libinterp/octave-value/ov-float.cc
libinterp/octave-value/ov-flt-complex.cc
libinterp/octave-value/ov-flt-cx-mat.cc
libinterp/octave-value/ov-flt-re-mat.cc
libinterp/octave-value/ov-int16.cc
libinterp/octave-value/ov-int32.cc
libinterp/octave-value/ov-int64.cc
libinterp/octave-value/ov-int8.cc
libinterp/octave-value/ov-java.cc
libinterp/octave-value/ov-range.cc
libinterp/octave-value/ov-re-mat.cc
libinterp/octave-value/ov-re-sparse.cc
libinterp/octave-value/ov-scalar.cc
libinterp/octave-value/ov-str-mat.cc
libinterp/octave-value/ov-struct.cc
libinterp/octave-value/ov-typeinfo.cc
libinterp/octave-value/ov-uint16.cc
libinterp/octave-value/ov-uint32.cc
libinterp/octave-value/ov-uint64.cc
libinterp/octave-value/ov-uint8.cc
libinterp/octave.cc
libinterp/parse-tree/bp-table.cc
libinterp/parse-tree/lex.h
libinterp/parse-tree/profiler.cc
libinterp/parse-tree/pt-arg-list.cc
libinterp/parse-tree/pt-array-list.cc
libinterp/parse-tree/pt-assign.cc
libinterp/parse-tree/pt-cell.cc
libinterp/parse-tree/pt-const.cc
libinterp/parse-tree/pt-eval.cc
libinterp/parse-tree/pt-exp.cc
libinterp/parse-tree/pt-fcn-handle.cc
libinterp/parse-tree/pt-jit.cc
libinterp/parse-tree/pt-pr-code.cc
libinterp/parse-tree/pt-tm-const.cc
libinterp/parse-tree/pt.cc
liboctave/array/Array.cc
liboctave/array/CColVector.cc
liboctave/array/CDiagMatrix.cc
liboctave/array/CMatrix.cc
liboctave/array/CNDArray.cc
liboctave/array/CRowVector.cc
liboctave/array/CSparse.cc
liboctave/array/DiagArray2.cc
liboctave/array/MArray.cc
liboctave/array/Range.cc
liboctave/array/Sparse.cc
liboctave/array/boolMatrix.cc
liboctave/array/boolSparse.cc
liboctave/array/chMatrix.cc
liboctave/array/dColVector.cc
liboctave/array/dDiagMatrix.cc
liboctave/array/dMatrix.cc
liboctave/array/dNDArray.cc
liboctave/array/dRowVector.cc
liboctave/array/dSparse.cc
liboctave/array/fCColVector.cc
liboctave/array/fCDiagMatrix.cc
liboctave/array/fCMatrix.cc
liboctave/array/fCNDArray.cc
liboctave/array/fCRowVector.cc
liboctave/array/fColVector.cc
liboctave/array/fDiagMatrix.cc
liboctave/array/fMatrix.cc
liboctave/array/fNDArray.cc
liboctave/array/fRowVector.cc
liboctave/array/idx-vector.cc
liboctave/numeric/CollocWt.cc
liboctave/numeric/eigs-base.cc
liboctave/system/file-ops.cc
liboctave/system/oct-time.cc
liboctave/util/cmd-hist.cc
liboctave/util/data-conv.cc
liboctave/util/data-conv.h
liboctave/util/file-info.cc
liboctave/util/lo-utils.cc
liboctave/util/lo-utils.h
liboctave/util/quit.cc
liboctave/util/str-vec.cc
liboctave/util/url-transfer.cc
liboctave/util/url-transfer.h
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Thu, 07 Jun 2018 10:11:54 -0400 |
parents | 6652d3823428 |
children | 00f796120a6d |
line wrap: on
line source
/* Copyright (C) 1996-2018 John W. Eaton 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 <https://www.gnu.org/licenses/>. */ #if defined (HAVE_CONFIG_H) # include "config.h" #endif #include <string> #include "LSODE.h" #include "lo-mappers.h" #include "defun.h" #include "error.h" #include "errwarn.h" #include "ovl.h" #include "ov-fcn.h" #include "ov-cell.h" #include "pager.h" #include "parse.h" #include "pr-output.h" #include "unwind-prot.h" #include "utils.h" #include "variables.h" #include "LSODE-opts.cc" // Global pointer for user defined function required by lsode. static octave_function *lsode_fcn; // Global pointer for optional user defined jacobian function used by lsode. static octave_function *lsode_jac; // Have we warned about imaginary values returned from user function? static bool warned_fcn_imaginary = false; static bool warned_jac_imaginary = false; // Is this a recursive call? static int call_depth = 0; ColumnVector lsode_user_function (const ColumnVector& x, double t) { ColumnVector retval; octave_value_list args; args(1) = t; args(0) = x; if (lsode_fcn) { octave_value_list tmp; try { tmp = octave::feval (lsode_fcn, args, 1); } catch (octave::execution_exception& e) { err_user_supplied_eval (e, "lsode"); } if (tmp.empty () || ! tmp(0).is_defined ()) err_user_supplied_eval ("lsode"); if (! warned_fcn_imaginary && tmp(0).iscomplex ()) { warning ("lsode: ignoring imaginary part returned from user-supplied function"); warned_fcn_imaginary = true; } retval = tmp(0).xvector_value ("lsode: expecting user supplied function to return numeric vector"); if (retval.isempty ()) err_user_supplied_eval ("lsode"); } return retval; } Matrix lsode_user_jacobian (const ColumnVector& x, double t) { Matrix retval; octave_value_list args; args(1) = t; args(0) = x; if (lsode_jac) { octave_value_list tmp; try { tmp = octave::feval (lsode_jac, args, 1); } catch (octave::execution_exception& e) { err_user_supplied_eval (e, "lsode"); } if (tmp.empty () || ! tmp(0).is_defined ()) err_user_supplied_eval ("lsode"); if (! warned_jac_imaginary && tmp(0).iscomplex ()) { warning ("lsode: ignoring imaginary part returned from user-supplied jacobian function"); warned_jac_imaginary = true; } retval = tmp(0).xmatrix_value ("lsode: expecting user supplied jacobian function to return numeric array"); if (retval.isempty ()) err_user_supplied_eval ("lsode"); } return retval; } DEFMETHOD (lsode, interp, args, nargout, doc: /* -*- texinfo -*- @deftypefn {} {[@var{x}, @var{istate}, @var{msg}] =} lsode (@var{fcn}, @var{x_0}, @var{t}) @deftypefnx {} {[@var{x}, @var{istate}, @var{msg}] =} lsode (@var{fcn}, @var{x_0}, @var{t}, @var{t_crit}) Ordinary Differential Equation (ODE) solver. The set of differential equations to solve is @tex $$ {dx \over dt} = f (x, t) $$ with $$ x(t_0) = x_0 $$ @end tex @ifnottex @example @group dx -- = f (x, t) dt @end group @end example @noindent with @example x(t_0) = x_0 @end example @end ifnottex The solution is returned in the matrix @var{x}, with each row corresponding to an element of the vector @var{t}. The first element of @var{t} should be @math{t_0} and should correspond to the initial state of the system @var{x_0}, so that the first row of the output is @var{x_0}. The first argument, @var{fcn}, is a string, inline, or function handle that names the function @math{f} to call to compute the vector of right hand sides for the set of equations. The function must have the form @example @var{xdot} = f (@var{x}, @var{t}) @end example @noindent in which @var{xdot} and @var{x} are vectors and @var{t} is a scalar. If @var{fcn} is a two-element string array or a two-element cell array of strings, inline functions, or function handles, the first element names the function @math{f} described above, and the second element names a function to compute the Jacobian of @math{f}. The Jacobian function must have the form @example @var{jac} = j (@var{x}, @var{t}) @end example @noindent in which @var{jac} is the matrix of partial derivatives @tex $$ J = {\partial f_i \over \partial x_j} = \left[\matrix{ {\partial f_1 \over \partial x_1} & {\partial f_1 \over \partial x_2} & \cdots & {\partial f_1 \over \partial x_N} \cr {\partial f_2 \over \partial x_1} & {\partial f_2 \over \partial x_2} & \cdots & {\partial f_2 \over \partial x_N} \cr \vdots & \vdots & \ddots & \vdots \cr {\partial f_3 \over \partial x_1} & {\partial f_3 \over \partial x_2} & \cdots & {\partial f_3 \over \partial x_N} \cr}\right]$$ @end tex @ifnottex @example @group | df_1 df_1 df_1 | | ---- ---- ... ---- | | dx_1 dx_2 dx_N | | | | df_2 df_2 df_2 | | ---- ---- ... ---- | df_i | dx_1 dx_2 dx_N | jac = ---- = | | dx_j | . . . . | | . . . . | | . . . . | | | | df_N df_N df_N | | ---- ---- ... ---- | | dx_1 dx_2 dx_N | @end group @end example @end ifnottex The second argument specifies the initial state of the system @math{x_0}. The third argument is a vector, @var{t}, specifying the time values for which a solution is sought. The fourth argument is optional, and may be used to specify a set of times that the ODE solver should not integrate past. It is useful for avoiding difficulties with singularities and points where there is a discontinuity in the derivative. After a successful computation, the value of @var{istate} will be 2 (consistent with the Fortran version of @sc{lsode}). If the computation is not successful, @var{istate} will be something other than 2 and @var{msg} will contain additional information. You can use the function @code{lsode_options} to set optional parameters for @code{lsode}. @seealso{daspk, dassl, dasrt} @end deftypefn */) { int nargin = args.length (); if (nargin < 3 || nargin > 4) print_usage (); warned_fcn_imaginary = false; warned_jac_imaginary = false; octave::unwind_protect frame; frame.protect_var (call_depth); call_depth++; if (call_depth > 1) error ("lsode: invalid recursive call"); octave::symbol_table& symtab = interp.get_symbol_table (); std::string fcn_name, fname, jac_name, jname; lsode_fcn = nullptr; lsode_jac = nullptr; octave_value f_arg = args(0); if (f_arg.iscell ()) { Cell c = f_arg.cell_value (); if (c.numel () == 1) f_arg = c(0); else if (c.numel () == 2) { if (c(0).is_function_handle () || c(0).is_inline_function ()) lsode_fcn = c(0).function_value (); else { fcn_name = unique_symbol_name ("__lsode_fcn__"); fname = "function y = "; fname.append (fcn_name); fname.append (" (x, t) y = "); lsode_fcn = extract_function (c(0), "lsode", fcn_name, fname, "; endfunction"); } if (lsode_fcn) { if (c(1).is_function_handle () || c(1).is_inline_function ()) lsode_jac = c(1).function_value (); else { jac_name = unique_symbol_name ("__lsode_jac__"); jname = "function jac = "; jname.append (jac_name); jname.append (" (x, t) jac = "); lsode_jac = extract_function (c(1), "lsode", jac_name, jname, "; endfunction"); if (! lsode_jac) { if (fcn_name.length ()) symtab.clear_function (fcn_name); lsode_fcn = nullptr; } } } } else error ("lsode: incorrect number of elements in cell array"); } if (! lsode_fcn && ! f_arg.iscell ()) { if (f_arg.is_function_handle () || f_arg.is_inline_function ()) lsode_fcn = f_arg.function_value (); else { switch (f_arg.rows ()) { case 1: do { fcn_name = unique_symbol_name ("__lsode_fcn__"); fname = "function y = "; fname.append (fcn_name); fname.append (" (x, t) y = "); lsode_fcn = extract_function (f_arg, "lsode", fcn_name, fname, "; endfunction"); } while (0); break; case 2: { string_vector tmp = f_arg.string_vector_value (); fcn_name = unique_symbol_name ("__lsode_fcn__"); fname = "function y = "; fname.append (fcn_name); fname.append (" (x, t) y = "); lsode_fcn = extract_function (tmp(0), "lsode", fcn_name, fname, "; endfunction"); if (lsode_fcn) { jac_name = unique_symbol_name ("__lsode_jac__"); jname = "function jac = "; jname.append (jac_name); jname.append (" (x, t) jac = "); lsode_jac = extract_function (tmp(1), "lsode", jac_name, jname, "; endfunction"); if (! lsode_jac) { if (fcn_name.length ()) symtab.clear_function (fcn_name); lsode_fcn = nullptr; } } } break; default: error ("lsode: first arg should be a string or 2-element string array"); } } } if (! lsode_fcn) error ("lsode: FCN argument is not a valid function name or handle"); ColumnVector state = args(1).xvector_value ("lsode: initial state X_0 must be a vector"); ColumnVector out_times = args(2).xvector_value ("lsode: output time variable T must be a vector"); ColumnVector crit_times; int crit_times_set = 0; if (nargin > 3) { crit_times = args(3).xvector_value ("lsode: list of critical times T_CRIT must be a vector"); crit_times_set = 1; } double tzero = out_times (0); ODEFunc func (lsode_user_function); if (lsode_jac) func.set_jacobian_function (lsode_user_jacobian); LSODE ode (state, tzero, func); ode.set_options (lsode_opts); Matrix output; if (crit_times_set) output = ode.integrate (out_times, crit_times); else output = ode.integrate (out_times); if (fcn_name.length ()) symtab.clear_function (fcn_name); if (jac_name.length ()) symtab.clear_function (jac_name); std::string msg = ode.error_message (); octave_value_list retval (3); if (ode.integration_ok ()) retval(0) = output; else if (nargout < 2) error ("lsode: %s", msg.c_str ()); else retval(0) = Matrix (); retval(1) = static_cast<double> (ode.integration_state ()); retval(2) = msg; return retval; } /* ## dassl-1.m ## ## Test lsode() function ## ## Author: David Billinghurst (David.Billinghurst@riotinto.com.au) ## Comalco Research and Technology ## 20 May 1998 ## ## Problem ## ## y1' = -y2, y1(0) = 1 ## y2' = y1, y2(0) = 0 ## ## Solution ## ## y1(t) = cos(t) ## y2(t) = sin(t) ## %!function xdot = __f (x, t) %! xdot = [-x(2); x(1)]; %!endfunction %!test %! %! x0 = [1; 0]; %! xdot0 = [0; 1]; %! t = (0:1:10)'; %! %! tol = 500 * lsode_options ("relative tolerance"); %! %! x = lsode ("__f", x0, t); %! %! y = [cos(t), sin(t)]; %! %! assert (x, y, tol); %!function xdotdot = __f (x, t) %! xdotdot = [x(2); -x(1)]; %!endfunction %!test %! %! x0 = [1; 0]; %! t = [0; 2*pi]; %! tol = 100 * dassl_options ("relative tolerance"); %! %! x = lsode ("__f", x0, t); %! %! y = [1, 0; 1, 0]; %! %! assert (x, y, tol); %!function xdot = __f (x, t) %! xdot = x; %!endfunction %!test %! %! x0 = 1; %! t = [0; 1]; %! tol = 100 * dassl_options ("relative tolerance"); %! %! x = lsode ("__f", x0, t); %! %! y = [1; e]; %! %! assert (x, y, tol); %!test %! lsode_options ("absolute tolerance", eps); %! assert (lsode_options ("absolute tolerance") == eps); %!error lsode_options ("foo", 1, 2) */