Mercurial > hg > ltpda
diff m-toolbox/classes/+utils/@math/lp2z.m @ 0:f0afece42f48
Import.
author | Daniele Nicolodi <nicolodi@science.unitn.it> |
---|---|
date | Wed, 23 Nov 2011 19:22:13 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/m-toolbox/classes/+utils/@math/lp2z.m Wed Nov 23 19:22:13 2011 +0100 @@ -0,0 +1,331 @@ +% LP2Z converts a continous TF in to a discrete TF. +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% DESCRIPTION: LP2Z converts a continous (lapalce notation) transfer +% function in a discrete (z transfor formalism) partial fractioned transfer +% function. +% +% Input function can be in rational, poles and zeros or partial fractions +% form: +% The rational case assumes an input function of the type: +% +% a(1)s^m + a(2)s^{m-1} + ... + a(m+1) +% H(s) = -------------------------------------- +% b(1)s^n + b(2)s^{n-1} + ... + b(n+1) +% +% The poles and zeros case assumes an impution function of the type: +% +% (s-Z(1))(s-Z(2))...(s-Z(n)) +% H(s) = K --------------------------- +% (s-P(1))(s-P(2))...(s-P(n)) +% +% The partail fraction case assumes an input function of the type: +% +% R(1) R(2) R(n) +% H(s) = -------- + -------- + ... + -------- + K(s) +% s - P(1) s - P(2) s - P(n) +% +% LP2Z function is also capable to handling input transfer functions with +% multiple poles. +% +% +% +% CALL: +% pfstruct = lp2z(varargin) +% [res,poles,dterm] = lp2z(varargin) +% [pfstruct,res,poles,dterm] = lp2z(varargin) +% +% +% +% INPUTS: +% Input parameters are: +% 'FS' sampling frequency +% 'RRTOL' the repeated-root tolerance, default value is +% 1e-15. If two roots differs less than rrtolerance value, they +% are reported as multiple roots. +% 'INOPT' define the input function type +% 'PF' use this option if you want to input a function +% expanded in partial fractions. Then you have to input the +% vectors containing: +% 'RES' the vector containig the residues +% 'POLES' The vector containing the poles +% 'DTERMS' The vector containing the direct terms +% 'RAT' input the continous function in rational form. +% then you have to input the vector of coefficients: +% 'NUM' is the vector with numerator coefficients. +% 'DEN' is the vector of denominator coefficienets. +% 'PZ' input the continuous function in poles and +% zeros form. Then you have to input the vectors with poles +% and zeros: +% 'POLES' the vector with poles +% 'ZEROS' the vector with zeros +% 'GAIN' the value of the gain +% 'MODE' Is the mode used for the calculation of the roots of a +% polynomial. Admitted values are: +% 'SYM' uses symbolic roots calculation (you need Symbolic +% Math Toolbox to use this option) +% 'DBL' uses the standard numerical matlab style roots +% claculation (double precision) +% +% +% OUTPUTS: +% Function output is a structure array with two fields: 'num' and +% 'den' respectively. Each term of the partial fraction expansion +% can be seen as rational transfer function in z domain. These +% reduced transfer functions can be used to filter in parallel a +% series of data. This representation is particularly useful when +% poles with multiplicity higher than one are present. In this +% case the corresponding terms of the partial fraction expansion +% are really rational transfer functions whose order depends from +% the pole multiplicity [1]. +% As a sencond option residues, poles and direct term are output +% as standard vectors (this possibility works only with simple +% poles). +% The third possibility is to call the function with four output, +% 1st is a struct, 2nd are residues, 3rd are ples and 4th is the +% direct term. +% +% NOTE1: The function is capable to convert in partial fractions +% only rational functions with numerator of order lower or equal +% to the order of the denominator. When the order of the +% numerator is higher than the order of the denominator (improper +% rational functions) the expansion in partial fractions is not +% useful and other methods are preferable. +% +% NOTE2: 'SYM' calculation mode requires Symbolic Math Toolbox +% to work +% +% +% +% REFERENCES: +% [1] Alan V. Oppenheim, Allan S. Willsky and Ian T. Young, Signals +% and Systems, Prentice-Hall Signal Processing Series, Prentice +% Hall (June 1982), ISBN-10: 0138097313. Pages 767 - 776. +% +% +% VERSION $Id: lp2z.m,v 1.11 2009/02/10 12:14:29 luigi Exp $ +% +% HISTORY: 16-04-2008 L Ferraioli +% Creation +% +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function varargout = lp2z(varargin) + + + %% Finding input parameters + + % Default values for the parameters + fs = 10; + inopt = 'RAT'; + tol = 1e-15; + mode = 'DBL'; + + % Finding input parameters + if ~isempty(varargin) + for j=1:length(varargin) + if strcmp(varargin{j},'INOPT') + inopt = varargin{j+1}; + end + if strcmp(varargin{j},'FS') + fs = varargin{j+1}; + end + if strcmp(varargin{j},'MODE') + mode = varargin{j+1}; + end + if strcmp(varargin{j},'RRTOL') + tol = varargin{j+1}; + end + end + end + + + %% Conversion to partial fractions and discretization + + % swithing between input options + switch inopt + case 'RAT' + % Finding proper parameters + for jj=1:length(varargin) + if strcmp(varargin{jj},'NUM') + num = varargin{jj+1}; + end + if strcmp(varargin{jj},'DEN') + den = varargin{jj+1}; + end + end + % conversion in partail fractions cP is the vector of residues, cP is the + % vector of poles and cK is the vector of direct terms + [cR, cP, cK, mul] = utils.math.cpf('INOPT', 'RAT', 'NUM', num,... + 'DEN', den, 'MODE', mode, 'RRTOL', tol); + + case 'PZ' + % Finding proper parameters + for jj=1:length(varargin) + if strcmp(varargin{jj},'ZEROS') + zer = varargin{jj+1}; + end + if strcmp(varargin{jj},'POLES') + pol = varargin{jj+1}; + end + if strcmp(varargin{jj},'GAIN') + gain = varargin{jj+1}; + end + end + % conversion in partail fractions cP is the vector of residues, cP is the + % vector of poles and cK is the vector of direct terms + [cR, cP, cK, mul] = utils.math.cpf('INOPT', 'PZ', 'ZEROS', zer,... + 'POLES', pol, 'GAIN', gain, 'RRTOL', tol); + + case 'PF' + % Finding proper parameters + for jj=1:length(varargin) + if strcmp(varargin{jj},'RES') + cR = varargin{jj+1}; + end + if strcmp(varargin{jj},'POLES') + cP = varargin{jj+1}; + end + if strcmp(varargin{jj},'DTERMS') + cK = varargin{jj+1}; + end + end + % finding poles multiplicity + mul = mpoles(cP,tol,0); + end + + % Checking for not proper functions + if length(cK)>1 + error('Unable to directly discretize not proper continuous functions ') + end + + % disctretization + T = 1/fs; + + dpls = exp(cP.*T); % poles discretization + + % Construct a struct array in which the elements of the partial + % fractions expansion are stored. Each partial fraction can be + % considered as rational function with proper numerator and denominator + % coefficients + pfstruct = struct(); + + indxmul = 0; + for kk=1:length(mul) + if mul(kk)==1 + pfstruct(kk).num = cR(kk).*T; + pfstruct(kk).den = [1 -1*dpls(kk)]; + else + coeffs = PolyLogCoeffs(1-mul(kk),exp(cP(kk)*T)); + coeffs = flipdim(coeffs,2); + pfstruct(kk).num = (cR(kk)*T^mul(kk)/prod(1:mul(kk)-1)).*coeffs; + pfstruct(kk).den = BinomialExpansion(mul(kk),exp(cP(kk)*T)); + indxmul = 1; + end + end + + % Inserting the coefficients relative to the presence of a direct term + if ((length(cK)==1)&&(not(cK(1)==0))) + pfstruct(length(mul)+1).num = cK.*T; + pfstruct(length(mul)+1).den = [1 0]; + end + + % Output also the vector of residues, poles and direct term if non multiple + % poles are found + if indxmul == 0 + res = cR.*T; + poles = dpls; + dterm = cK.*T; + else + res = []; + poles = []; + dterm = []; + end + + % Output empty fields struct in case of no input + if isempty(cR)||isempty(cP) + pfstruct.num = []; + pfstruct.den = []; + end + + %% Output data + + if indxmul == 1 + disp( ' Found poles with multiplicity higher than one. Results are output in struct form only. ') + end + + if nargout == 1 + varargout{1} = pfstruct; + elseif nargout == 3 + varargout{1} = res; + varargout{2} = poles; + varargout{3} = dterm; + elseif nargout == 4 + varargout{1} = pfstruct; + varargout{2} = res; + varargout{3} = poles; + varargout{4} = dterm; + else + error('Unespected number of outputs! Output must be 1, 3 or 4') + end + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% FUNCTION: Eulerian Number +% +% DESCRIPTION: Calculates the Eulerian Number +% +% HISTORY: 12-05-2008 L Ferraioli +% Creation +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function enum = eulerian(n,k) + + enum = 0; + for jj = 0:k+1; + enum = enum + ((-1)^jj)*(prod(1:n+1)/(prod(1:n+1-jj)*prod(1:jj)))*(k-jj+1)^n; + end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% FUNCTION: PloyLogCoeffs +% +% DESCRIPTION: Computes the coefficients of a poly-logarithm expansion for +% negative n values +% +% HISTORY: 12-05-2008 L Ferraioli +% Creation +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function coeffs = PolyLogCoeffs(n,x) + + if n>=0 + error('n must be a negative integer!') + else + % Now we keep the absolute value of n + n = -1*n; + end + + coeffs = []; + for ii=0:n; + coeffs = [coeffs eulerian(n,ii)*(x^(n-ii))]; + end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% FUNCTION: BinomialExpansion +% +% DESCRIPTION: Performs the binomial expamsion of the expression (1-x)^n +% +% HISTORY: 12-05-2008 L Ferraioli +% Creation +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function binexp = BinomialExpansion(n,x) + + binexp = []; + for jj=0:n + binexp = [binexp ((-1)^jj)*(prod(1:n)/(prod(1:n-jj)*prod(1:jj))*(x^jj))]; + end