changeset 8680:10f9883709ae octave-forge

control-devel: add oct-file for bstmodred
author paramaniac
date Wed, 26 Oct 2011 18:32:52 +0000
parents ddd705c59ea8
children 7fa6a02ce677
files extra/control-devel/devel/makefile_modred.m extra/control-devel/src/slab09hd.cc
diffstat 2 files changed, 274 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/extra/control-devel/devel/makefile_modred.m	Wed Oct 26 18:07:10 2011 +0000
+++ b/extra/control-devel/devel/makefile_modred.m	Wed Oct 26 18:32:52 2011 +0000
@@ -23,7 +23,9 @@
           MB04ND.f MB04OD.f SB03OR.f SB03OY.f MB04NY.f \
           MB04OY.f SB03OV.f
 
-mkoctfile AB09HD.f TB01ID.f AB04MD.f TB01KD.f AB09HY.f \
+mkoctfile "-Wl,-framework" "-Wl,vecLib" \
+          slab09hd.cc \
+          AB09HD.f TB01ID.f AB04MD.f TB01KD.f AB09HY.f \
           AB09IX.f MB03UD.f SB02MD.f AB09DD.f TB01LD.f \
           SB03OU.f MA02AD.f MB03QX.f select.f SB03OT.f \
           SB02MR.f SB02MS.f MB03QD.f SB02MU.f SB02MV.f \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extra/control-devel/src/slab09hd.cc	Wed Oct 26 18:32:52 2011 +0000
@@ -0,0 +1,271 @@
+/*
+
+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/>.
+
+Model reduction based on balanced stochastic truncation method.
+Uses SLICOT AB09HD by courtesy of NICONET e.V.
+<http://www.slicot.org>
+
+Author: Lukas Reichlin <lukas.reichlin@gmail.com>
+Created: October 2011
+Version: 0.1
+
+*/
+
+#include <octave/oct.h>
+#include <f77-fcn.h>
+#include "common.cc"
+
+extern "C"
+{ 
+    int F77_FUNC (ab09hd, AB09HD)
+                 (char& DICO, char& JOB, char& EQUIL, char& ORDSEL,
+                  int& N, int& M, int& P,
+                  int& NR,
+                  double& ALPHA, double& BETA,
+                  double* A, int& LDA,
+                  double* B, int& LDB,
+                  double* C, int& LDC,
+                  double* D, int& LDD,
+                  int& NS,
+                  double* HSV,
+                  double& TOL1, double& TOL2,
+                  int* IWORK,
+                  double* DWORK, int& LDWORK,
+                  bool* BWORK,
+                  int& IWARN, int& INFO);
+}
+     
+DEFUN_DLD (slab09hd, args, nargout,
+   "-*- texinfo -*-\n\
+Slicot AB09HD Release 5.0\n\
+No argument checking.\n\
+For internal use only.")
+{
+    int nargin = args.length ();
+    octave_value_list retval;
+    
+    if (nargin != 13)
+    {
+        print_usage ();
+    }
+    else
+    {
+        // arguments in
+        char dico;
+        char job;
+        char equil;
+        char ordsel;
+        
+        Matrix a = args(0).matrix_value ();
+        Matrix b = args(1).matrix_value ();
+        Matrix c = args(2).matrix_value ();
+        Matrix d = args(3).matrix_value ();
+        
+        const int idico = args(4).int_value ();
+        const int iequil = args(5).int_value ();
+        const int ijob = args(6).int_value ();
+        
+        int nr = args(7).int_value ();
+        const int iordsel = args(8).int_value ();
+        
+        double alpha = args(9).double_value ();
+        double beta = args(10).double_value ();
+        double tol1 = args(11).double_value ();
+        double tol2 = args(12).double_value ();
+
+        switch (ijob)
+        {
+            case 0:
+                job = 'B';
+                break;
+            case 1:
+                job = 'F';
+                break;
+            case 2:
+                job = 'S';
+                break;
+            case 3:
+                job = 'P';
+                break;
+            default:
+                error ("slab09hd: argument job invalid");
+        }
+
+        if (idico == 0)
+            dico = 'C';
+        else
+            dico = 'D';
+
+        if (iequil == 0)
+            equil = 'S';
+        else
+            equil = 'N';
+
+        if (iordsel == 0)
+            ordsel = 'F';
+        else
+            ordsel = 'A';
+
+        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);
+
+        // arguments out
+        int ns;
+        ColumnVector hsv (n);
+
+        // workspace
+        int liwork = max (1, 2*n);
+        int mb;
+        
+        if (beta == 0)
+            mb = m;
+        else
+            mb = m + p;
+        
+        int ldwork = 2*n*n + mb*(n+p)
+                     + max (2, n*(max (n,mb,p)+5), 2*n*p + max (p*(mb+2), 10*n*(n+1)));
+
+        OCTAVE_LOCAL_BUFFER (int, iwork, liwork);
+        OCTAVE_LOCAL_BUFFER (double, dwork, ldwork);
+        OCTAVE_LOCAL_BUFFER (bool, bwork, 2*n);
+        
+        // error indicators
+        int iwarn = 0;
+        int info = 0;
+
+
+        // SLICOT routine AB09HD
+        F77_XFCN (ab09hd, AB09HD,
+                 (dico, job, equil, ordsel,
+                  n, m, p,
+                  nr,
+                  alpha, beta,
+                  a.fortran_vec (), lda,
+                  b.fortran_vec (), ldb,
+                  c.fortran_vec (), ldc,
+                  d.fortran_vec (), ldd,
+                  ns,
+                  hsv.fortran_vec (),
+                  tol1, tol2,
+                  iwork,
+                  dwork, ldwork,
+                  bwork,
+                  iwarn, info));
+
+        if (f77_exception_encountered)
+            error ("bstmodred: exception in SLICOT subroutine AB09HD");
+            
+        if (info != 0)
+        {
+            if (info < 0)
+                error ("bstmodred: the %d-th argument had an invalid value", info);
+            else
+            {
+                switch (info)
+                {
+                    // FIXME: The code below looks nice, but the error message does not
+                    //        because there is much white space after each line break
+                    case 1:
+                        error ("bstmodred: 1: the computation of the ordered real Schur form of A\
+                                failed");
+                    case 2:
+                        error ("bstmodred: 2: the reduction of the Hamiltonian matrix to real\
+                                Schur form failed");
+                    case 3:
+                        error ("bstmodred: 3: the reordering of the real Schur form of the\
+                                Hamiltonian matrix failed");
+                    case 4:
+                        error ("bstmodred: 4: the Hamiltonian matrix has less than N stable\
+                                eigenvalues");
+                    case 5:
+                        error ("bstmodred: 5: the coefficient matrix U11 in the linear system\
+                                X*U11 = U21 to determine X is singular to working\
+                                precision");
+                    case 6:
+                        error ("bstmodred: 6: BETA = 0 and D has not a maximal row rank");
+                    case 7:
+                        error ("bstmodred: 7: the computation of Hankel singular values failed");
+                    case 8:
+                        error ("bstmodred: 8: the separation of the ALPHA-stable/unstable diagonal\
+                                blocks failed because of very close eigenvalues");
+                    case 9:
+                        error ("bstmodred: 9: the resulting order of reduced stable part is less\
+                                than the number of unstable zeros of the stable\
+                                part");
+                    default:
+                        error ("bstmodred: unknown error, info = %d", info);
+                }
+            }
+        }
+
+        if (iwarn != 0)
+        {
+            switch (iwarn)
+            {
+                case 1:
+                    warning ("bstmodred: 1: with ORDSEL = 'F', the selected order NR is greater\
+                              than NSMIN, the sum of the order of the\
+                              ALPHA-unstable part and the order of a minimal\
+                              realization of the ALPHA-stable part of the given\
+                              system; in this case, the resulting NR is set equal\
+                              to NSMIN.");
+                    break;
+                case 2:
+                    warning ("bstmodred: 2: with ORDSEL = 'F', the selected order NR corresponds\
+                              to repeated singular values for the ALPHA-stable\
+                              part, which are neither all included nor all\
+                              excluded from the reduced model; in this case, the\
+                              resulting NR is automatically decreased to exclude\
+                              all repeated singular values.");
+                    break;
+                case 3:
+                    warning ("bstmodred: 3: with ORDSEL = 'F', the selected order NR is less\
+                              than the order of the ALPHA-unstable part of the\
+                              given system; in this case NR is set equal to the\
+                              order of the ALPHA-unstable part.");
+                    break;
+                default:
+                    warning ("bstmodred: unknown warning, iwarn = %d", info);
+            }
+        }
+
+        // resize
+        a.resize (nr, nr);
+        b.resize (nr, m);
+        c.resize (p, nr);
+        hsv.resize (ns);
+        
+        // return values
+        retval(0) = a;
+        retval(1) = b;
+        retval(2) = c;
+        retval(3) = d;
+        retval(4) = octave_value (nr);
+        // retval(0) = hsv;
+        // retval(1) = octave_value (ns);
+    }
+    
+    return retval;
+}