Subversion Repositories slepc-dev

Rev

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

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