gusucode.com > symbolic工具箱matlab源码程序 > symbolic/@sym/decic.m
function [y0, yp0] = decic(eqs,vars,constraints,t0,y0,fixedVars,yp0,options) %DECIC Compute consistent initial conditions for a system of first-order % implicit ordinary differential equations with algebraic constraints. % % [y0,yp0] = decic(eqs,vars,constr,t0,y0_est,fixedVars,yp0_est,options) % % The call [eqs,constr] = reduceDAEToODE(DA_eqs,vars) reduces the system % of differential algebraic equations DA_eqs to the system of implicit % ordinary differential equations eqs. It also returns constraint equations % constr encountered during the system reduction. For the variables and % first derivatives of this ODE system, DECIC finds consistent initial % conditions y0, yp0 at the time t0. % % Substituting the numerical values y0, yp0 into the differential equations % % subs(eqs, [t;vars;diff(vars)], [t0; y0; yp0]) % % and the constraint equations % % subs(constr, [t;vars;diff(vars)], [t0; y0; yp0]) % % produces zero vectors. (Here, vars must be a column vector.) % % The input eqs must consist of first-order differential equations that % can be solved for the derivatives of all variables specified in vars. % For semi-linear systems, this requires det(M)~=0, where % [M,~] = MASSMATRIXFORM(eqs, vars) is the mass matrix of the system. % % The input parameter t0 must be a numerical scalar. % % The input vector y0_est provides numerical estimates for the values % of the variables at the time t0. % % The input vector fixedVars has entries 0 or 1. It indicates which % elements of y0_est are fixed values not modified during the numerical % search. Fixed values of y0_est correspond to values 1 in fixedVars. % The 0 entries in fixedVars correspond to those variables in y0_est % for which decic solves the constraint equations. % % The number of zero entries must coincide with the number of % constraints. The Jacobian matrix of the constraints with respect % to the variables vars(fixedVars == 0) must be invertible. % % The optional input vector yp0_est provides numerical estimates % for the values of the first-order derivatives of the variables. % % The parameter options is an ODESET object that allows to set % tolerances for the numerical search. % % The lengths of the input parameters eqs,vars,y0,fixedVars, and % yp0 must be the same. % % Example: % Create the following algebraic differential system % % >> syms x(t) y(t); % eqs0 = [diff(x(t),t) == cos(t) + y(t), ... % x(t)^2 + y(t)^2 == 1]; % vars = [x(t), y(t)]; % % Use REDUCEDAETOODE to convert this system to a system of % implicit ODEs. % % >> [eqs, constr, ~] = reduceDAEToODE(eqs0, vars) % % eqs = % diff(x(t), t) - y(t) - cos(t) % - 2*x(t)*diff(x(t), t) - 2*y(t)*diff(y(t), t) % % constr = % 1 - y(t)^2 - x(t)^2 % % Create an option structure that specifies numerical tolerances % for the numerical search: % % >> options = odeset('RelTol', 10.0^(-7), 'AbsTol', 10.0^(-7)); % % Fix values t0 = 0 for the time and numerical estimates for % consistent values of the variables and their derivatives: % % >> t0 = 0; % y0_est = [0.1, 0.9]; % yp0_est = [0.0, 0.0]; % % You can treat the constraint as an algebraic equation for the % variable x with the fixed parameter y. For this, set % fixedVars = [1 0]. Alternatively, you can treat it as an % algebraic equation for the variable y with the fixed parameter x. % For this, set fixedVars = [0 1]: % % First, set the initial value x(t0) = y0_est(1) = 0.1: % % >> fixedVars = [1 0]; % [y0,yp0] = decic(eqs,vars,constr,t0,y0_est,fixedVars,yp0_est,options) % % y0 = % 0.1000 % 0.9950 % % yp0 = % 1.9950 % -0.2005 % % Now, change the initial value y(t0) = y0_est(2) = 0.9 to get % different consistent initial values: % % >> fixedVars = [0 1]; % [y0,yp0] = decic(eqs,vars,constr,t0,y0_est,fixedVars,yp0_est,options) % % y0 = % -0.4359 % 0.9000 % % yp0 = % 1.9000 % 0.9202 % % See also: REDUCEDAETOODE, ODESET, ODE15I, ODE15S. % Copyright 2014 The MathWorks, Inc. narginchk(6, 8); yp0pos = 7; if nargin == 6 yp0 = []; options = struct([]); elseif nargin == 7 if isa(yp0, 'struct') options = yp0; yp0pos = 8; yp0 = []; else options = struct([]); end elseif nargin == 8 && isa(yp0, 'struct') tmp = yp0; yp0 = options; options = tmp; yp0pos = 8; end [eqs, vars] = checkDAEInput(eqs, vars); args = privResolveArgs(eqs,vars,constraints,t0,y0,fixedVars,yp0); if isa(args{1}, 'symfun') % all args{i} are symfuns args = cellfun(@formula, args, 'UniformOutput', false); end args = cellfun(@(x) reshape(x, numel(x), 1), args, 'UniformOutput', false); args = cellfun(@checkForNaNsAndInfs, args, 'UniformOutput', false); % extract the symbolic name of the time variable t = symvar(args{2}); if numel(t) ~= 1 error(message('symbolic:sym:decic:AllowOnlyFuncVars')); end m = numel(args{1}); n = numel(args{2}); r = numel(args{3}); if m ~= n error(message('symbolic:sym:decic:ExpectingAsManyEquationsAsVariables')); end t0 = double(args{4}); y0 = double(args{5}); if isempty(args{7}) yp0 = zeros(n, 1); else yp0 = double(args{7}); end fixedVars = args{6}; if isempty(fixedVars) autoMode = true; charIndices = feval(symengine, 'daetools::isSolvable', ... args{3}, args{2}, args{4}, '"ReturnCharIndices"'); fixedVars = ones(n,1); fixedVars(charIndices) = 0; else autoMode = false; fixedVars = double(fixedVars); end if ~isscalar(t0) error(message('symbolic:sym:decic:ExpectingScalar4')); end if numel(y0) ~= n error(message('symbolic:sym:decic:InconsistentArguments25')); end if numel(fixedVars) ~= n error(message('symbolic:sym:decic:InconsistentArguments26')); end if numel(yp0) ~= n if yp0pos == 7 error(message('symbolic:sym:decic:InconsistentArguments27')); else error(message('symbolic:sym:decic:InconsistentArguments28')); end end boundSymVars = privsubsref(args{2}, fixedVars == 0); boundSymVals = privsubsref(args{5}, fixedVars == 0); fixedSymVars = privsubsref(args{2}, fixedVars ~= 0); fixedSymVals = privsubsref(args{5}, fixedVars ~= 0); if numel(fixedSymVars) ~= n-r error(message('symbolic:sym:decic:InconsistentFixedVars')); end % insert the values for the 'fixed' variables. Then solve % the constraints for the remaining ('bound') variables: if ~isempty(args{3}) constraints = subs(args{3}, fixedSymVars, fixedSymVals); if ~autoMode % Check that the constraints can be solved for the boundSymVars. % MuPAD raises an error if jacobian(subs(constraints,t,t0),boundSymVars) % is not of full rank: feval(symengine, 'daetools::isSolvable', constraints, boundSymVars, t0); end try C = daeFunction(constraints, boundSymVars); [fixedVals0,~] = decic(C,double(t0),double(boundSymVals),[],zeros(r,1),ones(r,1),options); y0(fixedVars == 0) = fixedVals0; catch ME if strcmp(ME.identifier,'MATLAB:decic:TooManyFixed') error(message('symbolic:sym:decic:CannotResolveConstraints')); else rethrow(ME); end end end % A consistent initial condition y0 satisfying constraints(t0,y0) % is found. Now, solve F(t0, y0, yp0) for yp0: try F = daeFunction(args{1}, args{2}); % F defines the DAE [y0,yp0] = decic(F,t0,y0,ones(n,1),yp0,[],options); catch ME if strcmp(ME.identifier,'MATLAB:decic:TooManyFixed') error(message('symbolic:sym:decic:CannotFindConsistentInitConditions')); else rethrow(ME); end end end % ---------- utility -------------- function y = checkForNaNsAndInfs(x) if any(~isfinite(x)) error(message('symbolic:sym:InputMustNotContainNaNOrInf')); else y = x; end end