Spectral Integral Suite in C++
lyap.h
Go to the documentation of this file.
1 
2 #ifndef CD_T
3 typedef complex<double> Cd_t;
4 #endif
5 extern "C"
6 {
7  void zgees_(char *JOBVS, char *SORT, bool (*SELCTG)(Cd_t a), int *N, Cd_t *A, int *LDA, int *SDIM, Cd_t *W, Cd_t *VS, int *LDVS, Cd_t *WORK, int *LWORK, double *RWORK, bool *BWORK, int *INFO);
8 }
9 
10 extern "C"
11 {
12  void ztgsen_(int* IJOB,bool* WANTQ, bool* WANTZ, bool* SELECT, int* N, Cd_t* A,int* LDA, Cd_t* B,int* LDB, Cd_t* ALPHA, Cd_t* BETA, Cd_t* Q, int* LDQ,Cd_t* Z,int* LDZ, int* M, double* PL, double* PR, double* DIF, Cd_t* WORK, int* LWORK, int* IWORK, int* LIWORK, int* INFO);
13 }
14 extern "C"
15 {
16  bool criteria_(Cd_t alpha, Cd_t beta)
17  {
18  if (abs(alpha / beta) > 1e10 || (abs(beta) == 0.0) ) {
19  return false;
20  }
21  else{
22  return true;
23  }
24  };
25 }
26 
27 extern "C"
28 {
29  void zgges_(char *JOBVSL, char *JOBVSR, char *SORT, bool (*SELCTG)(Cd_t a, Cd_t b), int *N, Cd_t *A, int *LDA, Cd_t *B, int *LDB,
30  int *SDIM, Cd_t *ALPHA, Cd_t *BETA, Cd_t *VSL, int *LDVSL, Cd_t *VSR, int *LDVSR, Cd_t *WORK,
31  int *LWORK, double *RWORK, bool *BWORK, int *INFO);
32 }
33 
34 class OrdQz {
35  public:
36  Eigen::MatrixXcd S,T,VSL,VSR,alpha,beta;
37  int info;
38  int M;
39  OrdQz() {}
40  OrdQz(Eigen::MatrixXcd A, Eigen::MatrixXcd B)
41  {
42  compute(A,B);
43  }
44 
45  void compute(Eigen::MatrixXcd A, Eigen::MatrixXcd B){
46  char jobvl = 'V'; // Compute left evecs
47  char jobvr = 'V'; // Compute right evecs
48  std::complex<double> wkopt; // Eistimate optimum workspace
49 
50  int r = A.rows();
51  int N = r;
52 
53 
54  S.resize(r,r); S = A;
55  T.resize(r, r); T = B;
56  VSL.resize(r,r);
57  VSR.resize(r, r);
58  alpha.resize(r,1);
59  beta.resize(r, 1);
60 
61  int ldac = A.outerStride();
62  int ldbc = B.outerStride();
63 
64  // vl : left evecs, vr: right evecs.
65  int ldvl = VSL.outerStride();
66  int ldvr = VSR.outerStride();
67  double rwork[8 * r];
68 
69  char sort = 'S';
70  int sdim = 0;
71  int lwork = -1;
72  vector<Cd_t> workc;
73  workc.resize(1);
74  bool bwork[N];
75 
76  bwork[0] = true;
77  zgges_(&jobvl, &jobvr, &sort, &criteria_, &N, S.data(), &ldac, T.data(), &ldbc, &sdim, alpha.data(), beta.data(), VSL.data(), &ldvl, VSR.data(), &ldvr, &workc[0], &lwork, &rwork[0], bwork, &info);
78 
79  //cout << workc[0];
80  lwork = int(real(workc[0]));
81  workc.resize(lwork);
82 
83  zgges_(&jobvl, &jobvr, &sort, &criteria_, &N, S.data(), &ldac, T.data(), &ldbc, &sdim, alpha.data(), beta.data(), VSL.data(), &ldvl, VSR.data(), &ldvr, &workc[0], &lwork, &rwork[0], bwork, &info);
84 
85 
86  int ijob = 0;
87  bool wantq = true;
88  bool wantz = true;
89  bool select[N];
90  for (int i = 0; i < alpha.size(); i++) {
91  select[i] = criteria_(alpha(i, 0), beta(i, 0));
92  cout << select[i] << endl;
93  }
94  int bre;
95  cin >> bre;
96  Eigen::MatrixXcd S1 = S, T1 = T;
97 
98  double pr;
99  double pl;
100  double dif;
101  lwork = -1;
102  int liwork = -1;
103  vector<int> iwork;
104  iwork.resize(1);
105  ztgsen_(&ijob, &wantq, &wantz, select, &N, S.data(), &ldac, T.data(), &ldbc, alpha.data(), beta.data(), VSL.data(), &ldvl, VSR.data(), &ldvr, &M, &pl, &pr, &dif, &workc[0], &lwork, &iwork[0], &liwork, &info);
106  lwork = int(real(workc[0]));
107  workc.resize(lwork);
108  liwork = iwork[0];
109  iwork.resize(liwork);
110  ztgsen_(&ijob, &wantq, &wantz, select, &N, S.data(), &ldac, T.data(), &ldbc, alpha.data(), beta.data(), VSL.data(), &ldvl, VSR.data(), &ldvr, &M, &pl, &pr, &dif, &workc[0], &lwork, &iwork[0], &liwork, &info);
111  cout << "info : " << info << endl;
112  cin >> bre;
113  cout << "M : " << M << endl;
114  cin >> bre;
115  // cout << "Alpha: " << alpha << endl;
116  // cout << "beta: " << beta << endl;
117  // for (int i = 0; i < N; i++)
118  // {
119  // cout << "bwork["<< i << "] = " << bwork[i] << endl;
120  // }
121  // int bre;
122  // cin >> bre;
123  //delete bwork;
124  }
125 
126 };
127 
128 bool forZgees(Cd_t a){
129  return true;
130 }
131 
133 Eigen::MatrixXcd lyap(Eigen::MatrixXcd A, Eigen::MatrixXcd B, Eigen::MatrixXcd Q) {
134  Eigen::MatrixXcd X, X1; // to be computed.
135  X1.setConstant(Cd_t(0.0,0.0));
136 
137  // Compute the lower triangular Schur form of A. This is done by computing the Schur form of A' and then taking a conjugate transpose. Schur form is computed using LAPACK's zgees.
138  Eigen::MatrixXcd T, Aad;
139  Aad = A;
140  Aad.adjointInPlace();
141  T = Aad;
142  #ifdef DEBUG
143  cout << "A: " << A << endl;
144  cout << "Aad: " << Aad << endl;
145  #endif
146  char jobvs = 'V';
147  char sort = 'S';
148  int N = A.rows();
149 // cout << "N = " << N << endl;
150  X1.resize(N,N);
151  X.resize(N, N);
152  int lda = Aad.outerStride();
153  // cout << "lda = " << lda << endl;
154  int sdim = 1;
155  int ldvs = N;
156  Eigen::MatrixXcd W(N,1), Vs(N,N);
157  int lwork = -1;
158  vector<Cd_t> workc;
159  workc.resize(1);
160  bool *bwork;
161  bwork = new bool[N];
162  double rwork[8 * N];
163  int info;
164  zgees_(&jobvs, &sort, &forZgees, &N, T.data(), &lda, &sdim, W.data(), Vs.data(), &ldvs, &workc[0], &lwork, &rwork[0], bwork, &info);
165  lwork = int(real(workc[0]));
166  workc.resize(lwork);
167  zgees_(&jobvs, &sort, &forZgees, &N, T.data(), &lda, &sdim, W.data(), Vs.data(), &ldvs, &workc[0], &lwork, &rwork[0], bwork, &info);
168  // see that the norm is zero
169  delete bwork;
170  #ifdef DEBUG
171  cout << "Error in norm: " << (Aad - Vs*T*Vs.adjoint()).norm() << endl;
172  cout << "Error in norm: " << (A - Vs * T.adjoint() * Vs.adjoint()).norm() << endl;
173  #endif
174  // Hence T is represented by its adjoint.
175  Eigen::MatrixXcd Tad = T.adjoint(), T2 = B, Us(N,N);
176 
177 
178  // Now compute the schur decomposition of B:
179  zgees_(&jobvs, &sort, &forZgees, &N, T2.data(), &lda, &sdim, W.data(), Us.data(), &ldvs, &workc[0], &lwork, &rwork[0], bwork, &info);
180  #ifdef DEBUG
181  cout << "Error in norm: " << (B - Us * T2 * Us.adjoint()).norm() << endl;
182  #endif
183  // Now loop through to get transformed X. Note that Adash is Tad and Bdash is T2 in Bartels and Stewarts algorithm
184  int p = N, q = N;
185  //cout << "Done" << endl
186  // << flush;
187  //cout << "Tad: " << Tad << endl;
188  //cout << "T2: " << T2 << endl;
189  Eigen::MatrixXcd Q1 = Vs.adjoint() * Q * Us;
190  //cout << "Done" << endl
191  // << flush;
192  // int bre;
193  for (int k = 0; k < p; k++) {
194  for (int l = 0; l < q; l++) {
195  Cd_t sum1 = Cd_t(0.0, 0.0), sum2 = Cd_t(0.0, 0.0);
196  for (int j = 0; j < k ; j++) {
197  sum1 += (Tad(k, j) * X1(j, l));
198  }
199  for (int i = 0; i < l ; i++) {
200  sum2 += (X1(k, i) * T2(i, l));
201  }
202  X1(k, l) = (-Q1(k, l) - sum1 - sum2) / (Tad(k, k) + T2(l, l));
203  }
204  }
205  X = Vs*X1*Us.adjoint();
206 
207  #ifdef DEBUG
208  cout << "Error in norm: " << (Tad*X1 + X1*T2 + Q1).norm() << endl;
209  cout << "Error: " << (Tad * X1 + X1 * T2 + Q1) << endl;
210  cout << "Error in norm: " << (A * X + X * B + Q).norm() << endl;
211  cout << "Error: " << (A * X + X * B + Q) << endl;
212 #endif
213  return X;
214 }
215 
217 Eigen::MatrixXcd dlyap(Eigen::MatrixXcd A, Eigen::MatrixXcd B, Eigen::MatrixXcd Q)
218 {
219  Eigen::MatrixXcd X, X1; // to be computed.
220  X1.setConstant(Cd_t(0.0, 0.0));
221 
222  // Compute the lower triangular Schur form of A. This is done by computing the Schur form of A' and then taking a conjugate transpose. Schur form is computed using LAPACK's zgees.
223  Eigen::MatrixXcd T, Aad;
224  Aad = A;
225  Aad.adjointInPlace();
226  T = Aad;
227  //cout << "A: " << A << endl;
228  //cout << "Aad: " << Aad << endl;
229 
230  char jobvs = 'V';
231  char sort = 'S';
232  int N = A.rows();
233  //cout << "N = " << N << endl;
234  X1.resize(N, N);
235  X.resize(N, N);
236  int lda = Aad.outerStride();
237  //cout << "lda = " << lda << endl;
238  int sdim = 1;
239  int ldvs = N;
240  Eigen::MatrixXcd W(N, 1), Vs(N, N);
241  int lwork = -1;
242  vector<Cd_t> workc;
243  workc.resize(1);
244  bool *bwork;
245  bwork = new bool[N];
246  double rwork[8 * N];
247  int info;
248  zgees_(&jobvs, &sort, &forZgees, &N, T.data(), &lda, &sdim, W.data(), Vs.data(), &ldvs, &workc[0], &lwork, &rwork[0], bwork, &info);
249  lwork = int(real(workc[0]));
250  workc.resize(lwork);
251  zgees_(&jobvs, &sort, &forZgees, &N, T.data(), &lda, &sdim, W.data(), Vs.data(), &ldvs, &workc[0], &lwork, &rwork[0], bwork, &info);
252  // see that the norm is zero
253  delete bwork;
254 #ifdef DEBUG
255  cout << "Error in norm: " << (Aad - Vs * T * Vs.adjoint()).norm() << endl;
256  cout << "Error in norm: " << (A - Vs * T.adjoint() * Vs.adjoint()).norm() << endl;
257 #endif
258  // Hence T is represented by its adjoint.
259  Eigen::MatrixXcd Tad = T.adjoint(), T2 = B, Us(N, N);
260 
261  // Now compute the schur decomposition of B:
262  zgees_(&jobvs, &sort, &forZgees, &N, T2.data(), &lda, &sdim, W.data(), Us.data(), &ldvs, &workc[0], &lwork, &rwork[0], bwork, &info);
263 #ifdef DEBUG
264  cout << "Error in norm: " << (B - Us * T2 * Us.adjoint()).norm() << endl;
265 #endif
266  // Now loop through to get transformed X. Note that Adash is Tad and Bdash is T2 in Bartels and Stewarts algorithm
267  int p = N, q = N;
268  //cout << "Done" << endl
269  // << flush;
270  //cout << "Tad: " << Tad << endl;
271  //cout << "T2: " << T2 << endl;
272  Eigen::MatrixXcd Q1 = Vs.adjoint() * Q * Us;
273  //cout << "Done" << endl
274  // << flush;
275  //int bre;
276  for (int k = 0; k < p; k++) {
277  for (int l = 0; l < q; l++) {
278  Cd_t sum1 = Cd_t(0.0, 0.0);
279  for (int j = 0; j < k+1; j++) {
280  for ( int i = 0; i < l+1; i++) {
281  sum1 += (Tad(k, j) * X1(j, i) * T2(i,l));
282  }
283  }
284  //for (int i = 0; i < l; i++)
285  //{
286  // sum2 += (X1(k, i) * T2(i, l));
287  //}
288  X1(k, l) = (-Q1(k, l) - sum1) / (Tad(k, k) * T2(l, l) - Cd_t(1.0,0.0));
289  }
290  }
291  X = Vs * X1 * Us.adjoint();
292 
293 #ifdef DEBUG
294  cout << "Error in norm: " << (Tad * X1* T2 - X1 + Q1).norm() << endl;
295  cout << "Error: " << (Tad * X1 * T2 - X1 + Q1) << endl;
296  cout << "Error in norm: " << (A * X * B - X + Q).norm() << endl;
297  cout << "Error: " << (A * X * B - X + Q) << endl;
298 #endif
299  return X;
300 }
301 
Eigen::MatrixXcd beta
Definition: lyap.h:36
Eigen::MatrixXcd lyap(Eigen::MatrixXcd A, Eigen::MatrixXcd B, Eigen::MatrixXcd Q)
Solves the Lyapunov/ sylvester equation: AX + XB + Q = 0.
Definition: lyap.h:133
bool criteria_(Cd_t alpha, Cd_t beta)
Definition: lyap.h:16
Definition: lyap.h:34
Eigen::MatrixXcd S
Definition: lyap.h:36
int info
Definition: lyap.h:37
void ztgsen_(int *IJOB, bool *WANTQ, bool *WANTZ, bool *SELECT, int *N, Cd_t *A, int *LDA, Cd_t *B, int *LDB, Cd_t *ALPHA, Cd_t *BETA, Cd_t *Q, int *LDQ, Cd_t *Z, int *LDZ, int *M, double *PL, double *PR, double *DIF, Cd_t *WORK, int *LWORK, int *IWORK, int *LIWORK, int *INFO)
bool forZgees(Cd_t a)
Definition: lyap.h:128
Eigen::MatrixXcd VSR
Definition: lyap.h:36
Eigen::MatrixXcd T
Definition: lyap.h:36
void zgges_(char *JOBVSL, char *JOBVSR, char *SORT, bool(*SELCTG)(Cd_t a, Cd_t b), int *N, Cd_t *A, int *LDA, Cd_t *B, int *LDB, int *SDIM, Cd_t *ALPHA, Cd_t *BETA, Cd_t *VSL, int *LDVSL, Cd_t *VSR, int *LDVSR, Cd_t *WORK, int *LWORK, double *RWORK, bool *BWORK, int *INFO)
Eigen::MatrixXcd VSL
Definition: lyap.h:36
void zgees_(char *JOBVS, char *SORT, bool(*SELCTG)(Cd_t a), int *N, Cd_t *A, int *LDA, int *SDIM, Cd_t *W, Cd_t *VS, int *LDVS, Cd_t *WORK, int *LWORK, double *RWORK, bool *BWORK, int *INFO)
OrdQz()
Definition: lyap.h:39
int N
Specifies number of Chebyshev polynomials, default N = 31.
Definition: sis.hpp:472
int M
Definition: lyap.h:38
Eigen::MatrixXcd dlyap(Eigen::MatrixXcd A, Eigen::MatrixXcd B, Eigen::MatrixXcd Q)
Solves the Lyapunov/ sylvester equation: AXB - X + Q = 0.
Definition: lyap.h:217
valarray< T > real(const valarray< complex< T > > &in)
real part of a complex valarray
Definition: sis.hpp:280
void compute(Eigen::MatrixXcd A, Eigen::MatrixXcd B)
Definition: lyap.h:45
Eigen::MatrixXcd alpha
Definition: lyap.h:36
complex< double > Cd_t
Definition: lyap.h:3
complex< double > Cd_t
Definition: Ex_05.cpp:17
OrdQz(Eigen::MatrixXcd A, Eigen::MatrixXcd B)
Definition: lyap.h:40