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;
37
  int            i;
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) {
130
    ierr = PetscMalloc(sizeof(int)*eps->nconv, &eps->perm); CHKERRQ(ierr);
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
@*/
187
PetscErrorCode EPSGetIterationNumber(EPS eps,int *its)
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
@*/
1209 slepc 224
PetscErrorCode EPSGetOperationCounters(EPS eps,int* ops,int* dots,int* 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
@*/
257
PetscErrorCode EPSGetConverged(EPS eps,int *nconv)
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;
337
  int            i;
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;
386
  int            i;
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
@*/
438
PetscErrorCode EPSGetEigenpair(EPS eps, int i, PetscScalar *eigr, PetscScalar *eigi, Vec Vr, Vec Vi)
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
@*/
485
PetscErrorCode EPSGetValue(EPS eps, int i, PetscScalar *eigr, PetscScalar *eigi)
486
{
528 dsic.upv.es!antodo 487
  int            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
@*/
540
PetscErrorCode EPSGetRightVector(EPS eps, int i, Vec Vr, Vec Vi)
541
{
542
  PetscErrorCode ierr;
543
  int            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
@*/
611
PetscErrorCode EPSGetLeftVector(EPS eps, int i, Vec Wr, Vec Wi)
612
{
613
  PetscErrorCode ierr;
614
  int            k;
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
@*/
680
PetscErrorCode EPSGetErrorEstimate(EPS eps, int i, PetscReal *errest)
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
@*/
719
PetscErrorCode EPSGetErrorEstimateLeft(EPS eps, int i, PetscReal *errest)
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
@*/
763
PetscErrorCode EPSComputeResidualNorm(EPS eps, int i, PetscReal *norm)
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
@*/
846
PetscErrorCode EPSComputeResidualNormLeft(EPS eps, int i, PetscReal *norm)
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
@*/
925
PetscErrorCode EPSComputeRelativeError(EPS eps, int i, PetscReal *error)
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
@*/
998
PetscErrorCode EPSComputeRelativeErrorLeft(EPS eps, int i, PetscReal *error)
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
 
677 dsic.upv.es!antodo 1072
.seealso: EPSDenseNHEPSorted(), EPSSetWhichEigenpairs()
528 dsic.upv.es!antodo 1073
@*/
677 dsic.upv.es!antodo 1074
PetscErrorCode EPSSortEigenvalues(int n,PetscScalar *eig,PetscScalar *eigi,EPSWhich which,int nev,int *permout)
528 dsic.upv.es!antodo 1075
{
1076
  PetscErrorCode ierr;
982 slepc 1077
  int            i;
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) {
1128
        int tmp;
1129
        SWAP(permout[i], permout[i+1], tmp);
1130
      }
1131
    i++;
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__  
1142
#define __FUNCT__ "EPSGetStartVector"
1143
/*@
1144
   EPSGetStartVector - Gets a vector to be used as the starting vector
1145
   in an Arnoldi or Lanczos reduction.
1146
 
1147
   Collective on EPS and Vec
1148
 
1149
   Input Parameters:
1150
+  eps - the eigensolver context
1151
-  i   - index of the Arnoldi/Lanczos step
1152
 
1059 slepc 1153
   Output Parameters:
1154
+  vec - the start vector
1155
-  breakdown - flag indicating that a breakdown has occurred
689 dsic.upv.es!jroman 1156
 
1157
   Notes:
1158
   The start vector is computed from another vector: for the first step (i=0),
1159
   the initial vector is used (see EPSGetInitialVector()); otherwise a random
1229 slepc 1160
   vector is created. Then this vector is forced to be in the range of OP (only
1161
   for generalized definite problems) and orthonormalized with respect to all
1162
   V-vectors up to i-1.
689 dsic.upv.es!jroman 1163
 
1059 slepc 1164
   The flag breakdown is set to true if either i=0 and the vector belongs to the
1165
   deflation space, or i>0 and the vector is linearly dependent with respect
1166
   to the V-vectors.
1167
 
689 dsic.upv.es!jroman 1168
   The caller must pass a vector already allocated with dimensions conforming
1169
   to the initial vector. This vector is overwritten.
1170
 
1171
   Level: developer
1172
 
1173
.seealso: EPSGetInitialVector()
1174
 
1175
@*/
1057 slepc 1176
PetscErrorCode EPSGetStartVector(EPS eps,int i,Vec vec,PetscTruth *breakdown)
689 dsic.upv.es!jroman 1177
{
1178
  PetscErrorCode ierr;
1179
  PetscReal      norm;
1057 slepc 1180
  PetscTruth     lindep;
689 dsic.upv.es!jroman 1181
  Vec            w;
1182
 
1183
  PetscFunctionBegin;
1184
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
1185
  PetscValidHeaderSpecific(vec,VEC_COOKIE,3);
1186
 
1187
  /* For the first step, use the initial vector, otherwise a random one */
1188
  if (i==0) {
1385 slepc 1189
    w = eps->vec_initial;
1057 slepc 1190
  } else {
1385 slepc 1191
    ierr = VecDuplicate(eps->vec_initial,&w);CHKERRQ(ierr);
689 dsic.upv.es!jroman 1192
    ierr = SlepcVecSetRandom(w);CHKERRQ(ierr);
1193
  }
1194
 
1229 slepc 1195
  /* Force the vector to be in the range of OP for definite generalized problems */
1358 slepc 1196
  if (eps->ispositive) {
1229 slepc 1197
    ierr = STApply(eps->OP,w,vec);CHKERRQ(ierr);
1198
  } else {
1199
    ierr = VecCopy(w,vec);CHKERRQ(ierr);
1200
  }
689 dsic.upv.es!jroman 1201
 
1202
  /* Orthonormalize the vector with respect to previous vectors */
1345 slepc 1203
  ierr = IPOrthogonalize(eps->ip,i+eps->nds,PETSC_NULL,eps->DSV,vec,PETSC_NULL,&norm,&lindep,PETSC_NULL);CHKERRQ(ierr);
1057 slepc 1204
  if (breakdown) *breakdown = lindep;
1169 slepc 1205
  else if (lindep || norm == 0.0) {
1057 slepc 1206
    if (i==0) { SETERRQ(1,"Initial vector is zero or belongs to the deflation space"); }
750 dsic.upv.es!antodo 1207
    else { SETERRQ(1,"Unable to generate more start vectors"); }
1208
  }
1057 slepc 1209
 
828 dsic.upv.es!antodo 1210
  ierr = VecScale(vec,1/norm);CHKERRQ(ierr);
689 dsic.upv.es!jroman 1211
 
1212
  if (i!=0) {
1213
    ierr = VecDestroy(w);CHKERRQ(ierr);
1214
  }
1215
 
1216
  PetscFunctionReturn(0);
1217
}
780 dsic.upv.es!jroman 1218
#undef __FUNCT__  
1219
#define __FUNCT__ "EPSGetLeftStartVector"
1220
/*@
1221
   EPSGetLeftStartVector - Gets a vector to be used as the starting vector
1222
   in the left recurrence of a two-sided eigensolver.
689 dsic.upv.es!jroman 1223
 
780 dsic.upv.es!jroman 1224
   Collective on EPS and Vec
1225
 
1226
   Input Parameters:
1227
+  eps - the eigensolver context
1228
-  i   - index of the Arnoldi/Lanczos step
1229
 
1230
   Output Parameter:
1231
.  vec - the start vector
1232
 
1233
   Notes:
1234
   The start vector is computed from another vector: for the first step (i=0),
1235
   the left initial vector is used (see EPSGetLeftInitialVector()); otherwise
1236
   a random vector is created. Then this vector is forced to be in the range
1237
   of OP' and orthonormalized with respect to all W-vectors up to i-1.
1238
 
1239
   The caller must pass a vector already allocated with dimensions conforming
1240
   to the left initial vector. This vector is overwritten.
1241
 
1242
   Level: developer
1243
 
1244
.seealso: EPSGetLeftInitialVector()
1245
 
1246
@*/
1247
PetscErrorCode EPSGetLeftStartVector(EPS eps,int i,Vec vec)
1248
{
1249
  PetscErrorCode ierr;
1250
  PetscTruth     breakdown;
1251
  PetscReal      norm;
1252
  Vec            w;
1253
 
1254
  PetscFunctionBegin;
1255
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
1256
  PetscValidHeaderSpecific(vec,VEC_COOKIE,3);
1257
 
1258
  /* For the first step, use the initial vector, otherwise a random one */
1259
  if (i==0) {
1385 slepc 1260
    w = eps->vec_initial_left;
780 dsic.upv.es!jroman 1261
  }
1262
  else {
1385 slepc 1263
    ierr = VecDuplicate(eps->vec_initial_left,&w);CHKERRQ(ierr);
780 dsic.upv.es!jroman 1264
    ierr = SlepcVecSetRandom(w);CHKERRQ(ierr);
1265
  }
1266
 
1267
  /* Force the vector to be in the range of OP */
1268
  ierr = STApplyTranspose(eps->OP,w,vec);CHKERRQ(ierr);
1269
 
1270
  /* Orthonormalize the vector with respect to previous vectors */
1345 slepc 1271
  ierr = IPOrthogonalize(eps->ip,i,PETSC_NULL,eps->W,vec,PETSC_NULL,&norm,&breakdown,PETSC_NULL);CHKERRQ(ierr);
780 dsic.upv.es!jroman 1272
  if (breakdown) {
1273
    if (i==0) { SETERRQ(1,"Left initial vector is zero"); }
1274
    else { SETERRQ(1,"Unable to generate more left start vectors"); }
1275
  }
828 dsic.upv.es!antodo 1276
  ierr = VecScale(vec,1/norm);CHKERRQ(ierr);
780 dsic.upv.es!jroman 1277
 
1278
  if (i!=0) {
1279
    ierr = VecDestroy(w);CHKERRQ(ierr);
1280
  }
1281
 
1282
  PetscFunctionReturn(0);
1283
}
1284