Subversion Repositories slepc-dev

Rev

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

Rev Author Line No. Line
545 dsic.upv.es!jroman 1
/*
2
      EPS routines related to the solution process.
1376 slepc 3
 
4
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1672 slepc 5
   SLEPc - Scalable Library for Eigenvalue Problem Computations
6
   Copyright (c) 2002-2009, 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
 
1521 slepc 24
#include "private/epsimpl.h"   /*I "slepceps.h" I*/
528 dsic.upv.es!antodo 25
 
26
#undef __FUNCT__  
27
#define __FUNCT__ "EPSSolve"
28
/*@
29
   EPSSolve - Solves the eigensystem.
30
 
31
   Collective on EPS
32
 
33
   Input Parameter:
34
.  eps - eigensolver context obtained from EPSCreate()
35
 
36
   Options Database:
37
+   -eps_view - print information about the solver used
38
.   -eps_view_binary - save the matrices to the default binary file
39
-   -eps_plot_eigs - plot computed eigenvalues
40
 
41
   Level: beginner
42
 
43
.seealso: EPSCreate(), EPSSetUp(), EPSDestroy(), EPSSetTolerances()
44
@*/
45
PetscErrorCode EPSSolve(EPS eps)
46
{
47
  PetscErrorCode ierr;
1509 slepc 48
  PetscInt       i;
528 dsic.upv.es!antodo 49
  PetscReal      re,im;
50
  PetscTruth     flg;
51
  PetscViewer    viewer;
52
  PetscDraw      draw;
53
  PetscDrawSP    drawsp;
1654 slepc 54
  STMatMode      matmode;
528 dsic.upv.es!antodo 55
 
56
  PetscFunctionBegin;
57
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
58
 
1422 slepc 59
  ierr = PetscOptionsHasName(((PetscObject)eps)->prefix,"-eps_view_binary",&flg);CHKERRQ(ierr);
528 dsic.upv.es!antodo 60
  if (flg) {
61
    Mat A,B;
62
    ierr = STGetOperators(eps->OP,&A,&B);CHKERRQ(ierr);
1422 slepc 63
    ierr = MatView(A,PETSC_VIEWER_BINARY_(((PetscObject)eps)->comm));CHKERRQ(ierr);
64
    if (B) ierr = MatView(B,PETSC_VIEWER_BINARY_(((PetscObject)eps)->comm));CHKERRQ(ierr);
528 dsic.upv.es!antodo 65
  }
66
 
67
  /* reset the convergence flag from the previous solves */
68
  eps->reason = EPS_CONVERGED_ITERATING;
69
 
70
  if (!eps->setupcalled){ ierr = EPSSetUp(eps);CHKERRQ(ierr); }
1437 slepc 71
  ierr = STResetOperationCounters(eps->OP);CHKERRQ(ierr);
72
  ierr = IPResetOperationCounters(eps->ip);CHKERRQ(ierr);
528 dsic.upv.es!antodo 73
  eps->evecsavailable = PETSC_FALSE;
1220 slepc 74
  eps->nconv = 0;
75
  eps->its = 0;
76
  for (i=0;i<eps->ncv;i++) eps->eigr[i]=eps->eigi[i]=eps->errest[i]=0.0;
1588 slepc 77
  EPSMonitor(eps,eps->its,eps->nconv,eps->eigr,eps->eigi,eps->errest,eps->ncv);
780 dsic.upv.es!jroman 78
 
528 dsic.upv.es!antodo 79
  ierr = PetscLogEventBegin(EPS_Solve,eps,eps->V[0],eps->V[0],0);CHKERRQ(ierr);
780 dsic.upv.es!jroman 80
 
81
  switch (eps->solverclass) {
82
    case EPS_ONE_SIDE:
83
      ierr = (*eps->ops->solve)(eps);CHKERRQ(ierr); break;
84
    case EPS_TWO_SIDE:
85
      if (eps->ops->solvets) {
86
        ierr = (*eps->ops->solvets)(eps);CHKERRQ(ierr); break;
87
      } else {
955 dsic.upv.es!jroman 88
        SETERRQ(1,"Two-sided version unavailable for this solver");
780 dsic.upv.es!jroman 89
      }
90
    default:
91
      SETERRQ(1,"Wrong value of eps->solverclass");
92
  }
93
 
1654 slepc 94
  ierr = STGetMatMode(eps->OP,&matmode);CHKERRQ(ierr);
95
  if (matmode == STMATMODE_INPLACE && eps->ispositive) {
96
    /* Purge eigenvectors before reverting operator */
97
    ierr = (*eps->ops->computevectors)(eps);CHKERRQ(ierr);    
98
  }
1029 slepc 99
  ierr = STPostSolve(eps->OP);CHKERRQ(ierr);
528 dsic.upv.es!antodo 100
  ierr = PetscLogEventEnd(EPS_Solve,eps,eps->V[0],eps->V[0],0);CHKERRQ(ierr);
780 dsic.upv.es!jroman 101
 
528 dsic.upv.es!antodo 102
  if (!eps->reason) {
103
    SETERRQ(1,"Internal error, solver returned without setting converged reason");
104
  }
105
 
106
  /* Map eigenvalues back to the original problem, necessary in some
107
  * spectral transformations */
108
  ierr = (*eps->ops->backtransform)(eps);CHKERRQ(ierr);
109
 
889 dsic.upv.es!jroman 110
  /* Adjust left eigenvectors in generalized problems: y = B^T y */
111
  if (eps->isgeneralized && eps->solverclass == EPS_TWO_SIDE) {
112
    Mat B;
113
    KSP ksp;
114
    Vec w;
115
    ierr = STGetOperators(eps->OP,PETSC_NULL,&B);CHKERRQ(ierr);
1422 slepc 116
    ierr = KSPCreate(((PetscObject)eps)->comm,&ksp);CHKERRQ(ierr);
889 dsic.upv.es!jroman 117
    ierr = KSPSetOperators(ksp,B,B,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
118
    ierr = KSPSetFromOptions(ksp);CHKERRQ(ierr);
119
    ierr = MatGetVecs(B,PETSC_NULL,&w);CHKERRQ(ierr);
120
    for (i=0;i<eps->nconv;i++) {
121
      ierr = VecCopy(eps->W[i],w);CHKERRQ(ierr);
122
      ierr = KSPSolveTranspose(ksp,w,eps->W[i]);CHKERRQ(ierr);
123
    }
124
    ierr = KSPDestroy(ksp);CHKERRQ(ierr);
125
    ierr = VecDestroy(w);CHKERRQ(ierr);
126
  }
127
 
128
 
528 dsic.upv.es!antodo 129
#ifndef PETSC_USE_COMPLEX
130
  /* reorder conjugate eigenvalues (positive imaginary first) */
131
  for (i=0; i<eps->nconv-1; i++) {
132
    if (eps->eigi[i] != 0) {
133
      if (eps->eigi[i] < 0) {
134
        eps->eigi[i] = -eps->eigi[i];
135
        eps->eigi[i+1] = -eps->eigi[i+1];
828 dsic.upv.es!antodo 136
        ierr = VecScale(eps->V[i+1],-1.0); CHKERRQ(ierr);
528 dsic.upv.es!antodo 137
      }
138
      i++;
139
    }
140
  }
141
#endif
142
 
143
  /* sort eigenvalues according to eps->which parameter */
1040 slepc 144
  ierr = PetscFree(eps->perm);CHKERRQ(ierr);
528 dsic.upv.es!antodo 145
  if (eps->nconv > 0) {
1509 slepc 146
    ierr = PetscMalloc(sizeof(PetscInt)*eps->nconv, &eps->perm); CHKERRQ(ierr);
528 dsic.upv.es!antodo 147
    ierr = EPSSortEigenvalues(eps->nconv, eps->eigr, eps->eigi, eps->which, eps->nconv, eps->perm); CHKERRQ(ierr);
148
  }
149
 
1422 slepc 150
  ierr = PetscOptionsHasName(((PetscObject)eps)->prefix,"-eps_view",&flg);CHKERRQ(ierr);
528 dsic.upv.es!antodo 151
  if (flg && !PetscPreLoadingOn) { ierr = EPSView(eps,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); }
152
 
1422 slepc 153
  ierr = PetscOptionsHasName(((PetscObject)eps)->prefix,"-eps_plot_eigs",&flg);CHKERRQ(ierr);
528 dsic.upv.es!antodo 154
  if (flg) {
155
    ierr = PetscViewerDrawOpen(PETSC_COMM_SELF,0,"Computed Eigenvalues",
156
                             PETSC_DECIDE,PETSC_DECIDE,300,300,&viewer);CHKERRQ(ierr);
157
    ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
158
    ierr = PetscDrawSPCreate(draw,1,&drawsp);CHKERRQ(ierr);
159
    for( i=0; i<eps->nconv; i++ ) {
160
#if defined(PETSC_USE_COMPLEX)
161
      re = PetscRealPart(eps->eigr[i]);
162
      im = PetscImaginaryPart(eps->eigi[i]);
163
#else
164
      re = eps->eigr[i];
165
      im = eps->eigi[i];
166
#endif
167
      ierr = PetscDrawSPAddPoint(drawsp,&re,&im);CHKERRQ(ierr);
168
    }
169
    ierr = PetscDrawSPDraw(drawsp);CHKERRQ(ierr);
170
    ierr = PetscDrawSPDestroy(drawsp);CHKERRQ(ierr);
171
    ierr = PetscViewerDestroy(viewer);CHKERRQ(ierr);
172
  }
173
 
174
  PetscFunctionReturn(0);
175
}
176
 
177
#undef __FUNCT__  
178
#define __FUNCT__ "EPSGetIterationNumber"
179
/*@
180
   EPSGetIterationNumber - Gets the current iteration number. If the
181
   call to EPSSolve() is complete, then it returns the number of iterations
182
   carried out by the solution method.
183
 
184
   Not Collective
185
 
186
   Input Parameter:
187
.  eps - the eigensolver context
188
 
189
   Output Parameter:
190
.  its - number of iterations
191
 
192
   Level: intermediate
193
 
1343 slepc 194
   Note:
195
   During the i-th iteration this call returns i-1. If EPSSolve() is
196
   complete, then parameter "its" contains either the iteration number at
197
   which convergence was successfully reached, or failure was detected.  
198
   Call EPSGetConvergedReason() to determine if the solver converged or
199
   failed and why.
528 dsic.upv.es!antodo 200
 
1343 slepc 201
.seealso: EPSGetConvergedReason(), EPSSetTolerances()
528 dsic.upv.es!antodo 202
@*/
1509 slepc 203
PetscErrorCode EPSGetIterationNumber(EPS eps,PetscInt *its)
528 dsic.upv.es!antodo 204
{
205
  PetscFunctionBegin;
206
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
207
  PetscValidIntPointer(its,2);
208
  *its = eps->its;
209
  PetscFunctionReturn(0);
210
}
211
 
212
#undef __FUNCT__  
1209 slepc 213
#define __FUNCT__ "EPSGetOperationCounters"
528 dsic.upv.es!antodo 214
/*@
1209 slepc 215
   EPSGetOperationCounters - Gets the total number of operator applications,
216
   inner product operations and linear iterations used by the ST object
217
   during the last EPSSolve() call.
528 dsic.upv.es!antodo 218
 
219
   Not Collective
220
 
221
   Input Parameter:
222
.  eps - EPS context
223
 
224
   Output Parameter:
1209 slepc 225
+  ops  - number of operator applications
226
.  dots - number of inner product operations
227
-  lits - number of linear iterations
528 dsic.upv.es!antodo 228
 
229
   Notes:
230
   When the eigensolver algorithm invokes STApply() then a linear system
231
   must be solved (except in the case of standard eigenproblems and shift
232
   transformation). The number of iterations required in this solve is
233
   accumulated into a counter whose value is returned by this function.
234
 
1209 slepc 235
   These counters are reset to zero at each successive call to EPSSolve().
528 dsic.upv.es!antodo 236
 
237
   Level: intermediate
238
 
239
@*/
1509 slepc 240
PetscErrorCode EPSGetOperationCounters(EPS eps,PetscInt* ops,PetscInt* dots,PetscInt* lits)
528 dsic.upv.es!antodo 241
{
1358 slepc 242
  PetscErrorCode ierr;
243
 
528 dsic.upv.es!antodo 244
  PetscFunctionBegin;
245
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
1358 slepc 246
  ierr = STGetOperationCounters(eps->OP,ops,lits);CHKERRQ(ierr);
247
  if (dots) {
248
    ierr = IPGetOperationCounters(eps->ip,dots);CHKERRQ(ierr);
249
  }
528 dsic.upv.es!antodo 250
  PetscFunctionReturn(0);
251
}
252
 
253
#undef __FUNCT__  
254
#define __FUNCT__ "EPSGetConverged"
255
/*@
256
   EPSGetConverged - Gets the number of converged eigenpairs.
257
 
258
   Not Collective
259
 
260
   Input Parameter:
261
.  eps - the eigensolver context
262
 
263
   Output Parameter:
264
.  nconv - number of converged eigenpairs
265
 
266
   Note:
267
   This function should be called after EPSSolve() has finished.
268
 
269
   Level: beginner
270
 
271
.seealso: EPSSetDimensions()
272
@*/
1509 slepc 273
PetscErrorCode EPSGetConverged(EPS eps,PetscInt *nconv)
528 dsic.upv.es!antodo 274
{
275
  PetscFunctionBegin;
276
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
1209 slepc 277
  PetscValidIntPointer(nconv,2);
278
  *nconv = eps->nconv;
528 dsic.upv.es!antodo 279
  PetscFunctionReturn(0);
280
}
281
 
282
 
283
#undef __FUNCT__  
284
#define __FUNCT__ "EPSGetConvergedReason"
285
/*@C
286
   EPSGetConvergedReason - Gets the reason why the EPSSolve() iteration was
287
   stopped.
288
 
289
   Not Collective
290
 
291
   Input Parameter:
292
.  eps - the eigensolver context
293
 
294
   Output Parameter:
295
.  reason - negative value indicates diverged, positive value converged
296
   (see EPSConvergedReason)
297
 
298
   Possible values for reason:
299
+  EPS_CONVERGED_TOL - converged up to tolerance
300
.  EPS_DIVERGED_ITS - required more than its to reach convergence
301
.  EPS_DIVERGED_BREAKDOWN - generic breakdown in method
302
-  EPS_DIVERGED_NONSYMMETRIC - The operator is nonsymmetric
303
 
304
   Level: intermediate
305
 
306
   Notes: Can only be called after the call to EPSSolve() is complete.
307
 
308
.seealso: EPSSetTolerances(), EPSSolve(), EPSConvergedReason
309
@*/
310
PetscErrorCode EPSGetConvergedReason(EPS eps,EPSConvergedReason *reason)
311
{
312
  PetscFunctionBegin;
313
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
1209 slepc 314
  PetscValidIntPointer(reason,2);
528 dsic.upv.es!antodo 315
  *reason = eps->reason;
316
  PetscFunctionReturn(0);
317
}
318
 
319
#undef __FUNCT__  
320
#define __FUNCT__ "EPSGetInvariantSubspace"
321
/*@
761 dsic.upv.es!jroman 322
   EPSGetInvariantSubspace - Gets an orthonormal basis of the computed invariant
323
   subspace.
528 dsic.upv.es!antodo 324
 
325
   Not Collective
326
 
327
   Input Parameter:
328
.  eps - the eigensolver context
329
 
330
   Output Parameter:
331
.  v - an array of vectors
332
 
333
   Notes:
334
   This function should be called after EPSSolve() has finished.
335
 
336
   The user should provide in v an array of nconv vectors, where nconv is
337
   the value returned by EPSGetConverged().
338
 
761 dsic.upv.es!jroman 339
   The first k vectors returned in v span an invariant subspace associated
340
   with the first k computed eigenvalues (note that this is not true if the
341
   k-th eigenvalue is complex and matrix A is real; in this case the first
342
   k+1 vectors should be used). An invariant subspace X of A satisfies Ax
528 dsic.upv.es!antodo 343
   in X for all x in X (a similar definition applies for generalized
344
   eigenproblems).
345
 
346
   Level: intermediate
347
 
780 dsic.upv.es!jroman 348
.seealso: EPSGetEigenpair(), EPSGetConverged(), EPSSolve(), EPSGetLeftInvariantSubspace()
528 dsic.upv.es!antodo 349
@*/
350
PetscErrorCode EPSGetInvariantSubspace(EPS eps, Vec *v)
351
{
352
  PetscErrorCode ierr;
1509 slepc 353
  PetscInt       i;
528 dsic.upv.es!antodo 354
 
355
  PetscFunctionBegin;
356
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
796 dsic.upv.es!antodo 357
  PetscValidPointer(v,2);
780 dsic.upv.es!jroman 358
  PetscValidHeaderSpecific(*v,VEC_COOKIE,2);
528 dsic.upv.es!antodo 359
  if (!eps->V) {
360
    SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "EPSSolve must be called first");
361
  }
1582 slepc 362
  if (!eps->ishermitian && eps->evecsavailable) {
363
    SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "EPSGetInvariantSubspace must be called before EPSGetEigenpair,EPSGetRightVector,EPSComputeRelativeError or EPSComputeResidualNorm");
364
  }
528 dsic.upv.es!antodo 365
  for (i=0;i<eps->nconv;i++) {
366
    ierr = VecCopy(eps->V[i],v[i]);CHKERRQ(ierr);
367
  }
368
  PetscFunctionReturn(0);
369
}
370
 
371
#undef __FUNCT__  
780 dsic.upv.es!jroman 372
#define __FUNCT__ "EPSGetLeftInvariantSubspace"
373
/*@
374
   EPSGetLeftInvariantSubspace - Gets an orthonormal basis of the computed left
375
   invariant subspace (only available in two-sided eigensolvers).
376
 
377
   Not Collective
378
 
379
   Input Parameter:
380
.  eps - the eigensolver context
381
 
382
   Output Parameter:
383
.  v - an array of vectors
384
 
385
   Notes:
386
   This function should be called after EPSSolve() has finished.
387
 
388
   The user should provide in v an array of nconv vectors, where nconv is
389
   the value returned by EPSGetConverged().
390
 
391
   The first k vectors returned in v span a left invariant subspace associated
392
   with the first k computed eigenvalues (note that this is not true if the
393
   k-th eigenvalue is complex and matrix A is real; in this case the first
394
   k+1 vectors should be used). A left invariant subspace Y of A satisfies y'A
395
   in Y for all y in Y (a similar definition applies for generalized
396
   eigenproblems).
397
 
398
   Level: intermediate
399
 
400
.seealso: EPSGetEigenpair(), EPSGetConverged(), EPSSolve(), EPSGetInvariantSubspace
401
@*/
402
PetscErrorCode EPSGetLeftInvariantSubspace(EPS eps, Vec *v)
403
{
404
  PetscErrorCode ierr;
1509 slepc 405
  PetscInt       i;
780 dsic.upv.es!jroman 406
 
407
  PetscFunctionBegin;
408
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
819 dsic.upv.es!jroman 409
  PetscValidPointer(v,2);
780 dsic.upv.es!jroman 410
  PetscValidHeaderSpecific(*v,VEC_COOKIE,2);
411
  if (!eps->W) {
412
    if (eps->solverclass!=EPS_TWO_SIDE) {
413
      SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "Only available for two-sided solvers");
414
    } else {
415
      SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "EPSSolve must be called first");
416
    }
417
  }
418
  for (i=0;i<eps->nconv;i++) {
419
    ierr = VecCopy(eps->W[i],v[i]);CHKERRQ(ierr);
420
  }
421
  PetscFunctionReturn(0);
422
}
423
 
424
#undef __FUNCT__  
528 dsic.upv.es!antodo 425
#define __FUNCT__ "EPSGetEigenpair"
426
/*@
780 dsic.upv.es!jroman 427
   EPSGetEigenpair - Gets the i-th solution of the eigenproblem as computed by
428
   EPSSolve(). The solution consists in both the eigenvalue and the eigenvector.
528 dsic.upv.es!antodo 429
 
430
   Not Collective
431
 
432
   Input Parameters:
433
+  eps - eigensolver context
434
-  i   - index of the solution
435
 
436
   Output Parameters:
437
+  eigr - real part of eigenvalue
438
.  eigi - imaginary part of eigenvalue
439
.  Vr   - real part of eigenvector
440
-  Vi   - imaginary part of eigenvector
441
 
442
   Notes:
1389 slepc 443
   If the eigenvalue is real, then eigi and Vi are set to zero. If PETSc is
444
   configured with complex scalars the eigenvalue is stored
761 dsic.upv.es!jroman 445
   directly in eigr (eigi is set to zero) and the eigenvector in Vr (Vi is
528 dsic.upv.es!antodo 446
   set to zero).
447
 
1267 slepc 448
   The index i should be a value between 0 and nconv-1 (see EPSGetConverged()).
528 dsic.upv.es!antodo 449
   Eigenpairs are indexed according to the ordering criterion established
450
   with EPSSetWhichEigenpairs().
451
 
452
   Level: beginner
453
 
780 dsic.upv.es!jroman 454
.seealso: EPSGetValue(), EPSGetRightVector(), EPSGetLeftVector(), EPSSolve(),
455
          EPSGetConverged(), EPSSetWhichEigenpairs(), EPSGetInvariantSubspace()
528 dsic.upv.es!antodo 456
@*/
1509 slepc 457
PetscErrorCode EPSGetEigenpair(EPS eps, PetscInt i, PetscScalar *eigr, PetscScalar *eigi, Vec Vr, Vec Vi)
528 dsic.upv.es!antodo 458
{
459
  PetscErrorCode ierr;
780 dsic.upv.es!jroman 460
 
461
  PetscFunctionBegin;
462
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
463
  if (!eps->eigr || !eps->eigi || !eps->V) {
464
    SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "EPSSolve must be called first");
465
  }
466
  if (i<0 || i>=eps->nconv) {
467
    SETERRQ(PETSC_ERR_ARG_OUTOFRANGE, "Argument 2 out of range");
468
  }
469
  ierr = EPSGetValue(eps,i,eigr,eigi);CHKERRQ(ierr);
470
  ierr = EPSGetRightVector(eps,i,Vr,Vi);CHKERRQ(ierr);
471
 
472
  PetscFunctionReturn(0);
473
}
474
 
475
#undef __FUNCT__  
476
#define __FUNCT__ "EPSGetValue"
477
/*@
478
   EPSGetValue - Gets the i-th eigenvalue as computed by EPSSolve().
479
 
480
   Not Collective
481
 
482
   Input Parameters:
483
+  eps - eigensolver context
484
-  i   - index of the solution
485
 
486
   Output Parameters:
487
+  eigr - real part of eigenvalue
488
-  eigi - imaginary part of eigenvalue
489
 
490
   Notes:
1389 slepc 491
   If the eigenvalue is real, then eigi is set to zero. If PETSc is
492
   configured with complex scalars the eigenvalue is stored
780 dsic.upv.es!jroman 493
   directly in eigr (eigi is set to zero).
494
 
1267 slepc 495
   The index i should be a value between 0 and nconv-1 (see EPSGetConverged()).
780 dsic.upv.es!jroman 496
   Eigenpairs are indexed according to the ordering criterion established
497
   with EPSSetWhichEigenpairs().
498
 
499
   Level: beginner
500
 
501
.seealso: EPSSolve(), EPSGetConverged(), EPSSetWhichEigenpairs(),
502
          EPSGetEigenpair()
503
@*/
1509 slepc 504
PetscErrorCode EPSGetValue(EPS eps, PetscInt i, PetscScalar *eigr, PetscScalar *eigi)
780 dsic.upv.es!jroman 505
{
1509 slepc 506
  PetscInt       k;
780 dsic.upv.es!jroman 507
 
508
  PetscFunctionBegin;
509
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
510
  if (!eps->eigr || !eps->eigi) {
511
    SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "EPSSolve must be called first");
512
  }
513
  if (i<0 || i>=eps->nconv) {
514
    SETERRQ(PETSC_ERR_ARG_OUTOFRANGE, "Argument 2 out of range");
515
  }
516
 
517
  if (!eps->perm) k = i;
518
  else k = eps->perm[i];
519
#ifdef PETSC_USE_COMPLEX
520
  if (eigr) *eigr = eps->eigr[k];
521
  if (eigi) *eigi = 0;
522
#else
523
  if (eigr) *eigr = eps->eigr[k];
524
  if (eigi) *eigi = eps->eigi[k];
525
#endif
526
 
527
  PetscFunctionReturn(0);
528
}
529
 
530
#undef __FUNCT__  
531
#define __FUNCT__ "EPSGetRightVector"
532
/*@
533
   EPSGetRightVector - Gets the i-th right eigenvector as computed by EPSSolve().
534
 
535
   Not Collective
536
 
537
   Input Parameters:
538
+  eps - eigensolver context
539
-  i   - index of the solution
540
 
541
   Output Parameters:
542
+  Vr   - real part of eigenvector
543
-  Vi   - imaginary part of eigenvector
544
 
545
   Notes:
1389 slepc 546
   If the corresponding eigenvalue is real, then Vi is set to zero. If PETSc is
547
   configured with complex scalars the eigenvector is stored
780 dsic.upv.es!jroman 548
   directly in Vr (Vi is set to zero).
549
 
1267 slepc 550
   The index i should be a value between 0 and nconv-1 (see EPSGetConverged()).
780 dsic.upv.es!jroman 551
   Eigenpairs are indexed according to the ordering criterion established
552
   with EPSSetWhichEigenpairs().
553
 
554
   Level: beginner
555
 
556
.seealso: EPSSolve(), EPSGetConverged(), EPSSetWhichEigenpairs(),
557
          EPSGetEigenpair(), EPSGetLeftVector()
558
@*/
1509 slepc 559
PetscErrorCode EPSGetRightVector(EPS eps, PetscInt i, Vec Vr, Vec Vi)
780 dsic.upv.es!jroman 560
{
561
  PetscErrorCode ierr;
1509 slepc 562
  PetscInt       k;
528 dsic.upv.es!antodo 563
 
564
  PetscFunctionBegin;
565
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
780 dsic.upv.es!jroman 566
  if (!eps->V) {
528 dsic.upv.es!antodo 567
    SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "EPSSolve must be called first");
568
  }
569
  if (i<0 || i>=eps->nconv) {
570
    SETERRQ(PETSC_ERR_ARG_OUTOFRANGE, "Argument 2 out of range");
571
  }
572
  if (!eps->evecsavailable && (Vr || Vi) ) {
573
    ierr = (*eps->ops->computevectors)(eps);CHKERRQ(ierr);
574
  }  
575
 
576
  if (!eps->perm) k = i;
577
  else k = eps->perm[i];
578
#ifdef PETSC_USE_COMPLEX
1582 slepc 579
  if (Vr) { ierr = VecCopy(eps->V[k], Vr); CHKERRQ(ierr); }
828 dsic.upv.es!antodo 580
  if (Vi) { ierr = VecSet(Vi,0.0); CHKERRQ(ierr); }
528 dsic.upv.es!antodo 581
#else
582
  if (eps->eigi[k] > 0) { /* first value of conjugate pair */
1582 slepc 583
    if (Vr) { ierr = VecCopy(eps->V[k], Vr); CHKERRQ(ierr); }
584
    if (Vi) { ierr = VecCopy(eps->V[k+1], Vi); CHKERRQ(ierr); }
528 dsic.upv.es!antodo 585
  } else if (eps->eigi[k] < 0) { /* second value of conjugate pair */
1582 slepc 586
    if (Vr) { ierr = VecCopy(eps->V[k-1], Vr); CHKERRQ(ierr); }
528 dsic.upv.es!antodo 587
    if (Vi) {
1582 slepc 588
      ierr = VecCopy(eps->V[k], Vi); CHKERRQ(ierr);
828 dsic.upv.es!antodo 589
      ierr = VecScale(Vi,-1.0); CHKERRQ(ierr);
528 dsic.upv.es!antodo 590
    }
591
  } else { /* real eigenvalue */
1582 slepc 592
    if (Vr) { ierr = VecCopy(eps->V[k], Vr); CHKERRQ(ierr); }
828 dsic.upv.es!antodo 593
    if (Vi) { ierr = VecSet(Vi,0.0); CHKERRQ(ierr); }
528 dsic.upv.es!antodo 594
  }
595
#endif
596
 
597
  PetscFunctionReturn(0);
598
}
599
 
600
#undef __FUNCT__  
780 dsic.upv.es!jroman 601
#define __FUNCT__ "EPSGetLeftVector"
602
/*@
603
   EPSGetLeftVector - Gets the i-th left eigenvector as computed by EPSSolve()
604
   (only available in two-sided eigensolvers).
605
 
606
   Not Collective
607
 
608
   Input Parameters:
609
+  eps - eigensolver context
610
-  i   - index of the solution
611
 
612
   Output Parameters:
613
+  Wr   - real part of eigenvector
614
-  Wi   - imaginary part of eigenvector
615
 
616
   Notes:
1389 slepc 617
   If the corresponding eigenvalue is real, then Wi is set to zero. If PETSc is
618
   configured with complex scalars the eigenvector is stored
780 dsic.upv.es!jroman 619
   directly in Wr (Wi is set to zero).
620
 
1267 slepc 621
   The index i should be a value between 0 and nconv-1 (see EPSGetConverged()).
780 dsic.upv.es!jroman 622
   Eigenpairs are indexed according to the ordering criterion established
623
   with EPSSetWhichEigenpairs().
624
 
625
   Level: beginner
626
 
627
.seealso: EPSSolve(), EPSGetConverged(), EPSSetWhichEigenpairs(),
628
          EPSGetEigenpair(), EPSGetLeftVector()
629
@*/
1509 slepc 630
PetscErrorCode EPSGetLeftVector(EPS eps, PetscInt i, Vec Wr, Vec Wi)
780 dsic.upv.es!jroman 631
{
632
  PetscErrorCode ierr;
1509 slepc 633
  PetscInt       k;
780 dsic.upv.es!jroman 634
 
635
  PetscFunctionBegin;
636
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
637
  if (!eps->W) {
638
    if (eps->solverclass!=EPS_TWO_SIDE) {
639
      SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "Only available for two-sided solvers");
640
    } else {
641
      SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "EPSSolve must be called first");
642
    }
643
  }
644
  if (i<0 || i>=eps->nconv) {
645
    SETERRQ(PETSC_ERR_ARG_OUTOFRANGE, "Argument 2 out of range");
646
  }
647
  if (!eps->evecsavailable && (Wr || Wi) ) {
648
    ierr = (*eps->ops->computevectors)(eps);CHKERRQ(ierr);
649
  }  
650
 
651
  if (!eps->perm) k = i;
652
  else k = eps->perm[i];
653
#ifdef PETSC_USE_COMPLEX
1607 slepc 654
  if (Wr) { ierr = VecCopy(eps->W[k], Wr); CHKERRQ(ierr); }
828 dsic.upv.es!antodo 655
  if (Wi) { ierr = VecSet(Wi,0.0); CHKERRQ(ierr); }
780 dsic.upv.es!jroman 656
#else
657
  if (eps->eigi[k] > 0) { /* first value of conjugate pair */
1607 slepc 658
    if (Wr) { ierr = VecCopy(eps->W[k], Wr); CHKERRQ(ierr); }
659
    if (Wi) { ierr = VecCopy(eps->W[k+1], Wi); CHKERRQ(ierr); }
780 dsic.upv.es!jroman 660
  } else if (eps->eigi[k] < 0) { /* second value of conjugate pair */
1607 slepc 661
    if (Wr) { ierr = VecCopy(eps->W[k-1], Wr); CHKERRQ(ierr); }
780 dsic.upv.es!jroman 662
    if (Wi) {
1607 slepc 663
      ierr = VecCopy(eps->W[k], Wi); CHKERRQ(ierr);
828 dsic.upv.es!antodo 664
      ierr = VecScale(Wi,-1.0); CHKERRQ(ierr);
780 dsic.upv.es!jroman 665
    }
666
  } else { /* real eigenvalue */
1607 slepc 667
    if (Wr) { ierr = VecCopy(eps->W[k], Wr); CHKERRQ(ierr); }
828 dsic.upv.es!antodo 668
    if (Wi) { ierr = VecSet(Wi,0.0); CHKERRQ(ierr); }
780 dsic.upv.es!jroman 669
  }
670
#endif
671
 
672
  PetscFunctionReturn(0);
673
}
674
 
675
#undef __FUNCT__  
528 dsic.upv.es!antodo 676
#define __FUNCT__ "EPSGetErrorEstimate"
677
/*@
761 dsic.upv.es!jroman 678
   EPSGetErrorEstimate - Returns the error estimate associated to the i-th
679
   computed eigenpair.
528 dsic.upv.es!antodo 680
 
681
   Not Collective
682
 
683
   Input Parameter:
684
+  eps - eigensolver context
685
-  i   - index of eigenpair
686
 
687
   Output Parameter:
688
.  errest - the error estimate
689
 
761 dsic.upv.es!jroman 690
   Notes:
691
   This is the error estimate used internally by the eigensolver. The actual
692
   error bound can be computed with EPSComputeRelativeError(). See also the user's
693
   manual for details.
694
 
528 dsic.upv.es!antodo 695
   Level: advanced
696
 
697
.seealso: EPSComputeRelativeError()
698
@*/
1509 slepc 699
PetscErrorCode EPSGetErrorEstimate(EPS eps, PetscInt i, PetscReal *errest)
528 dsic.upv.es!antodo 700
{
701
  PetscFunctionBegin;
702
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
703
  if (!eps->eigr || !eps->eigi) {
704
    SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "EPSSolve must be called first");
705
  }
706
  if (i<0 || i>=eps->nconv) {
707
    SETERRQ(PETSC_ERR_ARG_OUTOFRANGE, "Argument 2 out of range");
708
  }
709
  if (eps->perm) i = eps->perm[i];  
710
  if (errest) *errest = eps->errest[i];
711
  PetscFunctionReturn(0);
712
}
713
 
780 dsic.upv.es!jroman 714
#undef __FUNCT__  
715
#define __FUNCT__ "EPSGetErrorEstimateLeft"
716
/*@
717
   EPSGetErrorEstimateLeft - Returns the left error estimate associated to the i-th
718
   computed eigenpair (only available in two-sided eigensolvers).
528 dsic.upv.es!antodo 719
 
780 dsic.upv.es!jroman 720
   Not Collective
721
 
722
   Input Parameter:
723
+  eps - eigensolver context
724
-  i   - index of eigenpair
725
 
726
   Output Parameter:
727
.  errest - the left error estimate
728
 
729
   Notes:
730
   This is the error estimate used internally by the eigensolver. The actual
731
   error bound can be computed with EPSComputeRelativeErrorLeft(). See also the user's
732
   manual for details.
733
 
734
   Level: advanced
735
 
736
.seealso: EPSComputeRelativeErrorLeft()
737
@*/
1509 slepc 738
PetscErrorCode EPSGetErrorEstimateLeft(EPS eps, PetscInt i, PetscReal *errest)
780 dsic.upv.es!jroman 739
{
740
  PetscFunctionBegin;
741
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
742
  if (!eps->eigr || !eps->eigi) {
743
    SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "EPSSolve must be called first");
744
  }
745
  if (eps->solverclass!=EPS_TWO_SIDE) {
746
    SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "Only available for two-sided solvers");
747
  }
748
  if (i<0 || i>=eps->nconv) {
749
    SETERRQ(PETSC_ERR_ARG_OUTOFRANGE, "Argument 2 out of range");
750
  }
751
  if (eps->perm) i = eps->perm[i];  
752
  if (errest) *errest = eps->errest_left[i];
753
  PetscFunctionReturn(0);
754
}
755
 
528 dsic.upv.es!antodo 756
#undef __FUNCT__  
757
#define __FUNCT__ "EPSComputeResidualNorm"
758
/*@
761 dsic.upv.es!jroman 759
   EPSComputeResidualNorm - Computes the norm of the residual vector associated with
760
   the i-th computed eigenpair.
528 dsic.upv.es!antodo 761
 
762
   Collective on EPS
763
 
764
   Input Parameter:
765
.  eps - the eigensolver context
766
.  i   - the solution index
767
 
768
   Output Parameter:
761 dsic.upv.es!jroman 769
.  norm - the residual norm, computed as ||Ax-kBx||_2 where k is the
528 dsic.upv.es!antodo 770
   eigenvalue and x is the eigenvector.
761 dsic.upv.es!jroman 771
   If k=0 then the residual norm is computed as ||Ax||_2.
528 dsic.upv.es!antodo 772
 
773
   Notes:
1267 slepc 774
   The index i should be a value between 0 and nconv-1 (see EPSGetConverged()).
528 dsic.upv.es!antodo 775
   Eigenpairs are indexed according to the ordering criterion established
776
   with EPSSetWhichEigenpairs().
777
 
778
   Level: beginner
779
 
780
.seealso: EPSSolve(), EPSGetConverged(), EPSSetWhichEigenpairs()
781
@*/
1509 slepc 782
PetscErrorCode EPSComputeResidualNorm(EPS eps, PetscInt i, PetscReal *norm)
528 dsic.upv.es!antodo 783
{
784
  PetscErrorCode ierr;
785
  Vec            u, v, w, xr, xi;
786
  Mat            A, B;
828 dsic.upv.es!antodo 787
  PetscScalar    kr, ki;
528 dsic.upv.es!antodo 788
#ifndef PETSC_USE_COMPLEX
789
  PetscReal      ni, nr;
790
#endif
791
 
792
  PetscFunctionBegin;
793
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
794
  ierr = STGetOperators(eps->OP,&A,&B);CHKERRQ(ierr);
1385 slepc 795
  ierr = VecDuplicate(eps->vec_initial,&u); CHKERRQ(ierr);
796
  ierr = VecDuplicate(eps->vec_initial,&v); CHKERRQ(ierr);
797
  ierr = VecDuplicate(eps->vec_initial,&w); CHKERRQ(ierr);
798
  ierr = VecDuplicate(eps->vec_initial,&xr); CHKERRQ(ierr);
799
  ierr = VecDuplicate(eps->vec_initial,&xi); CHKERRQ(ierr);
528 dsic.upv.es!antodo 800
  ierr = EPSGetEigenpair(eps,i,&kr,&ki,xr,xi); CHKERRQ(ierr);
801
 
802
#ifndef PETSC_USE_COMPLEX
803
  if (ki == 0 ||
804
    PetscAbsScalar(ki) < PetscAbsScalar(kr*PETSC_MACHINE_EPSILON)) {
805
#endif
806
    ierr = MatMult( A, xr, u ); CHKERRQ(ierr); /* u=A*x */
807
    if (PetscAbsScalar(kr) > PETSC_MACHINE_EPSILON) {
808
      if (eps->isgeneralized) { ierr = MatMult( B, xr, w ); CHKERRQ(ierr); }
809
      else { ierr = VecCopy( xr, w ); CHKERRQ(ierr); } /* w=B*x */
828 dsic.upv.es!antodo 810
      ierr = VecAXPY( u, -kr, w ); CHKERRQ(ierr); /* u=A*x-k*B*x */
528 dsic.upv.es!antodo 811
    }
812
    ierr = VecNorm( u, NORM_2, norm); CHKERRQ(ierr);  
813
#ifndef PETSC_USE_COMPLEX
814
  } else {
815
    ierr = MatMult( A, xr, u ); CHKERRQ(ierr); /* u=A*xr */
816
    if (eps->isgeneralized) { ierr = MatMult( B, xr, v ); CHKERRQ(ierr); }
817
    else { ierr = VecCopy( xr, v ); CHKERRQ(ierr); } /* v=B*xr */
828 dsic.upv.es!antodo 818
    ierr = VecAXPY( u, -kr, v ); CHKERRQ(ierr); /* u=A*xr-kr*B*xr */
528 dsic.upv.es!antodo 819
    if (eps->isgeneralized) { ierr = MatMult( B, xi, w ); CHKERRQ(ierr); }
820
    else { ierr = VecCopy( xi, w ); CHKERRQ(ierr); } /* w=B*xi */
828 dsic.upv.es!antodo 821
    ierr = VecAXPY( u, ki, w ); CHKERRQ(ierr); /* u=A*xr-kr*B*xr+ki*B*xi */
528 dsic.upv.es!antodo 822
    ierr = VecNorm( u, NORM_2, &nr ); CHKERRQ(ierr);
823
    ierr = MatMult( A, xi, u ); CHKERRQ(ierr); /* u=A*xi */
828 dsic.upv.es!antodo 824
    ierr = VecAXPY( u, -kr, w ); CHKERRQ(ierr); /* u=A*xi-kr*B*xi */
825
    ierr = VecAXPY( u, -ki, v ); CHKERRQ(ierr); /* u=A*xi-kr*B*xi-ki*B*xr */
528 dsic.upv.es!antodo 826
    ierr = VecNorm( u, NORM_2, &ni ); CHKERRQ(ierr);
827
    *norm = SlepcAbsEigenvalue( nr, ni );
828
  }
829
#endif
830
 
831
  ierr = VecDestroy(w); CHKERRQ(ierr);
832
  ierr = VecDestroy(v); CHKERRQ(ierr);
833
  ierr = VecDestroy(u); CHKERRQ(ierr);
834
  ierr = VecDestroy(xr); CHKERRQ(ierr);
835
  ierr = VecDestroy(xi); CHKERRQ(ierr);
836
  PetscFunctionReturn(0);
837
}
838
 
839
#undef __FUNCT__  
780 dsic.upv.es!jroman 840
#define __FUNCT__ "EPSComputeResidualNormLeft"
841
/*@
794 dsic.upv.es!antodo 842
   EPSComputeResidualNormLeft - Computes the norm of the residual vector associated with
780 dsic.upv.es!jroman 843
   the i-th computed left eigenvector (only available in two-sided eigensolvers).
844
 
845
   Collective on EPS
846
 
847
   Input Parameter:
848
.  eps - the eigensolver context
849
.  i   - the solution index
850
 
851
   Output Parameter:
852
.  norm - the residual norm, computed as ||y'A-ky'B||_2 where k is the
853
   eigenvalue and y is the left eigenvector.
854
   If k=0 then the residual norm is computed as ||y'A||_2.
855
 
856
   Notes:
1267 slepc 857
   The index i should be a value between 0 and nconv-1 (see EPSGetConverged()).
780 dsic.upv.es!jroman 858
   Eigenpairs are indexed according to the ordering criterion established
859
   with EPSSetWhichEigenpairs().
860
 
861
   Level: beginner
862
 
863
.seealso: EPSSolve(), EPSGetConverged(), EPSSetWhichEigenpairs()
864
@*/
1509 slepc 865
PetscErrorCode EPSComputeResidualNormLeft(EPS eps, PetscInt i, PetscReal *norm)
780 dsic.upv.es!jroman 866
{
867
  PetscErrorCode ierr;
868
  Vec            u, v, w, xr, xi;
869
  Mat            A, B;
828 dsic.upv.es!antodo 870
  PetscScalar    kr, ki;
780 dsic.upv.es!jroman 871
#ifndef PETSC_USE_COMPLEX
872
  PetscReal      ni, nr;
873
#endif
874
 
875
  PetscFunctionBegin;
876
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
877
  ierr = STGetOperators(eps->OP,&A,&B);CHKERRQ(ierr);
1385 slepc 878
  ierr = VecDuplicate(eps->vec_initial_left,&u); CHKERRQ(ierr);
879
  ierr = VecDuplicate(eps->vec_initial_left,&v); CHKERRQ(ierr);
880
  ierr = VecDuplicate(eps->vec_initial_left,&w); CHKERRQ(ierr);
881
  ierr = VecDuplicate(eps->vec_initial_left,&xr); CHKERRQ(ierr);
882
  ierr = VecDuplicate(eps->vec_initial_left,&xi); CHKERRQ(ierr);
780 dsic.upv.es!jroman 883
  ierr = EPSGetValue(eps,i,&kr,&ki); CHKERRQ(ierr);
884
  ierr = EPSGetLeftVector(eps,i,xr,xi); CHKERRQ(ierr);
885
 
886
#ifndef PETSC_USE_COMPLEX
887
  if (ki == 0 ||
888
    PetscAbsScalar(ki) < PetscAbsScalar(kr*PETSC_MACHINE_EPSILON)) {
889
#endif
890
    ierr = MatMultTranspose( A, xr, u ); CHKERRQ(ierr); /* u=A'*x */
891
    if (PetscAbsScalar(kr) > PETSC_MACHINE_EPSILON) {
892
      if (eps->isgeneralized) { ierr = MatMultTranspose( B, xr, w ); CHKERRQ(ierr); }
893
      else { ierr = VecCopy( xr, w ); CHKERRQ(ierr); } /* w=B'*x */
828 dsic.upv.es!antodo 894
      ierr = VecAXPY( u, -kr, w); CHKERRQ(ierr); /* u=A'*x-k*B'*x */
780 dsic.upv.es!jroman 895
    }
896
    ierr = VecNorm( u, NORM_2, norm); CHKERRQ(ierr);  
897
#ifndef PETSC_USE_COMPLEX
898
  } else {
899
    ierr = MatMultTranspose( A, xr, u ); CHKERRQ(ierr); /* u=A'*xr */
900
    if (eps->isgeneralized) { ierr = MatMultTranspose( B, xr, v ); CHKERRQ(ierr); }
901
    else { ierr = VecCopy( xr, v ); CHKERRQ(ierr); } /* v=B'*xr */
828 dsic.upv.es!antodo 902
    ierr = VecAXPY( u, -kr, v ); CHKERRQ(ierr); /* u=A'*xr-kr*B'*xr */
780 dsic.upv.es!jroman 903
    if (eps->isgeneralized) { ierr = MatMultTranspose( B, xi, w ); CHKERRQ(ierr); }
904
    else { ierr = VecCopy( xi, w ); CHKERRQ(ierr); } /* w=B'*xi */
828 dsic.upv.es!antodo 905
    ierr = VecAXPY( u, ki, w ); CHKERRQ(ierr); /* u=A'*xr-kr*B'*xr+ki*B'*xi */
780 dsic.upv.es!jroman 906
    ierr = VecNorm( u, NORM_2, &nr ); CHKERRQ(ierr);
907
    ierr = MatMultTranspose( A, xi, u ); CHKERRQ(ierr); /* u=A'*xi */
828 dsic.upv.es!antodo 908
    ierr = VecAXPY( u, -kr, w ); CHKERRQ(ierr); /* u=A'*xi-kr*B'*xi */
909
    ierr = VecAXPY( u, -ki, v ); CHKERRQ(ierr); /* u=A'*xi-kr*B'*xi-ki*B'*xr */
780 dsic.upv.es!jroman 910
    ierr = VecNorm( u, NORM_2, &ni ); CHKERRQ(ierr);
911
    *norm = SlepcAbsEigenvalue( nr, ni );
912
  }
913
#endif
914
 
915
  ierr = VecDestroy(w); CHKERRQ(ierr);
916
  ierr = VecDestroy(v); CHKERRQ(ierr);
917
  ierr = VecDestroy(u); CHKERRQ(ierr);
918
  ierr = VecDestroy(xr); CHKERRQ(ierr);
919
  ierr = VecDestroy(xi); CHKERRQ(ierr);
920
  PetscFunctionReturn(0);
921
}
922
 
923
#undef __FUNCT__  
528 dsic.upv.es!antodo 924
#define __FUNCT__ "EPSComputeRelativeError"
925
/*@
761 dsic.upv.es!jroman 926
   EPSComputeRelativeError - Computes the relative error bound associated
927
   with the i-th computed eigenpair.
528 dsic.upv.es!antodo 928
 
929
   Collective on EPS
930
 
931
   Input Parameter:
932
.  eps - the eigensolver context
933
.  i   - the solution index
934
 
935
   Output Parameter:
761 dsic.upv.es!jroman 936
.  error - the relative error bound, computed as ||Ax-kBx||_2/||kx||_2 where
937
   k is the eigenvalue and x is the eigenvector.
938
   If k=0 the relative error is computed as ||Ax||_2/||x||_2.
528 dsic.upv.es!antodo 939
 
940
   Level: beginner
941
 
761 dsic.upv.es!jroman 942
.seealso: EPSSolve(), EPSComputeResidualNorm(), EPSGetErrorEstimate()
528 dsic.upv.es!antodo 943
@*/
1509 slepc 944
PetscErrorCode EPSComputeRelativeError(EPS eps, PetscInt i, PetscReal *error)
528 dsic.upv.es!antodo 945
{
946
  PetscErrorCode ierr;
947
  Vec            xr, xi;  
948
  PetscScalar    kr, ki;  
949
  PetscReal      norm, er;
950
#ifndef PETSC_USE_COMPLEX
951
  Vec            u;
952
  PetscReal      ei;
953
#endif
954
 
955
  PetscFunctionBegin;
956
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);  
957
  ierr = EPSComputeResidualNorm(eps,i,&norm); CHKERRQ(ierr);
1385 slepc 958
  ierr = VecDuplicate(eps->vec_initial,&xr); CHKERRQ(ierr);
959
  ierr = VecDuplicate(eps->vec_initial,&xi); CHKERRQ(ierr);
528 dsic.upv.es!antodo 960
  ierr = EPSGetEigenpair(eps,i,&kr,&ki,xr,xi); CHKERRQ(ierr);
961
 
962
#ifndef PETSC_USE_COMPLEX
963
  if (ki == 0 ||
964
    PetscAbsScalar(ki) < PetscAbsScalar(kr*PETSC_MACHINE_EPSILON)) {
965
#endif
868 dsic.upv.es!antodo 966
    ierr = VecNorm(xr, NORM_2, &er); CHKERRQ(ierr);
1176 slepc 967
    if (PetscAbsScalar(kr) > norm) {
868 dsic.upv.es!antodo 968
      *error =  norm / (PetscAbsScalar(kr) * er);
969
    } else {
970
      *error = norm / er;
528 dsic.upv.es!antodo 971
    }
972
#ifndef PETSC_USE_COMPLEX
973
  } else {
1176 slepc 974
    if (SlepcAbsEigenvalue(kr,ki) > norm) {
975
      ierr = VecDuplicate(xi, &u); CHKERRQ(ierr);  
976
      ierr = VecCopy(xi, u); CHKERRQ(ierr);  
977
      ierr = VecAXPBY(u, kr, -ki, xr); CHKERRQ(ierr);  
978
      ierr = VecNorm(u, NORM_2, &er); CHKERRQ(ierr);  
979
      ierr = VecAXPBY(xi, kr, ki, xr);  CHKERRQ(ierr);      
980
      ierr = VecNorm(xi, NORM_2, &ei); CHKERRQ(ierr);  
981
      ierr = VecDestroy(u); CHKERRQ(ierr);  
982
    } else {
983
      ierr = VecDot(xr, xr, &er); CHKERRQ(ierr);  
984
      ierr = VecDot(xi, xi, &ei); CHKERRQ(ierr);  
985
    }
528 dsic.upv.es!antodo 986
    *error = norm / SlepcAbsEigenvalue(er, ei);
987
  }
988
#endif    
989
 
990
  ierr = VecDestroy(xr); CHKERRQ(ierr);
991
  ierr = VecDestroy(xi); CHKERRQ(ierr);
992
  PetscFunctionReturn(0);
993
}
994
 
995
#undef __FUNCT__  
780 dsic.upv.es!jroman 996
#define __FUNCT__ "EPSComputeRelativeErrorLeft"
997
/*@
998
   EPSComputeRelativeErrorLeft - Computes the relative error bound associated
999
   with the i-th computed eigenvalue and left eigenvector (only available in
1000
   two-sided eigensolvers).
1001
 
1002
   Collective on EPS
1003
 
1004
   Input Parameter:
1005
.  eps - the eigensolver context
1006
.  i   - the solution index
1007
 
1008
   Output Parameter:
1009
.  error - the relative error bound, computed as ||y'A-ky'B||_2/||ky||_2 where
1010
   k is the eigenvalue and y is the left eigenvector.
1011
   If k=0 the relative error is computed as ||y'A||_2/||y||_2.
1012
 
1013
   Level: beginner
1014
 
1015
.seealso: EPSSolve(), EPSComputeResidualNormLeft(), EPSGetErrorEstimateLeft()
1016
@*/
1509 slepc 1017
PetscErrorCode EPSComputeRelativeErrorLeft(EPS eps, PetscInt i, PetscReal *error)
780 dsic.upv.es!jroman 1018
{
1019
  PetscErrorCode ierr;
1020
  Vec            xr, xi;  
1021
  PetscScalar    kr, ki;  
1022
  PetscReal      norm, er;
1023
#ifndef PETSC_USE_COMPLEX
1024
  Vec            u;
1025
  PetscReal      ei;
1026
#endif
1027
 
1028
  PetscFunctionBegin;
1029
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);  
1030
  ierr = EPSComputeResidualNormLeft(eps,i,&norm); CHKERRQ(ierr);
1385 slepc 1031
  ierr = VecDuplicate(eps->vec_initial_left,&xr); CHKERRQ(ierr);
1032
  ierr = VecDuplicate(eps->vec_initial_left,&xi); CHKERRQ(ierr);
780 dsic.upv.es!jroman 1033
  ierr = EPSGetValue(eps,i,&kr,&ki); CHKERRQ(ierr);
1034
  ierr = EPSGetLeftVector(eps,i,xr,xi); CHKERRQ(ierr);
1035
 
1036
#ifndef PETSC_USE_COMPLEX
1037
  if (ki == 0 ||
1038
    PetscAbsScalar(ki) < PetscAbsScalar(kr*PETSC_MACHINE_EPSILON)) {
1039
#endif
868 dsic.upv.es!antodo 1040
    ierr = VecNorm(xr, NORM_2, &er); CHKERRQ(ierr);
780 dsic.upv.es!jroman 1041
    if (PetscAbsScalar(kr) > PETSC_MACHINE_EPSILON) {
868 dsic.upv.es!antodo 1042
      *error =  norm / (PetscAbsScalar(kr) * er);
1043
    } else {
1044
      *error = norm / er;
780 dsic.upv.es!jroman 1045
    }
1046
#ifndef PETSC_USE_COMPLEX
1047
  } else {
1048
    ierr = VecDuplicate(xi, &u); CHKERRQ(ierr);  
1049
    ierr = VecCopy(xi, u); CHKERRQ(ierr);  
828 dsic.upv.es!antodo 1050
    ierr = VecAXPBY(u, kr, -ki, xr); CHKERRQ(ierr);  
780 dsic.upv.es!jroman 1051
    ierr = VecNorm(u, NORM_2, &er); CHKERRQ(ierr);  
828 dsic.upv.es!antodo 1052
    ierr = VecAXPBY(xi, kr, ki, xr);  CHKERRQ(ierr);      
780 dsic.upv.es!jroman 1053
    ierr = VecNorm(xi, NORM_2, &ei); CHKERRQ(ierr);  
1054
    ierr = VecDestroy(u); CHKERRQ(ierr);  
1055
    *error = norm / SlepcAbsEigenvalue(er, ei);
1056
  }
1057
#endif    
1058
 
1059
  ierr = VecDestroy(xr); CHKERRQ(ierr);
1060
  ierr = VecDestroy(xi); CHKERRQ(ierr);
1061
  PetscFunctionReturn(0);
1062
}
1063
 
677 dsic.upv.es!antodo 1064
#define SWAP(a,b,t) {t=a;a=b;b=t;}
1065
 
528 dsic.upv.es!antodo 1066
#undef __FUNCT__  
677 dsic.upv.es!antodo 1067
#define __FUNCT__ "EPSSortEigenvalues"
528 dsic.upv.es!antodo 1068
/*@
677 dsic.upv.es!antodo 1069
   EPSSortEigenvalues - Sorts a list of eigenvalues according to a certain
1070
   criterion.
528 dsic.upv.es!antodo 1071
 
677 dsic.upv.es!antodo 1072
   Not Collective
528 dsic.upv.es!antodo 1073
 
677 dsic.upv.es!antodo 1074
   Input Parameters:
1075
+  n     - number of eigenvalue in the list
1076
.  eig   - pointer to the array containing the eigenvalues
1077
.  eigi  - imaginary part of the eigenvalues (only when using real numbers)
1078
.  which - sorting criterion
1079
-  nev   - number of wanted eigenvalues
528 dsic.upv.es!antodo 1080
 
677 dsic.upv.es!antodo 1081
   Output Parameter:
1082
.  permout - resulting permutation
528 dsic.upv.es!antodo 1083
 
677 dsic.upv.es!antodo 1084
   Notes:
1085
   The result is a list of indices in the original eigenvalue array
1086
   corresponding to the first nev eigenvalues sorted in the specified
1087
   criterion
528 dsic.upv.es!antodo 1088
 
677 dsic.upv.es!antodo 1089
   Level: developer
528 dsic.upv.es!antodo 1090
 
1628 slepc 1091
.seealso: EPSSortEigenvaluesReal(), EPSSetWhichEigenpairs()
528 dsic.upv.es!antodo 1092
@*/
1509 slepc 1093
PetscErrorCode EPSSortEigenvalues(PetscInt n,PetscScalar *eig,PetscScalar *eigi,EPSWhich which,PetscInt nev,PetscInt *permout)
528 dsic.upv.es!antodo 1094
{
1095
  PetscErrorCode ierr;
1509 slepc 1096
  PetscInt       i;
982 slepc 1097
  PetscInt       *perm;
677 dsic.upv.es!antodo 1098
  PetscReal      *values;
528 dsic.upv.es!antodo 1099
 
1100
  PetscFunctionBegin;
982 slepc 1101
  ierr = PetscMalloc(n*sizeof(PetscInt),&perm);CHKERRQ(ierr);
677 dsic.upv.es!antodo 1102
  ierr = PetscMalloc(n*sizeof(PetscReal),&values);CHKERRQ(ierr);
1103
  for (i=0; i<n; i++) { perm[i] = i;}
528 dsic.upv.es!antodo 1104
 
677 dsic.upv.es!antodo 1105
  switch(which) {
1106
    case EPS_LARGEST_MAGNITUDE:
1107
    case EPS_SMALLEST_MAGNITUDE:
1108
      for (i=0; i<n; i++) { values[i] = SlepcAbsEigenvalue(eig[i],eigi[i]); }
1109
      break;
1110
    case EPS_LARGEST_REAL:
1111
    case EPS_SMALLEST_REAL:
1112
      for (i=0; i<n; i++) { values[i] = PetscRealPart(eig[i]); }
1113
      break;
1114
    case EPS_LARGEST_IMAGINARY:
1115
    case EPS_SMALLEST_IMAGINARY:
1116
#if defined(PETSC_USE_COMPLEX)
1117
      for (i=0; i<n; i++) { values[i] = PetscImaginaryPart(eig[i]); }
1118
#else
1119
      for (i=0; i<n; i++) { values[i] = PetscAbsReal(eigi[i]); }
1120
#endif
1121
      break;
1122
    default: SETERRQ(1,"Wrong value of which");
1123
  }
528 dsic.upv.es!antodo 1124
 
677 dsic.upv.es!antodo 1125
  ierr = PetscSortRealWithPermutation(n,values,perm);CHKERRQ(ierr);
528 dsic.upv.es!antodo 1126
 
677 dsic.upv.es!antodo 1127
  switch(which) {
1128
    case EPS_LARGEST_MAGNITUDE:
1129
    case EPS_LARGEST_REAL:
1130
    case EPS_LARGEST_IMAGINARY:
1131
      for (i=0; i<nev; i++) { permout[i] = perm[n-1-i]; }
1132
      break;
1133
    case EPS_SMALLEST_MAGNITUDE:
1134
    case EPS_SMALLEST_REAL:
1135
    case EPS_SMALLEST_IMAGINARY:
1136
      for (i=0; i<nev; i++) { permout[i] = perm[i]; }
1137
      break;
1138
    default: SETERRQ(1,"Wrong value of which");
528 dsic.upv.es!antodo 1139
  }
1140
 
677 dsic.upv.es!antodo 1141
#if !defined(PETSC_USE_COMPLEX)
1142
  for (i=0; i<nev-1; i++) {
1143
    if (eigi[permout[i]] != 0.0) {
1144
      if (eig[permout[i]] == eig[permout[i+1]] &&
1145
          eigi[permout[i]] == -eigi[permout[i+1]] &&
1146
          eigi[permout[i]] < 0.0) {
1509 slepc 1147
        PetscInt tmp;
677 dsic.upv.es!antodo 1148
        SWAP(permout[i], permout[i+1], tmp);
1149
      }
1477 slepc 1150
      i++;
677 dsic.upv.es!antodo 1151
    }
1152
  }
1153
#endif
528 dsic.upv.es!antodo 1154
 
677 dsic.upv.es!antodo 1155
  ierr = PetscFree(values);CHKERRQ(ierr);
1156
  ierr = PetscFree(perm);CHKERRQ(ierr);
528 dsic.upv.es!antodo 1157
  PetscFunctionReturn(0);
1158
}
689 dsic.upv.es!jroman 1159
 
1160
#undef __FUNCT__  
1477 slepc 1161
#define __FUNCT__ "EPSSortEigenvaluesReal"
1162
/*@
1163
   EPSSortEigenvaluesReal - Sorts a list of eigenvalues according to a certain
1164
   criterion (version for real eigenvalues only).
1165
 
1166
   Not Collective
1167
 
1168
   Input Parameters:
1169
+  n     - number of eigenvalue in the list
1170
.  eig   - pointer to the array containing the eigenvalues (real)
1171
.  which - sorting criterion
1172
-  nev   - number of wanted eigenvalues
1173
 
1174
   Output Parameter:
1175
.  permout - resulting permutation
1176
 
1177
   Workspace:
1178
.  work - workspace for storing n real values and n integer values
1179
 
1180
   Notes:
1181
   The result is a list of indices in the original eigenvalue array
1182
   corresponding to the first nev eigenvalues sorted in the specified
1183
   criterion
1184
 
1185
   Level: developer
1186
 
1628 slepc 1187
.seealso: EPSSortEigenvalues(), EPSSetWhichEigenpairs()
1477 slepc 1188
@*/
1509 slepc 1189
PetscErrorCode EPSSortEigenvaluesReal(PetscInt n,PetscReal *eig,EPSWhich which,PetscInt nev,PetscInt *permout,PetscReal *work)
1477 slepc 1190
{
1191
  PetscErrorCode ierr;
1509 slepc 1192
  PetscInt            i;
1477 slepc 1193
  PetscReal      *values = work;
1502 slepc 1194
  PetscInt       *perm = (PetscInt*)(work+n);
1477 slepc 1195
 
1196
  PetscFunctionBegin;
1197
  for (i=0; i<n; i++) { perm[i] = i;}
1198
 
1199
  switch(which) {
1200
    case EPS_LARGEST_MAGNITUDE:
1201
    case EPS_SMALLEST_MAGNITUDE:
1478 slepc 1202
      for (i=0; i<n; i++) { values[i] = PetscAbsReal(eig[i]); }
1477 slepc 1203
      break;
1204
    case EPS_LARGEST_REAL:
1205
    case EPS_SMALLEST_REAL:
1206
      for (i=0; i<n; i++) { values[i] = eig[i]; }
1207
      break;
1208
    default: SETERRQ(1,"Wrong value of which");
1209
  }
1210
 
1211
  ierr = PetscSortRealWithPermutation(n,values,perm);CHKERRQ(ierr);
1212
 
1213
  switch(which) {
1214
    case EPS_LARGEST_MAGNITUDE:
1215
    case EPS_LARGEST_REAL:
1216
      for (i=0; i<nev; i++) { permout[i] = perm[n-1-i]; }
1217
      break;
1218
    case EPS_SMALLEST_MAGNITUDE:
1219
    case EPS_SMALLEST_REAL:
1220
      for (i=0; i<nev; i++) { permout[i] = perm[i]; }
1221
      break;
1222
    default: SETERRQ(1,"Wrong value of which");
1223
  }
1224
  PetscFunctionReturn(0);
1225
}
1226
 
1227
#undef __FUNCT__  
689 dsic.upv.es!jroman 1228
#define __FUNCT__ "EPSGetStartVector"
1229
/*@
1230
   EPSGetStartVector - Gets a vector to be used as the starting vector
1231
   in an Arnoldi or Lanczos reduction.
1232
 
1233
   Collective on EPS and Vec
1234
 
1235
   Input Parameters:
1236
+  eps - the eigensolver context
1237
-  i   - index of the Arnoldi/Lanczos step
1238
 
1059 slepc 1239
   Output Parameters:
1240
+  vec - the start vector
1241
-  breakdown - flag indicating that a breakdown has occurred
689 dsic.upv.es!jroman 1242
 
1243
   Notes:
1244
   The start vector is computed from another vector: for the first step (i=0),
1245
   the initial vector is used (see EPSGetInitialVector()); otherwise a random
1229 slepc 1246
   vector is created. Then this vector is forced to be in the range of OP (only
1247
   for generalized definite problems) and orthonormalized with respect to all
1248
   V-vectors up to i-1.
689 dsic.upv.es!jroman 1249
 
1059 slepc 1250
   The flag breakdown is set to true if either i=0 and the vector belongs to the
1251
   deflation space, or i>0 and the vector is linearly dependent with respect
1252
   to the V-vectors.
1253
 
689 dsic.upv.es!jroman 1254
   The caller must pass a vector already allocated with dimensions conforming
1255
   to the initial vector. This vector is overwritten.
1256
 
1257
   Level: developer
1258
 
1259
.seealso: EPSGetInitialVector()
1260
 
1261
@*/
1509 slepc 1262
PetscErrorCode EPSGetStartVector(EPS eps,PetscInt i,Vec vec,PetscTruth *breakdown)
689 dsic.upv.es!jroman 1263
{
1264
  PetscErrorCode ierr;
1265
  PetscReal      norm;
1057 slepc 1266
  PetscTruth     lindep;
689 dsic.upv.es!jroman 1267
  Vec            w;
1268
 
1269
  PetscFunctionBegin;
1270
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
1271
  PetscValidHeaderSpecific(vec,VEC_COOKIE,3);
1272
 
1273
  /* For the first step, use the initial vector, otherwise a random one */
1274
  if (i==0) {
1385 slepc 1275
    w = eps->vec_initial;
1057 slepc 1276
  } else {
1385 slepc 1277
    ierr = VecDuplicate(eps->vec_initial,&w);CHKERRQ(ierr);
689 dsic.upv.es!jroman 1278
    ierr = SlepcVecSetRandom(w);CHKERRQ(ierr);
1279
  }
1280
 
1229 slepc 1281
  /* Force the vector to be in the range of OP for definite generalized problems */
1358 slepc 1282
  if (eps->ispositive) {
1229 slepc 1283
    ierr = STApply(eps->OP,w,vec);CHKERRQ(ierr);
1284
  } else {
1285
    ierr = VecCopy(w,vec);CHKERRQ(ierr);
1286
  }
689 dsic.upv.es!jroman 1287
 
1288
  /* Orthonormalize the vector with respect to previous vectors */
1538 slepc 1289
  ierr = IPOrthogonalize(eps->ip,i+eps->nds,PETSC_NULL,eps->DSV,vec,PETSC_NULL,&norm,&lindep,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
1057 slepc 1290
  if (breakdown) *breakdown = lindep;
1169 slepc 1291
  else if (lindep || norm == 0.0) {
1057 slepc 1292
    if (i==0) { SETERRQ(1,"Initial vector is zero or belongs to the deflation space"); }
750 dsic.upv.es!antodo 1293
    else { SETERRQ(1,"Unable to generate more start vectors"); }
1294
  }
1057 slepc 1295
 
1509 slepc 1296
  ierr = VecScale(vec,1.0/norm);CHKERRQ(ierr);
689 dsic.upv.es!jroman 1297
 
1298
  if (i!=0) {
1299
    ierr = VecDestroy(w);CHKERRQ(ierr);
1300
  }
1301
 
1302
  PetscFunctionReturn(0);
1303
}
780 dsic.upv.es!jroman 1304
#undef __FUNCT__  
1305
#define __FUNCT__ "EPSGetLeftStartVector"
1306
/*@
1307
   EPSGetLeftStartVector - Gets a vector to be used as the starting vector
1308
   in the left recurrence of a two-sided eigensolver.
689 dsic.upv.es!jroman 1309
 
780 dsic.upv.es!jroman 1310
   Collective on EPS and Vec
1311
 
1312
   Input Parameters:
1313
+  eps - the eigensolver context
1314
-  i   - index of the Arnoldi/Lanczos step
1315
 
1316
   Output Parameter:
1317
.  vec - the start vector
1318
 
1319
   Notes:
1320
   The start vector is computed from another vector: for the first step (i=0),
1321
   the left initial vector is used (see EPSGetLeftInitialVector()); otherwise
1322
   a random vector is created. Then this vector is forced to be in the range
1323
   of OP' and orthonormalized with respect to all W-vectors up to i-1.
1324
 
1325
   The caller must pass a vector already allocated with dimensions conforming
1326
   to the left initial vector. This vector is overwritten.
1327
 
1328
   Level: developer
1329
 
1330
.seealso: EPSGetLeftInitialVector()
1331
 
1332
@*/
1509 slepc 1333
PetscErrorCode EPSGetLeftStartVector(EPS eps,PetscInt i,Vec vec)
780 dsic.upv.es!jroman 1334
{
1335
  PetscErrorCode ierr;
1336
  PetscTruth     breakdown;
1337
  PetscReal      norm;
1338
  Vec            w;
1339
 
1340
  PetscFunctionBegin;
1341
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
1342
  PetscValidHeaderSpecific(vec,VEC_COOKIE,3);
1343
 
1344
  /* For the first step, use the initial vector, otherwise a random one */
1345
  if (i==0) {
1385 slepc 1346
    w = eps->vec_initial_left;
780 dsic.upv.es!jroman 1347
  }
1348
  else {
1385 slepc 1349
    ierr = VecDuplicate(eps->vec_initial_left,&w);CHKERRQ(ierr);
780 dsic.upv.es!jroman 1350
    ierr = SlepcVecSetRandom(w);CHKERRQ(ierr);
1351
  }
1352
 
1353
  /* Force the vector to be in the range of OP */
1354
  ierr = STApplyTranspose(eps->OP,w,vec);CHKERRQ(ierr);
1355
 
1356
  /* Orthonormalize the vector with respect to previous vectors */
1538 slepc 1357
  ierr = IPOrthogonalize(eps->ip,i,PETSC_NULL,eps->W,vec,PETSC_NULL,&norm,&breakdown,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
780 dsic.upv.es!jroman 1358
  if (breakdown) {
1359
    if (i==0) { SETERRQ(1,"Left initial vector is zero"); }
1360
    else { SETERRQ(1,"Unable to generate more left start vectors"); }
1361
  }
828 dsic.upv.es!antodo 1362
  ierr = VecScale(vec,1/norm);CHKERRQ(ierr);
780 dsic.upv.es!jroman 1363
 
1364
  if (i!=0) {
1365
    ierr = VecDestroy(w);CHKERRQ(ierr);
1366
  }
1367
 
1368
  PetscFunctionReturn(0);
1369
}