123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133 |
- function [M0,M1,M2,L1,L2] = spm_soreduce(M,P)
- % reduction of a fully nonlinear MIMO system to second-order form
- % FORMAT [M0,M1,M2,L1,L2] = spm_soreduce(M,P);
- %
- % M - model specification structure
- % Required fields:
- % M.f - dx/dt = f(x,u,P,M) {function string or m-file}
- % M.g - y(t) = g(x,u,P,M) {function string or m-file}
- % M.x - (n x 1) = x(0) = expansion point: defaults to x = 0;
- % M.u - (m x 1) = u = expansion point: defaults to u = 0;
- %
- % P - model parameters
- %
- % A second order approximation is returned where the states are
- %
- % q(t) = [1; x(t) - x(0)]
- %
- %___________________________________________________________________________
- % Returns Matrix operators for the Bilinear approximation to the MIMO
- % system described by
- %
- % dx/dt = f(x,u,P)
- % y(t) = g(x,u,P)
- %
- % evaluated at x(0) = x and u = 0
- %
- % dq/dt = M0*q +
- % u(1)*M1{1}*q + u(2)*M1{2}*q + ....
- % x(1)*M2{1}*q + x(2)*M2{2}*q + ....
- % y(i) = L(i,:)*q + ...
- %
- %--------------------------------------------------------------------------
- % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
- % Karl Friston
- % $Id: spm_soreduce.m 5219 2013-01-29 17:07:07Z spm $
- % set up
- %==========================================================================
- % create inline functions
- %--------------------------------------------------------------------------
- try
- funx = fcnchk(M.f,'x','u','P','M');
- catch
- M.f = inline('sparse(0,1)','x','u','P','M');
- M.n = 0;
- M.x = sparse(0,0);
- funx = fcnchk(M.f,'x','u','P','M');
- end
- % add observer if not specified
- %--------------------------------------------------------------------------
- try
- fung = fcnchk(M.g,'x','u','P','M');
- catch
- M.g = inline('spm_vec(x)','x','u','P','M');
- M.l = M.n;
- fung = fcnchk(M.g,'x','u','P','M');
- end
- % expansion pointt
- %--------------------------------------------------------------------------
- x = M.x;
- try
- u = spm_vec(M.u);
- catch
- u = sparse(M.m,1);
- end
- % Partial derivatives for 1st order Bilinear operators
- %==========================================================================
- % f(x(0),0) and derivatives
- %--------------------------------------------------------------------------
- [dfdxx,dfdx,f0] = spm_diff(funx,x,u,P,M,[1 1]);
- [dfdxu,dfdx,f0] = spm_diff(funx,x,u,P,M,[1 2]);
- dfdu = spm_diff(funx,x,u,P,M,2);
- m = length(dfdxu); % m inputs
- n = length(f0); % n states
- % Bilinear operators
- %==========================================================================
- % Bilinear operator - M0
- %--------------------------------------------------------------------------
- M0 = spm_cat({0 [] ;
- (f0 - dfdx*spm_vec(x)) dfdx});
- % Bilinear operator - M1 = dM0/du
- %--------------------------------------------------------------------------
- for i = 1:m
- M1{i} = spm_cat({0, [] ;
- (dfdu(:,i) - dfdxu{i}*spm_vec(x)), dfdxu{i}});
- end
- % Bilinear operator - M2 = dM0/dx
- %--------------------------------------------------------------------------
- for i = 1:n
- M2{i} = spm_cat({0, [] ;
- (dfdx(:,i) - dfdxx{i}*spm_vec(x)), dfdxx{i}});
- end
- if nargout < 4, return, end
- % Output matrices - L1
- %==========================================================================
- % l(x(0),0)
- %--------------------------------------------------------------------------
- [dgdx,g0] = spm_diff(fung,x,u,P,M,1);
- L1 = spm_cat({(g0 - dgdx*spm_vec(x)), dgdx});
- l = length(g0);
- if nargout < 5, return, end
- % Output matrices - L2
- %--------------------------------------------------------------------------
- dgdxx = spm_diff(fung,x,u,P,M,[1 1]);
- for i = 1:l
- for j = 1:n
- D{i}(j,:) = dgdxx{j}(i,:);
- end
- end
- for i = 1:l
- L2{i} = spm_cat(spm_diag({0, D{i}}));
- end
-
|