From: <par...@us...> - 2011-09-03 18:50:42
|
Revision: 8488 http://octave.svn.sourceforge.net/octave/?rev=8488&view=rev Author: paramaniac Date: 2011-09-03 18:50:35 +0000 (Sat, 03 Sep 2011) Log Message: ----------- control: add bilinear transformation (c2d case) Modified Paths: -------------- trunk/octave-forge/main/control/devel/makefile_all.m trunk/octave-forge/main/control/inst/@ss/__c2d__.m trunk/octave-forge/main/control/inst/@tf/__c2d__.m trunk/octave-forge/main/control/inst/ltimodels.m trunk/octave-forge/main/control/src/Makefile Added Paths: ----------- trunk/octave-forge/main/control/devel/makefile_tustin.m trunk/octave-forge/main/control/src/AB04MD.f trunk/octave-forge/main/control/src/slab04md.cc Modified: trunk/octave-forge/main/control/devel/makefile_all.m =================================================================== --- trunk/octave-forge/main/control/devel/makefile_all.m 2011-09-03 16:37:43 UTC (rev 8487) +++ trunk/octave-forge/main/control/devel/makefile_all.m 2011-09-03 18:50:35 UTC (rev 8488) @@ -25,7 +25,7 @@ makefile_scale makefile_ss2tf makefile_staircase +makefile_tustin makefile_zero -system ("rm *.o"); cd (homedir); Added: trunk/octave-forge/main/control/devel/makefile_tustin.m =================================================================== --- trunk/octave-forge/main/control/devel/makefile_tustin.m (rev 0) +++ trunk/octave-forge/main/control/devel/makefile_tustin.m 2011-09-03 18:50:35 UTC (rev 8488) @@ -0,0 +1,19 @@ +## ============================================================================== +## Developer Makefile for OCT-files +## ============================================================================== +## USAGE: * fetch control from Octave-Forge by svn +## * add control/inst, control/src and control/devel to your Octave path +## * run makefile_* +## ============================================================================== + +homedir = pwd (); +develdir = fileparts (which ("makefile_tustin")); +srcdir = [develdir, "/../src"]; +cd (srcdir); + +## bilinear transformation +mkoctfile slab04md.cc \ + AB04MD.f + +system ("rm *.o"); +cd (homedir); Modified: trunk/octave-forge/main/control/inst/@ss/__c2d__.m =================================================================== --- trunk/octave-forge/main/control/inst/@ss/__c2d__.m 2011-09-03 16:37:43 UTC (rev 8487) +++ trunk/octave-forge/main/control/inst/@ss/__c2d__.m 2011-09-03 18:50:35 UTC (rev 8488) @@ -44,6 +44,19 @@ sys.a = tmp (1:n, 1:n); # F sys.b = tmp (1:n, n+(1:m)); # G + case {"tustin", "bilin"} + if (! isempty (sys.e)) + if (rcond (sys.e) < eps) + error ("ss: c2d: tustin method requires proper system"); + else + sys.a = sys.e \ sys.a; + sys.b = sys.e \ sys.b; + sys.e = []; # require ordinary state-space model + endif + endif + + [sys.a, sys.b, sys.c, sys.d] = slab04md (sys.a, sys.b, sys.c, sys.d, 1, 2/tsam, false); + otherwise error ("ss: c2d: %s is an invalid method", method); Modified: trunk/octave-forge/main/control/inst/@tf/__c2d__.m =================================================================== --- trunk/octave-forge/main/control/inst/@tf/__c2d__.m 2011-09-03 16:37:43 UTC (rev 8487) +++ trunk/octave-forge/main/control/inst/@tf/__c2d__.m 2011-09-03 18:50:35 UTC (rev 8488) @@ -26,13 +26,13 @@ [p, m] = size (sys); - switch (method) - case {"zoh", "std"} + ##switch (method) + ## case {"zoh", "std"} error ("tf: c2d: not implemented yet"); - otherwise - error ("tf: c2d: %s is an invalid method", method); + ## otherwise + ## error ("tf: c2d: %s is an invalid method", method); - endswitch + ##endswitch endfunction \ No newline at end of file Modified: trunk/octave-forge/main/control/inst/ltimodels.m =================================================================== --- trunk/octave-forge/main/control/inst/ltimodels.m 2011-09-03 16:37:43 UTC (rev 8487) +++ trunk/octave-forge/main/control/inst/ltimodels.m 2011-09-03 18:50:35 UTC (rev 8488) @@ -1229,3 +1229,71 @@ %! %!assert (NUM, NUMe, 1e-4); %!assert (DEN, DENe, 1e-4); + + +## bilinear transformation +%!shared Mo, Me +%! A = [ 1.0 0.5 +%! 0.5 1.0 ].'; +%! +%! B = [ 0.0 -1.0 +%! 1.0 0.0 ].'; +%! +%! C = [ -1.0 0.0 +%! 0.0 1.0 ].'; +%! +%! D = [ 1.0 0.0 +%! 0.0 -1.0 ].'; +%! +%! [Ao, Bo, Co, Do] = slab04md (A, B, C, D, 1.0, 1.0, false); +%! +%! Ae = [ -1.0000 -4.0000 +%! -4.0000 -1.0000 ]; +%! +%! Be = [ 2.8284 0.0000 +%! 0.0000 -2.8284 ]; +%! +%! Ce = [ 0.0000 2.8284 +%! -2.8284 0.0000 ]; +%! +%! De = [ -1.0000 0.0000 +%! 0.0000 -3.0000 ]; +%! +%! Mo = [Ao, Bo; Co, Do]; +%! Me = [Ae, Be; Ce, De]; +%! +%!assert (Mo, Me, 1e-4); + + +## bilinear transformation +%!shared Mo, Me +%! A = [ 1.0 0.5 +%! 0.5 1.0 ].'; +%! +%! B = [ 0.0 -1.0 +%! 1.0 0.0 ].'; +%! +%! C = [ -1.0 0.0 +%! 0.0 1.0 ].'; +%! +%! D = [ 1.0 0.0 +%! 0.0 -1.0 ].'; +%! +%! [Ao, Bo, Co, Do] = ssdata (c2d (ss (A, B, C, D), 2, "tustin")); +%! +%! Ae = [ -1.0000 -4.0000 +%! -4.0000 -1.0000 ]; +%! +%! Be = [ 2.8284 0.0000 +%! 0.0000 -2.8284 ]; +%! +%! Ce = [ 0.0000 2.8284 +%! -2.8284 0.0000 ]; +%! +%! De = [ -1.0000 0.0000 +%! 0.0000 -3.0000 ]; +%! +%! Mo = [Ao, Bo; Co, Do]; +%! Me = [Ae, Be; Ce, De]; +%! +%!assert (Mo, Me, 1e-4); Added: trunk/octave-forge/main/control/src/AB04MD.f =================================================================== --- trunk/octave-forge/main/control/src/AB04MD.f (rev 0) +++ trunk/octave-forge/main/control/src/AB04MD.f 2011-09-03 18:50:35 UTC (rev 8488) @@ -0,0 +1,345 @@ + SUBROUTINE AB04MD( TYPE, N, M, P, ALPHA, BETA, A, LDA, B, LDB, C, + $ LDC, D, LDD, IWORK, DWORK, LDWORK, INFO ) +C +C SLICOT RELEASE 5.0. +C +C Copyright (c) 2002-2010 NICONET e.V. +C +C This program is free software: you can redistribute it and/or +C modify it under the terms of the GNU General Public License as +C published by the Free Software Foundation, either version 2 of +C the License, or (at your option) any later version. +C +C This program is distributed in the hope that it will be useful, +C but WITHOUT ANY WARRANTY; without even the implied warranty of +C MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +C GNU General Public License for more details. +C +C You should have received a copy of the GNU General Public License +C along with this program. If not, see +C <http://www.gnu.org/licenses/>. +C +C PURPOSE +C +C To perform a transformation on the parameters (A,B,C,D) of a +C system, which is equivalent to a bilinear transformation of the +C corresponding transfer function matrix. +C +C ARGUMENTS +C +C Mode Parameters +C +C TYPE CHARACTER*1 +C Indicates the type of the original system and the +C transformation to be performed as follows: +C = 'D': discrete-time -> continuous-time; +C = 'C': continuous-time -> discrete-time. +C +C Input/Output Parameters +C +C N (input) INTEGER +C The order of the state matrix A. N >= 0. +C +C M (input) INTEGER +C The number of system inputs. M >= 0. +C +C P (input) INTEGER +C The number of system outputs. P >= 0. +C +C ALPHA, (input) DOUBLE PRECISION +C BETA Parameters specifying the bilinear transformation. +C Recommended values for stable systems: ALPHA = 1, +C BETA = 1. ALPHA <> 0, BETA <> 0. +C +C A (input/output) DOUBLE PRECISION array, dimension (LDA,N) +C On entry, the leading N-by-N part of this array must +C contain the state matrix A of the original system. +C On exit, the leading N-by-N part of this array contains +C _ +C the state matrix A of the transformed system. +C +C LDA INTEGER +C The leading dimension of array A. LDA >= MAX(1,N). +C +C B (input/output) DOUBLE PRECISION array, dimension (LDB,M) +C On entry, the leading N-by-M part of this array must +C contain the input matrix B of the original system. +C On exit, the leading N-by-M part of this array contains +C _ +C the input matrix B of the transformed system. +C +C LDB INTEGER +C The leading dimension of array B. LDB >= MAX(1,N). +C +C C (input/output) DOUBLE PRECISION array, dimension (LDC,N) +C On entry, the leading P-by-N part of this array must +C contain the output matrix C of the original system. +C On exit, the leading P-by-N part of this array contains +C _ +C the output matrix C of the transformed system. +C +C LDC INTEGER +C The leading dimension of array C. LDC >= MAX(1,P). +C +C D (input/output) DOUBLE PRECISION array, dimension (LDD,M) +C On entry, the leading P-by-M part of this array must +C contain the input/output matrix D for the original system. +C On exit, the leading P-by-M part of this array contains +C _ +C the input/output matrix D of the transformed system. +C +C LDD INTEGER +C The leading dimension of array D. LDD >= MAX(1,P). +C +C Workspace +C +C IWORK INTEGER array, dimension (N) +C +C DWORK DOUBLE PRECISION array, dimension (LDWORK) +C On exit, if INFO = 0, DWORK(1) returns the optimal value +C of LDWORK. +C +C LDWORK INTEGER +C The length of the array DWORK. LDWORK >= MAX(1,N). +C For optimum performance LDWORK >= MAX(1,N*NB), where NB +C is the optimal blocksize. +C +C Error Indicator +C +C INFO INTEGER +C = 0: successful exit; +C < 0: if INFO = -i, the i-th argument had an illegal +C value; +C = 1: if the matrix (ALPHA*I + A) is exactly singular; +C = 2: if the matrix (BETA*I - A) is exactly singular. +C +C METHOD +C +C The parameters of the discrete-time system are transformed into +C the parameters of the continuous-time system (TYPE = 'D'), or +C vice-versa (TYPE = 'C') by the transformation: +C +C 1. Discrete -> continuous +C _ -1 +C A = beta*(alpha*I + A) * (A - alpha*I) +C _ -1 +C B = sqrt(2*alpha*beta) * (alpha*I + A) * B +C _ -1 +C C = sqrt(2*alpha*beta) * C * (alpha*I + A) +C _ -1 +C D = D - C * (alpha*I + A) * B +C +C which is equivalent to the bilinear transformation +C +C z - alpha +C z -> s = beta --------- . +C z + alpha +C +C of one transfer matrix onto the other. +C +C 2. Continuous -> discrete +C _ -1 +C A = alpha*(beta*I - A) * (beta*I + A) +C _ -1 +C B = sqrt(2*alpha*beta) * (beta*I - A) * B +C _ -1 +C C = sqrt(2*alpha*beta) * C * (beta*I - A) +C _ -1 +C D = D + C * (beta*I - A) * B +C +C which is equivalent to the bilinear transformation +C +C beta + s +C s -> z = alpha -------- . +C beta - s +C +C of one transfer matrix onto the other. +C +C REFERENCES +C +C [1] Al-Saggaf, U.M. and Franklin, G.F. +C Model reduction via balanced realizations: a extension and +C frequency weighting techniques. +C IEEE Trans. Autom. Contr., AC-33, pp. 687-692, 1988. +C +C NUMERICAL ASPECTS +C 3 +C The time taken is approximately proportional to N . +C The accuracy depends mainly on the condition number of the matrix +C to be inverted. +C +C CONTRIBUTORS +C +C Release 3.0: V. Sima, Katholieke Univ. Leuven, Belgium, and +C A. Varga, German Aerospace Research Establishment, +C Oberpfaffenhofen, Germany, Nov. 1996. +C Supersedes Release 2.0 routine AB04AD by W. van der Linden, and +C A.J. Geurts, Technische Hogeschool Eindhoven, Holland. +C +C REVISIONS +C +C - +C +C KEYWORDS +C +C Bilinear transformation, continuous-time system, discrete-time +C system, state-space model. +C +C ****************************************************************** +C +C .. Parameters .. + DOUBLE PRECISION ZERO, ONE, TWO + PARAMETER ( ZERO=0.0D0, ONE=1.0D0, TWO=2.0D0 ) +C .. Scalar Arguments .. + CHARACTER TYPE + INTEGER INFO, LDA, LDB, LDC, LDD, LDWORK, M, N, P + DOUBLE PRECISION ALPHA, BETA +C .. Array Arguments .. + INTEGER IWORK(*) + DOUBLE PRECISION A(LDA,*), B(LDB,*), C(LDC,*), D(LDD,*), DWORK(*) +C .. Local Scalars .. + LOGICAL LTYPE + INTEGER I, IP + DOUBLE PRECISION AB2, PALPHA, PBETA, SQRAB2 +C .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +C .. External Subroutines .. + EXTERNAL DGEMM, DGETRF, DGETRS, DGETRI, DLASCL, DSCAL, + $ DSWAP, XERBLA +C .. Intrinsic Functions .. + INTRINSIC ABS, MAX, SIGN, SQRT +C .. Executable Statements .. +C + INFO = 0 + LTYPE = LSAME( TYPE, 'D' ) +C +C Test the input scalar arguments. +C + IF( .NOT.LTYPE .AND. .NOT.LSAME( TYPE, 'C' ) ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( M.LT.0 ) THEN + INFO = -3 + ELSE IF( P.LT.0 ) THEN + INFO = -4 + ELSE IF( ALPHA.EQ.ZERO ) THEN + INFO = -5 + ELSE IF( BETA.EQ.ZERO ) THEN + INFO = -6 + ELSE IF( LDA.LT.MAX( 1, N ) ) THEN + INFO = -8 + ELSE IF( LDB.LT.MAX( 1, N ) ) THEN + INFO = -10 + ELSE IF( LDC.LT.MAX( 1, P ) ) THEN + INFO = -12 + ELSE IF( LDD.LT.MAX( 1, P ) ) THEN + INFO = -14 + ELSE IF( LDWORK.LT.MAX( 1, N ) ) THEN + INFO = -17 + END IF +C + IF ( INFO.NE.0 ) THEN +C +C Error return. +C + CALL XERBLA( 'AB04MD', -INFO ) + RETURN + END IF +C +C Quick return if possible. +C + IF ( MAX( N, M, P ).EQ.0 ) + $ RETURN +C +C (Note: Comments in the code beginning "Workspace:" describe the +C minimal amount of real workspace needed at that point in the +C code, as well as the preferred amount for good performance. +C NB refers to the optimal block size for the immediately +C following subroutine, as returned by ILAENV.) +C + IF (LTYPE) THEN +C +C Discrete-time to continuous-time with (ALPHA, BETA). +C + PALPHA = ALPHA + PBETA = BETA + ELSE +C +C Continuous-time to discrete-time with (ALPHA, BETA) is +C equivalent with discrete-time to continuous-time with +C (-BETA, -ALPHA), if B and C change the sign. +C + PALPHA = -BETA + PBETA = -ALPHA + END IF +C + AB2 = PALPHA*PBETA*TWO + SQRAB2 = SIGN( SQRT( ABS( AB2 ) ), PALPHA ) +C -1 +C Compute (alpha*I + A) . +C + DO 10 I = 1, N + A(I,I) = A(I,I) + PALPHA + 10 CONTINUE +C + CALL DGETRF( N, N, A, LDA, IWORK, INFO ) +C + IF (INFO.NE.0) THEN +C +C Error return. +C + IF (LTYPE) THEN + INFO = 1 + ELSE + INFO = 2 + END IF + RETURN + END IF +C -1 +C Compute (alpha*I+A) *B. +C + CALL DGETRS( 'No transpose', N, M, A, LDA, IWORK, B, LDB, INFO ) +C -1 +C Compute D - C*(alpha*I+A) *B. +C + CALL DGEMM( 'No transpose', 'No transpose', P, M, N, -ONE, C, + $ LDC, B, LDB, ONE, D, LDD ) +C +C Scale B by sqrt(2*alpha*beta). +C + CALL DLASCL( 'General', 0, 0, ONE, SQRAB2, N, M, B, LDB, INFO ) +C -1 +C Compute sqrt(2*alpha*beta)*C*(alpha*I + A) . +C + CALL DTRSM( 'Right', 'Upper', 'No transpose', 'Non-unit', P, N, + $ SQRAB2, A, LDA, C, LDC ) +C + CALL DTRSM( 'Right', 'Lower', 'No transpose', 'Unit', P, N, ONE, + $ A, LDA, C, LDC ) +C +C Apply column interchanges to the solution matrix. +C + DO 20 I = N-1, 1, -1 + IP = IWORK(I) + IF ( IP.NE.I ) + $ CALL DSWAP( P, C(1,I), 1, C(1,IP), 1 ) + 20 CONTINUE +C -1 +C Compute beta*(alpha*I + A) *(A - alpha*I) as +C -1 +C beta*I - 2*alpha*beta*(alpha*I + A) . +C +C Workspace: need N; prefer N*NB. +C + CALL DGETRI( N, A, LDA, IWORK, DWORK, LDWORK, INFO ) +C + DO 30 I = 1, N + CALL DSCAL(N, -AB2, A(1,I), 1) + A(I,I) = A(I,I) + PBETA + 30 CONTINUE +C + RETURN +C *** Last line of AB04MD *** + END Property changes on: trunk/octave-forge/main/control/src/AB04MD.f ___________________________________________________________________ Added: svn:executable + * Modified: trunk/octave-forge/main/control/src/Makefile =================================================================== --- trunk/octave-forge/main/control/src/Makefile 2011-09-03 16:37:43 UTC (rev 8487) +++ trunk/octave-forge/main/control/src/Makefile 2011-09-03 18:50:35 UTC (rev 8488) @@ -4,6 +4,7 @@ sltb01pd.oct slsb03od.oct slsg03bd.oct slag08bd.oct sltg01jd.oct \ sltg01hd.oct sltg01id.oct slsg02ad.oct sltg04bx.oct sltb01id.oct \ sltg01ad.oct slsb10id.oct slsb10kd.oct slsb10zd.oct sltb04bd.oct \ + slab04md.oct \ is_real_scalar.oct is_real_vector.oct is_real_matrix.oct \ is_real_square_matrix.oct @@ -212,6 +213,11 @@ TB04BX.f MA02AD.f MB02RD.f MB01PD.f MB02SD.f \ MB01QD.f +# bilinear transformation +slab04md.oct: slab04md.cc + mkoctfile slab04md.cc \ + AB04MD.f + # helpers is_real_scalar.oct: is_real_scalar.cc mkoctfile is_real_scalar.cc Added: trunk/octave-forge/main/control/src/slab04md.cc =================================================================== --- trunk/octave-forge/main/control/src/slab04md.cc (rev 0) +++ trunk/octave-forge/main/control/src/slab04md.cc 2011-09-03 18:50:35 UTC (rev 8488) @@ -0,0 +1,128 @@ +/* + +Copyright (C) 2011 Lukas F. Reichlin + +This file is part of LTI Syncope. + +LTI Syncope is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +LTI Syncope is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with LTI Syncope. If not, see <http://www.gnu.org/licenses/>. + +Discrete-time <--> continuous-time systems conversion +by a bilinear transformation. +Uses SLICOT AB04MD by courtesy of NICONET e.V. +<http://www.slicot.org> + +Author: Lukas Reichlin <luk...@gm...> +Created: September 2011 +Version: 0.1 + +*/ + +#include <octave/oct.h> +#include <f77-fcn.h> +#include "common.cc" + +extern "C" +{ + int F77_FUNC (ab04md, AB04MD) + (char& TYPE, + int& N, int& M, int& P, + double& ALPHA, double& BETA, + double* A, int& LDA, + double* B, int& LDB, + double* C, int& LDC, + double* D, int& LDD, + int* IWORK, + double* DWORK, int& LDWORK, + int& INFO); +} + +DEFUN_DLD (slab04md, args, nargout, + "-*- texinfo -*-\n\ +Slicot AB04MD Release 5.0\n\ +No argument checking.\n\ +For internal use only.") +{ + int nargin = args.length (); + octave_value_list retval; + + if (nargin != 7) + { + print_usage (); + } + else + { + // arguments in + char type; + + Matrix a = args(0).matrix_value (); + Matrix b = args(1).matrix_value (); + Matrix c = args(2).matrix_value (); + Matrix d = args(3).matrix_value (); + + double alpha = args(4).double_value (); + double beta = args(5).double_value (); + int discrete = args(6).int_value (); + + if (discrete == 0) + type = 'C'; + else + type = 'D'; + + int n = a.rows (); // n: number of states + int m = b.columns (); // m: number of inputs + int p = c.rows (); // p: number of outputs + + int lda = max (1, n); + int ldb = max (1, n); + int ldc = max (1, p); + int ldd = max (1, p); + + // workspace + int ldwork = max (1, n); + + OCTAVE_LOCAL_BUFFER (int, iwork, n); + OCTAVE_LOCAL_BUFFER (double, dwork, ldwork); + + // error indicator + int info; + + + // SLICOT routine AB04MD + F77_XFCN (ab04md, AB04MD, + (type, + n, m, p, + alpha, beta, + a.fortran_vec (), lda, + b.fortran_vec (), ldb, + c.fortran_vec (), ldc, + d.fortran_vec (), ldd, + iwork, + dwork, ldwork, + info)); + + if (f77_exception_encountered) + error ("slab04md: exception in SLICOT subroutine AB04MD"); + + if (info != 0) + error ("slab04md: AB04MD returned info = %d", info); + + // return values + retval(0) = a; + retval(1) = b; + retval(2) = c; + retval(3) = d; + } + + return retval; +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |