Subversion Repositories slepc-dev

Rev

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

Rev Author Line No. Line
2758 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*/
2763 jroman 23
#include <slepcblaslapack.h>
2758 jroman 24
 
25
#undef __FUNCT__  
26
#define __FUNCT__ "PSAllocate_NHEP"
27
PetscErrorCode PSAllocate_NHEP(PS ps,PetscInt ld)
28
{
29
  PetscErrorCode ierr;
30
 
31
  PetscFunctionBegin;
32
  ierr = PSAllocateMat_Private(ps,PS_MAT_A);CHKERRQ(ierr);
33
  ierr = PSAllocateMat_Private(ps,PS_MAT_Q);CHKERRQ(ierr);
34
  PetscFunctionReturn(0);
35
}
36
 
2759 jroman 37
#undef __FUNCT__  
2777 jroman 38
#define __FUNCT__ "PSView_NHEP"
39
PetscErrorCode PSView_NHEP(PS ps,PetscViewer viewer)
40
{
41
  PetscErrorCode ierr;
42
 
43
  PetscFunctionBegin;
44
  ierr = PSViewMat_Private(ps,viewer,PS_MAT_A);CHKERRQ(ierr);
2784 jroman 45
  if (ps->state>PS_STATE_INTERMEDIATE) {
46
    ierr = PSViewMat_Private(ps,viewer,PS_MAT_Q);CHKERRQ(ierr);
47
  }
2777 jroman 48
  PetscFunctionReturn(0);
49
}
50
 
51
#undef __FUNCT__  
2807 jroman 52
#define __FUNCT__ "PSVectors_NHEP_Eigen_Some"
53
PetscErrorCode PSVectors_NHEP_Eigen_Some(PS ps,PetscInt *k,PetscReal *rnorm,PetscBool left)
54
{
55
#if defined(SLEPC_MISSING_LAPACK_TREVC)
56
  PetscFunctionBegin;
57
  SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"TREVC - Lapack routine is unavailable.");
58
#else
59
  PetscErrorCode ierr;
60
  PetscInt       i;
61
  PetscBLASInt   mm,mout,info,ld,n,inc = 1;
62
  PetscScalar    tmp,done=1.0,zero=0.0;
63
  PetscReal      norm;
64
  PetscBool      iscomplex = PETSC_FALSE;
65
  PetscBLASInt   *select;
66
  PetscScalar    *A = ps->mat[PS_MAT_A];
67
  PetscScalar    *Q = ps->mat[PS_MAT_Q];
68
  PetscScalar    *X = ps->mat[PS_MAT_X];
69
  PetscScalar    *Y;
70
#if defined(PETSC_USE_COMPLEX)
71
  PetscReal      *rwork;
72
#endif
73
 
74
  PetscFunctionBegin;
75
  if (ps->state<PS_STATE_CONDENSED) SETERRQ(((PetscObject)ps)->comm,PETSC_ERR_ORDER,"Must call PSSolve() first");
76
  if (left) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented for left eigenvectors");
77
  n  = PetscBLASIntCast(ps->n);
78
  ld = PetscBLASIntCast(ps->ld);
79
  if ((*k)<n-1 && A[(*k)+1+(*k)*ld]!=0.0) iscomplex = PETSC_TRUE;
80
  ierr = PSAllocateWork_Private(ps,0,0,ld);CHKERRQ(ierr);
81
  select = ps->iwork;
82
  for (i=0;i<n;i++) select[i] = (PetscBLASInt)PETSC_FALSE;
83
 
84
  /* Compute k-th eigenvector Y of A */
85
  Y = X+(*k)*ld;
86
  mm = iscomplex? 2: 1;
87
  select[*k] = (PetscBLASInt)PETSC_TRUE;
88
#if !defined(PETSC_USE_COMPLEX)
89
  if (iscomplex) select[(*k)+1] = (PetscBLASInt)PETSC_TRUE;
90
  ierr = PSAllocateWork_Private(ps,3*ld,0,0);CHKERRQ(ierr);
91
  LAPACKtrevc_("R","S",select,&n,A,&ld,PETSC_NULL,&ld,Y,&ld,&mm,&mout,ps->work,&info);
92
#else
93
  ierr = PSAllocateWork_Private(ps,2*ld,ld,0);CHKERRQ(ierr);
94
  LAPACKtrevc_("R","S",select,&n,A,&ld,PETSC_NULL,&ld,Y,&ld,&mm,&mout,ps->work,ps->rwork,&info);
95
#endif
96
  if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xTREVC %d",info);
97
  if (mout != mm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Inconsistent arguments");
98
  ierr = PetscMemcpy(ps->work,Y,mout*ld*sizeof(PetscScalar));CHKERRQ(ierr);
99
 
100
  /* accumulate and normalize eigenvectors */
101
  BLASgemv_("N",&n,&n,&done,Q,&ld,ps->work,&inc,&zero,Y,&inc);
102
#if !defined(PETSC_USE_COMPLEX)
103
  if (iscomplex) BLASgemv_("N",&n,&n,&done,Q,&ld,ps->work+ld,&inc,&zero,Y+ld,&inc);
104
#endif
105
  norm = BLASnrm2_(&n,Y,&inc);
106
#if !defined(PETSC_USE_COMPLEX)
107
  tmp  = BLASnrm2_(&n,Y+ld,&inc);
108
  norm = SlepcAbsEigenvalue(norm,tmp);
109
#endif
110
  tmp = 1.0 / norm;
111
  BLASscal_(&n,&tmp,Y,&inc);
112
#if !defined(PETSC_USE_COMPLEX)
113
  BLASscal_(&n,&tmp,Y+ld,&inc);
114
#endif
115
 
116
  /* set output arguments */
117
  if (iscomplex) (*k)++;
118
  if (rnorm) {
119
    if (iscomplex) *rnorm = SlepcAbsEigenvalue(Y[n-1],Y[n-1+ld]);
120
    else *rnorm = PetscAbsScalar(Y[n-1]);
121
  }
122
  PetscFunctionReturn(0);
123
#endif
124
}
125
 
126
#undef __FUNCT__  
127
#define __FUNCT__ "PSVectors_NHEP_Eigen_All"
128
PetscErrorCode PSVectors_NHEP_Eigen_All(PS ps,PetscBool left)
129
{
130
#if defined(SLEPC_MISSING_LAPACK_TREVC)
131
  PetscFunctionBegin;
132
  SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"TREVC - Lapack routine is unavailable.");
133
#else
134
  PetscErrorCode ierr;
135
  PetscBLASInt   n,ld,mout,info;
136
  PetscScalar    *A = ps->mat[PS_MAT_A];
137
  PetscScalar    *Q = ps->mat[PS_MAT_Q];
138
  PetscScalar    *X,*Y;
139
  const char     *side;
140
 
141
  PetscFunctionBegin;
142
  if (ps->state<PS_STATE_CONDENSED) SETERRQ(((PetscObject)ps)->comm,PETSC_ERR_ORDER,"Must call PSSolve() first");
143
  n  = PetscBLASIntCast(ps->n);
144
  ld = PetscBLASIntCast(ps->ld);
145
  if (left) {
146
    X = PETSC_NULL;
147
    Y = ps->mat[PS_MAT_Y];
148
    side = "L";
149
    ierr = PetscMemcpy(Y,Q,ld*ld*sizeof(PetscScalar));CHKERRQ(ierr);
150
  } else {
151
    X = ps->mat[PS_MAT_X];
152
    Y = PETSC_NULL;
153
    side = "R";
154
    ierr = PetscMemcpy(X,Q,ld*ld*sizeof(PetscScalar));CHKERRQ(ierr);
155
  }
156
#if !defined(PETSC_USE_COMPLEX)
157
  ierr = PSAllocateWork_Private(ps,3*ld,0,0);CHKERRQ(ierr);
158
  LAPACKtrevc_(side,"B",PETSC_NULL,&n,A,&ld,Y,&ld,X,&ld,&n,&mout,ps->work,&info);
159
#else
160
  ierr = PSAllocateWork_Private(ps,2*ld,ld,0);CHKERRQ(ierr);
161
  LAPACKtrevc_(side,"B",PETSC_NULL,&n,A,&ld,Y,&ld,X,&ld,&n,&mout,ps->work,ps->rwork,&info);
162
#endif
163
  if (info) SETERRQ1(((PetscObject)ps)->comm,PETSC_ERR_LIB,"Error in Lapack xTREVC %i",info);
164
  PetscFunctionReturn(0);
165
#endif
166
}
167
 
168
#undef __FUNCT__  
169
#define __FUNCT__ "PSVectors_NHEP"
170
PetscErrorCode PSVectors_NHEP(PS ps,PSMatType mat,PetscInt *k,PetscReal *rnorm)
171
{
172
  PetscErrorCode ierr;
173
 
174
  PetscFunctionBegin;
175
  switch (mat) {
176
    case PS_MAT_X:
177
      if (k) {
178
        ierr = PSVectors_NHEP_Eigen_Some(ps,k,rnorm,PETSC_FALSE);CHKERRQ(ierr);
179
      } else {
180
        ierr = PSVectors_NHEP_Eigen_All(ps,PETSC_FALSE);CHKERRQ(ierr);
181
      }
182
      break;
183
    case PS_MAT_Y:
184
      if (k) {
185
        ierr = PSVectors_NHEP_Eigen_Some(ps,k,rnorm,PETSC_TRUE);CHKERRQ(ierr);
186
      } else {
187
        ierr = PSVectors_NHEP_Eigen_All(ps,PETSC_TRUE);CHKERRQ(ierr);
188
      }
189
      break;
190
    case PS_MAT_U:
191
    case PS_MAT_VT:
192
      SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented yet");
193
      break;
194
    default:
195
      SETERRQ(((PetscObject)ps)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Invalid mat parameter");
196
  }
197
  PetscFunctionReturn(0);
198
}
199
 
200
#undef __FUNCT__  
2759 jroman 201
#define __FUNCT__ "PSSolve_NHEP"
2764 jroman 202
PetscErrorCode PSSolve_NHEP(PS ps,PetscScalar *wr,PetscScalar *wi)
2759 jroman 203
{
2764 jroman 204
#if defined(SLEPC_MISSING_LAPACK_GEHRD) || defined(SLEPC_MISSING_LAPACK_ORGHR) || defined(PETSC_MISSING_LAPACK_HSEQR)
205
  PetscFunctionBegin;
206
  SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"GEHRD/ORGHR/HSEQR - Lapack routines are unavailable.");
207
#else
2767 jroman 208
  PetscErrorCode ierr;
2770 jroman 209
  PetscScalar    *work,*tau;
2764 jroman 210
  PetscInt       i,j;
2767 jroman 211
  PetscBLASInt   ilo,lwork,info,n,ld;
2764 jroman 212
  PetscScalar    *A = ps->mat[PS_MAT_A];
213
  PetscScalar    *Q = ps->mat[PS_MAT_Q];
2759 jroman 214
 
215
  PetscFunctionBegin;
2775 jroman 216
  PetscValidPointer(wi,2);
2767 jroman 217
  n   = PetscBLASIntCast(ps->n);
218
  ld  = PetscBLASIntCast(ps->ld);
2764 jroman 219
  ilo = PetscBLASIntCast(ps->l+1);
2782 jroman 220
  ierr = PSAllocateWork_Private(ps,ld+ld*ld,0,0);CHKERRQ(ierr);
221
  tau  = ps->work;
222
  work = ps->work+ld;
223
  lwork = ld*ld;
224
 
225
  /* initialize orthogonal matrix */
226
  ierr = PetscMemzero(Q,ld*ld*sizeof(PetscScalar));CHKERRQ(ierr);
227
  for (i=0;i<n;i++)
228
    Q[i+i*ld] = 1.0;
229
  if (n==1) PetscFunctionReturn(0);    
230
 
2764 jroman 231
  /* reduce to upper Hessenberg form */
2763 jroman 232
  if (ps->state<PS_STATE_INTERMEDIATE) {
2767 jroman 233
    LAPACKgehrd_(&n,&ilo,&n,A,&ld,tau,work,&lwork,&info);
2764 jroman 234
    if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xGEHRD %d",info);
235
    for (j=0;j<n-1;j++) {
236
      for (i=j+2;i<n;i++) {
2767 jroman 237
        Q[i+j*ld] = A[i+j*ld];
238
        A[i+j*ld] = 0.0;
2764 jroman 239
      }
240
    }
2767 jroman 241
    LAPACKorghr_(&n,&ilo,&n,Q,&ld,tau,work,&lwork,&info);
2764 jroman 242
    if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xORGHR %d",info);
2759 jroman 243
  }
2782 jroman 244
 
2764 jroman 245
  /* compute the (real) Schur form */
246
#if !defined(PETSC_USE_COMPLEX)
2783 jroman 247
  LAPACKhseqr_("S","V",&n,&ilo,&n,A,&ld,wr,wi,Q,&ld,work,&lwork,&info);
248
  for (j=0;j<ps->l;j++) {
249
    if (j==n-1 || A[j+1+j*ld] == 0.0) {
250
      /* real eigenvalue */
251
      wr[j] = A[j+j*ld];
252
      wi[j] = 0.0;
253
    } else {
254
      /* complex eigenvalue */
255
      wr[j] = A[j+j*ld];
256
      wr[j+1] = A[j+j*ld];
257
      wi[j] = PetscSqrtReal(PetscAbsReal(A[j+1+j*ld])) *
258
              PetscSqrtReal(PetscAbsReal(A[j+(j+1)*ld]));
259
      wi[j+1] = -wi[j];
260
      j++;
2764 jroman 261
    }
2783 jroman 262
  }
2764 jroman 263
#else
2783 jroman 264
  LAPACKhseqr_("S","V",&n,&ilo,&n,A,&ld,wr,Q,&ld,work,&lwork,&info);
2764 jroman 265
#endif
2783 jroman 266
  if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xHSEQR %d",info);
2759 jroman 267
  PetscFunctionReturn(0);
2764 jroman 268
#endif
2759 jroman 269
}
270
 
271
#undef __FUNCT__  
272
#define __FUNCT__ "PSSort_NHEP"
2763 jroman 273
PetscErrorCode PSSort_NHEP(PS ps,PetscScalar *wr,PetscScalar *wi,PetscErrorCode (*comp_func)(PetscScalar,PetscScalar,PetscScalar,PetscScalar,PetscInt*,void*),void *comp_ctx)
2759 jroman 274
{
2763 jroman 275
#if defined(SLEPC_MISSING_LAPACK_TREXC)
276
  PetscFunctionBegin;
277
  SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"TREXC - Lapack routine is unavailable.");
278
#else
2759 jroman 279
  PetscErrorCode ierr;
2763 jroman 280
  PetscScalar    re,im;
281
  PetscInt       i,j,pos,result;
2767 jroman 282
  PetscBLASInt   ifst,ilst,info,n,ld;
2763 jroman 283
  PetscScalar    *T = ps->mat[PS_MAT_A];
284
  PetscScalar    *Q = ps->mat[PS_MAT_Q];
285
#if !defined(PETSC_USE_COMPLEX)
2770 jroman 286
  PetscScalar    *work;
2763 jroman 287
#endif
2759 jroman 288
 
289
  PetscFunctionBegin;
2775 jroman 290
  PetscValidPointer(wi,2);
2767 jroman 291
  n  = PetscBLASIntCast(ps->n);
292
  ld = PetscBLASIntCast(ps->ld);
2770 jroman 293
#if !defined(PETSC_USE_COMPLEX)
294
  ierr = PSAllocateWork_Private(ps,ld,0,0);CHKERRQ(ierr);
295
  work = ps->work;
296
#endif
2763 jroman 297
  /* selection sort */
298
  for (i=ps->l;i<n-1;i++) {
299
    re = wr[i];
300
    im = wi[i];
301
    pos = 0;
302
    j=i+1; /* j points to the next eigenvalue */
303
#if !defined(PETSC_USE_COMPLEX)
304
    if (im != 0) j=i+2;
305
#endif
306
    /* find minimum eigenvalue */
307
    for (;j<n;j++) {
308
      ierr = (*comp_func)(re,im,wr[j],wi[j],&result,comp_ctx);CHKERRQ(ierr);
309
      if (result > 0) {
310
        re = wr[j];
311
        im = wi[j];
312
        pos = j;
313
      }
314
#if !defined(PETSC_USE_COMPLEX)
315
      if (wi[j] != 0) j++;
316
#endif
317
    }
318
    if (pos) {
319
      /* interchange blocks */
2767 jroman 320
      ifst = PetscBLASIntCast(pos+1);
321
      ilst = PetscBLASIntCast(i+1);
2763 jroman 322
#if !defined(PETSC_USE_COMPLEX)
2767 jroman 323
      LAPACKtrexc_("V",&n,T,&ld,Q,&ld,&ifst,&ilst,work,&info);
2763 jroman 324
#else
2767 jroman 325
      LAPACKtrexc_("V",&n,T,&ld,Q,&ld,&ifst,&ilst,&info);
2763 jroman 326
#endif
327
      if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xTREXC %d",info);
328
      /* recover original eigenvalues from T matrix */
329
      for (j=i;j<n;j++) {
2767 jroman 330
        wr[j] = T[j+j*ld];
2763 jroman 331
#if !defined(PETSC_USE_COMPLEX)
2767 jroman 332
        if (j<n-1 && T[j+1+j*ld] != 0.0) {
2763 jroman 333
          /* complex conjugate eigenvalue */
2767 jroman 334
          wi[j] = PetscSqrtReal(PetscAbsReal(T[j+1+j*ld])) *
335
                  PetscSqrtReal(PetscAbsReal(T[j+(j+1)*ld]));
2763 jroman 336
          wr[j+1] = wr[j];
337
          wi[j+1] = -wi[j];
338
          j++;
339
        } else
340
#endif
341
        wi[j] = 0.0;
342
      }
343
    }
344
#if !defined(PETSC_USE_COMPLEX)
345
    if (wi[i] != 0) i++;
346
#endif
347
  }
2759 jroman 348
  PetscFunctionReturn(0);
2763 jroman 349
#endif
2759 jroman 350
}
351
 
2766 jroman 352
#undef __FUNCT__  
353
#define __FUNCT__ "PSCond_NHEP"
354
PetscErrorCode PSCond_NHEP(PS ps,PetscReal *cond)
355
{
356
#if defined(PETSC_MISSING_LAPACK_GETRF) || defined(SLEPC_MISSING_LAPACK_GETRI) || defined(SLEPC_MISSING_LAPACK_LANGE) || defined(SLEPC_MISSING_LAPACK_LANHS)
357
  PetscFunctionBegin;
358
  SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"GETRF/GETRI/LANGE/LANHS - Lapack routines are unavailable.");
359
#else
360
  PetscErrorCode ierr;
2770 jroman 361
  PetscScalar    *work;
362
  PetscReal      *rwork;
363
  PetscBLASInt   *ipiv;
2767 jroman 364
  PetscBLASInt   lwork,info,n,ld;
2766 jroman 365
  PetscReal      hn,hin;
366
  PetscScalar    *A;
367
 
368
  PetscFunctionBegin;
2767 jroman 369
  n  = PetscBLASIntCast(ps->n);
370
  ld = PetscBLASIntCast(ps->ld);
2770 jroman 371
  lwork = 8*ld;
372
  ierr = PSAllocateWork_Private(ps,lwork,ld,ld);CHKERRQ(ierr);
373
  work  = ps->work;
374
  rwork = ps->rwork;
375
  ipiv  = ps->iwork;
2766 jroman 376
 
377
  /* use workspace matrix W to avoid overwriting A */
2793 jroman 378
  ierr = PSAllocateMat_Private(ps,PS_MAT_W);CHKERRQ(ierr);
2766 jroman 379
  A = ps->mat[PS_MAT_W];
380
  ierr = PetscMemcpy(A,ps->mat[PS_MAT_A],sizeof(PetscScalar)*ps->ld*ps->ld);CHKERRQ(ierr);
381
 
382
  /* norm of A */
2767 jroman 383
  if (ps->state<PS_STATE_INTERMEDIATE) hn = LAPACKlange_("I",&n,&n,A,&ld,rwork);
384
  else hn = LAPACKlanhs_("I",&n,A,&ld,rwork);
2766 jroman 385
 
386
  /* norm of inv(A) */
2767 jroman 387
  LAPACKgetrf_(&n,&n,A,&ld,ipiv,&info);
2766 jroman 388
  if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xGETRF %d",info);
2767 jroman 389
  LAPACKgetri_(&n,A,&ld,ipiv,work,&lwork,&info);
2766 jroman 390
  if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xGETRI %d",info);
2767 jroman 391
  hin = LAPACKlange_("I",&n,&n,A,&ld,rwork);
2766 jroman 392
 
393
  *cond = hn*hin;
394
  PetscFunctionReturn(0);
395
#endif
396
}
397
 
2772 jroman 398
#undef __FUNCT__  
399
#define __FUNCT__ "PSTranslateHarmonic_NHEP"
2773 jroman 400
PetscErrorCode PSTranslateHarmonic_NHEP(PS ps,PetscScalar tau,PetscReal beta,PetscBool recover,PetscScalar *gin,PetscReal *gamma)
2772 jroman 401
{
402
#if defined(PETSC_MISSING_LAPACK_GETRF) || defined(PETSC_MISSING_LAPACK_GETRS)
403
  PetscFunctionBegin;
404
  SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"GETRF/GETRS - Lapack routines are unavailable.");
405
#else
406
  PetscErrorCode ierr;
2773 jroman 407
  PetscInt       i,j;
408
  PetscBLASInt   *ipiv,info,n,ld,one=1,ncol;
409
  PetscScalar    *A,*B,*Q,*g=gin,*ghat;
410
  PetscScalar    done=1.0,dmone=-1.0,dzero=0.0;
411
  PetscReal      gnorm;
2772 jroman 412
 
413
  PetscFunctionBegin;
414
  n  = PetscBLASIntCast(ps->n);
415
  ld = PetscBLASIntCast(ps->ld);
2773 jroman 416
  A  = ps->mat[PS_MAT_A];
2772 jroman 417
 
2773 jroman 418
  if (!recover) {
419
 
420
    ierr = PSAllocateWork_Private(ps,0,0,ld);CHKERRQ(ierr);
421
    ipiv = ps->iwork;
422
    if (!g) {
423
      ierr = PSAllocateWork_Private(ps,ld,0,0);CHKERRQ(ierr);
424
      g = ps->work;
425
    }
426
    /* use workspace matrix W to factor A-tau*eye(n) */
2793 jroman 427
    ierr = PSAllocateMat_Private(ps,PS_MAT_W);CHKERRQ(ierr);
2773 jroman 428
    B = ps->mat[PS_MAT_W];
429
    ierr = PetscMemcpy(B,A,sizeof(PetscScalar)*ld*ld);CHKERRQ(ierr);
430
 
431
    /* Vector g initialy stores b = beta*e_n^T */
432
    ierr = PetscMemzero(g,n*sizeof(PetscScalar));CHKERRQ(ierr);
433
    g[n-1] = beta;
2772 jroman 434
 
2773 jroman 435
    /* g = (A-tau*eye(n))'\b */
436
    for (i=0;i<n;i++)
437
      B[i+i*ld] -= tau;
438
    LAPACKgetrf_(&n,&n,B,&ld,ipiv,&info);
439
    if (info<0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Bad argument to LU factorization");
440
    if (info>0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MAT_LU_ZRPVT,"Bad LU factorization");
441
    ierr = PetscLogFlops(2.0*n*n*n/3.0);CHKERRQ(ierr);
442
    LAPACKgetrs_("C",&n,&one,B,&ld,ipiv,g,&ld,&info);
443
    if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"GETRS - Bad solve");
444
    ierr = PetscLogFlops(2.0*n*n-n);CHKERRQ(ierr);
2772 jroman 445
 
2773 jroman 446
    /* A = A + g*b' */
447
    for (i=0;i<n;i++)
448
      A[i+(n-1)*ld] += g[i]*beta;
449
 
450
  } else { /* recover */
451
 
452
    PetscValidPointer(g,6);
453
    ierr = PSAllocateWork_Private(ps,ld,0,0);CHKERRQ(ierr);
454
    ghat = ps->work;
455
    Q    = ps->mat[PS_MAT_Q];
456
 
457
    /* g^ = -Q(:,idx)'*g */
458
    ncol = PetscBLASIntCast(ps->l+ps->k);
459
    BLASgemv_("C",&n,&ncol,&dmone,Q,&ld,g,&one,&dzero,ghat,&one);
460
 
461
    /* A = A + g^*b' */
462
    for (i=0;i<ps->l+ps->k;i++)
463
      for (j=ps->l;j<ps->l+ps->k;j++)
464
        A[i+j*ld] += ghat[i]*Q[n-1+j*ld]*beta;
465
 
466
    /* g~ = (I-Q(:,idx)*Q(:,idx)')*g = g+Q(:,idx)*g^ */
467
    BLASgemv_("N",&n,&ncol,&done,Q,&ld,ghat,&one,&done,g,&one);
468
  }
469
 
470
  /* Compute gamma factor */
471
  if (gamma) {
472
    gnorm = 0.0;
473
    for (i=0;i<n;i++)
474
      gnorm = gnorm + PetscRealPart(g[i]*PetscConj(g[i]));
475
    *gamma = PetscSqrtReal(1.0+gnorm);
476
  }
2772 jroman 477
  PetscFunctionReturn(0);
478
#endif
479
}
480
 
2758 jroman 481
EXTERN_C_BEGIN
482
#undef __FUNCT__  
483
#define __FUNCT__ "PSCreate_NHEP"
484
PetscErrorCode PSCreate_NHEP(PS ps)
485
{
486
  PetscFunctionBegin;
2793 jroman 487
  ps->nmeth  = 1;
2758 jroman 488
  ps->ops->allocate      = PSAllocate_NHEP;
2777 jroman 489
  ps->ops->view          = PSView_NHEP;
2807 jroman 490
  ps->ops->vectors       = PSVectors_NHEP;
2759 jroman 491
  ps->ops->solve         = PSSolve_NHEP;
492
  ps->ops->sort          = PSSort_NHEP;
2766 jroman 493
  ps->ops->cond          = PSCond_NHEP;
2772 jroman 494
  ps->ops->translate     = PSTranslateHarmonic_NHEP;
2758 jroman 495
  PetscFunctionReturn(0);
496
}
497
EXTERN_C_END
498