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