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