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
521 dsic.upv.es!antodo 1
/*
545 dsic.upv.es!jroman 2
     This file contains some simple default routines for common operations.  
1376 slepc 3
 
4
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1672 slepc 5
   SLEPc - Scalable Library for Eigenvalue Problem Computations
2116 eromero 6
   Copyright (c) 2002-2010, Universidad Politecnica de Valencia, Spain
1376 slepc 7
 
1672 slepc 8
   This file is part of SLEPc.
9
 
10
   SLEPc is free software: you can redistribute it and/or modify it under  the
11
   terms of version 3 of the GNU Lesser General Public License as published by
12
   the Free Software Foundation.
13
 
14
   SLEPc  is  distributed in the hope that it will be useful, but WITHOUT  ANY
15
   WARRANTY;  without even the implied warranty of MERCHANTABILITY or  FITNESS
16
   FOR  A  PARTICULAR PURPOSE. See the GNU Lesser General Public  License  for
17
   more details.
18
 
19
   You  should have received a copy of the GNU Lesser General  Public  License
20
   along with SLEPc. If not, see <http://www.gnu.org/licenses/>.
1376 slepc 21
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
545 dsic.upv.es!jroman 22
*/
1376 slepc 23
 
2283 jroman 24
#include <private/epsimpl.h>   /*I "slepceps.h" I*/
25
#include <slepcblaslapack.h>
521 dsic.upv.es!antodo 26
 
27
#undef __FUNCT__  
2348 jroman 28
#define __FUNCT__ "EPSReset_Default"
29
PetscErrorCode EPSReset_Default(EPS eps)
521 dsic.upv.es!antodo 30
{
31
  PetscErrorCode ierr;
32
 
33
  PetscFunctionBegin;
2213 jroman 34
  PetscValidHeaderSpecific(eps,EPS_CLASSID,1);
521 dsic.upv.es!antodo 35
  ierr = EPSDefaultFreeWork(eps);CHKERRQ(ierr);
36
  ierr = EPSFreeSolution(eps);CHKERRQ(ierr);
37
  PetscFunctionReturn(0);
38
}
39
 
40
#undef __FUNCT__  
41
#define __FUNCT__ "EPSBackTransform_Default"
42
PetscErrorCode EPSBackTransform_Default(EPS eps)
43
{
44
  PetscErrorCode ierr;
45
 
46
  PetscFunctionBegin;
2213 jroman 47
  PetscValidHeaderSpecific(eps,EPS_CLASSID,1);
1778 antodo 48
  ierr = STBackTransform(eps->OP,eps->nconv,eps->eigr,eps->eigi);CHKERRQ(ierr);
521 dsic.upv.es!antodo 49
  PetscFunctionReturn(0);
50
}
51
 
52
#undef __FUNCT__  
53
#define __FUNCT__ "EPSComputeVectors_Default"
545 dsic.upv.es!jroman 54
/*
55
  EPSComputeVectors_Default - Compute eigenvectors from the vectors
56
  provided by the eigensolver. This version just copies the vectors
57
  and is intended for solvers such as power that provide the eigenvector.
58
 */
521 dsic.upv.es!antodo 59
PetscErrorCode EPSComputeVectors_Default(EPS eps)
60
{
61
  PetscFunctionBegin;
62
  eps->evecsavailable = PETSC_TRUE;
63
  PetscFunctionReturn(0);
64
}
65
 
66
#undef __FUNCT__  
1243 slepc 67
#define __FUNCT__ "EPSComputeVectors_Hermitian"
68
/*
69
  EPSComputeVectors_Hermitian - Copies the Lanczos vectors as eigenvectors
70
  using purification for generalized eigenproblems.
71
 */
72
PetscErrorCode EPSComputeVectors_Hermitian(EPS eps)
73
{
74
  PetscErrorCode ierr;
1509 slepc 75
  PetscInt       i;
1243 slepc 76
  PetscReal      norm;
1582 slepc 77
  Vec            w;
1243 slepc 78
 
79
  PetscFunctionBegin;
1582 slepc 80
  if (eps->isgeneralized) {
81
    /* Purify eigenvectors */
82
    ierr = VecDuplicate(eps->V[0],&w);CHKERRQ(ierr);
83
    for (i=0;i<eps->nconv;i++) {
84
      ierr = VecCopy(eps->V[i],w);CHKERRQ(ierr);
85
      ierr = STApply(eps->OP,w,eps->V[i]);CHKERRQ(ierr);
1765 antodo 86
      ierr = IPNorm(eps->ip,eps->V[i],&norm);CHKERRQ(ierr);
87
      ierr = VecScale(eps->V[i],1.0/norm);CHKERRQ(ierr);
1243 slepc 88
    }
2305 jroman 89
    ierr = VecDestroy(&w);CHKERRQ(ierr);
1582 slepc 90
  }
1243 slepc 91
  eps->evecsavailable = PETSC_TRUE;
92
  PetscFunctionReturn(0);
93
}
94
 
95
#undef __FUNCT__  
521 dsic.upv.es!antodo 96
#define __FUNCT__ "EPSComputeVectors_Schur"
545 dsic.upv.es!jroman 97
/*
98
  EPSComputeVectors_Schur - Compute eigenvectors from the vectors
99
  provided by the eigensolver. This version is intended for solvers
100
  that provide Schur vectors. Given the partial Schur decomposition
101
  OP*V=V*T, the following steps are performed:
780 dsic.upv.es!jroman 102
      1) compute eigenvectors of T: T*Z=Z*D
103
      2) compute eigenvectors of OP: X=V*Z
104
  If left eigenvectors are required then also do Z'*Tl=D*Z', Y=W*Z
545 dsic.upv.es!jroman 105
 */
521 dsic.upv.es!antodo 106
PetscErrorCode EPSComputeVectors_Schur(EPS eps)
107
{
806 dsic.upv.es!antodo 108
#if defined(SLEPC_MISSING_LAPACK_TREVC)
2214 jroman 109
  SETERRQ(((PetscObject)eps)->comm,PETSC_ERR_SUP,"TREVC - Lapack routine is unavailable.");
806 dsic.upv.es!antodo 110
#else
521 dsic.upv.es!antodo 111
  PetscErrorCode ierr;
1509 slepc 112
  PetscInt       i;
1850 antodo 113
  PetscBLASInt   ncv,nconv,mout,info,one = 1;
114
  PetscScalar    *Z,*work,tmp;
521 dsic.upv.es!antodo 115
#if defined(PETSC_USE_COMPLEX)
116
  PetscReal      *rwork;
1850 antodo 117
#else
118
  PetscReal      normi;
521 dsic.upv.es!antodo 119
#endif
1243 slepc 120
  PetscReal      norm;
121
  Vec            w;
521 dsic.upv.es!antodo 122
 
123
  PetscFunctionBegin;
1635 slepc 124
  ncv = PetscBLASIntCast(eps->ncv);
125
  nconv = PetscBLASIntCast(eps->nconv);
521 dsic.upv.es!antodo 126
  if (eps->ishermitian) {
1243 slepc 127
    ierr = EPSComputeVectors_Hermitian(eps);CHKERRQ(ierr);
521 dsic.upv.es!antodo 128
    PetscFunctionReturn(0);
129
  }
130
 
1587 slepc 131
  ierr = PetscMalloc(nconv*nconv*sizeof(PetscScalar),&Z);CHKERRQ(ierr);
132
  ierr = PetscMalloc(3*nconv*sizeof(PetscScalar),&work);CHKERRQ(ierr);
521 dsic.upv.es!antodo 133
#if defined(PETSC_USE_COMPLEX)
1587 slepc 134
  ierr = PetscMalloc(nconv*sizeof(PetscReal),&rwork);CHKERRQ(ierr);
521 dsic.upv.es!antodo 135
#endif
136
 
780 dsic.upv.es!jroman 137
  /* right eigenvectors */
521 dsic.upv.es!antodo 138
#if !defined(PETSC_USE_COMPLEX)
1587 slepc 139
  LAPACKtrevc_("R","A",PETSC_NULL,&nconv,eps->T,&ncv,PETSC_NULL,&nconv,Z,&nconv,&nconv,&mout,work,&info);
521 dsic.upv.es!antodo 140
#else
1587 slepc 141
  LAPACKtrevc_("R","A",PETSC_NULL,&nconv,eps->T,&ncv,PETSC_NULL,&nconv,Z,&nconv,&nconv,&mout,work,rwork,&info);
521 dsic.upv.es!antodo 142
#endif
2214 jroman 143
  if (info) SETERRQ1(((PetscObject)eps)->comm,PETSC_ERR_LIB,"Error in Lapack xTREVC %i",info);
521 dsic.upv.es!antodo 144
 
1850 antodo 145
  /* normalize eigenvectors (when not using purification nor balancing)*/
1940 jroman 146
  if (!(eps->ispositive || (eps->balance!=EPS_BALANCE_NONE && eps->D))) {
1850 antodo 147
    for (i=0;i<eps->nconv;i++) {
148
#if !defined(PETSC_USE_COMPLEX)
149
      if (eps->eigi[i] != 0.0) {
150
        norm = BLASnrm2_(&nconv,Z+i*nconv,&one);
151
        normi = BLASnrm2_(&nconv,Z+(i+1)*nconv,&one);
152
        tmp = 1.0 / SlepcAbsEigenvalue(norm,normi);
153
        BLASscal_(&nconv,&tmp,Z+i*nconv,&one);
154
        BLASscal_(&nconv,&tmp,Z+(i+1)*nconv,&one);
155
        i++;    
156
      } else
157
#endif
158
      {
159
        norm = BLASnrm2_(&nconv,Z+i*nconv,&one);
160
        tmp = 1.0 / norm;
161
        BLASscal_(&nconv,&tmp,Z+i*nconv,&one);
162
      }
163
    }
164
  }
165
 
870 dsic.upv.es!antodo 166
  /* AV = V * Z */
1601 slepc 167
  ierr = SlepcUpdateVectors(eps->nconv,eps->V,0,eps->nconv,Z,eps->nconv,PETSC_FALSE);CHKERRQ(ierr);
1850 antodo 168
 
169
  /* Purify eigenvectors */
1582 slepc 170
  if (eps->ispositive) {
1850 antodo 171
    ierr = VecDuplicate(eps->V[0],&w);CHKERRQ(ierr);
1582 slepc 172
    for (i=0;i<eps->nconv;i++) {
173
      ierr = VecCopy(eps->V[i],w);CHKERRQ(ierr);
174
      ierr = STApply(eps->OP,w,eps->V[i]);CHKERRQ(ierr);
1243 slepc 175
    }
2305 jroman 176
    ierr = VecDestroy(&w);CHKERRQ(ierr);
1582 slepc 177
  }
1850 antodo 178
 
179
  /* Fix eigenvectors if balancing was used */
1940 jroman 180
  if (eps->balance!=EPS_BALANCE_NONE && eps->D) {
1850 antodo 181
    for (i=0;i<eps->nconv;i++) {
182
      ierr = VecPointwiseDivide(eps->V[i],eps->V[i],eps->D);CHKERRQ(ierr);
183
    }
184
  }
185
 
186
  /* normalize eigenvectors (when using purification or balancing) */
1940 jroman 187
  if (eps->ispositive || (eps->balance!=EPS_BALANCE_NONE && eps->D)) {
1850 antodo 188
    for (i=0;i<eps->nconv;i++) {
189
#if !defined(PETSC_USE_COMPLEX)
190
      if (eps->eigi[i] != 0.0) {
191
        ierr = VecNorm(eps->V[i],NORM_2,&norm);CHKERRQ(ierr);
192
        ierr = VecNorm(eps->V[i+1],NORM_2,&normi);CHKERRQ(ierr);
193
        tmp = 1.0 / SlepcAbsEigenvalue(norm,normi);
194
        ierr = VecScale(eps->V[i],tmp);CHKERRQ(ierr);
195
        ierr = VecScale(eps->V[i+1],tmp);CHKERRQ(ierr);
196
        i++;    
197
      } else
198
#endif
199
      {
200
        ierr = VecNormalize(eps->V[i],PETSC_NULL);CHKERRQ(ierr);
201
      }
202
    }
203
  }
521 dsic.upv.es!antodo 204
 
780 dsic.upv.es!jroman 205
  /* left eigenvectors */
1947 jroman 206
  if (eps->leftvecs) {
780 dsic.upv.es!jroman 207
#if !defined(PETSC_USE_COMPLEX)
1587 slepc 208
    LAPACKtrevc_("R","A",PETSC_NULL,&nconv,eps->Tl,&ncv,PETSC_NULL,&nconv,Z,&nconv,&nconv,&mout,work,&info);
780 dsic.upv.es!jroman 209
#else
1587 slepc 210
    LAPACKtrevc_("R","A",PETSC_NULL,&nconv,eps->Tl,&ncv,PETSC_NULL,&nconv,Z,&nconv,&nconv,&mout,work,rwork,&info);
780 dsic.upv.es!jroman 211
#endif
2214 jroman 212
    if (info) SETERRQ1(((PetscObject)eps)->comm,PETSC_ERR_LIB,"Error in Lapack xTREVC %i",info);
780 dsic.upv.es!jroman 213
 
870 dsic.upv.es!antodo 214
    /* AW = W * Z */
1607 slepc 215
    ierr = SlepcUpdateVectors(eps->nconv,eps->W,0,eps->nconv,Z,eps->nconv,PETSC_FALSE);CHKERRQ(ierr);
780 dsic.upv.es!jroman 216
  }
217
 
218
  ierr = PetscFree(Z);CHKERRQ(ierr);
521 dsic.upv.es!antodo 219
  ierr = PetscFree(work);CHKERRQ(ierr);
220
#if defined(PETSC_USE_COMPLEX)
221
  ierr = PetscFree(rwork);CHKERRQ(ierr);
222
#endif
223
  eps->evecsavailable = PETSC_TRUE;
224
  PetscFunctionReturn(0);
806 dsic.upv.es!antodo 225
#endif
521 dsic.upv.es!antodo 226
}
533 dsic.upv.es!antodo 227
 
228
#undef __FUNCT__  
229
#define __FUNCT__ "EPSDefaultGetWork"
230
/*
231
  EPSDefaultGetWork - Gets a number of work vectors.
232
 */
2331 jroman 233
PetscErrorCode EPSDefaultGetWork(EPS eps,PetscInt nw)
533 dsic.upv.es!antodo 234
{
235
  PetscErrorCode ierr;
236
 
237
  PetscFunctionBegin;
238
  if (eps->nwork != nw) {
2348 jroman 239
    ierr = SlepcVecDestroyVecs(eps->nwork,&eps->work);CHKERRQ(ierr);
533 dsic.upv.es!antodo 240
    eps->nwork = nw;
2348 jroman 241
    ierr = SlepcVecDuplicateVecs(eps->V[0],nw,&eps->work);CHKERRQ(ierr);
790 dsic.upv.es!antodo 242
    ierr = PetscLogObjectParents(eps,nw,eps->work);
533 dsic.upv.es!antodo 243
  }
244
  PetscFunctionReturn(0);
245
}
246
 
247
#undef __FUNCT__  
248
#define __FUNCT__ "EPSDefaultFreeWork"
249
/*
250
  EPSDefaultFreeWork - Free work vectors.
251
 */
252
PetscErrorCode EPSDefaultFreeWork(EPS eps)
253
{
254
  PetscErrorCode ierr;
255
 
256
  PetscFunctionBegin;
2213 jroman 257
  PetscValidHeaderSpecific(eps,EPS_CLASSID,1);
2348 jroman 258
  ierr = SlepcVecDestroyVecs(eps->nwork,&eps->work);CHKERRQ(ierr);
533 dsic.upv.es!antodo 259
  PetscFunctionReturn(0);
260
}
1785 antodo 261
 
262
#undef __FUNCT__  
2083 eromero 263
#define __FUNCT__ "EPSEigRelativeConverged"
1794 antodo 264
/*
2070 jroman 265
  EPSDefaultConverged - Checks convergence relative to the eigenvalue.
1794 antodo 266
*/
2083 eromero 267
PetscErrorCode EPSEigRelativeConverged(EPS eps,PetscScalar eigr,PetscScalar eigi,PetscReal res,PetscReal *errest,void *ctx)
1785 antodo 268
{
1794 antodo 269
  PetscReal w;
2317 jroman 270
 
1785 antodo 271
  PetscFunctionBegin;
2030 jroman 272
  w = SlepcAbsEigenvalue(eigr,eigi);
2070 jroman 273
  *errest = res;
274
  if (w > res) *errest = res / w;
1785 antodo 275
  PetscFunctionReturn(0);
276
}
277
 
278
#undef __FUNCT__  
279
#define __FUNCT__ "EPSAbsoluteConverged"
1794 antodo 280
/*
2070 jroman 281
  EPSAbsoluteConverged - Checks convergence absolutely.
1794 antodo 282
*/
2070 jroman 283
PetscErrorCode EPSAbsoluteConverged(EPS eps,PetscScalar eigr,PetscScalar eigi,PetscReal res,PetscReal *errest,void *ctx)
1785 antodo 284
{
285
  PetscFunctionBegin;
2070 jroman 286
  *errest = res;
1794 antodo 287
  PetscFunctionReturn(0);
288
}
289
 
290
#undef __FUNCT__  
2071 jroman 291
#define __FUNCT__ "EPSNormRelativeConverged"
292
/*
293
  EPSNormRelativeConverged - Checks convergence relative to the eigenvalue and
294
  the matrix norms.
295
*/
296
PetscErrorCode EPSNormRelativeConverged(EPS eps,PetscScalar eigr,PetscScalar eigi,PetscReal res,PetscReal *errest,void *ctx)
297
{
298
  PetscReal w;
2317 jroman 299
 
2071 jroman 300
  PetscFunctionBegin;
301
  w = SlepcAbsEigenvalue(eigr,eigi);
302
  *errest = res / (eps->nrma + w*eps->nrmb);
303
  PetscFunctionReturn(0);
304
}
305
 
306
#undef __FUNCT__  
2045 jroman 307
#define __FUNCT__ "EPSComputeTrueResidual"
308
/*
309
  EPSComputeTrueResidual - Computes the true residual norm of a given Ritz pair:
310
    ||r|| = ||A*x - lambda*B*x||
311
  where lambda is the Ritz value and x is the Ritz vector.
312
 
313
  Real lambda:
314
    lambda = eigr
315
    x = V*Z  (V is an array of nv vectors, Z has length nv)
316
 
317
  Complex lambda:
318
    lambda = eigr+i*eigi
319
    x = V*Z[0*nv]+i*V*Z[1*nv]  (Z has length 2*nv)
320
*/
321
PetscErrorCode EPSComputeTrueResidual(EPS eps,PetscScalar eigr,PetscScalar eigi,PetscScalar *Z,Vec *V,PetscInt nv,PetscReal *resnorm)
322
{
323
  PetscErrorCode ierr;
2309 jroman 324
  Vec            x,y,z=0;
2139 jroman 325
  PetscReal      norm;
2045 jroman 326
 
327
  PetscFunctionBegin;
328
  /* allocate workspace */
329
  ierr = VecDuplicate(V[0],&x);CHKERRQ(ierr);
330
  ierr = VecDuplicate(V[0],&y);CHKERRQ(ierr);
331
  if (!eps->ishermitian && eps->ispositive) { ierr = VecDuplicate(V[0],&z);CHKERRQ(ierr); }
332
 
333
  /* compute eigenvector */
2053 jroman 334
  ierr = SlepcVecMAXPBY(x,0.0,1.0,nv,Z,V);CHKERRQ(ierr);
335
 
2045 jroman 336
  /* purify eigenvector in positive generalized problems */
337
  if (eps->ispositive) {
338
    ierr = STApply(eps->OP,x,y);CHKERRQ(ierr);
339
    if (eps->ishermitian) {
340
      ierr = IPNorm(eps->ip,y,&norm);CHKERRQ(ierr);
341
    } else {
342
      ierr = VecNorm(y,NORM_2,&norm);CHKERRQ(ierr);          
343
    }
344
    ierr = VecScale(y,1.0/norm);CHKERRQ(ierr);
345
    ierr = VecCopy(y,x);CHKERRQ(ierr);
346
  }
347
  /* fix eigenvector if balancing is used */
348
  if (!eps->ishermitian && eps->balance!=EPS_BALANCE_NONE && eps->D) {
349
    ierr = VecPointwiseDivide(x,x,eps->D);CHKERRQ(ierr);
350
    ierr = VecNormalize(x,&norm);CHKERRQ(ierr);
351
  }
2320 jroman 352
#if !defined(PETSC_USE_COMPLEX)
2045 jroman 353
  /* compute imaginary part of eigenvector */
2056 jroman 354
  if (!eps->ishermitian && eigi != 0.0) {
2045 jroman 355
    ierr = SlepcVecMAXPBY(y,0.0,1.0,nv,Z+nv,V);CHKERRQ(ierr);
356
    if (eps->ispositive) {
357
      ierr = STApply(eps->OP,y,z);CHKERRQ(ierr);
358
      ierr = VecNorm(z,NORM_2,&norm);CHKERRQ(ierr);          
359
      ierr = VecScale(z,1.0/norm);CHKERRQ(ierr);
360
      ierr = VecCopy(z,y);CHKERRQ(ierr);
361
    }
362
    if (eps->balance!=EPS_BALANCE_NONE && eps->D) {
363
      ierr = VecPointwiseDivide(y,y,eps->D);CHKERRQ(ierr);
364
      ierr = VecNormalize(y,&norm);CHKERRQ(ierr);
365
    }
366
  }
367
#endif
368
  /* compute relative error and update convergence flag */
2056 jroman 369
  ierr = EPSComputeResidualNorm_Private(eps,eigr,eigi,x,y,resnorm);
2045 jroman 370
 
371
  /* free workspace */
2305 jroman 372
  ierr = VecDestroy(&x);CHKERRQ(ierr);
373
  ierr = VecDestroy(&y);CHKERRQ(ierr);
2306 jroman 374
  ierr = VecDestroy(&z);CHKERRQ(ierr);
2045 jroman 375
  PetscFunctionReturn(0);
376
}
377
 
378
#undef __FUNCT__  
1800 jroman 379
#define __FUNCT__ "EPSBuildBalance_Krylov"
380
/*
381
  EPSBuildBalance_Krylov - uses a Krylov subspace method to compute the
382
  diagonal matrix to be applied for balancing in non-Hermitian problems.
383
*/
384
PetscErrorCode EPSBuildBalance_Krylov(EPS eps)
385
{
2334 jroman 386
  Vec               z,p,r;
387
  PetscInt          i,j;
388
  PetscReal         norma;
389
  PetscScalar       *pz,*pD;
390
  const PetscScalar *pr,*pp;
391
  PetscErrorCode    ierr;
1800 jroman 392
 
393
  PetscFunctionBegin;
1933 jroman 394
  ierr = VecDuplicate(eps->V[0],&r);CHKERRQ(ierr);
395
  ierr = VecDuplicate(eps->V[0],&p);CHKERRQ(ierr);
396
  ierr = VecDuplicate(eps->V[0],&z);CHKERRQ(ierr);
1800 jroman 397
  ierr = VecSet(eps->D,1.0);CHKERRQ(ierr);
398
 
399
  for (j=0;j<eps->balance_its;j++) {
400
 
401
    /* Build a random vector of +-1's */
2027 jroman 402
    ierr = SlepcVecSetRandom(z,eps->rand);CHKERRQ(ierr);
1800 jroman 403
    ierr = VecGetArray(z,&pz);CHKERRQ(ierr);
1929 jroman 404
    for (i=0;i<eps->nloc;i++) {
1819 jroman 405
      if (PetscRealPart(pz[i])<0.5) pz[i]=-1.0;
1800 jroman 406
      else pz[i]=1.0;
407
    }
408
    ierr = VecRestoreArray(z,&pz);CHKERRQ(ierr);
409
 
410
    /* Compute p=DA(D\z) */
411
    ierr = VecPointwiseDivide(r,z,eps->D);CHKERRQ(ierr);
412
    ierr = STApply(eps->OP,r,p);CHKERRQ(ierr);
413
    ierr = VecPointwiseMult(p,p,eps->D);CHKERRQ(ierr);
1804 jroman 414
    if (j==0) {
415
      /* Estimate the matrix inf-norm */
416
      ierr = VecAbs(p);CHKERRQ(ierr);
417
      ierr = VecMax(p,PETSC_NULL,&norma);CHKERRQ(ierr);
418
    }
1940 jroman 419
    if (eps->balance == EPS_BALANCE_TWOSIDE) {
1800 jroman 420
      /* Compute r=D\(A'Dz) */
421
      ierr = VecPointwiseMult(z,z,eps->D);CHKERRQ(ierr);
422
      ierr = STApplyTranspose(eps->OP,z,r);CHKERRQ(ierr);
423
      ierr = VecPointwiseDivide(r,r,eps->D);CHKERRQ(ierr);
424
    }
425
 
426
    /* Adjust values of D */
2334 jroman 427
    ierr = VecGetArrayRead(r,&pr);CHKERRQ(ierr);
428
    ierr = VecGetArrayRead(p,&pp);CHKERRQ(ierr);
1800 jroman 429
    ierr = VecGetArray(eps->D,&pD);CHKERRQ(ierr);
1929 jroman 430
    for (i=0;i<eps->nloc;i++) {
1940 jroman 431
      if (eps->balance == EPS_BALANCE_TWOSIDE) {
1800 jroman 432
        if (PetscAbsScalar(pp[i])>eps->balance_cutoff*norma && pr[i]!=0.0)
433
          pD[i] *= sqrt(PetscAbsScalar(pr[i]/pp[i]));
434
      } else {
435
        if (pp[i]!=0.0) pD[i] *= 1.0/PetscAbsScalar(pp[i]);
436
      }
437
    }
2334 jroman 438
    ierr = VecRestoreArrayRead(r,&pr);CHKERRQ(ierr);
439
    ierr = VecRestoreArrayRead(p,&pp);CHKERRQ(ierr);
1800 jroman 440
    ierr = VecRestoreArray(eps->D,&pD);CHKERRQ(ierr);
441
  }
442
 
2305 jroman 443
  ierr = VecDestroy(&r);CHKERRQ(ierr);
444
  ierr = VecDestroy(&p);CHKERRQ(ierr);
445
  ierr = VecDestroy(&z);CHKERRQ(ierr);
1800 jroman 446
  PetscFunctionReturn(0);
447
}
448