Subversion Repositories slepc-dev

Rev

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

Rev Author Line No. Line
2783 jroman 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
 
2826 jroman 25
PetscErrorCode PSSolve_HEP_QR(PS,PetscScalar*,PetscScalar*);
26
PetscErrorCode PSSolve_HEP_MRRR(PS,PetscScalar*,PetscScalar*);
27
typedef PetscErrorCode (*solvefun)(PS,PetscScalar*,PetscScalar*);
28
static const solvefun solve[] = {
29
                     PSSolve_HEP_QR,
30
                     PSSolve_HEP_MRRR
31
};
32
static const char *methodname[] = {
33
                     "Implicit QR method (_steqr)",
34
                     "Relatively Robust Representations (_stevr)"
35
};
36
 
2783 jroman 37
#undef __FUNCT__  
38
#define __FUNCT__ "PSAllocate_HEP"
39
PetscErrorCode PSAllocate_HEP(PS ps,PetscInt ld)
40
{
41
  PetscErrorCode ierr;
42
 
43
  PetscFunctionBegin;
44
  ierr = PSAllocateMat_Private(ps,PS_MAT_A);CHKERRQ(ierr);
2789 jroman 45
  ierr = PSAllocateMat_Private(ps,PS_MAT_Q);CHKERRQ(ierr);
2783 jroman 46
  ierr = PSAllocateMatReal_Private(ps,PS_MAT_T);CHKERRQ(ierr);
47
  PetscFunctionReturn(0);
48
}
49
 
2821 jroman 50
/*   0       l           k                 n-1
2818 jroman 51
    -----------------------------------------
52
    |*       ·           ·                  |
53
    |  *     ·           ·                  |
54
    |    *   ·           ·                  |
55
    |      * ·           ·                  |
56
    |· · · · o           o                  |
57
    |          o         o                  |
58
    |            o       o                  |
59
    |              o     o                  |
60
    |                o   o                  |
61
    |                  o o                  |
62
    |· · · · o o o o o o o x                |
63
    |                    x x x              |
64
    |                      x x x            |
65
    |                        x x x          |
66
    |                          x x x        |
67
    |                            x x x      |
68
    |                              x x x    |
69
    |                                x x x  |
70
    |                                  x x x|
71
    |                                    x x|
72
    -----------------------------------------
73
*/
74
 
2783 jroman 75
#undef __FUNCT__  
2813 jroman 76
#define __FUNCT__ "PSSwitchFormat_HEP"
77
PetscErrorCode PSSwitchFormat_HEP(PS ps,PetscBool tocompact)
78
{
79
  PetscReal   *T = ps->rmat[PS_MAT_T];
80
  PetscScalar *A = ps->mat[PS_MAT_A];
81
  PetscInt    i,n=ps->n,k=ps->k,ld=ps->ld;
82
 
83
  PetscFunctionBegin;
84
  if (ps->compact==tocompact) PetscFunctionReturn(0);
85
  if (tocompact) { /* switch from dense (arrow) to compact storage */
86
    for (i=0;i<k;i++) {
87
      T[i] = PetscRealPart(A[i+i*ld]);
88
      T[i+ld] = PetscRealPart(A[k+i*ld]);
89
    }
90
    for (i=k;i<n;i++) {
91
      T[i] = PetscRealPart(A[i+i*ld]);
92
      T[i+ld] = PetscRealPart(A[i+1+i*ld]);
93
    }
94
  } else { /* switch from compact (arrow) to dense storage */
95
    for (i=0;i<k;i++) {
96
      A[i+i*ld] = T[i];
97
      A[k+i*ld] = T[i+ld];
98
      A[i+k*ld] = T[i+ld];
99
    }
100
    A[k+k*ld] = T[k];
101
    for (i=k+1;i<n;i++) {
102
      A[i+i*ld] = T[i];
103
      A[i-1+i*ld] = T[i-1+ld];
104
      A[i+(i-1)*ld] = T[i-1+ld];
105
    }
106
  }
107
  PetscFunctionReturn(0);
108
}
109
 
110
#undef __FUNCT__  
2783 jroman 111
#define __FUNCT__ "PSView_HEP"
112
PetscErrorCode PSView_HEP(PS ps,PetscViewer viewer)
113
{
114
  PetscErrorCode    ierr;
2793 jroman 115
  PetscViewerFormat format;
2796 jroman 116
  PetscInt          i,j,r,c;
117
  PetscReal         value;
2783 jroman 118
 
119
  PetscFunctionBegin;
2793 jroman 120
  ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
121
  if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
2826 jroman 122
    ierr = PetscViewerASCIIPrintf(viewer,"solving the problem with: %s\n",methodname[ps->method]);CHKERRQ(ierr);
2796 jroman 123
    PetscFunctionReturn(0);
2793 jroman 124
  }
2796 jroman 125
  if (ps->compact) {
126
    ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
127
    if (format == PETSC_VIEWER_ASCII_MATLAB) {
128
      ierr = PetscViewerASCIIPrintf(viewer,"%% Size = %D %D\n",ps->n,ps->n);CHKERRQ(ierr);
129
      ierr = PetscViewerASCIIPrintf(viewer,"zzz = zeros(%D,3);\n",3*ps->n);CHKERRQ(ierr);
130
      ierr = PetscViewerASCIIPrintf(viewer,"zzz = [\n");CHKERRQ(ierr);
131
      for (i=0;i<ps->n;i++) {
132
        ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e\n",i+1,i+1,*(ps->rmat[PS_MAT_T]+i));CHKERRQ(ierr);
133
      }
134
      for (i=0;i<ps->n-1;i++) {
135
        r = PetscMax(i+2,ps->k+1);
136
        c = i+1;
137
        ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e\n",r,c,*(ps->rmat[PS_MAT_T]+ps->ld+i));CHKERRQ(ierr);
138
        ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e\n",c,r,*(ps->rmat[PS_MAT_T]+ps->ld+i));CHKERRQ(ierr);
139
      }
140
      ierr = PetscViewerASCIIPrintf(viewer,"];\n%s = spconvert(zzz);\n",PSMatName[PS_MAT_T]);CHKERRQ(ierr);
141
    } else {
142
      for (i=0;i<ps->n;i++) {
143
        for (j=0;j<ps->n;j++) {
144
          if (i==j) value = *(ps->rmat[PS_MAT_T]+i);
145
          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));
146
          else if (i==j+1 && i>ps->k) value = *(ps->rmat[PS_MAT_T]+ps->ld+i-1);
147
          else if (i+1==j && j>ps->k) value = *(ps->rmat[PS_MAT_T]+ps->ld+j-1);
148
          else value = 0.0;
149
          ierr = PetscViewerASCIIPrintf(viewer," %18.16e ",value);CHKERRQ(ierr);
150
        }
151
        ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
152
      }
153
    }
154
    ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
155
    ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
156
  } else {
157
    ierr = PSViewMat_Private(ps,viewer,PS_MAT_A);CHKERRQ(ierr);
158
  }
2787 jroman 159
  if (ps->state>PS_STATE_INTERMEDIATE) {
2789 jroman 160
    ierr = PSViewMat_Private(ps,viewer,PS_MAT_Q);CHKERRQ(ierr);
2787 jroman 161
  }
2783 jroman 162
  PetscFunctionReturn(0);
163
}
164
 
165
#undef __FUNCT__  
2807 jroman 166
#define __FUNCT__ "PSVectors_HEP"
2818 jroman 167
PetscErrorCode PSVectors_HEP(PS ps,PSMatType mat,PetscInt *j,PetscReal *rnorm)
2807 jroman 168
{
169
  PetscScalar    *Q = ps->mat[PS_MAT_Q];
170
  PetscInt       ld = ps->ld;
171
  PetscErrorCode ierr;
172
 
173
  PetscFunctionBegin;
174
  if (ps->state<PS_STATE_CONDENSED) SETERRQ(((PetscObject)ps)->comm,PETSC_ERR_ORDER,"Must call PSSolve() first");
175
  switch (mat) {
176
    case PS_MAT_X:
177
    case PS_MAT_Y:
2818 jroman 178
      if (j) {
179
        ierr = PetscMemcpy(ps->mat[mat]+(*j)*ld,Q+(*j)*ld,ld*sizeof(PetscScalar));CHKERRQ(ierr);
2807 jroman 180
      } else {
181
        ierr = PetscMemcpy(ps->mat[mat],Q,ld*ld*sizeof(PetscScalar));CHKERRQ(ierr);
182
      }
2818 jroman 183
      if (rnorm) *rnorm = PetscAbsScalar(Q[ps->n-1+(*j)*ld]);
2807 jroman 184
      break;
185
    case PS_MAT_U:
186
    case PS_MAT_VT:
187
      SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented yet");
188
      break;
189
    default:
190
      SETERRQ(((PetscObject)ps)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Invalid mat parameter");
191
  }
192
  PetscFunctionReturn(0);
193
}
194
 
195
#undef __FUNCT__  
2829 jroman 196
#define __FUNCT__ "ArrowTridiag"
2826 jroman 197
/*
2829 jroman 198
  ARROWTRIDIAG reduces a symmetric arrowhead matrix of the form
199
 
200
                [ d 0 0 0 e ]
201
                [ 0 d 0 0 e ]
202
            A = [ 0 0 d 0 e ]
203
                [ 0 0 0 d e ]
204
                [ e e e e d ]
205
 
206
  to tridiagonal form
207
 
208
                [ d e 0 0 0 ]
209
                [ e d e 0 0 ]
210
   T = Q'*A*Q = [ 0 e d e 0 ],
211
                [ 0 0 e d e ]
212
                [ 0 0 0 e d ]
213
 
214
  where Q is an orthogonal matrix. Rutishauser's algorithm is used to
215
  perform the reduction, which requires O(n**2) flops. The accumulation
216
  of the orthogonal factor Q, however, requires O(n**3) flops.
217
 
218
  Arguments
219
  =========
220
 
221
  N       (input) INTEGER
222
          The order of the matrix A.  N >= 0.
223
 
224
  D       (input/output) DOUBLE PRECISION array, dimension (N)
225
          On entry, the diagonal entries of the matrix A to be
226
          reduced.
227
          On exit, the diagonal entries of the reduced matrix T.
228
 
229
  E       (input/output) DOUBLE PRECISION array, dimension (N-1)
230
          On entry, the off-diagonal entries of the matrix A to be
231
          reduced.
232
          On exit, the subdiagonal entries of the reduced matrix T.
233
 
234
  Q       (input/output) DOUBLE PRECISION array, dimension (LDQ, N)
235
          On exit, the orthogonal matrix Q.
236
 
237
  LDQ     (input) INTEGER
238
          The leading dimension of the array Q.
239
 
240
  Note
241
  ====
242
  Based on Fortran code contributed by Daniel Kressner
2826 jroman 243
*/
2829 jroman 244
static PetscErrorCode ArrowTridiag(PetscBLASInt *n,PetscReal *d,PetscReal *e,PetscScalar *Q,PetscBLASInt *ldq)
2783 jroman 245
{
2829 jroman 246
  PetscBLASInt i,j,j2,ld=*ldq,one=1;
247
  PetscReal    c,s,p,off,temp;
248
 
249
  PetscFunctionBegin;
250
  if (*n<=2) PetscFunctionReturn(0);
251
 
252
  for (j=0;j<*n-2;j++) {
253
 
254
    /* Eliminate entry e(j) by a rotation in the planes (j,j+1) */
255
    temp = e[j+1];
256
    LAPACKlartg_(&temp,&e[j],&c,&s,&e[j+1]);
257
    s = -s;
258
 
259
    /* Apply rotation to diagonal elements */
260
    temp   = d[j+1];
261
    e[j]   = c*s*(temp-d[j]);
262
    d[j+1] = s*s*d[j] + c*c*temp;
263
    d[j]   = c*c*d[j] + s*s*temp;
264
 
265
    /* Apply rotation to Q */
266
    j2 = j+2;
267
    BLASrot_(&j2,Q+j*ld,&one,Q+(j+1)*ld,&one,&c,&s);
268
 
269
    /* Chase newly introduced off-diagonal entry to the top left corner */
270
    for (i=j-1;i>=0;i--) {
271
      off  = -s*e[i];
272
      e[i] = c*e[i];
273
      temp = e[i+1];
274
      LAPACKlartg_(&temp,&off,&c,&s,&e[i+1]);
275
      s = -s;
276
      temp = (d[i]-d[i+1])*s - 2.0*c*e[i];
277
      p = s*temp;
278
      d[i+1] += p;
279
      d[i] -= p;
280
      e[i] = -e[i] - c*temp;
281
      j2 = j+2;
282
      BLASrot_(&j2,Q+i*ld,&one,Q+(i+1)*ld,&one,&c,&s);
283
    }
284
  }
285
  PetscFunctionReturn(0);
286
}
287
 
288
#undef __FUNCT__  
289
#define __FUNCT__ "PSIntermediate_HEP_Flip"
290
/*
291
   Reduce to tridiagonal form by flipping the matrix and using standard
292
   LAPACK tridiagonal reduction
293
*/
294
static PetscErrorCode PSIntermediate_HEP_Flip(PS ps)
295
{
2826 jroman 296
#if defined(SLEPC_MISSING_LAPACK_SYTRD) || defined(SLEPC_MISSING_LAPACK_ORGTR)
2783 jroman 297
  PetscFunctionBegin;
2826 jroman 298
  SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"SYTRD/ORGTR - Lapack routine is unavailable.");
2783 jroman 299
#else
300
  PetscErrorCode ierr;
2796 jroman 301
  PetscInt       i,j;
2826 jroman 302
  PetscBLASInt   n1,n2,n3,lwork,info,l,n,ld,off;
303
  PetscScalar    *A,*S,*Q,*work,*tau;
304
  PetscReal      *d,*e;
2783 jroman 305
 
306
  PetscFunctionBegin;
307
  n  = PetscBLASIntCast(ps->n);
2818 jroman 308
  l  = PetscBLASIntCast(ps->l);
2783 jroman 309
  ld = PetscBLASIntCast(ps->ld);
2818 jroman 310
  n1 = PetscBLASIntCast(ps->k-l+1);  /* size of leading block, excluding locked */
311
  n2 = PetscBLASIntCast(n-ps->k-1);  /* size of trailing block */
312
  n3 = n1+n2;
313
  off = l+l*ld;
2821 jroman 314
  A  = ps->mat[PS_MAT_A];
2789 jroman 315
  Q  = ps->mat[PS_MAT_Q];
2783 jroman 316
  d  = ps->rmat[PS_MAT_T];
317
  e  = ps->rmat[PS_MAT_T]+ld;
2818 jroman 318
  ierr = PetscMemzero(Q,ld*ld*sizeof(PetscScalar));CHKERRQ(ierr);
319
  for (i=0;i<n;i++) Q[i+i*ld] = 1.0;
2783 jroman 320
 
2796 jroman 321
  if (ps->compact) {
322
 
2787 jroman 323
    /* reduce to tridiagonal form */
2796 jroman 324
    if (ps->state<PS_STATE_INTERMEDIATE) {
325
 
326
      ierr = PSAllocateMat_Private(ps,PS_MAT_W);CHKERRQ(ierr);
327
      S = ps->mat[PS_MAT_W];
328
      ierr = PetscMemzero(S,ld*ld*sizeof(PetscScalar));CHKERRQ(ierr);
329
      ierr = PSAllocateWork_Private(ps,ld+ld*ld,0,0);CHKERRQ(ierr);
330
      tau  = ps->work;
331
      work = ps->work+ld;
332
      lwork = ld*ld;
333
 
334
      /* Flip matrix S */
2818 jroman 335
      for (i=l;i<n;i++) S[(n3-1-i+l)+(n3-1-i+l)*ld] = d[i];
336
      for (i=l;i<ps->k;i++) S[(n3-1-i+l)+(n3-1-ps->k+l)*ld] = e[i];
337
      for (i=ps->k;i<n-1;i++) S[(n3-1-i+l)+(n3-1-i-1+l)*ld] = e[i];
2796 jroman 338
 
339
      /* Reduce (2,2)-block of flipped S to tridiagonal form */
2818 jroman 340
      LAPACKsytrd_("L",&n1,S+n2+n2*ld,&ld,d+l,e+l,tau,work,&lwork,&info);
2796 jroman 341
      if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xSYTRD %d",info);
342
 
343
      /* Flip back diag and subdiag, put them in d and e */
2818 jroman 344
      for (i=0;i<n1-1;i++) {
345
        d[l+n1-i-1] = PetscRealPart(S[n2+i+(n2+i)*ld]);
346
        e[l+n1-i-2] = PetscRealPart(S[n2+i+1+(n2+i)*ld]);
2796 jroman 347
      }
2818 jroman 348
      d[l] = PetscRealPart(S[n3-1+(n3-1)*ld]);
2796 jroman 349
 
350
      /* Compute the orthogonal matrix used for tridiagonalization */
351
      LAPACKorgtr_("L",&n1,S+n2+n2*ld,&ld,tau,work,&lwork,&info);
352
      if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xORGTR %d",info);
353
 
354
      /* Create full-size Q, flipped back to original order */
355
      for (i=0;i<n1;i++)
356
        for (j=0;j<n1;j++)
2818 jroman 357
          Q[l+i+(l+j)*ld] = S[n3-i-1+(n3-j-1)*ld];
2796 jroman 358
 
359
    }
360
 
2787 jroman 361
  } else {
2796 jroman 362
 
2818 jroman 363
    for (i=0;i<l;i++) { d[i] = PetscRealPart(A[i+i*ld]); e[i] = 0.0; }
2796 jroman 364
 
365
    if (ps->state<PS_STATE_INTERMEDIATE) {
2821 jroman 366
      ierr = PSCopyMatrix_Private(ps,PS_MAT_Q,PS_MAT_A);CHKERRQ(ierr);
2796 jroman 367
      ierr = PSAllocateWork_Private(ps,ld+ld*ld,0,0);CHKERRQ(ierr);
368
      tau  = ps->work;
369
      work = ps->work+ld;
370
      lwork = ld*ld;
2818 jroman 371
      LAPACKsytrd_("L",&n3,Q+off,&ld,d+l,e+l,tau,work,&lwork,&info);
2796 jroman 372
      if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xSYTRD %d",info);
2818 jroman 373
      LAPACKorgtr_("L",&n3,Q+off,&ld,tau,work,&lwork,&info);
2796 jroman 374
      if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xORGTR %d",info);
375
    } else {
2818 jroman 376
      /* copy tridiagonal to d,e */
377
      for (i=l;i<n;i++) d[i] = PetscRealPart(A[i+i*ld]);
378
      for (i=l;i<n-1;i++) e[i] = PetscRealPart(A[(i+1)+i*ld]);
2796 jroman 379
    }
2783 jroman 380
  }
2826 jroman 381
  PetscFunctionReturn(0);
382
#endif
383
}
2783 jroman 384
 
2826 jroman 385
#undef __FUNCT__  
2829 jroman 386
#define __FUNCT__ "PSIntermediate_HEP"
387
/*
388
   Reduce to tridiagonal form by means of ArrowTridiag.
389
*/
390
static PetscErrorCode PSIntermediate_HEP(PS ps)
391
{
392
#if defined(SLEPC_MISSING_LAPACK_SYTRD) || defined(SLEPC_MISSING_LAPACK_ORGTR)
393
  PetscFunctionBegin;
394
  SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"SYTRD/ORGTR - Lapack routine is unavailable.");
395
#else
396
  PetscErrorCode ierr;
397
  PetscInt       i,j;
398
  PetscBLASInt   n1,n2,n3,lwork,info,l,n,ld,off;
399
  PetscScalar    *A,*S,*Q,*work,*tau;
400
  PetscReal      *d,*e;
401
 
402
  PetscFunctionBegin;
403
  n  = PetscBLASIntCast(ps->n);
404
  l  = PetscBLASIntCast(ps->l);
405
  ld = PetscBLASIntCast(ps->ld);
406
  n1 = PetscBLASIntCast(ps->k-l+1);  /* size of leading block, excluding locked */
407
  n2 = PetscBLASIntCast(n-ps->k-1);  /* size of trailing block */
408
  n3 = n1+n2;
409
  off = l+l*ld;
410
  A  = ps->mat[PS_MAT_A];
411
  Q  = ps->mat[PS_MAT_Q];
412
  d  = ps->rmat[PS_MAT_T];
413
  e  = ps->rmat[PS_MAT_T]+ld;
414
  ierr = PetscMemzero(Q,ld*ld*sizeof(PetscScalar));CHKERRQ(ierr);
415
  for (i=0;i<n;i++) Q[i+i*ld] = 1.0;
416
 
417
  if (ps->compact) {
418
 
419
    if (ps->state<PS_STATE_INTERMEDIATE) ArrowTridiag(&n1,d+l,e+l,Q+off,&ld);
420
 
421
  } else {
422
 
423
    for (i=0;i<l;i++) { d[i] = PetscRealPart(A[i+i*ld]); e[i] = 0.0; }
424
 
425
    if (ps->state<PS_STATE_INTERMEDIATE) {
426
      ierr = PSCopyMatrix_Private(ps,PS_MAT_Q,PS_MAT_A);CHKERRQ(ierr);
427
      ierr = PSAllocateWork_Private(ps,ld+ld*ld,0,0);CHKERRQ(ierr);
428
      tau  = ps->work;
429
      work = ps->work+ld;
430
      lwork = ld*ld;
431
      LAPACKsytrd_("L",&n3,Q+off,&ld,d+l,e+l,tau,work,&lwork,&info);
432
      if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xSYTRD %d",info);
433
      LAPACKorgtr_("L",&n3,Q+off,&ld,tau,work,&lwork,&info);
434
      if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xORGTR %d",info);
435
    } else {
436
      /* copy tridiagonal to d,e */
437
      for (i=l;i<n;i++) d[i] = PetscRealPart(A[i+i*ld]);
438
      for (i=l;i<n-1;i++) e[i] = PetscRealPart(A[(i+1)+i*ld]);
439
    }
440
  }
441
  PetscFunctionReturn(0);
442
#endif
443
}
444
 
445
#undef __FUNCT__  
2826 jroman 446
#define __FUNCT__ "PSSolve_HEP_QR"
447
PetscErrorCode PSSolve_HEP_QR(PS ps,PetscScalar *wr,PetscScalar *wi)
448
{
449
#if defined(SLEPC_MISSING_LAPACK_STEQR)
450
  PetscFunctionBegin;
451
  SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"STEQR - Lapack routine is unavailable.");
452
#else
453
  PetscErrorCode ierr;
454
  PetscInt       i;
455
  PetscBLASInt   n1,n2,n3,info,l,n,ld,off;
456
  PetscScalar    *A,*Q;
457
  PetscReal      *d,*e;
458
#if defined(PETSC_USE_COMPLEX)
459
  PetscReal      *ritz;
460
#endif
461
 
462
  PetscFunctionBegin;
463
  n  = PetscBLASIntCast(ps->n);
464
  l  = PetscBLASIntCast(ps->l);
465
  ld = PetscBLASIntCast(ps->ld);
466
  n1 = PetscBLASIntCast(ps->k-l+1);  /* size of leading block, excluding locked */
467
  n2 = PetscBLASIntCast(n-ps->k-1);  /* size of trailing block */
468
  n3 = n1+n2;
469
  off = l+l*ld;
470
  A  = ps->mat[PS_MAT_A];
471
  Q  = ps->mat[PS_MAT_Q];
472
  d  = ps->rmat[PS_MAT_T];
473
  e  = ps->rmat[PS_MAT_T]+ld;
474
 
475
  /* Reduce to tridiagonal form */
476
  ierr = PSIntermediate_HEP(ps);CHKERRQ(ierr);
477
 
2783 jroman 478
  /* Solve the tridiagonal eigenproblem */
2821 jroman 479
  for (i=0;i<l;i++) wr[i] = d[i];
2826 jroman 480
 
481
  ierr = PSAllocateWork_Private(ps,0,2*ld,0);CHKERRQ(ierr);
482
  LAPACKsteqr_("V",&n3,d+l,e+l,Q+off,&ld,ps->rwork,&info);
483
  if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xSTEQR %d",info);
484
  for (i=l;i<n;i++) wr[i] = d[i];
485
 
486
  if (ps->compact) {
487
    ierr = PetscMemzero(e,(n-1)*sizeof(PetscReal));CHKERRQ(ierr);
488
  } else {
489
    ierr = PetscMemzero(A,ld*ld*sizeof(PetscScalar));CHKERRQ(ierr);
490
    for (i=0;i<n;i++) A[i+i*ld] = d[i];
491
  }
492
  PetscFunctionReturn(0);
493
#endif
494
}
495
 
496
#undef __FUNCT__  
497
#define __FUNCT__ "PSSolve_HEP_MRRR"
498
PetscErrorCode PSSolve_HEP_MRRR(PS ps,PetscScalar *wr,PetscScalar *wi)
499
{
500
#if defined(SLEPC_MISSING_LAPACK_STEVR)
501
  PetscFunctionBegin;
502
  SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"STEVR - Lapack routine is unavailable.");
503
#else
504
  PetscErrorCode ierr;
505
  PetscInt       i;
506
  PetscBLASInt   n1,n2,n3,lwork,liwork,info,l,n,m,ld,off,il,iu,*isuppz;
507
  PetscScalar    *A,*Q,*W,one=1.0,zero=0.0;
508
  PetscReal      *d,*e,abstol=0.0,vl,vu;
2819 jroman 509
#if defined(PETSC_USE_COMPLEX)
2826 jroman 510
  PetscReal      *ritz;
2819 jroman 511
#endif
2826 jroman 512
 
513
  PetscFunctionBegin;
514
  n  = PetscBLASIntCast(ps->n);
515
  l  = PetscBLASIntCast(ps->l);
516
  ld = PetscBLASIntCast(ps->ld);
517
  n1 = PetscBLASIntCast(ps->k-l+1);  /* size of leading block, excluding locked */
518
  n2 = PetscBLASIntCast(n-ps->k-1);  /* size of trailing block */
519
  n3 = n1+n2;
520
  off = l+l*ld;
521
  A  = ps->mat[PS_MAT_A];
522
  Q  = ps->mat[PS_MAT_Q];
523
  d  = ps->rmat[PS_MAT_T];
524
  e  = ps->rmat[PS_MAT_T]+ld;
525
 
526
  /* Reduce to tridiagonal form */
527
  ierr = PSIntermediate_HEP(ps);CHKERRQ(ierr);
528
 
529
  /* Solve the tridiagonal eigenproblem */
530
  for (i=0;i<l;i++) wr[i] = d[i];
531
 
532
  if (ps->state<PS_STATE_INTERMEDIATE) {  /* Q contains useful info */
533
    ierr = PSAllocateMat_Private(ps,PS_MAT_W);CHKERRQ(ierr);
534
    W = ps->mat[PS_MAT_W];
535
    ierr = PSCopyMatrix_Private(ps,PS_MAT_W,PS_MAT_Q);CHKERRQ(ierr);
536
  }
2819 jroman 537
#if defined(PETSC_USE_COMPLEX)
2826 jroman 538
  ierr = PSAllocateMatReal_Private(ps,PS_MAT_Q);CHKERRQ(ierr);
539
#endif
540
  lwork = 20*ld;
541
  liwork = 10*ld;
542
  ierr = PSAllocateWork_Private(ps,0,lwork+ld,liwork+2*ld);CHKERRQ(ierr);
543
  isuppz = ps->iwork+liwork;
544
#if defined(PETSC_USE_COMPLEX)
545
  ritz = ps->rwork+lwork;
546
  LAPACKstevr_("V","A",&n3,d+l,e+l,&vl,&vu,&il,&iu,&abstol,&m,ritz+l,ps->rmat[PS_MAT_Q]+off,&ld,isuppz,ps->rwork,&lwork,ps->iwork,&liwork,&info);
547
  for (i=l;i<n;i++) wr[i] = ritz[i];
2819 jroman 548
#else
2826 jroman 549
  LAPACKstevr_("V","A",&n3,d+l,e+l,&vl,&vu,&il,&iu,&abstol,&m,wr+l,Q+off,&ld,isuppz,ps->rwork,&lwork,ps->iwork,&liwork,&info);
2819 jroman 550
#endif
2826 jroman 551
  if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack DSTEVR %d",info);
2819 jroman 552
#if defined(PETSC_USE_COMPLEX)
2826 jroman 553
  for (i=l;i<n;i++)
554
    for (j=l;j<n;j++)
555
      Q[i+j*ld] = (ps->rmat[PS_MAT_Q])[i+j*ld];
2819 jroman 556
#endif
2826 jroman 557
  if (ps->state<PS_STATE_INTERMEDIATE) {  /* accumulate previous Q */
558
    BLASgemm_("N","N",&n3,&n3,&n3,&one,W+off,&ld,Q+off,&ld,&zero,A+off,&ld);
559
    ierr = PSCopyMatrix_Private(ps,PS_MAT_Q,PS_MAT_A);CHKERRQ(ierr);
2819 jroman 560
  }
2826 jroman 561
  for (i=l;i<n;i++) d[i] = wr[i];
562
 
2796 jroman 563
  if (ps->compact) {
564
    ierr = PetscMemzero(e,(n-1)*sizeof(PetscReal));CHKERRQ(ierr);
565
  } else {
566
    ierr = PetscMemzero(A,ld*ld*sizeof(PetscScalar));CHKERRQ(ierr);
567
    for (i=0;i<n;i++) A[i+i*ld] = d[i];
568
  }
2783 jroman 569
  PetscFunctionReturn(0);
570
#endif
571
}
572
 
573
#undef __FUNCT__  
574
#define __FUNCT__ "PSSort_HEP"
575
PetscErrorCode PSSort_HEP(PS ps,PetscScalar *wr,PetscScalar *wi,PetscErrorCode (*comp_func)(PetscScalar,PetscScalar,PetscScalar,PetscScalar,PetscInt*,void*),void *comp_ctx)
576
{
577
  PetscErrorCode ierr;
2818 jroman 578
  PetscInt       n,l,i,*perm;
2792 jroman 579
  PetscScalar    *A;
2791 jroman 580
  PetscReal      *d;
2783 jroman 581
 
582
  PetscFunctionBegin;
2791 jroman 583
  n = ps->n;
2818 jroman 584
  l = ps->l;
2791 jroman 585
  d = ps->rmat[PS_MAT_T];
586
  ierr = PSAllocateWork_Private(ps,0,0,ps->ld);CHKERRQ(ierr);
2783 jroman 587
  perm = ps->iwork;
2818 jroman 588
  ierr = PSSortEigenvaluesReal_Private(ps,l,n,d,perm,comp_func,comp_ctx);CHKERRQ(ierr);
589
  for (i=l;i<n;i++) wr[i] = d[perm[i]];
590
  ierr = PSPermuteColumns_Private(ps,l,n,PS_MAT_Q,perm);CHKERRQ(ierr);
2796 jroman 591
  if (ps->compact) {
2818 jroman 592
    for (i=l;i<n;i++) d[i] = PetscRealPart(wr[i]);
2796 jroman 593
  } else {
594
    A  = ps->mat[PS_MAT_A];
2818 jroman 595
    for (i=l;i<n;i++) A[i+i*ps->ld] = wr[i];
2796 jroman 596
  }
2783 jroman 597
  PetscFunctionReturn(0);
598
}
599
 
600
#undef __FUNCT__  
601
#define __FUNCT__ "PSCond_HEP"
602
PetscErrorCode PSCond_HEP(PS ps,PetscReal *cond)
603
{
604
#if defined(PETSC_MISSING_LAPACK_GETRF) || defined(SLEPC_MISSING_LAPACK_GETRI) || defined(SLEPC_MISSING_LAPACK_LANGE) || defined(SLEPC_MISSING_LAPACK_LANHS)
605
  PetscFunctionBegin;
606
  SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"GETRF/GETRI/LANGE/LANHS - Lapack routines are unavailable.");
607
#else
608
  PetscErrorCode ierr;
609
  PetscScalar    *work;
610
  PetscReal      *rwork;
611
  PetscBLASInt   *ipiv;
612
  PetscBLASInt   lwork,info,n,ld;
613
  PetscReal      hn,hin;
614
  PetscScalar    *A;
615
 
616
  PetscFunctionBegin;
617
  n  = PetscBLASIntCast(ps->n);
618
  ld = PetscBLASIntCast(ps->ld);
619
  lwork = 8*ld;
620
  ierr = PSAllocateWork_Private(ps,lwork,ld,ld);CHKERRQ(ierr);
621
  work  = ps->work;
622
  rwork = ps->rwork;
623
  ipiv  = ps->iwork;
2813 jroman 624
  ierr = PSSwitchFormat_HEP(ps,PETSC_FALSE);CHKERRQ(ierr);
2783 jroman 625
 
626
  /* use workspace matrix W to avoid overwriting A */
2793 jroman 627
  ierr = PSAllocateMat_Private(ps,PS_MAT_W);CHKERRQ(ierr);
2783 jroman 628
  A = ps->mat[PS_MAT_W];
629
  ierr = PetscMemcpy(A,ps->mat[PS_MAT_A],sizeof(PetscScalar)*ps->ld*ps->ld);CHKERRQ(ierr);
630
 
631
  /* norm of A */
632
  hn = LAPACKlange_("I",&n,&n,A,&ld,rwork);
633
 
634
  /* norm of inv(A) */
635
  LAPACKgetrf_(&n,&n,A,&ld,ipiv,&info);
636
  if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xGETRF %d",info);
637
  LAPACKgetri_(&n,A,&ld,ipiv,work,&lwork,&info);
638
  if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xGETRI %d",info);
639
  hin = LAPACKlange_("I",&n,&n,A,&ld,rwork);
640
 
641
  *cond = hn*hin;
642
  PetscFunctionReturn(0);
643
#endif
644
}
645
 
2814 jroman 646
#undef __FUNCT__  
647
#define __FUNCT__ "PSTranslateRKS_HEP"
648
PetscErrorCode PSTranslateRKS_HEP(PS ps,PetscScalar alpha)
649
{
650
#if defined(PETSC_MISSING_LAPACK_GEQRF) || defined(SLEPC_MISSING_LAPACK_ORGQR)
651
  PetscFunctionBegin;
652
  SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"GEQRF/ORGQR - Lapack routines are unavailable.");
653
#else
654
  PetscErrorCode ierr;
655
  PetscInt       i,j,k=ps->k;
656
  PetscScalar    *Q,*A,*R,*tau,*work;
657
  PetscBLASInt   ld,n1,n0,lwork,info;
658
 
659
  PetscFunctionBegin;
660
  ld = PetscBLASIntCast(ps->ld);
661
  ierr = PSAllocateWork_Private(ps,ld*ld,0,0);CHKERRQ(ierr);
662
  tau = ps->work;
663
  work = ps->work+ld;
664
  lwork = PetscBLASIntCast(ld*(ld-1));
665
  ierr = PSAllocateMat_Private(ps,PS_MAT_W);CHKERRQ(ierr);
666
  A  = ps->mat[PS_MAT_A];
667
  Q  = ps->mat[PS_MAT_Q];
668
  R  = ps->mat[PS_MAT_W];
669
  /* Copy I+alpha*A */
670
  ierr = PetscMemzero(Q,ld*ld*sizeof(PetscScalar));CHKERRQ(ierr);
671
  ierr = PetscMemzero(R,ld*ld*sizeof(PetscScalar));CHKERRQ(ierr);
672
  for (i=0;i<k;i++) {
673
    Q[i+i*ld] = 1.0 + alpha*A[i+i*ld];
674
    Q[k+i*ld] = alpha*A[k+i*ld];
675
  }
676
  /* Compute qr */
677
  n1 = PetscBLASIntCast(k+1);
678
  n0 = PetscBLASIntCast(k);
679
  LAPACKgeqrf_(&n1,&n0,Q,&ld,tau,work,&lwork,&info);
680
  if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xGEQRF %d",info);
681
  /* Copy R from Q */
682
  for (j=0;j<k;j++)
683
    for(i=0;i<=j;i++)
684
      R[i+j*ld] = Q[i+j*ld];
685
  /* Compute orthogonal matrix in Q */
686
  LAPACKorgqr_(&n1,&n1,&n0,Q,&ld,tau,work,&lwork,&info);
687
  if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xORGQR %d",info);
688
  /* Compute the updated matrix of projected problem */
689
  for(j=0;j<k;j++){
690
    for(i=0;i<k+1;i++)
691
      A[j*ld+i] = Q[i*ld+j];
692
  }
693
  alpha = -1.0/alpha;
694
  BLAStrsm_("R","U","N","N",&n1,&n0,&alpha,R,&ld,A,&ld);
695
  for(i=0;i<k;i++)
696
    A[ld*i+i]-=alpha;
697
  PetscFunctionReturn(0);
698
#endif
699
}
700
 
2783 jroman 701
EXTERN_C_BEGIN
702
#undef __FUNCT__  
703
#define __FUNCT__ "PSCreate_HEP"
704
PetscErrorCode PSCreate_HEP(PS ps)
705
{
706
  PetscFunctionBegin;
2819 jroman 707
  ps->nmeth  = 2;
2783 jroman 708
  ps->ops->allocate      = PSAllocate_HEP;
709
  ps->ops->view          = PSView_HEP;
2807 jroman 710
  ps->ops->vectors       = PSVectors_HEP;
2826 jroman 711
  ps->ops->solve         = solve[ps->method];
2783 jroman 712
  ps->ops->sort          = PSSort_HEP;
713
  ps->ops->cond          = PSCond_HEP;
2814 jroman 714
  ps->ops->transrks      = PSTranslateRKS_HEP;
2783 jroman 715
  PetscFunctionReturn(0);
716
}
717
EXTERN_C_END
718