Subversion Repositories slepc-dev

Rev

Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2808 carcamgo 1
/*
2
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3
   SLEPc - Scalable Library for Eigenvalue Problem Computations
4
   Copyright (c) 2002-2011, Universitat Politecnica de Valencia, Spain
5
 
6
   This file is part of SLEPc.
7
 
8
   SLEPc is free software: you can redistribute it and/or modify it under  the
9
   terms of version 3 of the GNU Lesser General Public License as published by
10
   the Free Software Foundation.
11
 
12
   SLEPc  is  distributed in the hope that it will be useful, but WITHOUT  ANY
13
   WARRANTY;  without even the implied warranty of MERCHANTABILITY or  FITNESS
14
   FOR  A  PARTICULAR PURPOSE. See the GNU Lesser General Public  License  for
15
   more details.
16
 
17
   You  should have received a copy of the GNU Lesser General  Public  License
18
   along with SLEPc. If not, see <http://www.gnu.org/licenses/>.
19
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
20
*/
21
 
22
#include <slepc-private/psimpl.h>      /*I "slepcps.h" I*/
23
#include <slepcblaslapack.h>
24
 
2836 carcamgo 25
/*
26
  compute X = X - Y*s^{-1}*Y^T*B*X where s=Y^T*B*Y
27
  B diagonal (signature matrix)
28
*/
2808 carcamgo 29
#undef __FUNCT__  
2836 carcamgo 30
#define __FUNCT__ "PSOrthog_private"
31
static PetscErrorCode PSOrthog_private(PetscScalar *B, PetscScalar *Y, PetscReal ss, PetscScalar *X, PetscScalar *h,PetscInt n)
32
{
33
  PetscInt i;
34
  PetscScalar h_,r;
35
  PetscFunctionBegin;
36
  if(Y){
37
    h_ = 0.0; /* h_=(Y^Tdiag(B)*Y)^{-1}*Y^T*diag(B)*X*/
38
    for(i=0;i<n;i++){ h_+=Y[i]*B[i]*X[i];}
39
    h_ /= ss;
40
    for(i=0;i<n;i++){X[i] -= h_*Y[i];} /* X = X-h_*Y */
41
    /* repeat */
42
    r = 0.0;
43
    for(i=0;i<n;i++){ r+=Y[i]*B[i]*X[i];}
44
    r /= ss;
45
    for(i=0;i<n;i++){X[i] -= r*Y[i];}
46
    h_ += r;
47
  }else h_ = 0.0;
48
  if(h) *h = h_;
49
  PetscFunctionReturn(0);
50
}
51
/* normalization with a indefinite norm */
52
#undef __FUNCT__
53
#define __FUNCT__ "PSNormIndef_private"
2838 carcamgo 54
static PetscErrorCode PSNormIndef_private(PetscReal *s,PetscScalar *X, PetscScalar *norm,PetscInt n)
2836 carcamgo 55
{
56
  PetscInt      i;
57
  PetscReal     norm_;
58
  /* s-normalization */
59
  norm_ = 0.0;
2838 carcamgo 60
  for(i=0;i<n;i++){norm_ += X[i]*s[i]*X[i];}
2836 carcamgo 61
  if(norm_<0){norm_ = -PetscSqrtReal(-norm_);}
62
  else {norm_ = PetscSqrtReal(norm_);}
63
  for(i=0;i<n;i++)X[i] /= norm_;
64
  if(norm) *norm = norm_;
65
  PetscFunctionReturn(0);
66
}
67
 
68
 
69
#undef __FUNCT__  
2808 carcamgo 70
#define __FUNCT__ "PSAllocate_GHIEP"
71
PetscErrorCode PSAllocate_GHIEP(PS ps,PetscInt ld)
72
{
73
  PetscErrorCode ierr;
74
 
75
  PetscFunctionBegin;
76
  ierr = PSAllocateMat_Private(ps,PS_MAT_A);CHKERRQ(ierr);
2836 carcamgo 77
  ierr = PSAllocateMat_Private(ps,PS_MAT_B);CHKERRQ(ierr);
2808 carcamgo 78
  ierr = PSAllocateMat_Private(ps,PS_MAT_Q);CHKERRQ(ierr);
79
  ierr = PSAllocateMatReal_Private(ps,PS_MAT_T);CHKERRQ(ierr);
80
  PetscFunctionReturn(0);
81
}
82
 
83
#undef __FUNCT__  
2836 carcamgo 84
#define __FUNCT__ "PSSwitchFormat_GHIEP"
85
PetscErrorCode PSSwitchFormat_GHIEP(PS ps,PetscBool tocompact)
86
{
87
  PetscReal     *T;
88
  PetscScalar   *A,*B;
89
  PetscInt      i,k,ld;
90
 
91
  PetscFunctionBegin;
92
  A = ps->mat[PS_MAT_A];
93
  B = ps->mat[PS_MAT_B];
94
  T = ps->rmat[PS_MAT_T];
95
  k = ps->k;
96
  ld = ps->ld;
97
  if(tocompact){ /* switch from dense (arrow) to compact */
98
    for(i=0; i < k; i++){
99
      T[i] = PetscRealPart(A[i*(1+ld)]);
100
      T[ld +i] = PetscRealPart(A[k+i*ld]);
101
      T[2*ld +i] = PetscRealPart(B[i*(1+ld)]);
102
    }
103
    for(i=k; i < ps->n; i++){
104
      T[i] = PetscRealPart(A[i*(1+ld)]);
105
      T[ld +i] = PetscRealPart(A[i*(ld+1)+1]);
106
      T[2*ld +i] = PetscRealPart(B[i*(1+ld)]);
107
    }
108
  }else{ /* switch from compact (arrow) to dense */
109
    for(i=0; i < k; i++){
110
      A[i*(1+ld)] = T[i];
111
      A[k+i*ld] = T[ld+i];
112
      A[i+k*ld] = T[ld+i];
113
      B[i*(1+ld)] = T[2*ld+i];
114
    }
115
    A[k*(ld+1)] = T[k];
116
    B[k*(ld+1)] = T[2*ld+k];
117
    for(i=k+1; i < ps->n; i++){
118
      A[i*(1+ld)] = T[i];
119
      A[i*ld + i-1] = T[i-1+ld];
120
      A[(i-1)*ld + i] = T[i-1+ld];
121
      B[i*(1+ld)] = T[2*ld+i];
122
    }
123
  }
124
  PetscFunctionReturn(0);
125
}
126
 
127
 
128
#undef __FUNCT__  
2808 carcamgo 129
#define __FUNCT__ "PSView_GHIEP"
130
PetscErrorCode PSView_GHIEP(PS ps,PetscViewer viewer)
131
{
132
  PetscErrorCode    ierr;
133
  PetscViewerFormat format;
134
  PetscInt          i,j,r,c;
135
  PetscReal         value;
2836 carcamgo 136
  const char *methodname[] = {
137
                     "QR method",
138
                     "QR + Inverse Iteration"
139
  };
2808 carcamgo 140
 
141
  PetscFunctionBegin;
142
  ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
143
  if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
2836 carcamgo 144
    ierr = PetscViewerASCIIPrintf(viewer,"solving the problem with: %s\n",methodname[ps->method]);CHKERRQ(ierr);
2808 carcamgo 145
    PetscFunctionReturn(0);
146
  }
147
  if (ps->compact) {
148
    ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
149
    if (format == PETSC_VIEWER_ASCII_MATLAB) {
150
      ierr = PetscViewerASCIIPrintf(viewer,"%% Size = %D %D\n",ps->n,ps->n);CHKERRQ(ierr);
151
      ierr = PetscViewerASCIIPrintf(viewer,"zzz = zeros(%D,3);\n",3*ps->n);CHKERRQ(ierr);
152
      ierr = PetscViewerASCIIPrintf(viewer,"zzz = [\n");CHKERRQ(ierr);
153
      for (i=0;i<ps->n;i++) {
154
        ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e\n",i+1,i+1,*(ps->rmat[PS_MAT_T]+i));CHKERRQ(ierr);
155
      }
156
      for (i=0;i<ps->n-1;i++) {
157
        r = PetscMax(i+2,ps->k+1);
158
        c = i+1;
159
        ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e\n",r,c,*(ps->rmat[PS_MAT_T]+ps->ld+i));CHKERRQ(ierr);
160
        ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e\n",c,r,*(ps->rmat[PS_MAT_T]+ps->ld+i));CHKERRQ(ierr);
161
      }
162
      ierr = PetscViewerASCIIPrintf(viewer,"];\n%s = spconvert(zzz);\n",PSMatName[PS_MAT_T]);CHKERRQ(ierr);
2836 carcamgo 163
 
164
      ierr = PetscViewerASCIIPrintf(viewer,"%% Size = %D %D\n",ps->n,ps->n);CHKERRQ(ierr);
165
      ierr = PetscViewerASCIIPrintf(viewer,"omega = zeros(%D,3);\n",3*ps->n);CHKERRQ(ierr);
166
      ierr = PetscViewerASCIIPrintf(viewer,"omega = [\n");CHKERRQ(ierr);
167
      for (i=0;i<ps->n;i++) {
168
        ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e\n",i+1,i+1,*(ps->rmat[PS_MAT_T]+2*(ps->ld)+i));CHKERRQ(ierr);
169
      }
170
      ierr = PetscViewerASCIIPrintf(viewer,"];\n%s = spconvert(omega);\n",PSMatName[PS_MAT_B]);CHKERRQ(ierr);
171
 
2808 carcamgo 172
    } else {
2836 carcamgo 173
      ierr = PetscViewerASCIIPrintf(viewer,"T\n");CHKERRQ(ierr);
2808 carcamgo 174
      for (i=0;i<ps->n;i++) {
175
        for (j=0;j<ps->n;j++) {
176
          if (i==j) value = *(ps->rmat[PS_MAT_T]+i);
177
          else if ((i<ps->k && j==ps->k) || (i==ps->k && j<ps->k)) value = *(ps->rmat[PS_MAT_T]+ps->ld+PetscMin(i,j));
178
          else if (i==j+1 && i>ps->k) value = *(ps->rmat[PS_MAT_T]+ps->ld+i-1);
179
          else if (i+1==j && j>ps->k) value = *(ps->rmat[PS_MAT_T]+ps->ld+j-1);
180
          else value = 0.0;
181
          ierr = PetscViewerASCIIPrintf(viewer," %18.16e ",value);CHKERRQ(ierr);
182
        }
183
        ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
184
      }
2836 carcamgo 185
      ierr = PetscViewerASCIIPrintf(viewer,"omega\n");CHKERRQ(ierr);
186
      for (i=0;i<ps->n;i++) {
187
        for (j=0;j<ps->n;j++) {
188
          if (i==j) value = *(ps->rmat[PS_MAT_T]+2*(ps->ld)+i);
189
          else value = 0.0;
190
          ierr = PetscViewerASCIIPrintf(viewer," %18.16e ",value);CHKERRQ(ierr);
191
        }
192
        ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
193
      }
2808 carcamgo 194
    }
195
    ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
196
    ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
197
  } else {
2836 carcamgo 198
    ierr = PSViewMat_Private(ps,viewer,PS_MAT_A);CHKERRQ(ierr);
199
    ierr = PSViewMat_Private(ps,viewer,PS_MAT_B);CHKERRQ(ierr);
2808 carcamgo 200
  }
201
  if (ps->state>PS_STATE_INTERMEDIATE) {
202
    ierr = PSViewMat_Private(ps,viewer,PS_MAT_Q);CHKERRQ(ierr);
203
  }
204
  PetscFunctionReturn(0);
205
}
206
 
207
#undef __FUNCT__  
2836 carcamgo 208
#define __FUNCT__ "PSVectors_GHIEP_Eigen_Some"
209
PetscErrorCode PSVectors_GHIEP_Eigen_Some(PS ps,PetscInt *k,PetscReal *rnorm,PetscBool left)
210
{
211
 
212
  /// to complete  /////
213
  PetscScalar    *Q = ps->mat[PS_MAT_Q];
214
  PetscReal      s1,s2,d1,d2,b;
215
  PetscInt       ld = ps->ld,k_;
216
  PetscErrorCode ierr;
217
  PSMatType      mat;
218
 
219
  PetscFunctionBegin;
220
  if (left) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented for left eigenvectors");
221
  else mat = PS_MAT_Q;
222
  k_ = *k;
223
  if(k_ < ps->n-1){
224
   b = (ps->compact)?*(ps->rmat[PS_MAT_T]+ld+k_):*(ps->mat[PS_MAT_A]+(k_+1)+ld*k_);
225
  }else b = 0;
226
  if(b==0){/* real */
227
    ierr = PetscMemcpy(ps->mat[mat]+(k_)*ld,Q+(k_)*ld,ld*sizeof(PetscScalar));CHKERRQ(ierr);
228
  }else{ /* complex block */
229
    if(ps->compact){
230
      s1 = *(ps->rmat[PS_MAT_T]+2*ld+k_);
231
      d1 = *(ps->rmat[PS_MAT_T]+k_);
232
      s2 = *(ps->rmat[PS_MAT_T]+2*ld+k_+1);
233
      d2 = *(ps->rmat[PS_MAT_T]+k_+1);
234
    }else{
235
      s1 = PetscRealPart(*(ps->mat[PS_MAT_B]+2*ld+k_));
236
      d1 = PetscRealPart(*(ps->mat[PS_MAT_A]+k_));
237
      s2 = PetscRealPart(*(ps->mat[PS_MAT_B]+2*ld+k_+1));
238
      d2 = PetscRealPart(*(ps->mat[PS_MAT_A]+k_+1));
239
    }
240
  }
241
  if (rnorm) *rnorm = PetscAbsScalar(Q[ps->n-1+(k_)*ld]);
242
  PetscFunctionReturn(0);
243
}
244
 
245
#undef __FUNCT__  
2808 carcamgo 246
#define __FUNCT__ "PSVectors_GHIEP"
247
PetscErrorCode PSVectors_GHIEP(PS ps,PSMatType mat,PetscInt *k,PetscReal *rnorm)
248
{
2836 carcamgo 249
  PetscInt       i;
250
  PetscBool      left;
2808 carcamgo 251
  PetscErrorCode ierr;
252
 
253
  PetscFunctionBegin;
254
  if (ps->state<PS_STATE_CONDENSED) SETERRQ(((PetscObject)ps)->comm,PETSC_ERR_ORDER,"Must call PSSolve() first");
255
  switch (mat) {
2836 carcamgo 256
    case PS_MAT_Y:
257
      left = PETSC_TRUE;
2808 carcamgo 258
    case PS_MAT_X:
2836 carcamgo 259
      if (k){
260
        ierr = PSVectors_GHIEP_Eigen_Some(ps,k,rnorm,left);CHKERRQ(ierr);
261
      }else{
262
        for(i=0; i<ps->n; i++){
263
          ierr = PSVectors_GHIEP_Eigen_Some(ps,&i,rnorm,left);CHKERRQ(ierr);
264
        }
2808 carcamgo 265
      }
266
      break;
267
    case PS_MAT_U:
268
    case PS_MAT_VT:
269
      SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented yet");
270
      break;
271
    default:
272
      SETERRQ(((PetscObject)ps)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Invalid mat parameter");
273
  }
274
  PetscFunctionReturn(0);
275
}
276
 
2836 carcamgo 277
#undef __FUNCT__
278
#define __FUNCT__ "PSComplexEigs_private"
279
static PetscErrorCode PSComplexEigs_private(PS ps, PetscInt n0, PetscInt n1, PetscScalar *wr, PetscScalar *wi){
280
  PetscInt      j,ld;
281
  PetscScalar   *A,*B;
282
  PetscReal     *d,*e,*s,d1,d2,e1,e2,disc;
283
 
284
  PetscFunctionBegin;
285
  ld = ps->ld;
286
  if (ps->compact){
287
    d = ps->rmat[PS_MAT_T];
288
    e = d + ld;
289
    s = e + ld;
290
    for (j=n0;j<n1;j++) {
291
      if (j==n1-1 || e[j] == 0.0) {
292
        /* real eigenvalue */
293
        wr[j] = d[j]/s[j];
294
        wi[j] = 0.0 ;
295
      } else {
296
      /* diagonal block */
297
        d1 = d[j]/s[j]; d2 = d[j+1]/s[j+1]; e1 = e[j]/s[j+1]; e2 = e[j]/s[j];
298
        wr[j] = (d1+d2)/2;  wr[j+1] = wr[j];
299
        disc = (d1-d2)*(d1-d2) - (e1-e2)*(e1-e2);
300
        if (disc<0){ /* complex eigenvalues */
301
          wi[j] = PetscSqrtReal(-disc)/2; wi[j+1] = -wi[j];
302
        }else{ /* real eigenvalues */
303
          disc = PetscSqrtReal(disc)/2;
304
          wr[j] = wr[j]+disc; wr[j+1]=wr[j+1]-disc; wi[j] = 0.0; wi[j+1] = 0.0;
305
        }
306
        j++;
307
      }
308
    }
309
  }else{
310
    A = ps->mat[PS_MAT_A];
311
    B = ps->mat[PS_MAT_B];
312
    for (j=n0;j<n1;j++) {
313
      if (j==n1-1 || A[(j+1)+j*ld] == 0.0) {
314
        /* real eigenvalue */
315
        wr[j] = A[j+j*ld]/B[j+j*ld];
316
        wi[j] = 0.0 ;
317
      } else {
318
      /* diagonal block */
319
        d1 = A[j+j*ld]/B[j+j*ld]; d2 = A[(j+1)+(j+1)*ld]/B[(j+1)+(j+1)*ld];
320
        e1 = A[j+(j+1)*ld]/B[j+j*ld]; e2 = A[(j+1)+j*ld]/B[(j+1)+(j+1)*ld];
321
        wr[j] = (d1+d2)/2;  wr[j+1] = wr[j];
322
        disc = (d1-d2)*(d1-d2) - (e1-e2)*(e1-e2);
323
        if (disc<0){ /* complex eigenvalues */
324
          wi[j] = PetscSqrtReal(-disc)/2; wi[j+1] = -wi[j];
325
        }else{ /* real eigenvalues */
326
          disc = PetscSqrtReal(disc)/2;
327
          wr[j] = wr[j]+disc; wr[j+1]=wr[j+1]-disc; wi[j] = 0.0; wi[j+1] = 0.0;
328
        }
329
        j++;
330
      }
331
    }
332
  }
333
  PetscFunctionReturn(0);
334
}
335
 
336
 
2808 carcamgo 337
#undef __FUNCT__  
2836 carcamgo 338
#define __FUNCT__ "PSSolve_GHIEP_QR_II"
339
PetscErrorCode PSSolve_GHIEP_QR_II(PS ps,PetscScalar *wr,PetscScalar *wi)
2808 carcamgo 340
{
2837 jroman 341
#if defined(SLEPC_MISSING_LAPACK_GEHRD) || defined(SLEPC_MISSING_LAPACK_ORGHR) || defined(PETSC_MISSING_LAPACK_HSEQR) || defined(PETSC_MISSING_LAPACK_HSEIN)
2808 carcamgo 342
  PetscFunctionBegin;
2837 jroman 343
  SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"GEHRD/ORGHR/HSEQR/HSEIN - Lapack routines are unavailable.");
2808 carcamgo 344
#else
345
  PetscErrorCode ierr;
2836 carcamgo 346
  PetscInt       i,j,off;
347
  PetscBLASInt   lwork,info,n1,one,ld,*select,*infoC,mout;
348
  PetscScalar    *A,*B,*W,*Q,*work,*tau,zero,oneS;
349
  PetscScalar    h;
350
  PetscReal      *d,*e,*s,*ss,toldeg=1e-5,d1,d2;
2808 carcamgo 351
 
352
  PetscFunctionBegin;
2836 carcamgo 353
  n1  = PetscBLASIntCast(ps->n - ps->l);
354
  one = PetscBLASIntCast(1);
355
  oneS = 1.0;
356
  zero = 0.0;
2808 carcamgo 357
  ld = PetscBLASIntCast(ps->ld);
2836 carcamgo 358
  off = ps->l + ps->l*ld;
359
  A  = ps->mat[PS_MAT_A];
360
  B  = ps->mat[PS_MAT_B];
361
  Q = ps->mat[PS_MAT_Q];
2808 carcamgo 362
  d  = ps->rmat[PS_MAT_T];
2836 carcamgo 363
  e  = ps->rmat[PS_MAT_T] + ld;
364
  s  = ps->rmat[PS_MAT_T] + 2*ld;
365
  ierr = PSAllocateWork_Private(ps,ld+ld*ld,ld,ld*2);CHKERRQ(ierr);
366
  tau  = ps->work;
367
  work = ps->work+ld;
368
  lwork = ld*ld;
369
  select = ps->iwork;
370
  infoC = ps->iwork + ld;
371
   /* initialize orthogonal matrix */
372
  ierr = PetscMemzero(Q,ld*ld*sizeof(PetscScalar));CHKERRQ(ierr);
373
  for (i=0;i< ps->n;i++)
374
    Q[i+i*ld] = 1.0;
375
  if (n1 == 1) {
376
    if(ps->compact){
377
      wr[ps->l] = d[ps->l]/s[ps->l]; wi[ps->l] = 0.0;
378
    }else{
379
      d[ps->l] = PetscRealPart(A[off]); s[ps->l] = PetscRealPart(B[off]);
380
      wr[ps->l] = d[ps->l]/s[ps->l]; wi[ps->l] = 0.0;  
381
    }
382
    PetscFunctionReturn(0);
383
  }
2808 carcamgo 384
 
2836 carcamgo 385
  /* form standard problem in A */
2808 carcamgo 386
  if (ps->compact) {
2836 carcamgo 387
    ierr = PetscMemzero(A,ld*ld*sizeof(PetscScalar));CHKERRQ(ierr);
388
    for(i=ps->l; i < ps->k; i++){
389
      A[i+i*ld] = d[i]/s[i];
390
      A[ps->k+i*ld] = e[i]/s[ps->k];
391
      A[i + ps->k*ld] = e[i]/s[i];
392
    }
393
    A[ps->k + ps->k*ld] = d[ps->k]/s[ps->k];
394
    for(i=ps->k+1; i < ps->n; i++){
395
      A[i+i*ld] = d[i]/s[i];
396
      A[(i-1)+i*ld] = e[i-1]/s[i-1];
397
      A[i+(i-1)*ld] = e[i-1]/s[i];
398
    }
399
  }else{
400
    for(j=ps->l; j<ps->n; j++){
401
      for(i=ps->l; i<ps->n; i++){
402
        A[i+j*ld] /= B[i+i*ld];
403
      }
404
    }
405
  }
406
 
407
  /* reduce to upper Hessemberg form */
408
  if (ps->state<PS_STATE_INTERMEDIATE) {
409
  LAPACKgehrd_(&n1,&one,&n1,A+off,&ld,tau,work,&lwork,&info);
410
    if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xGEHRD %d",&info);
411
    for (j=ps->l;j<ps->n-1;j++) {
412
      for (i=j+2;i<ps->n;i++) {
413
        Q[i+j*ld] = A[i+j*ld];
414
        A[i+j*ld] = 0.0;
415
      }
416
    }
417
    LAPACKorghr_(&n1,&one,&n1,Q+off,&ld,tau,work,&lwork,&info);
418
    if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xORGHR %d",&info);
419
  }
420
 
421
  /* Compute Eigenvalues (QR)*/
422
  ierr = PSAllocateMat_Private(ps,PS_MAT_W);CHKERRQ(ierr);
423
  W = ps->mat[PS_MAT_W];
424
  ierr = PetscMemcpy(W,A,ld*ld*sizeof(PetscScalar));CHKERRQ(ierr);
425
 
426
#if !defined(PETSC_USE_COMPLEX)
427
  LAPACKhseqr_("E","N",&n1,&one,&n1,W+off,&ld,wr+ps->l,wi+ps->l,PETSC_NULL,&ld,work,&lwork,&info);
428
#else
429
  LAPACKhseqr_("E","N",&n1,&one,&n1,W+off,&ld,wr+ps->l,PETSC_NULL,&ld,work,&lwork,&info);
430
#endif
431
  if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xHSEQR %d",&info);
2808 carcamgo 432
 
2836 carcamgo 433
  /* Compute Eigenvectors with Inverse Iteration */
434
#if !defined(PETSC_USE_COMPLEX)  
435
  for(i=0;i<n1;i++)select[i]=1;
2837 jroman 436
  LAPACKhsein_("R","N","N",select,&n1,A+off,&ld,wr+ps->l,wi+ps->l,PETSC_NULL,&ld,W+off,&ld,&n1,&mout,work,PETSC_NULL,infoC,&info);
2836 carcamgo 437
#else
438
  SETERRQ1(((PetscObject)ps)->comm,PETSC_ERR_SUP," In PSSolve, QR + II method not implemented for complex indefinite problems",info);
439
#endif
440
  /* accumulate previous Q */
441
  if (ps->state<PS_STATE_INTERMEDIATE) {  
442
    BLASgemm_("N","N",&n1,&n1,&n1,&oneS,Q+off,&ld,W+off,&ld,&zero,A+off,&ld);
443
    ierr = PSCopyMatrix_Private(ps,PS_MAT_Q,PS_MAT_A);CHKERRQ(ierr);
444
  }else {ierr = PSCopyMatrix_Private(ps,PS_MAT_Q,PS_MAT_W);CHKERRQ(ierr);}
445
  /* compute real s-orthonormal base */
446
  ss = ps->rwork;
447
  for(i=ps->l;i<ps->n;i++){
448
    if(wi[i]==0.0){/* real */
449
      for(j=i-1;j>=ps->l;j--){
450
         /* s-orthogonalization with close eigenvalues */
451
        if(wi[j]==0 && PetscAbsReal(wr[j]-wr[i])<toldeg){
452
          ierr = PSOrthog_private(s+ps->l, Q+j*ld+ps->l, ss[j],Q+i*ld+ps->l, PETSC_NULL,n1);CHKERRQ(ierr);
453
        }
2808 carcamgo 454
      }
2836 carcamgo 455
      ierr = PSNormIndef_private(s+ps->l,Q+i*ld+ps->l,&h,n1);CHKERRQ(ierr);
456
      ss[i] = (h<0)?-1:1;
457
      d[i] = wr[i]*ss[i]; e[i] = 0.0;
458
    }else{
459
      for(j=i-1;j>=ps->l;j--){
460
        /* s-orthogonalization of Qi and Qi+1*/
461
        if(PetscAbsReal(wr[j]-wr[i])<toldeg && PetscAbsReal(PetscAbsReal(wi[j])-PetscAbsReal(wi[i]))<toldeg){
2837 jroman 462
          ierr = PSOrthog_private(s+ps->l, Q+j*ld+ps->l, ss[j],Q+i*ld+ps->l, PETSC_NULL,n1);CHKERRQ(ierr);
2836 carcamgo 463
          ierr = PSOrthog_private(s+ps->l, Q+j*ld+ps->l, ss[j],Q+(i+1)*ld+ps->l, PETSC_NULL,n1);CHKERRQ(ierr);
464
        }
465
      }
466
      ierr = PSNormIndef_private(s+ps->l,Q+i*ld+ps->l,&d1,n1);CHKERRQ(ierr);
467
      ss[i] = (d1<0)?-1:1;
468
      ierr = PSOrthog_private(s+ps->l, Q+i*ld+ps->l, ss[i],Q+(i+1)*ld+ps->l, &h,n1);CHKERRQ(ierr);
469
      ierr = PSNormIndef_private(s+ps->l,Q+(i+1)*ld+ps->l,&d2,n1);CHKERRQ(ierr);
470
      ss[i+1] = (d2<0)?-1:1;
471
      d[i] = (wr[i]-wi[i]*h/d1)*ss[i]; d[i+1] = (wr[i]+wi[i]*h/d1)*ss[i+1];
472
      e[i] = wi[i]*d2/d1*ss[i]; e[i+1] = 0.0;
473
      i++;
474
    }
475
  }
476
  for(i=ps->l;i<ps->n;i++) s[i] = ss[i];
477
  ps->k = ps->l;
2808 carcamgo 478
 
2836 carcamgo 479
  /* The result is stored in both places (compact and regular) */
480
  if (!ps->compact) {
481
    ierr = PetscMemzero(A+ps->l*ld,n1*ld*sizeof(PetscScalar));CHKERRQ(ierr);
482
    ierr = PSSwitchFormat_GHIEP(ps,PETSC_FALSE);CHKERRQ(ierr);
483
  }
484
  /* Recover eigenvalues from diagonal */
485
  //ierr = PSComplexEigs_private(ps, 0, ps->n, wr, wi);CHKERRQ(ierr);
486
#endif
487
    PetscFunctionReturn(0);
488
}
2808 carcamgo 489
 
490
 
2836 carcamgo 491
/*
492
Parameters:
493
ps (In/Out): On input the ps object contains (T,S) symmetric pencil with S  indefinite diagonal (signature matrix)
494
        On output ps contains Q and (D,SS), equivalent symmetric pencil whit D block diagonal and SS diagonal,
495
        verifying: Q^T*T*Q = D and Q^T*S*Q = SS
496
wr,wi (Out): eigenvalues of equivalent pencils
2808 carcamgo 497
 
2836 carcamgo 498
(Modified only rows and columns ps->l to ps->n in T and S)
499
*/
500
#undef __FUNCT__  
501
#define __FUNCT__ "PSSolve_GHIEP_QR"
502
PetscErrorCode PSSolve_GHIEP_QR(PS ps,PetscScalar *wr,PetscScalar *wi)
503
{
504
#if defined(SLEPC_MISSING_LAPACK_GEHRD) || defined(SLEPC_MISSING_LAPACK_ORGHR) || defined(PETSC_MISSING_LAPACK_HSEQR)
505
  PetscFunctionBegin;
506
  SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"GEHRD/ORGHR/HSEQR - Lapack routines are unavailable.");
507
#else
508
  PetscErrorCode ierr;
509
  PetscInt       i,j,off;
510
  PetscBLASInt   lwork,info,n1,one,mout,ld;
511
  PetscScalar    *A,*B,*Q,*work,*tau;
512
  PetscScalar    h;
513
  PetscReal      *d,*e,*s,*ss,toldeg=1e-5,d1,d2;
2808 carcamgo 514
 
2836 carcamgo 515
  PetscFunctionBegin;
516
  n1  = PetscBLASIntCast(ps->n - ps->l);
517
  one = PetscBLASIntCast(1);
518
  ld = PetscBLASIntCast(ps->ld);
519
  off = ps->l + ps->l*ld;
520
  A  = ps->mat[PS_MAT_A];
521
  B  = ps->mat[PS_MAT_B];
522
  Q = ps->mat[PS_MAT_Q];
523
  d  = ps->rmat[PS_MAT_T];
524
  e  = ps->rmat[PS_MAT_T] + ld;
525
  s  = ps->rmat[PS_MAT_T] + 2*ld;
526
  ierr = PSAllocateWork_Private(ps,ld+ld*ld,ld,0);CHKERRQ(ierr);
527
  tau  = ps->work;
528
  work = ps->work+ld;
529
  lwork = ld*ld;
2808 carcamgo 530
 
2836 carcamgo 531
   /* initialize orthogonal matrix */
532
  ierr = PetscMemzero(Q,ld*ld*sizeof(PetscScalar));CHKERRQ(ierr);
533
  for (i=0;i< ps->n;i++)
534
    Q[i+i*ld] = 1.0;
535
  if (n1 == 1) {
536
    if(ps->compact){
537
      wr[ps->l] = d[ps->l]/s[ps->l]; wi[ps->l] = 0.0;
538
    }else{
539
      d[ps->l] = PetscRealPart(A[off]); s[ps->l] = PetscRealPart(B[off]);
540
      wr[ps->l] = d[ps->l]/s[ps->l]; wi[ps->l] = 0.0;  
2808 carcamgo 541
    }
2836 carcamgo 542
    PetscFunctionReturn(0);
2808 carcamgo 543
  }
544
 
2836 carcamgo 545
  /* form standard problem in A */
2808 carcamgo 546
  if (ps->compact) {
547
    ierr = PetscMemzero(A,ld*ld*sizeof(PetscScalar));CHKERRQ(ierr);
2836 carcamgo 548
    for(i=ps->l; i < ps->k; i++){
549
      A[i+i*ld] = d[i]/s[i];
550
      A[ps->k+i*ld] = e[i]/s[ps->k];
551
      A[i + ps->k*ld] = e[i]/s[i];
552
    }
553
    A[ps->k + ps->k*ld] = d[ps->k]/s[ps->k];
554
    for(i=ps->k+1; i < ps->n; i++){
555
      A[i+i*ld] = d[i]/s[i];
556
      A[(i-1)+i*ld] = e[i-1]/s[i-1];
557
      A[i+(i-1)*ld] = e[i-1]/s[i];
558
    }
559
  }else{
560
    for(j=ps->l; j<ps->n; j++){
561
      for(i=ps->l; i<ps->n; i++){
562
        A[i+j*ld] /= B[i+i*ld];
563
      }
564
    }
2808 carcamgo 565
  }
2836 carcamgo 566
 
567
  /* reduce to upper Hessemberg form */
568
  if (ps->state<PS_STATE_INTERMEDIATE) {
569
  LAPACKgehrd_(&n1,&one,&n1,A+off,&ld,tau,work,&lwork,&info);
570
    if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xGEHRD %d",&info);
571
    for (j=ps->l;j<ps->n-1;j++) {
572
      for (i=j+2;i<ps->n;i++) {
573
        Q[i+j*ld] = A[i+j*ld];
574
        A[i+j*ld] = 0.0;
575
      }
576
    }
577
    LAPACKorghr_(&n1,&one,&n1,Q+off,&ld,tau,work,&lwork,&info);
578
    if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xORGHR %d",&info);
579
  }
2808 carcamgo 580
 
2836 carcamgo 581
  /* compute the real Schur form */
582
#if !defined(PETSC_USE_COMPLEX)
583
  LAPACKhseqr_("S","V",&n1,&one,&n1,A+off,&ld,wr+ps->l,wi+ps->l,Q+off,&ld,work,&lwork,&info);
584
#else
585
  LAPACKhseqr_("S","V",&n1,&one,&n1,A+off,&ld,wr,Q+off,&ld,work,&lwork,&info);
586
#endif
587
  if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xHSEQR %d",&info);
588
 
589
  /* compute eigenvectors */
590
#if !defined(PETSC_USE_COMPLEX)
591
  LAPACKtrevc_("R","B",PETSC_NULL,&n1,A+off,&ld,PETSC_NULL,&ld,Q+off,&ld,&n1,&mout,ps->work,&info);
592
#else
593
  LAPACKtrevc_("R","B",PETSC_NULL,&n1,A+off,&ld,PETSC_NULL,&ld,Q+off,&ld,&n1,&mout,work,ps->rwork,&info);
594
#endif
595
  if (info) SETERRQ1(((PetscObject)ps)->comm,PETSC_ERR_LIB,"Error in Lapack xTREVC %i",&info);
596
  /* compute real s-orthonormal base */
597
#if !defined(PETSC_USE_COMPLEX)
598
  ss = ps->rwork;
599
  for(i=ps->l;i<ps->n;i++){
600
    if(wi[i]==0.0){/* real */
601
      for(j=i-1;j>=ps->l;j--){
602
         /* s-orthogonalization with close eigenvalues */
603
        if(wi[j]==0 && PetscAbsReal(wr[j]-wr[i])<toldeg){
604
          ierr = PSOrthog_private(s+ps->l, Q+j*ld+ps->l, ss[j],Q+i*ld+ps->l, PETSC_NULL,n1);CHKERRQ(ierr);
605
        }
606
      }
607
      ierr = PSNormIndef_private(s+ps->l,Q+i*ld+ps->l,&h,n1);CHKERRQ(ierr);
608
      ss[i] = (h<0)?-1:1;
609
      d[i] = wr[i]*ss[i]; e[i] = 0.0;
610
    }else{
611
      for(j=i-1;j>=ps->l;j--){
612
        /* s-orthogonalization of Qi and Qi+1*/
613
        if(PetscAbsReal(wr[j]-wr[i])<toldeg && PetscAbsReal(PetscAbsReal(wi[j])-PetscAbsReal(wi[i]))<toldeg){
614
          ierr =  PSOrthog_private(s+ps->l, Q+j*ld+ps->l, ss[j],Q+i*ld+ps->l, PETSC_NULL,n1);CHKERRQ(ierr);
615
          ierr = PSOrthog_private(s+ps->l, Q+j*ld+ps->l, ss[j],Q+(i+1)*ld+ps->l, PETSC_NULL,n1);CHKERRQ(ierr);
616
        }
617
      }
618
      ierr = PSNormIndef_private(s+ps->l,Q+i*ld+ps->l,&d1,n1);CHKERRQ(ierr);
619
      ss[i] = (d1<0)?-1:1;
620
      ierr = PSOrthog_private(s+ps->l, Q+i*ld+ps->l, ss[i],Q+(i+1)*ld+ps->l, &h,n1);CHKERRQ(ierr);
621
      ierr = PSNormIndef_private(s+ps->l,Q+(i+1)*ld+ps->l,&d2,n1);CHKERRQ(ierr);
622
      ss[i+1] = (d2<0)?-1:1;
623
      d[i] = (wr[i]-wi[i]*h/d1)*ss[i]; d[i+1] = (wr[i]+wi[i]*h/d1)*ss[i+1];
624
      e[i] = wi[i]*d2/d1*ss[i]; e[i+1] = 0.0;
625
      i++;
626
    }
627
  }
628
  for(i=ps->l;i<ps->n;i++) s[i] = ss[i];
629
  ps->k = ps->l;
2808 carcamgo 630
  /* The result is stored in both places (compact and regular) */
2836 carcamgo 631
  if (!ps->compact) {
632
    ierr = PetscMemzero(A+ps->l*ld,n1*ld*sizeof(PetscScalar));CHKERRQ(ierr);
633
    ierr = PSSwitchFormat_GHIEP(ps,PETSC_FALSE);CHKERRQ(ierr);
634
  }
635
  /* Recover eigenvalues from diagonal */
636
  //ierr = PSComplexEigs_private(ps, 0, ps->n, wr, wi);CHKERRQ(ierr);
637
#else
638
  SETERRQ1(((PetscObject)ps)->comm,PETSC_ERR_SUP," In PSSolve, QR method not implemented for complex indefinite problems",info);
639
#endif
2808 carcamgo 640
  PetscFunctionReturn(0);
641
#endif
642
}
643
 
2836 carcamgo 644
#undef __FUNCT__
645
#define __FUNCT__ "PSSortEigenvalues_Private"
646
static PetscErrorCode PSSortEigenvalues_Private(PS ps,PetscScalar *wr,PetscScalar *wi,PetscInt *perm,PetscErrorCode (*comp_func)(PetscScalar,PetscScalar,PetscScalar,PetscScalar,PetscInt*,void*),void *comp_ctx)
647
{
648
  PetscErrorCode ierr;
649
  PetscScalar    re,im;
650
  PetscInt       i,j,result,tmp1,tmp2,d=1;
651
 
652
  PetscFunctionBegin;
653
  PetscValidScalarPointer(wi,3);
654
 
655
  for (i=0;i<ps->n;i++) perm[i] = i;
656
  /* insertion sort */
657
  i=ps->l+1;
658
#if !defined(PETSC_USE_COMPLEX)
659
  if(wi[perm[i-1]]!=0.0) i++; /* initial value is complex */
660
#else
661
  if(PetscImaginaryPart(wr[perm[i-1]])!=0.0) i++;
662
#endif
663
  for (;i<ps->n;i+=d) {
664
    re = wr[perm[i]];
665
    im = wi[perm[i]];
666
    tmp1 = perm[i];
667
#if !defined(PETSC_USE_COMPLEX)
668
    if(im!=0.0) {d = 2; tmp2 = perm[i+1];}else d = 1;
669
#else
670
    if(PetscImaginaryPart(re)!=0.0) {d = 2; tmp2 = perm[i+1];}else d = 1;
671
#endif
672
    j = i-1;
673
    ierr = (*comp_func)(re,im,wr[perm[j]],wi[perm[j]],&result,comp_ctx);CHKERRQ(ierr);
674
    while (result<0 && j>=ps->l) {
675
      perm[j+d]=perm[j]; j--;
676
#if !defined(PETSC_USE_COMPLEX)
677
      if(wi[perm[j+1]]!=0)
678
#else
679
      if(PetscImaginaryPart(wr[perm[j+1]])!=0)
680
#endif
681
        {perm[j+d]=perm[j]; j--;}
682
 
683
     if (j>=ps->l) {
684
        ierr = (*comp_func)(re,im,wr[perm[j]],wi[perm[j]],&result,comp_ctx);CHKERRQ(ierr);
685
      }
686
    }
687
    perm[j+1] = tmp1;
688
    if(d==2) perm[j+2] = tmp2;
689
  }
690
  PetscFunctionReturn(0);
691
}
692
 
693
 
2808 carcamgo 694
#undef __FUNCT__  
695
#define __FUNCT__ "PSSort_GHIEP"
696
PetscErrorCode PSSort_GHIEP(PS ps,PetscScalar *wr,PetscScalar *wi,PetscErrorCode (*comp_func)(PetscScalar,PetscScalar,PetscScalar,PetscScalar,PetscInt*,void*),void *comp_ctx)
697
{
698
  PetscErrorCode ierr;
2836 carcamgo 699
  PetscInt       n,i,*perm;
700
  PetscReal      *d,*e,*s,*w;
2808 carcamgo 701
 
702
  PetscFunctionBegin;
703
  n = ps->n;
704
  d = ps->rmat[PS_MAT_T];
2836 carcamgo 705
  e = d + ps->ld;
706
  s = d + 2*ps->ld;
707
  w = ps->work;
708
  ierr = PSAllocateWork_Private(ps,ps->ld,0,ps->ld);CHKERRQ(ierr);
2808 carcamgo 709
  perm = ps->iwork;
2836 carcamgo 710
  ierr = PSSortEigenvalues_Private(ps,wr,wi,perm,comp_func,comp_ctx);CHKERRQ(ierr);
711
  ierr = PetscMemcpy(ps->work,wr,n*sizeof(PetscScalar));CHKERRQ(ierr);
712
  for (i=ps->l;i<n;i++) {
713
    wr[i] = w[perm[i]];
2808 carcamgo 714
  }
2836 carcamgo 715
  ierr = PetscMemcpy(ps->work,wi,n*sizeof(PetscScalar));CHKERRQ(ierr);
716
  for (i=ps->l;i<n;i++) {
717
    wi[i] = w[perm[i]];
718
  }
719
  ierr = PetscMemcpy(ps->work,s,n*sizeof(PetscScalar));CHKERRQ(ierr);
720
  for (i=ps->l;i<n;i++) {
721
    s[i] = w[perm[i]];
722
  }
723
  ierr = PetscMemcpy(w,d,n*sizeof(PetscScalar));CHKERRQ(ierr);
724
  for (i=ps->l;i<n;i++) {
725
    d[i] = w[perm[i]];
726
  }
727
  ierr = PetscMemcpy(w,e,n*sizeof(PetscScalar));CHKERRQ(ierr);
728
  for (i=ps->l;i<n-1;i++) {
729
    e[i] = w[perm[i]];
730
  }
731
  if(!ps->compact){ ierr = PSSwitchFormat_GHIEP(ps,PETSC_FALSE);CHKERRQ(ierr);}
732
  ierr = PSPermuteColumns_Private(ps,ps->l,n,PS_MAT_Q,perm);CHKERRQ(ierr);
2808 carcamgo 733
  PetscFunctionReturn(0);
734
}
735
 
736
EXTERN_C_BEGIN
737
#undef __FUNCT__  
738
#define __FUNCT__ "PSCreate_GHIEP"
739
PetscErrorCode PSCreate_GHIEP(PS ps)
740
{
741
  PetscFunctionBegin;
742
  ps->ops->allocate      = PSAllocate_GHIEP;
743
  ps->ops->view          = PSView_GHIEP;
744
  ps->ops->vectors       = PSVectors_GHIEP;
2836 carcamgo 745
  ps->ops->solve[0]      = PSSolve_GHIEP_QR;
746
  ps->ops->solve[1]      = PSSolve_GHIEP_QR_II;
2808 carcamgo 747
  ps->ops->sort          = PSSort_GHIEP;
748
  PetscFunctionReturn(0);
749
}
750
EXTERN_C_END