Subversion Repositories slepc-dev

Rev

Go to most recent revision | 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
 
2830 jroman 288
#if 0
2829 jroman 289
#undef __FUNCT__  
290
#define __FUNCT__ "PSIntermediate_HEP_Flip"
291
/*
292
   Reduce to tridiagonal form by flipping the matrix and using standard
293
   LAPACK tridiagonal reduction
294
*/
295
static PetscErrorCode PSIntermediate_HEP_Flip(PS ps)
296
{
2826 jroman 297
#if defined(SLEPC_MISSING_LAPACK_SYTRD) || defined(SLEPC_MISSING_LAPACK_ORGTR)
2783 jroman 298
  PetscFunctionBegin;
2826 jroman 299
  SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"SYTRD/ORGTR - Lapack routine is unavailable.");
2783 jroman 300
#else
301
  PetscErrorCode ierr;
2796 jroman 302
  PetscInt       i,j;
2826 jroman 303
  PetscBLASInt   n1,n2,n3,lwork,info,l,n,ld,off;
304
  PetscScalar    *A,*S,*Q,*work,*tau;
305
  PetscReal      *d,*e;
2783 jroman 306
 
307
  PetscFunctionBegin;
308
  n  = PetscBLASIntCast(ps->n);
2818 jroman 309
  l  = PetscBLASIntCast(ps->l);
2783 jroman 310
  ld = PetscBLASIntCast(ps->ld);
2818 jroman 311
  n1 = PetscBLASIntCast(ps->k-l+1);  /* size of leading block, excluding locked */
312
  n2 = PetscBLASIntCast(n-ps->k-1);  /* size of trailing block */
313
  n3 = n1+n2;
314
  off = l+l*ld;
2821 jroman 315
  A  = ps->mat[PS_MAT_A];
2789 jroman 316
  Q  = ps->mat[PS_MAT_Q];
2783 jroman 317
  d  = ps->rmat[PS_MAT_T];
318
  e  = ps->rmat[PS_MAT_T]+ld;
2818 jroman 319
  ierr = PetscMemzero(Q,ld*ld*sizeof(PetscScalar));CHKERRQ(ierr);
320
  for (i=0;i<n;i++) Q[i+i*ld] = 1.0;
2783 jroman 321
 
2796 jroman 322
  if (ps->compact) {
323
 
2787 jroman 324
    /* reduce to tridiagonal form */
2796 jroman 325
    if (ps->state<PS_STATE_INTERMEDIATE) {
326
 
327
      ierr = PSAllocateMat_Private(ps,PS_MAT_W);CHKERRQ(ierr);
328
      S = ps->mat[PS_MAT_W];
329
      ierr = PetscMemzero(S,ld*ld*sizeof(PetscScalar));CHKERRQ(ierr);
330
      ierr = PSAllocateWork_Private(ps,ld+ld*ld,0,0);CHKERRQ(ierr);
331
      tau  = ps->work;
332
      work = ps->work+ld;
333
      lwork = ld*ld;
334
 
335
      /* Flip matrix S */
2818 jroman 336
      for (i=l;i<n;i++) S[(n3-1-i+l)+(n3-1-i+l)*ld] = d[i];
337
      for (i=l;i<ps->k;i++) S[(n3-1-i+l)+(n3-1-ps->k+l)*ld] = e[i];
338
      for (i=ps->k;i<n-1;i++) S[(n3-1-i+l)+(n3-1-i-1+l)*ld] = e[i];
2796 jroman 339
 
340
      /* Reduce (2,2)-block of flipped S to tridiagonal form */
2818 jroman 341
      LAPACKsytrd_("L",&n1,S+n2+n2*ld,&ld,d+l,e+l,tau,work,&lwork,&info);
2796 jroman 342
      if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xSYTRD %d",info);
343
 
344
      /* Flip back diag and subdiag, put them in d and e */
2818 jroman 345
      for (i=0;i<n1-1;i++) {
346
        d[l+n1-i-1] = PetscRealPart(S[n2+i+(n2+i)*ld]);
347
        e[l+n1-i-2] = PetscRealPart(S[n2+i+1+(n2+i)*ld]);
2796 jroman 348
      }
2818 jroman 349
      d[l] = PetscRealPart(S[n3-1+(n3-1)*ld]);
2796 jroman 350
 
351
      /* Compute the orthogonal matrix used for tridiagonalization */
352
      LAPACKorgtr_("L",&n1,S+n2+n2*ld,&ld,tau,work,&lwork,&info);
353
      if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xORGTR %d",info);
354
 
355
      /* Create full-size Q, flipped back to original order */
356
      for (i=0;i<n1;i++)
357
        for (j=0;j<n1;j++)
2818 jroman 358
          Q[l+i+(l+j)*ld] = S[n3-i-1+(n3-j-1)*ld];
2796 jroman 359
 
360
    }
361
 
2787 jroman 362
  } else {
2796 jroman 363
 
2818 jroman 364
    for (i=0;i<l;i++) { d[i] = PetscRealPart(A[i+i*ld]); e[i] = 0.0; }
2796 jroman 365
 
366
    if (ps->state<PS_STATE_INTERMEDIATE) {
2821 jroman 367
      ierr = PSCopyMatrix_Private(ps,PS_MAT_Q,PS_MAT_A);CHKERRQ(ierr);
2796 jroman 368
      ierr = PSAllocateWork_Private(ps,ld+ld*ld,0,0);CHKERRQ(ierr);
369
      tau  = ps->work;
370
      work = ps->work+ld;
371
      lwork = ld*ld;
2818 jroman 372
      LAPACKsytrd_("L",&n3,Q+off,&ld,d+l,e+l,tau,work,&lwork,&info);
2796 jroman 373
      if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xSYTRD %d",info);
2818 jroman 374
      LAPACKorgtr_("L",&n3,Q+off,&ld,tau,work,&lwork,&info);
2796 jroman 375
      if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xORGTR %d",info);
376
    } else {
2818 jroman 377
      /* copy tridiagonal to d,e */
378
      for (i=l;i<n;i++) d[i] = PetscRealPart(A[i+i*ld]);
379
      for (i=l;i<n-1;i++) e[i] = PetscRealPart(A[(i+1)+i*ld]);
2796 jroman 380
    }
2783 jroman 381
  }
2826 jroman 382
  PetscFunctionReturn(0);
383
#endif
384
}
2830 jroman 385
#endif
2783 jroman 386
 
2826 jroman 387
#undef __FUNCT__  
2829 jroman 388
#define __FUNCT__ "PSIntermediate_HEP"
389
/*
390
   Reduce to tridiagonal form by means of ArrowTridiag.
391
*/
392
static PetscErrorCode PSIntermediate_HEP(PS ps)
393
{
394
#if defined(SLEPC_MISSING_LAPACK_SYTRD) || defined(SLEPC_MISSING_LAPACK_ORGTR)
395
  PetscFunctionBegin;
396
  SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"SYTRD/ORGTR - Lapack routine is unavailable.");
397
#else
398
  PetscErrorCode ierr;
2830 jroman 399
  PetscInt       i;
2829 jroman 400
  PetscBLASInt   n1,n2,n3,lwork,info,l,n,ld,off;
2830 jroman 401
  PetscScalar    *A,*Q,*work,*tau;
2829 jroman 402
  PetscReal      *d,*e;
403
 
404
  PetscFunctionBegin;
405
  n  = PetscBLASIntCast(ps->n);
406
  l  = PetscBLASIntCast(ps->l);
407
  ld = PetscBLASIntCast(ps->ld);
408
  n1 = PetscBLASIntCast(ps->k-l+1);  /* size of leading block, excluding locked */
409
  n2 = PetscBLASIntCast(n-ps->k-1);  /* size of trailing block */
410
  n3 = n1+n2;
411
  off = l+l*ld;
412
  A  = ps->mat[PS_MAT_A];
413
  Q  = ps->mat[PS_MAT_Q];
414
  d  = ps->rmat[PS_MAT_T];
415
  e  = ps->rmat[PS_MAT_T]+ld;
416
  ierr = PetscMemzero(Q,ld*ld*sizeof(PetscScalar));CHKERRQ(ierr);
417
  for (i=0;i<n;i++) Q[i+i*ld] = 1.0;
418
 
419
  if (ps->compact) {
420
 
421
    if (ps->state<PS_STATE_INTERMEDIATE) ArrowTridiag(&n1,d+l,e+l,Q+off,&ld);
422
 
423
  } else {
424
 
425
    for (i=0;i<l;i++) { d[i] = PetscRealPart(A[i+i*ld]); e[i] = 0.0; }
426
 
427
    if (ps->state<PS_STATE_INTERMEDIATE) {
428
      ierr = PSCopyMatrix_Private(ps,PS_MAT_Q,PS_MAT_A);CHKERRQ(ierr);
429
      ierr = PSAllocateWork_Private(ps,ld+ld*ld,0,0);CHKERRQ(ierr);
430
      tau  = ps->work;
431
      work = ps->work+ld;
432
      lwork = ld*ld;
433
      LAPACKsytrd_("L",&n3,Q+off,&ld,d+l,e+l,tau,work,&lwork,&info);
434
      if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xSYTRD %d",info);
435
      LAPACKorgtr_("L",&n3,Q+off,&ld,tau,work,&lwork,&info);
436
      if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xORGTR %d",info);
437
    } else {
438
      /* copy tridiagonal to d,e */
439
      for (i=l;i<n;i++) d[i] = PetscRealPart(A[i+i*ld]);
440
      for (i=l;i<n-1;i++) e[i] = PetscRealPart(A[(i+1)+i*ld]);
441
    }
442
  }
443
  PetscFunctionReturn(0);
444
#endif
445
}
446
 
447
#undef __FUNCT__  
2826 jroman 448
#define __FUNCT__ "PSSolve_HEP_QR"
449
PetscErrorCode PSSolve_HEP_QR(PS ps,PetscScalar *wr,PetscScalar *wi)
450
{
451
#if defined(SLEPC_MISSING_LAPACK_STEQR)
452
  PetscFunctionBegin;
453
  SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"STEQR - Lapack routine is unavailable.");
454
#else
455
  PetscErrorCode ierr;
456
  PetscInt       i;
457
  PetscBLASInt   n1,n2,n3,info,l,n,ld,off;
458
  PetscScalar    *A,*Q;
459
  PetscReal      *d,*e;
460
#if defined(PETSC_USE_COMPLEX)
461
  PetscReal      *ritz;
462
#endif
463
 
464
  PetscFunctionBegin;
465
  n  = PetscBLASIntCast(ps->n);
466
  l  = PetscBLASIntCast(ps->l);
467
  ld = PetscBLASIntCast(ps->ld);
468
  n1 = PetscBLASIntCast(ps->k-l+1);  /* size of leading block, excluding locked */
469
  n2 = PetscBLASIntCast(n-ps->k-1);  /* size of trailing block */
470
  n3 = n1+n2;
471
  off = l+l*ld;
472
  A  = ps->mat[PS_MAT_A];
473
  Q  = ps->mat[PS_MAT_Q];
474
  d  = ps->rmat[PS_MAT_T];
475
  e  = ps->rmat[PS_MAT_T]+ld;
476
 
477
  /* Reduce to tridiagonal form */
478
  ierr = PSIntermediate_HEP(ps);CHKERRQ(ierr);
479
 
2783 jroman 480
  /* Solve the tridiagonal eigenproblem */
2821 jroman 481
  for (i=0;i<l;i++) wr[i] = d[i];
2826 jroman 482
 
483
  ierr = PSAllocateWork_Private(ps,0,2*ld,0);CHKERRQ(ierr);
484
  LAPACKsteqr_("V",&n3,d+l,e+l,Q+off,&ld,ps->rwork,&info);
485
  if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xSTEQR %d",info);
486
  for (i=l;i<n;i++) wr[i] = d[i];
487
 
488
  if (ps->compact) {
489
    ierr = PetscMemzero(e,(n-1)*sizeof(PetscReal));CHKERRQ(ierr);
490
  } else {
491
    ierr = PetscMemzero(A,ld*ld*sizeof(PetscScalar));CHKERRQ(ierr);
492
    for (i=0;i<n;i++) A[i+i*ld] = d[i];
493
  }
494
  PetscFunctionReturn(0);
495
#endif
496
}
497
 
498
#undef __FUNCT__  
499
#define __FUNCT__ "PSSolve_HEP_MRRR"
500
PetscErrorCode PSSolve_HEP_MRRR(PS ps,PetscScalar *wr,PetscScalar *wi)
501
{
502
#if defined(SLEPC_MISSING_LAPACK_STEVR)
503
  PetscFunctionBegin;
504
  SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"STEVR - Lapack routine is unavailable.");
505
#else
506
  PetscErrorCode ierr;
2831 jroman 507
  PetscInt       i;
2826 jroman 508
  PetscBLASInt   n1,n2,n3,lwork,liwork,info,l,n,m,ld,off,il,iu,*isuppz;
509
  PetscScalar    *A,*Q,*W,one=1.0,zero=0.0;
510
  PetscReal      *d,*e,abstol=0.0,vl,vu;
2819 jroman 511
#if defined(PETSC_USE_COMPLEX)
2831 jroman 512
  PetscInt       j;
2826 jroman 513
  PetscReal      *ritz;
2819 jroman 514
#endif
2826 jroman 515
 
516
  PetscFunctionBegin;
517
  n  = PetscBLASIntCast(ps->n);
518
  l  = PetscBLASIntCast(ps->l);
519
  ld = PetscBLASIntCast(ps->ld);
520
  n1 = PetscBLASIntCast(ps->k-l+1);  /* size of leading block, excluding locked */
521
  n2 = PetscBLASIntCast(n-ps->k-1);  /* size of trailing block */
522
  n3 = n1+n2;
523
  off = l+l*ld;
524
  A  = ps->mat[PS_MAT_A];
525
  Q  = ps->mat[PS_MAT_Q];
526
  d  = ps->rmat[PS_MAT_T];
527
  e  = ps->rmat[PS_MAT_T]+ld;
528
 
529
  /* Reduce to tridiagonal form */
530
  ierr = PSIntermediate_HEP(ps);CHKERRQ(ierr);
531
 
532
  /* Solve the tridiagonal eigenproblem */
533
  for (i=0;i<l;i++) wr[i] = d[i];
534
 
535
  if (ps->state<PS_STATE_INTERMEDIATE) {  /* Q contains useful info */
536
    ierr = PSAllocateMat_Private(ps,PS_MAT_W);CHKERRQ(ierr);
537
    W = ps->mat[PS_MAT_W];
538
    ierr = PSCopyMatrix_Private(ps,PS_MAT_W,PS_MAT_Q);CHKERRQ(ierr);
539
  }
2819 jroman 540
#if defined(PETSC_USE_COMPLEX)
2826 jroman 541
  ierr = PSAllocateMatReal_Private(ps,PS_MAT_Q);CHKERRQ(ierr);
542
#endif
543
  lwork = 20*ld;
544
  liwork = 10*ld;
545
  ierr = PSAllocateWork_Private(ps,0,lwork+ld,liwork+2*ld);CHKERRQ(ierr);
546
  isuppz = ps->iwork+liwork;
547
#if defined(PETSC_USE_COMPLEX)
548
  ritz = ps->rwork+lwork;
549
  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);
550
  for (i=l;i<n;i++) wr[i] = ritz[i];
2819 jroman 551
#else
2826 jroman 552
  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 553
#endif
2826 jroman 554
  if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack DSTEVR %d",info);
2819 jroman 555
#if defined(PETSC_USE_COMPLEX)
2826 jroman 556
  for (i=l;i<n;i++)
557
    for (j=l;j<n;j++)
558
      Q[i+j*ld] = (ps->rmat[PS_MAT_Q])[i+j*ld];
2819 jroman 559
#endif
2826 jroman 560
  if (ps->state<PS_STATE_INTERMEDIATE) {  /* accumulate previous Q */
561
    BLASgemm_("N","N",&n3,&n3,&n3,&one,W+off,&ld,Q+off,&ld,&zero,A+off,&ld);
562
    ierr = PSCopyMatrix_Private(ps,PS_MAT_Q,PS_MAT_A);CHKERRQ(ierr);
2819 jroman 563
  }
2826 jroman 564
  for (i=l;i<n;i++) d[i] = wr[i];
565
 
2796 jroman 566
  if (ps->compact) {
567
    ierr = PetscMemzero(e,(n-1)*sizeof(PetscReal));CHKERRQ(ierr);
568
  } else {
569
    ierr = PetscMemzero(A,ld*ld*sizeof(PetscScalar));CHKERRQ(ierr);
570
    for (i=0;i<n;i++) A[i+i*ld] = d[i];
571
  }
2783 jroman 572
  PetscFunctionReturn(0);
573
#endif
574
}
575
 
576
#undef __FUNCT__  
577
#define __FUNCT__ "PSSort_HEP"
578
PetscErrorCode PSSort_HEP(PS ps,PetscScalar *wr,PetscScalar *wi,PetscErrorCode (*comp_func)(PetscScalar,PetscScalar,PetscScalar,PetscScalar,PetscInt*,void*),void *comp_ctx)
579
{
580
  PetscErrorCode ierr;
2818 jroman 581
  PetscInt       n,l,i,*perm;
2792 jroman 582
  PetscScalar    *A;
2791 jroman 583
  PetscReal      *d;
2783 jroman 584
 
585
  PetscFunctionBegin;
2791 jroman 586
  n = ps->n;
2818 jroman 587
  l = ps->l;
2791 jroman 588
  d = ps->rmat[PS_MAT_T];
589
  ierr = PSAllocateWork_Private(ps,0,0,ps->ld);CHKERRQ(ierr);
2783 jroman 590
  perm = ps->iwork;
2818 jroman 591
  ierr = PSSortEigenvaluesReal_Private(ps,l,n,d,perm,comp_func,comp_ctx);CHKERRQ(ierr);
592
  for (i=l;i<n;i++) wr[i] = d[perm[i]];
593
  ierr = PSPermuteColumns_Private(ps,l,n,PS_MAT_Q,perm);CHKERRQ(ierr);
2796 jroman 594
  if (ps->compact) {
2818 jroman 595
    for (i=l;i<n;i++) d[i] = PetscRealPart(wr[i]);
2796 jroman 596
  } else {
597
    A  = ps->mat[PS_MAT_A];
2818 jroman 598
    for (i=l;i<n;i++) A[i+i*ps->ld] = wr[i];
2796 jroman 599
  }
2783 jroman 600
  PetscFunctionReturn(0);
601
}
602
 
603
#undef __FUNCT__  
604
#define __FUNCT__ "PSCond_HEP"
605
PetscErrorCode PSCond_HEP(PS ps,PetscReal *cond)
606
{
607
#if defined(PETSC_MISSING_LAPACK_GETRF) || defined(SLEPC_MISSING_LAPACK_GETRI) || defined(SLEPC_MISSING_LAPACK_LANGE) || defined(SLEPC_MISSING_LAPACK_LANHS)
608
  PetscFunctionBegin;
609
  SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"GETRF/GETRI/LANGE/LANHS - Lapack routines are unavailable.");
610
#else
611
  PetscErrorCode ierr;
612
  PetscScalar    *work;
613
  PetscReal      *rwork;
614
  PetscBLASInt   *ipiv;
615
  PetscBLASInt   lwork,info,n,ld;
616
  PetscReal      hn,hin;
617
  PetscScalar    *A;
618
 
619
  PetscFunctionBegin;
620
  n  = PetscBLASIntCast(ps->n);
621
  ld = PetscBLASIntCast(ps->ld);
622
  lwork = 8*ld;
623
  ierr = PSAllocateWork_Private(ps,lwork,ld,ld);CHKERRQ(ierr);
624
  work  = ps->work;
625
  rwork = ps->rwork;
626
  ipiv  = ps->iwork;
2813 jroman 627
  ierr = PSSwitchFormat_HEP(ps,PETSC_FALSE);CHKERRQ(ierr);
2783 jroman 628
 
629
  /* use workspace matrix W to avoid overwriting A */
2793 jroman 630
  ierr = PSAllocateMat_Private(ps,PS_MAT_W);CHKERRQ(ierr);
2783 jroman 631
  A = ps->mat[PS_MAT_W];
632
  ierr = PetscMemcpy(A,ps->mat[PS_MAT_A],sizeof(PetscScalar)*ps->ld*ps->ld);CHKERRQ(ierr);
633
 
634
  /* norm of A */
635
  hn = LAPACKlange_("I",&n,&n,A,&ld,rwork);
636
 
637
  /* norm of inv(A) */
638
  LAPACKgetrf_(&n,&n,A,&ld,ipiv,&info);
639
  if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xGETRF %d",info);
640
  LAPACKgetri_(&n,A,&ld,ipiv,work,&lwork,&info);
641
  if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xGETRI %d",info);
642
  hin = LAPACKlange_("I",&n,&n,A,&ld,rwork);
643
 
644
  *cond = hn*hin;
645
  PetscFunctionReturn(0);
646
#endif
647
}
648
 
2814 jroman 649
#undef __FUNCT__  
650
#define __FUNCT__ "PSTranslateRKS_HEP"
651
PetscErrorCode PSTranslateRKS_HEP(PS ps,PetscScalar alpha)
652
{
653
#if defined(PETSC_MISSING_LAPACK_GEQRF) || defined(SLEPC_MISSING_LAPACK_ORGQR)
654
  PetscFunctionBegin;
655
  SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"GEQRF/ORGQR - Lapack routines are unavailable.");
656
#else
657
  PetscErrorCode ierr;
658
  PetscInt       i,j,k=ps->k;
659
  PetscScalar    *Q,*A,*R,*tau,*work;
660
  PetscBLASInt   ld,n1,n0,lwork,info;
661
 
662
  PetscFunctionBegin;
663
  ld = PetscBLASIntCast(ps->ld);
664
  ierr = PSAllocateWork_Private(ps,ld*ld,0,0);CHKERRQ(ierr);
665
  tau = ps->work;
666
  work = ps->work+ld;
667
  lwork = PetscBLASIntCast(ld*(ld-1));
668
  ierr = PSAllocateMat_Private(ps,PS_MAT_W);CHKERRQ(ierr);
669
  A  = ps->mat[PS_MAT_A];
670
  Q  = ps->mat[PS_MAT_Q];
671
  R  = ps->mat[PS_MAT_W];
672
  /* Copy I+alpha*A */
673
  ierr = PetscMemzero(Q,ld*ld*sizeof(PetscScalar));CHKERRQ(ierr);
674
  ierr = PetscMemzero(R,ld*ld*sizeof(PetscScalar));CHKERRQ(ierr);
675
  for (i=0;i<k;i++) {
676
    Q[i+i*ld] = 1.0 + alpha*A[i+i*ld];
677
    Q[k+i*ld] = alpha*A[k+i*ld];
678
  }
679
  /* Compute qr */
680
  n1 = PetscBLASIntCast(k+1);
681
  n0 = PetscBLASIntCast(k);
682
  LAPACKgeqrf_(&n1,&n0,Q,&ld,tau,work,&lwork,&info);
683
  if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xGEQRF %d",info);
684
  /* Copy R from Q */
685
  for (j=0;j<k;j++)
686
    for(i=0;i<=j;i++)
687
      R[i+j*ld] = Q[i+j*ld];
688
  /* Compute orthogonal matrix in Q */
689
  LAPACKorgqr_(&n1,&n1,&n0,Q,&ld,tau,work,&lwork,&info);
690
  if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xORGQR %d",info);
691
  /* Compute the updated matrix of projected problem */
692
  for(j=0;j<k;j++){
693
    for(i=0;i<k+1;i++)
694
      A[j*ld+i] = Q[i*ld+j];
695
  }
696
  alpha = -1.0/alpha;
697
  BLAStrsm_("R","U","N","N",&n1,&n0,&alpha,R,&ld,A,&ld);
698
  for(i=0;i<k;i++)
699
    A[ld*i+i]-=alpha;
700
  PetscFunctionReturn(0);
701
#endif
702
}
703
 
2783 jroman 704
EXTERN_C_BEGIN
705
#undef __FUNCT__  
706
#define __FUNCT__ "PSCreate_HEP"
707
PetscErrorCode PSCreate_HEP(PS ps)
708
{
709
  PetscFunctionBegin;
2819 jroman 710
  ps->nmeth  = 2;
2783 jroman 711
  ps->ops->allocate      = PSAllocate_HEP;
712
  ps->ops->view          = PSView_HEP;
2807 jroman 713
  ps->ops->vectors       = PSVectors_HEP;
2826 jroman 714
  ps->ops->solve         = solve[ps->method];
2783 jroman 715
  ps->ops->sort          = PSSort_HEP;
716
  ps->ops->cond          = PSCond_HEP;
2814 jroman 717
  ps->ops->transrks      = PSTranslateRKS_HEP;
2783 jroman 718
  PetscFunctionReturn(0);
719
}
720
EXTERN_C_END
721