⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 numjac.m

📁 国外经典书籍MULTIVARIABLE FEEDBACK CONTROL-多变量反馈控制 的源码
💻 M
字号:
function [dFdy,fac,g,nfevals] = numjac(F,t,y,Fty,thresh,fac,vectorized,S,g)%NUMJAC NUMerically compute the JACobian dF/dY of function F(T,Y).%	[DFDY,FAC] = NUMJAC('F',T,Y,FTY,THRESH,FAC,VECTORIZED) numerically%	computes the Jacobian of function F(T,Y), returning it as full%	matrix DFDY.  The string 'F' contains the name of function F.  T is%	the independent variable and column vector Y contains the dependent%	variables.  Function F must return a column vector.  Vector FTY is F%	evaluated at (T,Y).  Column vector THRESH provides a threshold of%	significance for Y, i.e. the exact value of a component Y(i) with%	abs(Y(i)) < THRESH(i) is not important.  All components of THRESH%	must be positive.  Column FAC is working storage.  On the first%	call, set FAC to [].  Do not alter the returned value between calls.%	Set the Boolean variable VECTORIZED to true if F(t,y) has been coded%	so that F(t,[y1 y2 ...]) returns [F(t,y1) F(t,y2) ...].%	(Vectorizing function F may speed up the computation of DFDY.)%	%	[DFDY,FAC,G] = NUMJAC('F',T,Y,FTY,THRESH,FAC,VECTORIZED,S,G)%	numerically computes a sparse Jacobian matrix DFDY.  S is a%	non-empty sparse matrix of 0's and 1's.  A value of 0 for S(i,j)%	means that component i of the function F(t,y) does not depend on%	component j of vector y (hence DFDY(i,j) = 0).  Column vector G is%	working storage.  On the first call, set G to [].  Do not alter the%	returned value between calls.%	%	Although NUMJAC was developed specifically for the approximation of%	partial derivatives when integrating a system of ODE's, it can be%	used for other applications.  In particular, when the length of the%	vector returned by F(T,Y) is different from the length of Y, DFDY is%	rectangular.%	%	See also COLGROUP, ODE15S, ODE23S, ODESET.%	NUMJAC is an implementation of an exceptionally robust scheme due to%	Salane for the approximation of partial derivatives when integrating%	a system of ODEs, Y' = F(T,Y).  It is called when the ODE code has%	an approximation Y at time T and is about to step to T+H.  The ODE%	code controls the error in Y to be less than the absolute error%	tolerance ATOL = THRESH.  Experience computing partial derivatives%	at previous steps is recorded in FAC.  A sparse Jacobian is computed%	efficiently by using COLGROUP(S) to find groups of columns of DFDY%	that can be approximated with a single call to function F.  COLGROUP%	tries two schemes (first-fit and first-fit after reverse COLMMD%	ordering) and returns the better grouping.%	%	D.E. Salane, "Adaptive Routines for Forming Jacobians Numerically",%	SAND86-1319, Sandia National Laboratories, 1986.%	%	T.F. Coleman, B.S. Garbow, and J.J. More, Software for estimating%	sparse Jacobian matrices, ACM Trans. Math. Software, 11(1984)%	329-345.%	%	The MATLAB ODE Suite, L.F. Shampine and M. W. Reichelt, Rept. 94-6,%	Math. Dept., SMU, Dallas, TX, 1994.%	Mark W. Reichelt and Lawrence F. Shampine, 3-28-94%	Copyright (c) 1984-95 by The MathWorks, Inc.% Initialize.br = eps ^ (0.875);bl = eps ^ (0.75);bu = eps ^ (0.25);facmin = eps ^ (0.78);facmax = 0.1;ny = length(y);nF = length(Fty);if length(fac) == 0  fac = sqrt(eps) + zeros(ny,1);end% Select an increment del for a difference approximation to% column j of dFdy.  The vector fac accounts for experience% gained in previous calls to numjac.yscale = max(abs(y),thresh);del = (y + fac .* yscale) - y;for j = find(del == 0)  while 1    if fac(j) < facmax      fac(j) = min(100*fac(j),facmax);      del(j) = (y(j) + fac(j)*yscale(j)) - y(j);      if del(j)	break      end    else      del(j) = thresh(j);      break;    end  endendif nF == ny  s = (sign(Fty) >= 0);  del = (s - (~s)) .* abs(del); 	% keep del pointing into regionend% Form a difference approximation to all columns of dFdy.if nargin < 8  S = [];endif length(S) == 0 			% generate full matrix dFdy  g = [];  ones1ny = ones(1,ny);  ydel = y(:,ones1ny) + diag(del);  if vectorized    Fdel = feval(F,t,ydel);  else    for j = ny:-1:1      Fdel(:,j) = feval(F,t,ydel(:,j));    end  end  nfevals = ny; 			% stats (at least one per loop)  Fdiff = Fdel - Fty(:,ones1ny);  dFdy = Fdiff * diag(1 ./ del);  [Difmax,Rowmax] = max(abs(Fdiff));  absFdelRm = abs(Fdel((0:ny-1)*nF + Rowmax));else 					% sparse dFdy with structure S  if length(g) == 0    g = colgroup(S); 			% Determine the column grouping.  end  ng = max(g);  ones1ng = ones(1,ng);  one2ny = (1:ny)';  ydel = y(:,ones1ng);  i = (g-1)*ny + one2ny;  ydel(i) = ydel(i) + del;  if vectorized    Fdel = feval(F,t,ydel);  else    for j = ng:-1:1      Fdel(:,j) = feval(F,t,ydel(:,j));    end  end  nfevals = ng; 			% stats (at least one per column)  Fdiff = Fdel - Fty(:,ones1ng);  [i j] = find(S);  Fdiff = sparse(i,j,Fdiff((g(j)-1)*nF + i),ny,ny);  dFdy = Fdiff * sparse(one2ny,one2ny,1 ./ del,ny,ny);  [Difmax,Rowmax] = max(abs(Fdiff));  absFdelRm = abs(Fdel((g-1)'*nF + Rowmax));end  % Adjust fac for next call to numjac.absFty = abs(Fty);absFtyRm = absFty(Rowmax)';j = (absFdelRm ~= 0) & (absFtyRm ~= 0);if any(j)  ydel = y;  Fscale = max(absFdelRm,absFtyRm);  % If the difference in f values is so small that the column might be just  % roundoff error, try a bigger increment.   k1 = (Difmax < br*Fscale);  for k = find(j & k1)    tmpfac = min(sqrt(fac(k)),facmax);    del = (y(k) + tmpfac*yscale(k)) - y(k);    if (tmpfac ~= fac(k)) & (del ~= 0)      if nF == ny	if Fty(k) >= 0 			% keep del pointing into region	  del = abs(del);	else	  del = -abs(del);	end      end	      ydel(k) = y(k) + del;      fdel = feval(F,t,ydel);      nfevals = nfevals + 1; 		% stats      ydel(k) = y(k);      fdiff = fdel - Fty;      tmp = fdiff ./ del;	      [difmax,rowmax] = max(abs(fdiff));      if tmpfac * norm(tmp,inf) > norm(dFdy(:,k),inf);	% The new difference is more significant, so	% use the column computed with this increment.	if length(S) == 0	  dFdy(:,k) = tmp;	else	  i = find(S(:,k));	  dFdy(i,k) = tmp(i);	end  	% Adjust fac for the next call to numjac.	fscale = max(abs(fdel(rowmax)),absFty(rowmax));	  	if difmax <= bl*fscale	  % The difference is small, so increase the increment.	  fac(k) = min(10*tmpfac, facmax);	  	elseif difmax > bu*fscale	  % The difference is large, so reduce the increment.	  fac(k) = max(0.1*tmpfac, facmin);	else	  fac(k) = tmpfac;	    	end      end    end  end    % If the difference is small, increase the increment.  k = find(j & ~k1 & (Difmax <= bl*Fscale));  if length(k)    fac(k) = min(10*fac(k), facmax);  end  % If the difference is large, reduce the increment.  k = find(j & (Difmax > bu*Fscale));  if length(k)    fac(k) = max(0.1*fac(k), facmin);  endend

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -