spm_soreduce.m 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. function [M0,M1,M2,L1,L2] = spm_soreduce(M,P)
  2. % reduction of a fully nonlinear MIMO system to second-order form
  3. % FORMAT [M0,M1,M2,L1,L2] = spm_soreduce(M,P);
  4. %
  5. % M - model specification structure
  6. % Required fields:
  7. % M.f - dx/dt = f(x,u,P,M) {function string or m-file}
  8. % M.g - y(t) = g(x,u,P,M) {function string or m-file}
  9. % M.x - (n x 1) = x(0) = expansion point: defaults to x = 0;
  10. % M.u - (m x 1) = u = expansion point: defaults to u = 0;
  11. %
  12. % P - model parameters
  13. %
  14. % A second order approximation is returned where the states are
  15. %
  16. % q(t) = [1; x(t) - x(0)]
  17. %
  18. %___________________________________________________________________________
  19. % Returns Matrix operators for the Bilinear approximation to the MIMO
  20. % system described by
  21. %
  22. % dx/dt = f(x,u,P)
  23. % y(t) = g(x,u,P)
  24. %
  25. % evaluated at x(0) = x and u = 0
  26. %
  27. % dq/dt = M0*q +
  28. % u(1)*M1{1}*q + u(2)*M1{2}*q + ....
  29. % x(1)*M2{1}*q + x(2)*M2{2}*q + ....
  30. % y(i) = L(i,:)*q + ...
  31. %
  32. %--------------------------------------------------------------------------
  33. % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
  34. % Karl Friston
  35. % $Id: spm_soreduce.m 5219 2013-01-29 17:07:07Z spm $
  36. % set up
  37. %==========================================================================
  38. % create inline functions
  39. %--------------------------------------------------------------------------
  40. try
  41. funx = fcnchk(M.f,'x','u','P','M');
  42. catch
  43. M.f = inline('sparse(0,1)','x','u','P','M');
  44. M.n = 0;
  45. M.x = sparse(0,0);
  46. funx = fcnchk(M.f,'x','u','P','M');
  47. end
  48. % add observer if not specified
  49. %--------------------------------------------------------------------------
  50. try
  51. fung = fcnchk(M.g,'x','u','P','M');
  52. catch
  53. M.g = inline('spm_vec(x)','x','u','P','M');
  54. M.l = M.n;
  55. fung = fcnchk(M.g,'x','u','P','M');
  56. end
  57. % expansion pointt
  58. %--------------------------------------------------------------------------
  59. x = M.x;
  60. try
  61. u = spm_vec(M.u);
  62. catch
  63. u = sparse(M.m,1);
  64. end
  65. % Partial derivatives for 1st order Bilinear operators
  66. %==========================================================================
  67. % f(x(0),0) and derivatives
  68. %--------------------------------------------------------------------------
  69. [dfdxx,dfdx,f0] = spm_diff(funx,x,u,P,M,[1 1]);
  70. [dfdxu,dfdx,f0] = spm_diff(funx,x,u,P,M,[1 2]);
  71. dfdu = spm_diff(funx,x,u,P,M,2);
  72. m = length(dfdxu); % m inputs
  73. n = length(f0); % n states
  74. % Bilinear operators
  75. %==========================================================================
  76. % Bilinear operator - M0
  77. %--------------------------------------------------------------------------
  78. M0 = spm_cat({0 [] ;
  79. (f0 - dfdx*spm_vec(x)) dfdx});
  80. % Bilinear operator - M1 = dM0/du
  81. %--------------------------------------------------------------------------
  82. for i = 1:m
  83. M1{i} = spm_cat({0, [] ;
  84. (dfdu(:,i) - dfdxu{i}*spm_vec(x)), dfdxu{i}});
  85. end
  86. % Bilinear operator - M2 = dM0/dx
  87. %--------------------------------------------------------------------------
  88. for i = 1:n
  89. M2{i} = spm_cat({0, [] ;
  90. (dfdx(:,i) - dfdxx{i}*spm_vec(x)), dfdxx{i}});
  91. end
  92. if nargout < 4, return, end
  93. % Output matrices - L1
  94. %==========================================================================
  95. % l(x(0),0)
  96. %--------------------------------------------------------------------------
  97. [dgdx,g0] = spm_diff(fung,x,u,P,M,1);
  98. L1 = spm_cat({(g0 - dgdx*spm_vec(x)), dgdx});
  99. l = length(g0);
  100. if nargout < 5, return, end
  101. % Output matrices - L2
  102. %--------------------------------------------------------------------------
  103. dgdxx = spm_diff(fung,x,u,P,M,[1 1]);
  104. for i = 1:l
  105. for j = 1:n
  106. D{i}(j,:) = dgdxx{j}(i,:);
  107. end
  108. end
  109. for i = 1:l
  110. L2{i} = spm_cat(spm_diag({0, D{i}}));
  111. end