gusucode.com > symbolic工具箱matlab源码程序 > symbolic/dsolve.m

    function varargout = dsolve(varargin)
%DSOLVE Symbolic solution of ordinary differential equations.
%   DSOLVE(eqn1,eqn2, ...) accepts symbolic equations representing
%   ordinary differential equations and initial conditions. The
%   equations may be strings or symbolic expressions. 
%
%   By default, the independent variable is 't'. The independent variable
%   may be changed from 't' to some other symbolic variable by including
%   that variable as the last input argument.
%
%   Equations specified as symbolic expressions use '==' for equality. The
%   DIFF function constructs derivatives of symbolic functions (see sym/symfun).
%   Initial conditions involving derivatives must use an intermediate
%   variable. For example,
%     syms x(t)
%     Dx = diff(x);
%     dsolve(diff(Dx) == -x, Dx(0) == 1)
%
%   Equations specified as strings may use '==' or '=' for equality.
%   The letter 'D' denotes differentiation with respect to the independent
%   variable, i.e. usually d/dt.  A "D" followed by a digit denotes
%   repeated differentiation; e.g., D2 is d^2/dt^2.  Any characters
%   immediately following these differentiation operators are taken to be
%   the dependent variables; e.g., D3y denotes the third derivative
%   of y(t). Note that the names of symbolic variables should not contain
%   the letter "D".
%   If expressed as strings several equations or initial conditions may 
%   be grouped together, separated by commas, in a single input argument.
%
%   Initial conditions are specified by equations like 'y(a)=b' or
%   'Dy(a) = b' where y is one of the dependent variables and a and b are
%   constants.  If the number of initial conditions given is less than the
%   number of dependent variables, the resulting solutions will obtain
%   arbitrary constants, C1, C2, etc.
%   
%   Three different types of output are possible.  For one equation and one
%   output, the resulting solution is returned, with multiple solutions to
%   a nonlinear equation in a symbolic vector.  For several equations and
%   an equal number of outputs, the results are sorted in lexicographic
%   order and assigned to the outputs.  For several equations and a single
%   output, a structure containing the solutions is returned.
%
%   If no closed-form (explicit) solution is found, an implicit solution is
%   attempted.  When an implicit solution is returned, a warning is given.
%   If neither an explicit nor implicit solution can be computed, then a
%   warning is given and the empty sym is returned.  In some cases involving
%   nonlinear equations, the output will be an equivalent lower order
%   differential equation or an integral.
%
%   DSOLVE(...,'IgnoreAnalyticConstraints',VAL) controls the level of 
%   mathematical rigor to use on the analytical constraints of the solution 
%   (branch cuts, division by zero, etc). The options for VAL are TRUE or 
%   FALSE. Specify FALSE to use the highest level of mathematical rigor
%   in finding any solutions. The default is TRUE.
%
%   DSOLVE(...,'MaxDegree',n) controls the maximum degree of polynomials
%   for which explicit formulas will be used in SOLVE calls during the
%   computation. n must be a positive integer smaller than 5. 
%   The default is 2.
%
%   Examples:
%
%      % Example 1
%      syms x(t) a
%      dsolve(diff(x) == -a*x) returns
%
%        ans = C1/exp(a*t)
%
%      % Example 2: changing the independent variable 
%      x = dsolve(diff(x) == -a*x, x(0) == 1, 's') returns
%
%        x = 1/exp(a*s)
%
%      syms x(s) a
%      x = dsolve(diff(x) == -a*x, x(0) == 1) returns
%
%        x = 1/exp(a*s)
%
%      % Example 3: solving systems of ODEs
%      syms f(t) g(t)
%      S = dsolve(diff(f) == f + g, diff(g) == -f + g,f(0) == 1,g(0) == 2)
%      returns a structure S with fields
%
%        S.f = (i + 1/2)/exp(t*(i - 1)) - exp(t*(i + 1))*(i - 1/2)
%        S.g = exp(t*(i + 1))*(i/2 + 1) - (i/2 - 1)/exp(t*(i - 1))
%
%      syms f(t) g(t)
%      v = [f;g];
%      A = [1 1; -1 1];
%      S = dsolve(diff(v) == A*v, v(0) == [1;2])
%      returns a structure S with fields
%
%        S.f = exp(t)*cos(t) + 2*exp(t)*sin(t)
%        S.g = 2*exp(t)*cos(t) - exp(t)*sin(t)
%
%      % Example 3: using options
%      syms y(t)
%      dsolve(sqrt(diff(y))==y) returns
%      
%        ans = 0
%      
%      syms y(t)
%      dsolve(sqrt(diff(y))==y, 'IgnoreAnalyticConstraints', false) warns
%        Warning: The solutions are subject to the following conditions:
%        (C67 + t)*(1/(C67 + t)^2)^(1/2) = -1 
%      
%      and returns
%       
%        ans = -1/(C67 + t)
%
%      % Example 4: Higher order systems
%      syms y(t) a
%      Dy = diff(y);
%      D2y = diff(y,2);
%      dsolve(D2y == -a^2*y, y(0) == 1, Dy(pi/a) == 0)
%      syms w(t)
%      Dw = diff(w); 
%      D2w = diff(w,2);
%      w = dsolve(diff(D2w) == -w, w(0)==1, Dw(0)==0, D2w(0)==0)
%
%   See also SOLVE, SUBS, SYM/DIFF, odeToVectorfield.

%   Copyright 1993-2014 The MathWorks, Inc.

eng = symengine;

% parse arguments, step 1: Look for options
args = varargin;
% default:
if nargin > 0 && ischar(args{1}) 
    options = '"stringInput", IgnoreAnalyticConstraints = TRUE, IgnoreSpecialCases = TRUE';
else 
    options = 'IgnoreAnalyticConstraints = TRUE, IgnoreSpecialCases = TRUE';
end
k = 1;
while k <= length(args)
  v = args{k};
  if strcmpi(v, 'IgnoreAnalyticConstraints')
    if k == size(args, 2);
      error(message('symbolic:sym:optRequiresArg', v))
    end
    value = sym.checkIgnoreAnalyticConstraintsValue(args{k+1});
    if value == true
      value = 'TRUE';
    else 
      value = 'FALSE';
    end
    options = [options ', IgnoreAnalyticConstraints =' value]; %#ok<AGROW>
    args(k:k+1) = [];
  elseif strcmpi(v, 'IgnoreProperties')
    if k == size(args, 2);
      error(message('symbolic:sym:optRequiresArg', v))
    end
    value = args{k+1};
    if value == true
      value = 'TRUE';
    elseif value == false
      value = 'FALSE';
    else
      error(message('symbolic:sym:badArgForOpt', v))
    end
    options = [options ', IgnoreProperties =' value]; %#ok<AGROW>
    args(k:k+1) = [];
  elseif strcmpi(v, 'MaxDegree')
    if k == size(args, 2)
      error(message('symbolic:sym:optRequiresArg', v))
    end
    value = args{k+1};
    if isnumeric(value) && 0 < value && 5 > value && round(value) == value
      options = [options ', MaxDegree =' int2str(value)]; %#ok<AGROW>
    else
      error(message('symbolic:sym:badArgForOpt', v))
    end
    args(k:k+1) = [];
  elseif strcmpi(v, 'Type')
    if k == size(args, 2)
      error(message('symbolic:sym:optRequiresArg', v))
    end
    value = char(args{k+1});
    options = [options ', Type =' value]; %#ok<AGROW>
    args(k:k+1) = [];
  else
    k = k+1;
  end
end

if isempty(args) || (ischar(args{end}) && isempty(strtrim(args{end})))
   warning(message('symbolic:dsolve:warnmsg3'))
   varargout{1} = sym([]);
   return
end

sol = mupadDsolve(args, options);

% If no solution, give up
failsol = char(eng.feval('_index',sol,'"FailedSolution"'));
nosol = char(eng.feval('_index',sol,'"NoSolution"'));
implicitsol = char(eng.feval('_index',sol,'"ImplicitSolution"'));

if strcmp(nosol,'TRUE') || strcmp(failsol,'TRUE')
   warning(message('symbolic:dsolve:warnmsg2'));
   varargout = cell(1,nargout);
   varargout{1} = sym([]);
   return
end

if strcmp(implicitsol,'TRUE') 
   warning(message('symbolic:dsolve:implicitSolution'));
end

dropped = eng.feval('_index',sol,'"Dropped"');
if ~isempty(dropped)
    dropped = char(eng.feval('output::tableForm',dropped,'String'));
    dropped(dropped=='"') = [];
    dropped = sprintf(['\n' dropped]);
    warning(message('symbolic:solve:ParametrizedFamily',dropped));
end
conds = eng.feval('_index',sol,'"Conditions"');
if ~isempty(conds)
    conds = char(eng.feval('output::tableForm',conds,'String'));
    conds(conds=='"') = [];
    conds = sprintf(['\n' conds]);
    warning(message('symbolic:dsolve:DiscardedConditions',conds));
end

varargout = assignOutputs(nargout,sol);

function out = assignOutputs(nout,sol)
out = cell(1,nout);
eng = symengine;
symvars = eng.feval('_index',sol,'"VariableNames"');
emptysol = char(eng.feval('_index',sol,'"EmptySolution"'));
solTable = eng.feval('_index',sol,'"Sols"');
set = eng.feval('_index',sol,'"SetSolution"');
if (isscalar(symvars) && nout <= 1) || strcmp(emptysol,'TRUE')

   % One variable and at most one output.
   % Return a single scalar or vector sym.
   val1 = eng.feval('symobj::index',solTable,char(symvars));
   val = eng.feval('symobj::extractscalar',val1);
   if isempty(val)
       val = set;
   end
   out{1} = val;

else
   nvars = length(symvars);

   % Form the output structure
   for j = 1:nvars
       name = char(symvars(j));
       fname = name(1:find(name=='(',1)-1);
       val = eng.feval('symobj::index',solTable,name);
       S.(fname) = eng.feval('symobj::extractscalar',val);
   end
   
   if nout <= 1

      % At most one output, return the structure.
      out{1} = S;

   elseif nout == nvars

      % Same number of outputs as variables.
      % Match results in lexicographic order to outputs.
      v = sort(fieldnames(S));
      for j = 1:nvars
         out{j} = S.(v{j});
      end

   else
      error(message('symbolic:dsolve:errmsg5', nvars, nout))
   end
end

    
function T = mupadDsolve(args,options)

narg = length(args);

% The default independent variable is t.
default_varname = true;
x = sym('t');

% Pick up the independent variable, if specified.
if isvarname(char(args{end}))
   default_varname = false;
   x = sym(args{end});
   args(end) = [];
   narg = narg-1;
end
% Concatenate equation(s) and initial condition(s) inputs into SYS.
sys = args(1:narg);
sys_class = cellfun(@class,sys,'UniformOutput',false);
chars = strcmp(sys_class,'char');
sys_char = sys(chars);

% look for problematic symbols names in strings
if ~isempty(sys_char)
    search = regexp(sys_char, ...
        '\<D\d*(psi|euler|beta|gamma|theta|I|PI|E)\>', 'tokens');
    search = [search{:}];
    search = [search{:}];
    if ~isempty(search)
        search = unique(search);
        % Mapping sym on the variables initializes the 
        % corresponding output aliasses on the MuPAD side.
        cellfun(@sym,search,'UniformOutput',false);
        search = strcat(search,'|');
        search = [search{:}];
        search(end) = '';
        sys_char = regexprep(sys_char, ...
            ['\<(D\d*)?(' search ')\>'], '$1$2_Var');
    end
end

% look for symfuns and pick out independent variable
sys_sym = [sys{~chars}];
syminputs = [];
if ~isempty(sys_sym) && isa(sys_sym,'symfun')
    syminputs = argnames(sys_sym);
end
if ~isempty(syminputs)
    if ~isscalar(syminputs)
        error(message('symbolic:dsolve:OneVar'));
    end
    if default_varname
        x = syminputs;
    else
        sys_sym = sys_sym(x);
    end
end
sys_char(2,:) = {','};
sys_str = ['[' sys_char{1:end-1} ']'];
sys = [sys_sym evalin(symengine, sys_str)];
T = feval(symengine,'symobj::dsolve',sys,x,options);