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
 
25
#undef __FUNCT__  
26
#define __FUNCT__ "PSAllocate_HEP"
27
PetscErrorCode PSAllocate_HEP(PS ps,PetscInt ld)
28
{
29
  PetscErrorCode ierr;
30
 
31
  PetscFunctionBegin;
32
  ierr = PSAllocateMat_Private(ps,PS_MAT_A);CHKERRQ(ierr);
2789 jroman 33
  ierr = PSAllocateMat_Private(ps,PS_MAT_Q);CHKERRQ(ierr);
2783 jroman 34
  ierr = PSAllocateMatReal_Private(ps,PS_MAT_T);CHKERRQ(ierr);
35
  PetscFunctionReturn(0);
36
}
37
 
2821 jroman 38
/*   0       l           k                 n-1
2818 jroman 39
    -----------------------------------------
40
    |*       ·           ·                  |
41
    |  *     ·           ·                  |
42
    |    *   ·           ·                  |
43
    |      * ·           ·                  |
44
    |· · · · o           o                  |
45
    |          o         o                  |
46
    |            o       o                  |
47
    |              o     o                  |
48
    |                o   o                  |
49
    |                  o o                  |
50
    |· · · · o o o o o o o x                |
51
    |                    x x x              |
52
    |                      x x x            |
53
    |                        x x x          |
54
    |                          x x x        |
55
    |                            x x x      |
56
    |                              x x x    |
57
    |                                x x x  |
58
    |                                  x x x|
59
    |                                    x x|
60
    -----------------------------------------
61
*/
62
 
2783 jroman 63
#undef __FUNCT__  
2813 jroman 64
#define __FUNCT__ "PSSwitchFormat_HEP"
65
PetscErrorCode PSSwitchFormat_HEP(PS ps,PetscBool tocompact)
66
{
67
  PetscReal   *T = ps->rmat[PS_MAT_T];
68
  PetscScalar *A = ps->mat[PS_MAT_A];
69
  PetscInt    i,n=ps->n,k=ps->k,ld=ps->ld;
70
 
71
  PetscFunctionBegin;
72
  if (ps->compact==tocompact) PetscFunctionReturn(0);
73
  if (tocompact) { /* switch from dense (arrow) to compact storage */
74
    for (i=0;i<k;i++) {
75
      T[i] = PetscRealPart(A[i+i*ld]);
76
      T[i+ld] = PetscRealPart(A[k+i*ld]);
77
    }
78
    for (i=k;i<n;i++) {
79
      T[i] = PetscRealPart(A[i+i*ld]);
80
      T[i+ld] = PetscRealPart(A[i+1+i*ld]);
81
    }
82
  } else { /* switch from compact (arrow) to dense storage */
83
    for (i=0;i<k;i++) {
84
      A[i+i*ld] = T[i];
85
      A[k+i*ld] = T[i+ld];
86
      A[i+k*ld] = T[i+ld];
87
    }
88
    A[k+k*ld] = T[k];
89
    for (i=k+1;i<n;i++) {
90
      A[i+i*ld] = T[i];
91
      A[i-1+i*ld] = T[i-1+ld];
92
      A[i+(i-1)*ld] = T[i-1+ld];
93
    }
94
  }
95
  PetscFunctionReturn(0);
96
}
97
 
98
#undef __FUNCT__  
2783 jroman 99
#define __FUNCT__ "PSView_HEP"
100
PetscErrorCode PSView_HEP(PS ps,PetscViewer viewer)
101
{
102
  PetscErrorCode    ierr;
2793 jroman 103
  PetscViewerFormat format;
2796 jroman 104
  PetscInt          i,j,r,c;
105
  PetscReal         value;
2832 jroman 106
  const char *methodname[] = {
107
                     "Implicit QR method (_steqr)",
108
                     "Relatively Robust Representations (_stevr)"
109
  };
2783 jroman 110
 
111
  PetscFunctionBegin;
2793 jroman 112
  ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
113
  if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
2826 jroman 114
    ierr = PetscViewerASCIIPrintf(viewer,"solving the problem with: %s\n",methodname[ps->method]);CHKERRQ(ierr);
2796 jroman 115
    PetscFunctionReturn(0);
2793 jroman 116
  }
2796 jroman 117
  if (ps->compact) {
118
    ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
119
    if (format == PETSC_VIEWER_ASCII_MATLAB) {
120
      ierr = PetscViewerASCIIPrintf(viewer,"%% Size = %D %D\n",ps->n,ps->n);CHKERRQ(ierr);
121
      ierr = PetscViewerASCIIPrintf(viewer,"zzz = zeros(%D,3);\n",3*ps->n);CHKERRQ(ierr);
122
      ierr = PetscViewerASCIIPrintf(viewer,"zzz = [\n");CHKERRQ(ierr);
123
      for (i=0;i<ps->n;i++) {
124
        ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e\n",i+1,i+1,*(ps->rmat[PS_MAT_T]+i));CHKERRQ(ierr);
125
      }
126
      for (i=0;i<ps->n-1;i++) {
127
        r = PetscMax(i+2,ps->k+1);
128
        c = i+1;
129
        ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e\n",r,c,*(ps->rmat[PS_MAT_T]+ps->ld+i));CHKERRQ(ierr);
130
        ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e\n",c,r,*(ps->rmat[PS_MAT_T]+ps->ld+i));CHKERRQ(ierr);
131
      }
132
      ierr = PetscViewerASCIIPrintf(viewer,"];\n%s = spconvert(zzz);\n",PSMatName[PS_MAT_T]);CHKERRQ(ierr);
133
    } else {
134
      for (i=0;i<ps->n;i++) {
135
        for (j=0;j<ps->n;j++) {
136
          if (i==j) value = *(ps->rmat[PS_MAT_T]+i);
137
          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));
138
          else if (i==j+1 && i>ps->k) value = *(ps->rmat[PS_MAT_T]+ps->ld+i-1);
139
          else if (i+1==j && j>ps->k) value = *(ps->rmat[PS_MAT_T]+ps->ld+j-1);
140
          else value = 0.0;
141
          ierr = PetscViewerASCIIPrintf(viewer," %18.16e ",value);CHKERRQ(ierr);
142
        }
143
        ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
144
      }
145
    }
146
    ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
147
    ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
148
  } else {
149
    ierr = PSViewMat_Private(ps,viewer,PS_MAT_A);CHKERRQ(ierr);
150
  }
2787 jroman 151
  if (ps->state>PS_STATE_INTERMEDIATE) {
2789 jroman 152
    ierr = PSViewMat_Private(ps,viewer,PS_MAT_Q);CHKERRQ(ierr);
2787 jroman 153
  }
2783 jroman 154
  PetscFunctionReturn(0);
155
}
156
 
157
#undef __FUNCT__  
2807 jroman 158
#define __FUNCT__ "PSVectors_HEP"
2818 jroman 159
PetscErrorCode PSVectors_HEP(PS ps,PSMatType mat,PetscInt *j,PetscReal *rnorm)
2807 jroman 160
{
161
  PetscScalar    *Q = ps->mat[PS_MAT_Q];
162
  PetscInt       ld = ps->ld;
163
  PetscErrorCode ierr;
164
 
165
  PetscFunctionBegin;
166
  if (ps->state<PS_STATE_CONDENSED) SETERRQ(((PetscObject)ps)->comm,PETSC_ERR_ORDER,"Must call PSSolve() first");
167
  switch (mat) {
168
    case PS_MAT_X:
169
    case PS_MAT_Y:
2818 jroman 170
      if (j) {
171
        ierr = PetscMemcpy(ps->mat[mat]+(*j)*ld,Q+(*j)*ld,ld*sizeof(PetscScalar));CHKERRQ(ierr);
2807 jroman 172
      } else {
173
        ierr = PetscMemcpy(ps->mat[mat],Q,ld*ld*sizeof(PetscScalar));CHKERRQ(ierr);
174
      }
2818 jroman 175
      if (rnorm) *rnorm = PetscAbsScalar(Q[ps->n-1+(*j)*ld]);
2807 jroman 176
      break;
177
    case PS_MAT_U:
178
    case PS_MAT_VT:
179
      SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented yet");
180
      break;
181
    default:
182
      SETERRQ(((PetscObject)ps)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Invalid mat parameter");
183
  }
184
  PetscFunctionReturn(0);
185
}
186
 
187
#undef __FUNCT__  
2829 jroman 188
#define __FUNCT__ "ArrowTridiag"
2826 jroman 189
/*
2829 jroman 190
  ARROWTRIDIAG reduces a symmetric arrowhead matrix of the form
191
 
192
                [ d 0 0 0 e ]
193
                [ 0 d 0 0 e ]
194
            A = [ 0 0 d 0 e ]
195
                [ 0 0 0 d e ]
196
                [ e e e e d ]
197
 
198
  to tridiagonal form
199
 
200
                [ d e 0 0 0 ]
201
                [ e d e 0 0 ]
202
   T = Q'*A*Q = [ 0 e d e 0 ],
203
                [ 0 0 e d e ]
204
                [ 0 0 0 e d ]
205
 
206
  where Q is an orthogonal matrix. Rutishauser's algorithm is used to
207
  perform the reduction, which requires O(n**2) flops. The accumulation
208
  of the orthogonal factor Q, however, requires O(n**3) flops.
209
 
210
  Arguments
211
  =========
212
 
213
  N       (input) INTEGER
214
          The order of the matrix A.  N >= 0.
215
 
216
  D       (input/output) DOUBLE PRECISION array, dimension (N)
217
          On entry, the diagonal entries of the matrix A to be
218
          reduced.
219
          On exit, the diagonal entries of the reduced matrix T.
220
 
221
  E       (input/output) DOUBLE PRECISION array, dimension (N-1)
222
          On entry, the off-diagonal entries of the matrix A to be
223
          reduced.
224
          On exit, the subdiagonal entries of the reduced matrix T.
225
 
226
  Q       (input/output) DOUBLE PRECISION array, dimension (LDQ, N)
227
          On exit, the orthogonal matrix Q.
228
 
229
  LDQ     (input) INTEGER
230
          The leading dimension of the array Q.
231
 
232
  Note
233
  ====
234
  Based on Fortran code contributed by Daniel Kressner
2826 jroman 235
*/
2829 jroman 236
static PetscErrorCode ArrowTridiag(PetscBLASInt *n,PetscReal *d,PetscReal *e,PetscScalar *Q,PetscBLASInt *ldq)
2783 jroman 237
{
2833 jroman 238
#if defined(SLEPC_MISSING_LAPACK_LARTG)
239
  PetscFunctionBegin;
240
  SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"LARTG - Lapack routine is unavailable.");
241
#else
2829 jroman 242
  PetscBLASInt i,j,j2,ld=*ldq,one=1;
243
  PetscReal    c,s,p,off,temp;
244
 
245
  PetscFunctionBegin;
246
  if (*n<=2) PetscFunctionReturn(0);
247
 
248
  for (j=0;j<*n-2;j++) {
249
 
250
    /* Eliminate entry e(j) by a rotation in the planes (j,j+1) */
251
    temp = e[j+1];
252
    LAPACKlartg_(&temp,&e[j],&c,&s,&e[j+1]);
253
    s = -s;
254
 
255
    /* Apply rotation to diagonal elements */
256
    temp   = d[j+1];
257
    e[j]   = c*s*(temp-d[j]);
258
    d[j+1] = s*s*d[j] + c*c*temp;
259
    d[j]   = c*c*d[j] + s*s*temp;
260
 
261
    /* Apply rotation to Q */
262
    j2 = j+2;
263
    BLASrot_(&j2,Q+j*ld,&one,Q+(j+1)*ld,&one,&c,&s);
264
 
265
    /* Chase newly introduced off-diagonal entry to the top left corner */
266
    for (i=j-1;i>=0;i--) {
267
      off  = -s*e[i];
268
      e[i] = c*e[i];
269
      temp = e[i+1];
270
      LAPACKlartg_(&temp,&off,&c,&s,&e[i+1]);
271
      s = -s;
272
      temp = (d[i]-d[i+1])*s - 2.0*c*e[i];
273
      p = s*temp;
274
      d[i+1] += p;
275
      d[i] -= p;
276
      e[i] = -e[i] - c*temp;
277
      j2 = j+2;
278
      BLASrot_(&j2,Q+i*ld,&one,Q+(i+1)*ld,&one,&c,&s);
279
    }
280
  }
281
  PetscFunctionReturn(0);
2833 jroman 282
#endif
2829 jroman 283
}
284
 
2830 jroman 285
#if 0
2829 jroman 286
#undef __FUNCT__  
287
#define __FUNCT__ "PSIntermediate_HEP_Flip"
288
/*
289
   Reduce to tridiagonal form by flipping the matrix and using standard
290
   LAPACK tridiagonal reduction
291
*/
292
static PetscErrorCode PSIntermediate_HEP_Flip(PS ps)
293
{
2826 jroman 294
#if defined(SLEPC_MISSING_LAPACK_SYTRD) || defined(SLEPC_MISSING_LAPACK_ORGTR)
2783 jroman 295
  PetscFunctionBegin;
2826 jroman 296
  SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"SYTRD/ORGTR - Lapack routine is unavailable.");
2783 jroman 297
#else
298
  PetscErrorCode ierr;
2796 jroman 299
  PetscInt       i,j;
2826 jroman 300
  PetscBLASInt   n1,n2,n3,lwork,info,l,n,ld,off;
301
  PetscScalar    *A,*S,*Q,*work,*tau;
302
  PetscReal      *d,*e;
2783 jroman 303
 
304
  PetscFunctionBegin;
305
  n  = PetscBLASIntCast(ps->n);
2818 jroman 306
  l  = PetscBLASIntCast(ps->l);
2783 jroman 307
  ld = PetscBLASIntCast(ps->ld);
2818 jroman 308
  n1 = PetscBLASIntCast(ps->k-l+1);  /* size of leading block, excluding locked */
309
  n2 = PetscBLASIntCast(n-ps->k-1);  /* size of trailing block */
310
  n3 = n1+n2;
311
  off = l+l*ld;
2821 jroman 312
  A  = ps->mat[PS_MAT_A];
2789 jroman 313
  Q  = ps->mat[PS_MAT_Q];
2783 jroman 314
  d  = ps->rmat[PS_MAT_T];
315
  e  = ps->rmat[PS_MAT_T]+ld;
2818 jroman 316
  ierr = PetscMemzero(Q,ld*ld*sizeof(PetscScalar));CHKERRQ(ierr);
317
  for (i=0;i<n;i++) Q[i+i*ld] = 1.0;
2783 jroman 318
 
2796 jroman 319
  if (ps->compact) {
320
 
2787 jroman 321
    /* reduce to tridiagonal form */
2796 jroman 322
    if (ps->state<PS_STATE_INTERMEDIATE) {
323
 
324
      ierr = PSAllocateMat_Private(ps,PS_MAT_W);CHKERRQ(ierr);
325
      S = ps->mat[PS_MAT_W];
326
      ierr = PetscMemzero(S,ld*ld*sizeof(PetscScalar));CHKERRQ(ierr);
327
      ierr = PSAllocateWork_Private(ps,ld+ld*ld,0,0);CHKERRQ(ierr);
328
      tau  = ps->work;
329
      work = ps->work+ld;
330
      lwork = ld*ld;
331
 
332
      /* Flip matrix S */
2818 jroman 333
      for (i=l;i<n;i++) S[(n3-1-i+l)+(n3-1-i+l)*ld] = d[i];
334
      for (i=l;i<ps->k;i++) S[(n3-1-i+l)+(n3-1-ps->k+l)*ld] = e[i];
335
      for (i=ps->k;i<n-1;i++) S[(n3-1-i+l)+(n3-1-i-1+l)*ld] = e[i];
2796 jroman 336
 
337
      /* Reduce (2,2)-block of flipped S to tridiagonal form */
2818 jroman 338
      LAPACKsytrd_("L",&n1,S+n2+n2*ld,&ld,d+l,e+l,tau,work,&lwork,&info);
2796 jroman 339
      if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xSYTRD %d",info);
340
 
341
      /* Flip back diag and subdiag, put them in d and e */
2818 jroman 342
      for (i=0;i<n1-1;i++) {
343
        d[l+n1-i-1] = PetscRealPart(S[n2+i+(n2+i)*ld]);
344
        e[l+n1-i-2] = PetscRealPart(S[n2+i+1+(n2+i)*ld]);
2796 jroman 345
      }
2818 jroman 346
      d[l] = PetscRealPart(S[n3-1+(n3-1)*ld]);
2796 jroman 347
 
348
      /* Compute the orthogonal matrix used for tridiagonalization */
349
      LAPACKorgtr_("L",&n1,S+n2+n2*ld,&ld,tau,work,&lwork,&info);
350
      if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xORGTR %d",info);
351
 
352
      /* Create full-size Q, flipped back to original order */
353
      for (i=0;i<n1;i++)
354
        for (j=0;j<n1;j++)
2818 jroman 355
          Q[l+i+(l+j)*ld] = S[n3-i-1+(n3-j-1)*ld];
2796 jroman 356
 
357
    }
358
 
2787 jroman 359
  } else {
2796 jroman 360
 
2818 jroman 361
    for (i=0;i<l;i++) { d[i] = PetscRealPart(A[i+i*ld]); e[i] = 0.0; }
2796 jroman 362
 
363
    if (ps->state<PS_STATE_INTERMEDIATE) {
2821 jroman 364
      ierr = PSCopyMatrix_Private(ps,PS_MAT_Q,PS_MAT_A);CHKERRQ(ierr);
2796 jroman 365
      ierr = PSAllocateWork_Private(ps,ld+ld*ld,0,0);CHKERRQ(ierr);
366
      tau  = ps->work;
367
      work = ps->work+ld;
368
      lwork = ld*ld;
2818 jroman 369
      LAPACKsytrd_("L",&n3,Q+off,&ld,d+l,e+l,tau,work,&lwork,&info);
2796 jroman 370
      if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xSYTRD %d",info);
2818 jroman 371
      LAPACKorgtr_("L",&n3,Q+off,&ld,tau,work,&lwork,&info);
2796 jroman 372
      if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xORGTR %d",info);
373
    } else {
2818 jroman 374
      /* copy tridiagonal to d,e */
375
      for (i=l;i<n;i++) d[i] = PetscRealPart(A[i+i*ld]);
376
      for (i=l;i<n-1;i++) e[i] = PetscRealPart(A[(i+1)+i*ld]);
2796 jroman 377
    }
2783 jroman 378
  }
2826 jroman 379
  PetscFunctionReturn(0);
380
#endif
381
}
2830 jroman 382
#endif
2783 jroman 383
 
2826 jroman 384
#undef __FUNCT__  
2829 jroman 385
#define __FUNCT__ "PSIntermediate_HEP"
386
/*
387
   Reduce to tridiagonal form by means of ArrowTridiag.
388
*/
389
static PetscErrorCode PSIntermediate_HEP(PS ps)
390
{
391
#if defined(SLEPC_MISSING_LAPACK_SYTRD) || defined(SLEPC_MISSING_LAPACK_ORGTR)
392
  PetscFunctionBegin;
393
  SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"SYTRD/ORGTR - Lapack routine is unavailable.");
394
#else
395
  PetscErrorCode ierr;
2830 jroman 396
  PetscInt       i;
2829 jroman 397
  PetscBLASInt   n1,n2,n3,lwork,info,l,n,ld,off;
2830 jroman 398
  PetscScalar    *A,*Q,*work,*tau;
2829 jroman 399
  PetscReal      *d,*e;
400
 
401
  PetscFunctionBegin;
402
  n  = PetscBLASIntCast(ps->n);
403
  l  = PetscBLASIntCast(ps->l);
404
  ld = PetscBLASIntCast(ps->ld);
405
  n1 = PetscBLASIntCast(ps->k-l+1);  /* size of leading block, excluding locked */
406
  n2 = PetscBLASIntCast(n-ps->k-1);  /* size of trailing block */
407
  n3 = n1+n2;
408
  off = l+l*ld;
409
  A  = ps->mat[PS_MAT_A];
410
  Q  = ps->mat[PS_MAT_Q];
411
  d  = ps->rmat[PS_MAT_T];
412
  e  = ps->rmat[PS_MAT_T]+ld;
413
  ierr = PetscMemzero(Q,ld*ld*sizeof(PetscScalar));CHKERRQ(ierr);
414
  for (i=0;i<n;i++) Q[i+i*ld] = 1.0;
415
 
416
  if (ps->compact) {
417
 
418
    if (ps->state<PS_STATE_INTERMEDIATE) ArrowTridiag(&n1,d+l,e+l,Q+off,&ld);
419
 
420
  } else {
421
 
422
    for (i=0;i<l;i++) { d[i] = PetscRealPart(A[i+i*ld]); e[i] = 0.0; }
423
 
424
    if (ps->state<PS_STATE_INTERMEDIATE) {
425
      ierr = PSCopyMatrix_Private(ps,PS_MAT_Q,PS_MAT_A);CHKERRQ(ierr);
426
      ierr = PSAllocateWork_Private(ps,ld+ld*ld,0,0);CHKERRQ(ierr);
427
      tau  = ps->work;
428
      work = ps->work+ld;
429
      lwork = ld*ld;
430
      LAPACKsytrd_("L",&n3,Q+off,&ld,d+l,e+l,tau,work,&lwork,&info);
431
      if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xSYTRD %d",info);
432
      LAPACKorgtr_("L",&n3,Q+off,&ld,tau,work,&lwork,&info);
433
      if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xORGTR %d",info);
434
    } else {
435
      /* copy tridiagonal to d,e */
436
      for (i=l;i<n;i++) d[i] = PetscRealPart(A[i+i*ld]);
437
      for (i=l;i<n-1;i++) e[i] = PetscRealPart(A[(i+1)+i*ld]);
438
    }
439
  }
440
  PetscFunctionReturn(0);
441
#endif
442
}
443
 
444
#undef __FUNCT__  
2826 jroman 445
#define __FUNCT__ "PSSolve_HEP_QR"
446
PetscErrorCode PSSolve_HEP_QR(PS ps,PetscScalar *wr,PetscScalar *wi)
447
{
448
#if defined(SLEPC_MISSING_LAPACK_STEQR)
449
  PetscFunctionBegin;
450
  SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"STEQR - Lapack routine is unavailable.");
451
#else
452
  PetscErrorCode ierr;
453
  PetscInt       i;
454
  PetscBLASInt   n1,n2,n3,info,l,n,ld,off;
455
  PetscScalar    *A,*Q;
456
  PetscReal      *d,*e;
457
#if defined(PETSC_USE_COMPLEX)
458
  PetscReal      *ritz;
459
#endif
460
 
461
  PetscFunctionBegin;
462
  n  = PetscBLASIntCast(ps->n);
463
  l  = PetscBLASIntCast(ps->l);
464
  ld = PetscBLASIntCast(ps->ld);
465
  n1 = PetscBLASIntCast(ps->k-l+1);  /* size of leading block, excluding locked */
466
  n2 = PetscBLASIntCast(n-ps->k-1);  /* size of trailing block */
467
  n3 = n1+n2;
468
  off = l+l*ld;
469
  A  = ps->mat[PS_MAT_A];
470
  Q  = ps->mat[PS_MAT_Q];
471
  d  = ps->rmat[PS_MAT_T];
472
  e  = ps->rmat[PS_MAT_T]+ld;
473
 
474
  /* Reduce to tridiagonal form */
475
  ierr = PSIntermediate_HEP(ps);CHKERRQ(ierr);
476
 
2783 jroman 477
  /* Solve the tridiagonal eigenproblem */
2821 jroman 478
  for (i=0;i<l;i++) wr[i] = d[i];
2826 jroman 479
 
480
  ierr = PSAllocateWork_Private(ps,0,2*ld,0);CHKERRQ(ierr);
481
  LAPACKsteqr_("V",&n3,d+l,e+l,Q+off,&ld,ps->rwork,&info);
482
  if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xSTEQR %d",info);
483
  for (i=l;i<n;i++) wr[i] = d[i];
484
 
485
  if (ps->compact) {
486
    ierr = PetscMemzero(e,(n-1)*sizeof(PetscReal));CHKERRQ(ierr);
487
  } else {
488
    ierr = PetscMemzero(A,ld*ld*sizeof(PetscScalar));CHKERRQ(ierr);
489
    for (i=0;i<n;i++) A[i+i*ld] = d[i];
490
  }
491
  PetscFunctionReturn(0);
492
#endif
493
}
494
 
495
#undef __FUNCT__  
496
#define __FUNCT__ "PSSolve_HEP_MRRR"
497
PetscErrorCode PSSolve_HEP_MRRR(PS ps,PetscScalar *wr,PetscScalar *wi)
498
{
499
#if defined(SLEPC_MISSING_LAPACK_STEVR)
500
  PetscFunctionBegin;
501
  SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"STEVR - Lapack routine is unavailable.");
502
#else
503
  PetscErrorCode ierr;
2831 jroman 504
  PetscInt       i;
2826 jroman 505
  PetscBLASInt   n1,n2,n3,lwork,liwork,info,l,n,m,ld,off,il,iu,*isuppz;
506
  PetscScalar    *A,*Q,*W,one=1.0,zero=0.0;
507
  PetscReal      *d,*e,abstol=0.0,vl,vu;
2819 jroman 508
#if defined(PETSC_USE_COMPLEX)
2831 jroman 509
  PetscInt       j;
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;
707
  ps->ops->allocate      = PSAllocate_HEP;
708
  ps->ops->view          = PSView_HEP;
2807 jroman 709
  ps->ops->vectors       = PSVectors_HEP;
2832 jroman 710
  ps->ops->solve[0]      = PSSolve_HEP_QR;
711
  ps->ops->solve[1]      = PSSolve_HEP_MRRR;
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