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.
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); }
50
  ierr = STResetNumberLinearIterations(eps->OP);
51
  eps->evecsavailable = PETSC_FALSE;
52
  ierr = PetscLogEventBegin(EPS_Solve,eps,eps->V[0],eps->V[0],0);CHKERRQ(ierr);
53
  ierr = STPreSolve(eps->OP,eps);CHKERRQ(ierr);
54
  ierr = (*eps->ops->solve)(eps);CHKERRQ(ierr);
55
  ierr = STPostSolve(eps->OP,eps);CHKERRQ(ierr);
56
  ierr = PetscLogEventEnd(EPS_Solve,eps,eps->V[0],eps->V[0],0);CHKERRQ(ierr);
57
  if (!eps->reason) {
58
    SETERRQ(1,"Internal error, solver returned without setting converged reason");
59
  }
60
 
61
  /* Map eigenvalues back to the original problem, necessary in some
62
  * spectral transformations */
63
  ierr = (*eps->ops->backtransform)(eps);CHKERRQ(ierr);
64
 
65
#ifndef PETSC_USE_COMPLEX
66
  /* reorder conjugate eigenvalues (positive imaginary first) */
67
  for (i=0; i<eps->nconv-1; i++) {
68
    PetscScalar minus = -1.0;
69
    if (eps->eigi[i] != 0) {
70
      if (eps->eigi[i] < 0) {
71
        eps->eigi[i] = -eps->eigi[i];
72
        eps->eigi[i+1] = -eps->eigi[i+1];
73
        ierr = VecScale(&minus, eps->V[i+1]); CHKERRQ(ierr);
74
      }
75
      i++;
76
    }
77
  }
78
#endif
79
 
80
  /* sort eigenvalues according to eps->which parameter */
81
  if (eps->perm) {
82
    ierr = PetscFree(eps->perm); CHKERRQ(ierr);
83
    eps->perm = PETSC_NULL;
84
  }
85
  if (eps->nconv > 0) {
86
    ierr = PetscMalloc(sizeof(int)*eps->nconv, &eps->perm); CHKERRQ(ierr);
87
    ierr = EPSSortEigenvalues(eps->nconv, eps->eigr, eps->eigi, eps->which, eps->nconv, eps->perm); CHKERRQ(ierr);
88
  }
89
 
90
  ierr = PetscOptionsHasName(eps->prefix,"-eps_view",&flg);CHKERRQ(ierr);
91
  if (flg && !PetscPreLoadingOn) { ierr = EPSView(eps,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); }
92
 
93
  ierr = PetscOptionsHasName(eps->prefix,"-eps_plot_eigs",&flg);CHKERRQ(ierr);
94
  if (flg) {
95
    ierr = PetscViewerDrawOpen(PETSC_COMM_SELF,0,"Computed Eigenvalues",
96
                             PETSC_DECIDE,PETSC_DECIDE,300,300,&viewer);CHKERRQ(ierr);
97
    ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
98
    ierr = PetscDrawSPCreate(draw,1,&drawsp);CHKERRQ(ierr);
99
    for( i=0; i<eps->nconv; i++ ) {
100
#if defined(PETSC_USE_COMPLEX)
101
      re = PetscRealPart(eps->eigr[i]);
102
      im = PetscImaginaryPart(eps->eigi[i]);
103
#else
104
      re = eps->eigr[i];
105
      im = eps->eigi[i];
106
#endif
107
      ierr = PetscDrawSPAddPoint(drawsp,&re,&im);CHKERRQ(ierr);
108
    }
109
    ierr = PetscDrawSPDraw(drawsp);CHKERRQ(ierr);
110
    ierr = PetscDrawSPDestroy(drawsp);CHKERRQ(ierr);
111
    ierr = PetscViewerDestroy(viewer);CHKERRQ(ierr);
112
  }
113
 
114
  PetscFunctionReturn(0);
115
}
116
 
117
#undef __FUNCT__  
118
#define __FUNCT__ "EPSGetIterationNumber"
119
/*@
120
   EPSGetIterationNumber - Gets the current iteration number. If the
121
   call to EPSSolve() is complete, then it returns the number of iterations
122
   carried out by the solution method.
123
 
124
   Not Collective
125
 
126
   Input Parameter:
127
.  eps - the eigensolver context
128
 
129
   Output Parameter:
130
.  its - number of iterations
131
 
132
   Level: intermediate
133
 
134
   Notes:
135
      During the i-th iteration this call returns i-1. If EPSSolve() is
136
      complete, then parameter "its" contains either the iteration number at
137
      which convergence was successfully reached, or failure was detected.  
138
      Call EPSGetConvergedReason() to determine if the solver converged or
139
      failed and why.
140
 
141
@*/
142
PetscErrorCode EPSGetIterationNumber(EPS eps,int *its)
143
{
144
  PetscFunctionBegin;
145
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
146
  PetscValidIntPointer(its,2);
147
  *its = eps->its;
148
  PetscFunctionReturn(0);
149
}
150
 
151
#undef __FUNCT__  
152
#define __FUNCT__ "EPSGetNumberLinearIterations"
153
/*@
154
   EPSGetNumberLinearIterations - Gets the total number of iterations
155
   required by the linear solves associated to the ST object during the
156
   last EPSSolve() call.
157
 
158
   Not Collective
159
 
160
   Input Parameter:
161
.  eps - EPS context
162
 
163
   Output Parameter:
164
.  lits - number of linear iterations
165
 
166
   Notes:
167
   When the eigensolver algorithm invokes STApply() then a linear system
168
   must be solved (except in the case of standard eigenproblems and shift
169
   transformation). The number of iterations required in this solve is
170
   accumulated into a counter whose value is returned by this function.
171
 
172
   The iteration counter is reset to zero at each successive call to EPSSolve().
173
 
174
   Level: intermediate
175
 
176
@*/
177
PetscErrorCode EPSGetNumberLinearIterations(EPS eps,int* lits)
178
{
179
  PetscFunctionBegin;
180
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
181
  PetscValidIntPointer(lits,2);
182
  STGetNumberLinearIterations(eps->OP, lits);
183
  PetscFunctionReturn(0);
184
}
185
 
186
#undef __FUNCT__  
187
#define __FUNCT__ "EPSGetConverged"
188
/*@
189
   EPSGetConverged - Gets the number of converged eigenpairs.
190
 
191
   Not Collective
192
 
193
   Input Parameter:
194
.  eps - the eigensolver context
195
 
196
   Output Parameter:
197
.  nconv - number of converged eigenpairs
198
 
199
   Note:
200
   This function should be called after EPSSolve() has finished.
201
 
202
   Level: beginner
203
 
204
.seealso: EPSSetDimensions()
205
@*/
206
PetscErrorCode EPSGetConverged(EPS eps,int *nconv)
207
{
208
  PetscFunctionBegin;
209
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
210
  if (nconv) *nconv = eps->nconv;
211
  PetscFunctionReturn(0);
212
}
213
 
214
 
215
#undef __FUNCT__  
216
#define __FUNCT__ "EPSGetConvergedReason"
217
/*@C
218
   EPSGetConvergedReason - Gets the reason why the EPSSolve() iteration was
219
   stopped.
220
 
221
   Not Collective
222
 
223
   Input Parameter:
224
.  eps - the eigensolver context
225
 
226
   Output Parameter:
227
.  reason - negative value indicates diverged, positive value converged
228
   (see EPSConvergedReason)
229
 
230
   Possible values for reason:
231
+  EPS_CONVERGED_TOL - converged up to tolerance
232
.  EPS_DIVERGED_ITS - required more than its to reach convergence
233
.  EPS_DIVERGED_BREAKDOWN - generic breakdown in method
234
-  EPS_DIVERGED_NONSYMMETRIC - The operator is nonsymmetric
235
 
236
   Level: intermediate
237
 
238
   Notes: Can only be called after the call to EPSSolve() is complete.
239
 
240
.seealso: EPSSetTolerances(), EPSSolve(), EPSConvergedReason
241
@*/
242
PetscErrorCode EPSGetConvergedReason(EPS eps,EPSConvergedReason *reason)
243
{
244
  PetscFunctionBegin;
245
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
246
  *reason = eps->reason;
247
  PetscFunctionReturn(0);
248
}
249
 
250
#undef __FUNCT__  
251
#define __FUNCT__ "EPSGetInvariantSubspace"
252
/*@
761 dsic.upv.es!jroman 253
   EPSGetInvariantSubspace - Gets an orthonormal basis of the computed invariant
254
   subspace.
528 dsic.upv.es!antodo 255
 
256
   Not Collective
257
 
258
   Input Parameter:
259
.  eps - the eigensolver context
260
 
261
   Output Parameter:
262
.  v - an array of vectors
263
 
264
   Notes:
265
   This function should be called after EPSSolve() has finished.
266
 
267
   The user should provide in v an array of nconv vectors, where nconv is
268
   the value returned by EPSGetConverged().
269
 
761 dsic.upv.es!jroman 270
   The first k vectors returned in v span an invariant subspace associated
271
   with the first k computed eigenvalues (note that this is not true if the
272
   k-th eigenvalue is complex and matrix A is real; in this case the first
273
   k+1 vectors should be used). An invariant subspace X of A satisfies Ax
528 dsic.upv.es!antodo 274
   in X for all x in X (a similar definition applies for generalized
275
   eigenproblems).
276
 
277
   Level: intermediate
278
 
279
.seealso: EPSGetEigenpair(), EPSGetConverged(), EPSSolve()
280
@*/
281
PetscErrorCode EPSGetInvariantSubspace(EPS eps, Vec *v)
282
{
283
  PetscErrorCode ierr;
284
  int            i;
285
 
286
  PetscFunctionBegin;
287
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
288
  PetscValidHeaderSpecific(v,VEC_COOKIE,3);
289
  if (!eps->V) {
290
    SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "EPSSolve must be called first");
291
  }
292
  for (i=0;i<eps->nconv;i++) {
293
    ierr = VecCopy(eps->V[i],v[i]);CHKERRQ(ierr);
294
  }
295
  PetscFunctionReturn(0);
296
}
297
 
298
#undef __FUNCT__  
299
#define __FUNCT__ "EPSGetEigenpair"
300
/*@
301
   EPSGetEigenpair - Gets the i-th solution of the eigenproblem
302
   as computed by EPSSolve(). The solution consists in both the eigenvalue
761 dsic.upv.es!jroman 303
   and the eigenvector.
528 dsic.upv.es!antodo 304
 
305
   Not Collective
306
 
307
   Input Parameters:
308
+  eps - eigensolver context
309
-  i   - index of the solution
310
 
311
   Output Parameters:
312
+  eigr - real part of eigenvalue
313
.  eigi - imaginary part of eigenvalue
314
.  Vr   - real part of eigenvector
315
-  Vi   - imaginary part of eigenvector
316
 
317
   Notes:
318
   If the eigenvalue is real, then eigi and Vi are set to zero. In the
319
   complex case (e.g. with BOPT=O_complex) the eigenvalue is stored
761 dsic.upv.es!jroman 320
   directly in eigr (eigi is set to zero) and the eigenvector in Vr (Vi is
528 dsic.upv.es!antodo 321
   set to zero).
322
 
323
   The index i should be a value between 0 and nconv (see EPSGetConverged()).
324
   Eigenpairs are indexed according to the ordering criterion established
325
   with EPSSetWhichEigenpairs().
326
 
327
   Level: beginner
328
 
329
.seealso: EPSSolve(), EPSGetConverged(), EPSSetWhichEigenpairs(),
330
          EPSGetInvariantSubspace()
331
@*/
332
PetscErrorCode EPSGetEigenpair(EPS eps, int i, PetscScalar *eigr, PetscScalar *eigi, Vec Vr, Vec Vi)
333
{
334
  PetscErrorCode ierr;
335
  int            k;
336
  PetscScalar    zero = 0.0;
337
#ifndef PETSC_USE_COMPLEX
338
  PetscScalar    minus = -1.0;
339
#endif
340
 
341
  PetscFunctionBegin;
342
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
343
  if (!eps->eigr || !eps->eigi || !eps->V) {
344
    SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "EPSSolve must be called first");
345
  }
346
  if (i<0 || i>=eps->nconv) {
347
    SETERRQ(PETSC_ERR_ARG_OUTOFRANGE, "Argument 2 out of range");
348
  }
349
  if (!eps->evecsavailable && (Vr || Vi) ) {
350
    ierr = (*eps->ops->computevectors)(eps);CHKERRQ(ierr);
351
  }  
352
 
353
  if (!eps->perm) k = i;
354
  else k = eps->perm[i];
355
#ifdef PETSC_USE_COMPLEX
356
  if (eigr) *eigr = eps->eigr[k];
357
  if (eigi) *eigi = 0;
358
  if (Vr) { ierr = VecCopy(eps->AV[k], Vr); CHKERRQ(ierr); }
359
  if (Vi) { ierr = VecSet(&zero, Vi); CHKERRQ(ierr); }
360
#else
361
  if (eigr) *eigr = eps->eigr[k];
362
  if (eigi) *eigi = eps->eigi[k];
363
  if (eps->eigi[k] > 0) { /* first value of conjugate pair */
364
    if (Vr) { ierr = VecCopy(eps->AV[k], Vr); CHKERRQ(ierr); }
365
    if (Vi) { ierr = VecCopy(eps->AV[k+1], Vi); CHKERRQ(ierr); }
366
  } else if (eps->eigi[k] < 0) { /* second value of conjugate pair */
367
    if (Vr) { ierr = VecCopy(eps->AV[k-1], Vr); CHKERRQ(ierr); }
368
    if (Vi) {
369
      ierr = VecCopy(eps->AV[k], Vi); CHKERRQ(ierr);
370
      ierr = VecScale(&minus, Vi); CHKERRQ(ierr);
371
    }
372
  } else { /* real eigenvalue */
373
    if (Vr) { ierr = VecCopy(eps->AV[k], Vr); CHKERRQ(ierr); }
374
    if (Vi) { ierr = VecSet(&zero, Vi); CHKERRQ(ierr); }
375
  }
376
#endif
377
 
378
  PetscFunctionReturn(0);
379
}
380
 
381
#undef __FUNCT__  
382
#define __FUNCT__ "EPSGetErrorEstimate"
383
/*@
761 dsic.upv.es!jroman 384
   EPSGetErrorEstimate - Returns the error estimate associated to the i-th
385
   computed eigenpair.
528 dsic.upv.es!antodo 386
 
387
   Not Collective
388
 
389
   Input Parameter:
390
+  eps - eigensolver context
391
-  i   - index of eigenpair
392
 
393
   Output Parameter:
394
.  errest - the error estimate
395
 
761 dsic.upv.es!jroman 396
   Notes:
397
   This is the error estimate used internally by the eigensolver. The actual
398
   error bound can be computed with EPSComputeRelativeError(). See also the user's
399
   manual for details.
400
 
528 dsic.upv.es!antodo 401
   Level: advanced
402
 
403
.seealso: EPSComputeRelativeError()
404
@*/
405
PetscErrorCode EPSGetErrorEstimate(EPS eps, int i, PetscReal *errest)
406
{
407
  PetscFunctionBegin;
408
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
409
  if (!eps->eigr || !eps->eigi) {
410
    SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "EPSSolve must be called first");
411
  }
412
  if (i<0 || i>=eps->nconv) {
413
    SETERRQ(PETSC_ERR_ARG_OUTOFRANGE, "Argument 2 out of range");
414
  }
415
  if (eps->perm) i = eps->perm[i];  
416
  if (errest) *errest = eps->errest[i];
417
  PetscFunctionReturn(0);
418
}
419
 
420
 
421
#undef __FUNCT__  
422
#define __FUNCT__ "EPSComputeResidualNorm"
423
/*@
761 dsic.upv.es!jroman 424
   EPSComputeResidualNorm - Computes the norm of the residual vector associated with
425
   the i-th computed eigenpair.
528 dsic.upv.es!antodo 426
 
427
   Collective on EPS
428
 
429
   Input Parameter:
430
.  eps - the eigensolver context
431
.  i   - the solution index
432
 
433
   Output Parameter:
761 dsic.upv.es!jroman 434
.  norm - the residual norm, computed as ||Ax-kBx||_2 where k is the
528 dsic.upv.es!antodo 435
   eigenvalue and x is the eigenvector.
761 dsic.upv.es!jroman 436
   If k=0 then the residual norm is computed as ||Ax||_2.
528 dsic.upv.es!antodo 437
 
438
   Notes:
439
   The index i should be a value between 0 and nconv (see EPSGetConverged()).
440
   Eigenpairs are indexed according to the ordering criterion established
441
   with EPSSetWhichEigenpairs().
442
 
443
   Level: beginner
444
 
445
.seealso: EPSSolve(), EPSGetConverged(), EPSSetWhichEigenpairs()
446
@*/
447
PetscErrorCode EPSComputeResidualNorm(EPS eps, int i, PetscReal *norm)
448
{
449
  PetscErrorCode ierr;
450
  Vec            u, v, w, xr, xi;
451
  Mat            A, B;
452
  PetscScalar    alpha, kr, ki;
453
#ifndef PETSC_USE_COMPLEX
454
  PetscReal      ni, nr;
455
#endif
456
 
457
  PetscFunctionBegin;
458
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
459
  ierr = STGetOperators(eps->OP,&A,&B);CHKERRQ(ierr);
460
  ierr = VecDuplicate(eps->vec_initial,&u); CHKERRQ(ierr);
461
  ierr = VecDuplicate(eps->vec_initial,&v); CHKERRQ(ierr);
462
  ierr = VecDuplicate(eps->vec_initial,&w); CHKERRQ(ierr);
463
  ierr = VecDuplicate(eps->vec_initial,&xr); CHKERRQ(ierr);
464
  ierr = VecDuplicate(eps->vec_initial,&xi); CHKERRQ(ierr);
465
  ierr = EPSGetEigenpair(eps,i,&kr,&ki,xr,xi); CHKERRQ(ierr);
466
 
467
#ifndef PETSC_USE_COMPLEX
468
  if (ki == 0 ||
469
    PetscAbsScalar(ki) < PetscAbsScalar(kr*PETSC_MACHINE_EPSILON)) {
470
#endif
471
    ierr = MatMult( A, xr, u ); CHKERRQ(ierr); /* u=A*x */
472
    if (PetscAbsScalar(kr) > PETSC_MACHINE_EPSILON) {
473
      if (eps->isgeneralized) { ierr = MatMult( B, xr, w ); CHKERRQ(ierr); }
474
      else { ierr = VecCopy( xr, w ); CHKERRQ(ierr); } /* w=B*x */
475
      alpha = -kr;
476
      ierr = VecAXPY( &alpha, w, u ); CHKERRQ(ierr); /* u=A*x-k*B*x */
477
    }
478
    ierr = VecNorm( u, NORM_2, norm); CHKERRQ(ierr);  
479
#ifndef PETSC_USE_COMPLEX
480
  } else {
481
    ierr = MatMult( A, xr, u ); CHKERRQ(ierr); /* u=A*xr */
482
    if (eps->isgeneralized) { ierr = MatMult( B, xr, v ); CHKERRQ(ierr); }
483
    else { ierr = VecCopy( xr, v ); CHKERRQ(ierr); } /* v=B*xr */
484
    alpha = -kr;
485
    ierr = VecAXPY( &alpha, v, u ); CHKERRQ(ierr); /* u=A*xr-kr*B*xr */
486
    if (eps->isgeneralized) { ierr = MatMult( B, xi, w ); CHKERRQ(ierr); }
487
    else { ierr = VecCopy( xi, w ); CHKERRQ(ierr); } /* w=B*xi */
488
    alpha = ki;
489
    ierr = VecAXPY( &alpha, w, u ); CHKERRQ(ierr); /* u=A*xr-kr*B*xr+ki*B*xi */
490
    ierr = VecNorm( u, NORM_2, &nr ); CHKERRQ(ierr);
491
    ierr = MatMult( A, xi, u ); CHKERRQ(ierr); /* u=A*xi */
492
    alpha = -kr;
493
    ierr = VecAXPY( &alpha, w, u ); CHKERRQ(ierr); /* u=A*xi-kr*B*xi */
494
    alpha = -ki;
495
    ierr = VecAXPY( &alpha, v, u ); CHKERRQ(ierr); /* u=A*xi-kr*B*xi-ki*B*xr */
496
    ierr = VecNorm( u, NORM_2, &ni ); CHKERRQ(ierr);
497
    *norm = SlepcAbsEigenvalue( nr, ni );
498
  }
499
#endif
500
 
501
  ierr = VecDestroy(w); CHKERRQ(ierr);
502
  ierr = VecDestroy(v); CHKERRQ(ierr);
503
  ierr = VecDestroy(u); CHKERRQ(ierr);
504
  ierr = VecDestroy(xr); CHKERRQ(ierr);
505
  ierr = VecDestroy(xi); CHKERRQ(ierr);
506
  PetscFunctionReturn(0);
507
}
508
 
509
#undef __FUNCT__  
510
#define __FUNCT__ "EPSComputeRelativeError"
511
/*@
761 dsic.upv.es!jroman 512
   EPSComputeRelativeError - Computes the relative error bound associated
513
   with the i-th computed eigenpair.
528 dsic.upv.es!antodo 514
 
515
   Collective on EPS
516
 
517
   Input Parameter:
518
.  eps - the eigensolver context
519
.  i   - the solution index
520
 
521
   Output Parameter:
761 dsic.upv.es!jroman 522
.  error - the relative error bound, computed as ||Ax-kBx||_2/||kx||_2 where
523
   k is the eigenvalue and x is the eigenvector.
524
   If k=0 the relative error is computed as ||Ax||_2/||x||_2.
528 dsic.upv.es!antodo 525
 
526
   Level: beginner
527
 
761 dsic.upv.es!jroman 528
.seealso: EPSSolve(), EPSComputeResidualNorm(), EPSGetErrorEstimate()
528 dsic.upv.es!antodo 529
@*/
530
PetscErrorCode EPSComputeRelativeError(EPS eps, int i, PetscReal *error)
531
{
532
  PetscErrorCode ierr;
533
  Vec            xr, xi;  
534
  PetscScalar    kr, ki;  
535
  PetscReal      norm, er;
536
#ifndef PETSC_USE_COMPLEX
537
  Vec            u;
538
  PetscScalar    alpha;
539
  PetscReal      ei;
540
#endif
541
 
542
  PetscFunctionBegin;
543
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);  
544
  ierr = EPSComputeResidualNorm(eps,i,&norm); CHKERRQ(ierr);
545
  ierr = VecDuplicate(eps->vec_initial,&xr); CHKERRQ(ierr);
546
  ierr = VecDuplicate(eps->vec_initial,&xi); CHKERRQ(ierr);
547
  ierr = EPSGetEigenpair(eps,i,&kr,&ki,xr,xi); CHKERRQ(ierr);
548
 
549
#ifndef PETSC_USE_COMPLEX
550
  if (ki == 0 ||
551
    PetscAbsScalar(ki) < PetscAbsScalar(kr*PETSC_MACHINE_EPSILON)) {
552
#endif
553
    if (PetscAbsScalar(kr) > PETSC_MACHINE_EPSILON) {
554
      ierr = VecScale(&kr, xr); CHKERRQ(ierr);
555
    }
556
    ierr = VecNorm(xr, NORM_2, &er); CHKERRQ(ierr);
557
    *error = norm / er;
558
#ifndef PETSC_USE_COMPLEX
559
  } else {
560
    ierr = VecDuplicate(xi, &u); CHKERRQ(ierr);  
561
    ierr = VecCopy(xi, u); CHKERRQ(ierr);  
562
    alpha = -ki;
563
    ierr = VecAXPBY(&kr, &alpha, xr, u); CHKERRQ(ierr);  
564
    ierr = VecNorm(u, NORM_2, &er); CHKERRQ(ierr);  
565
    ierr = VecAXPBY(&kr, &ki, xr, xi);  CHKERRQ(ierr);      
566
    ierr = VecNorm(xi, NORM_2, &ei); CHKERRQ(ierr);  
567
    ierr = VecDestroy(u); CHKERRQ(ierr);  
568
    *error = norm / SlepcAbsEigenvalue(er, ei);
569
  }
570
#endif    
571
 
572
  ierr = VecDestroy(xr); CHKERRQ(ierr);
573
  ierr = VecDestroy(xi); CHKERRQ(ierr);
574
  PetscFunctionReturn(0);
575
}
576
 
577
#undef __FUNCT__  
578
#define __FUNCT__ "EPSReverseProjection"
579
/*@
580
   EPSReverseProjection - Compute the operation V=V*S, where the columns of
581
   V are m of the basis vectors of the EPS object and S is an mxm dense
582
   matrix.
583
 
584
   Collective on EPS
585
 
586
   Input Parameter:
587
+  eps - the eigenproblem solver context
588
.  V - basis vectors
589
.  S - pointer to the values of matrix S
590
.  k - starting column
591
.  m - dimension of matrix S
592
-  work - workarea of m vectors for intermediate results
593
 
594
   Level: developer
595
 
596
@*/
597
PetscErrorCode EPSReverseProjection(EPS eps,Vec* V,PetscScalar *S,int k,int m,Vec* work)
598
{
599
  PetscErrorCode ierr;
600
  int            i;
601
  PetscScalar    zero = 0.0;
602
 
603
  PetscFunctionBegin;
756 dsic.upv.es!antodo 604
  ierr = PetscLogEventBegin(EPS_ReverseProjection,eps,0,0,0);CHKERRQ(ierr);
528 dsic.upv.es!antodo 605
  for (i=k;i<m;i++) {
606
    ierr = VecSet(&zero,work[i]);CHKERRQ(ierr);
607
    ierr = VecMAXPY(m,S+m*i,work[i],V);CHKERRQ(ierr);
608
  }    
609
  for (i=k;i<m;i++) {
610
    ierr = VecCopy(work[i],V[i]);CHKERRQ(ierr);
611
  }    
756 dsic.upv.es!antodo 612
  ierr = PetscLogEventEnd(EPS_ReverseProjection,eps,0,0,0);CHKERRQ(ierr);
528 dsic.upv.es!antodo 613
  PetscFunctionReturn(0);
614
}
615
 
677 dsic.upv.es!antodo 616
#define SWAP(a,b,t) {t=a;a=b;b=t;}
617
 
528 dsic.upv.es!antodo 618
#undef __FUNCT__  
677 dsic.upv.es!antodo 619
#define __FUNCT__ "EPSSortEigenvalues"
528 dsic.upv.es!antodo 620
/*@
677 dsic.upv.es!antodo 621
   EPSSortEigenvalues - Sorts a list of eigenvalues according to a certain
622
   criterion.
528 dsic.upv.es!antodo 623
 
677 dsic.upv.es!antodo 624
   Not Collective
528 dsic.upv.es!antodo 625
 
677 dsic.upv.es!antodo 626
   Input Parameters:
627
+  n     - number of eigenvalue in the list
628
.  eig   - pointer to the array containing the eigenvalues
629
.  eigi  - imaginary part of the eigenvalues (only when using real numbers)
630
.  which - sorting criterion
631
-  nev   - number of wanted eigenvalues
528 dsic.upv.es!antodo 632
 
677 dsic.upv.es!antodo 633
   Output Parameter:
634
.  permout - resulting permutation
528 dsic.upv.es!antodo 635
 
677 dsic.upv.es!antodo 636
   Notes:
637
   The result is a list of indices in the original eigenvalue array
638
   corresponding to the first nev eigenvalues sorted in the specified
639
   criterion
528 dsic.upv.es!antodo 640
 
677 dsic.upv.es!antodo 641
   Level: developer
528 dsic.upv.es!antodo 642
 
677 dsic.upv.es!antodo 643
.seealso: EPSDenseNHEPSorted(), EPSSetWhichEigenpairs()
528 dsic.upv.es!antodo 644
@*/
677 dsic.upv.es!antodo 645
PetscErrorCode EPSSortEigenvalues(int n,PetscScalar *eig,PetscScalar *eigi,EPSWhich which,int nev,int *permout)
528 dsic.upv.es!antodo 646
{
647
  PetscErrorCode ierr;
677 dsic.upv.es!antodo 648
  int            i,*perm;
649
  PetscReal      *values;
528 dsic.upv.es!antodo 650
 
651
  PetscFunctionBegin;
677 dsic.upv.es!antodo 652
  ierr = PetscMalloc(n*sizeof(int),&perm);CHKERRQ(ierr);
653
  ierr = PetscMalloc(n*sizeof(PetscReal),&values);CHKERRQ(ierr);
654
  for (i=0; i<n; i++) { perm[i] = i;}
528 dsic.upv.es!antodo 655
 
677 dsic.upv.es!antodo 656
  switch(which) {
657
    case EPS_LARGEST_MAGNITUDE:
658
    case EPS_SMALLEST_MAGNITUDE:
659
      for (i=0; i<n; i++) { values[i] = SlepcAbsEigenvalue(eig[i],eigi[i]); }
660
      break;
661
    case EPS_LARGEST_REAL:
662
    case EPS_SMALLEST_REAL:
663
      for (i=0; i<n; i++) { values[i] = PetscRealPart(eig[i]); }
664
      break;
665
    case EPS_LARGEST_IMAGINARY:
666
    case EPS_SMALLEST_IMAGINARY:
667
#if defined(PETSC_USE_COMPLEX)
668
      for (i=0; i<n; i++) { values[i] = PetscImaginaryPart(eig[i]); }
669
#else
670
      for (i=0; i<n; i++) { values[i] = PetscAbsReal(eigi[i]); }
671
#endif
672
      break;
673
    default: SETERRQ(1,"Wrong value of which");
674
  }
528 dsic.upv.es!antodo 675
 
677 dsic.upv.es!antodo 676
  ierr = PetscSortRealWithPermutation(n,values,perm);CHKERRQ(ierr);
528 dsic.upv.es!antodo 677
 
677 dsic.upv.es!antodo 678
  switch(which) {
679
    case EPS_LARGEST_MAGNITUDE:
680
    case EPS_LARGEST_REAL:
681
    case EPS_LARGEST_IMAGINARY:
682
      for (i=0; i<nev; i++) { permout[i] = perm[n-1-i]; }
683
      break;
684
    case EPS_SMALLEST_MAGNITUDE:
685
    case EPS_SMALLEST_REAL:
686
    case EPS_SMALLEST_IMAGINARY:
687
      for (i=0; i<nev; i++) { permout[i] = perm[i]; }
688
      break;
689
    default: SETERRQ(1,"Wrong value of which");
528 dsic.upv.es!antodo 690
  }
691
 
677 dsic.upv.es!antodo 692
#if !defined(PETSC_USE_COMPLEX)
693
  for (i=0; i<nev-1; i++) {
694
    if (eigi[permout[i]] != 0.0) {
695
      if (eig[permout[i]] == eig[permout[i+1]] &&
696
          eigi[permout[i]] == -eigi[permout[i+1]] &&
697
          eigi[permout[i]] < 0.0) {
698
        int tmp;
699
        SWAP(permout[i], permout[i+1], tmp);
700
      }
701
    i++;
702
    }
703
  }
704
#endif
528 dsic.upv.es!antodo 705
 
677 dsic.upv.es!antodo 706
  ierr = PetscFree(values);CHKERRQ(ierr);
707
  ierr = PetscFree(perm);CHKERRQ(ierr);
528 dsic.upv.es!antodo 708
  PetscFunctionReturn(0);
709
}
689 dsic.upv.es!jroman 710
 
711
#undef __FUNCT__  
712
#define __FUNCT__ "EPSGetStartVector"
713
/*@
714
   EPSGetStartVector - Gets a vector to be used as the starting vector
715
   in an Arnoldi or Lanczos reduction.
716
 
717
   Collective on EPS and Vec
718
 
719
   Input Parameters:
720
+  eps - the eigensolver context
721
-  i   - index of the Arnoldi/Lanczos step
722
 
723
   Input/Output Parameter:
724
.  vec - the start vector
725
 
726
   Input/Output Parameter:
727
.  norm - the start vector
728
 
729
   Notes:
730
   The start vector is computed from another vector: for the first step (i=0),
731
   the initial vector is used (see EPSGetInitialVector()); otherwise a random
732
   vector is created. Then this vector is forced to be in the range of OP and
733
   orthonormalized with respect to all V-vectors up to i-1.
734
 
735
   The caller must pass a vector already allocated with dimensions conforming
736
   to the initial vector. This vector is overwritten.
737
 
738
   Level: developer
739
 
740
.seealso: EPSGetInitialVector()
741
 
742
@*/
743
PetscErrorCode EPSGetStartVector(EPS eps,int i,Vec vec)
744
{
745
  PetscErrorCode ierr;
746
  PetscTruth     breakdown;
747
  PetscScalar    t;
748
  PetscReal      norm;
749
  Vec            w;
750
 
751
  PetscFunctionBegin;
752
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
753
  PetscValidHeaderSpecific(vec,VEC_COOKIE,3);
754
 
755
  /* For the first step, use the initial vector, otherwise a random one */
756
  if (i==0) {
757
    w = eps->vec_initial;
758
  }
759
  else {
760
    ierr = VecDuplicate(eps->vec_initial,&w);CHKERRQ(ierr);
761
    ierr = SlepcVecSetRandom(w);CHKERRQ(ierr);
762
  }
763
 
764
  /* Force the vector to be in the range of OP */
765
  ierr = STApply(eps->OP,w,vec);CHKERRQ(ierr);
766
 
767
  /* Orthonormalize the vector with respect to previous vectors */
768
  ierr = EPSOrthogonalize(eps,i+eps->nds,eps->DSV,vec,PETSC_NULL,&norm,&breakdown);CHKERRQ(ierr);
750 dsic.upv.es!antodo 769
  if (breakdown) {
770
    if (i==0) { SETERRQ(1,"Initial vector is zero or belongs to the deflation space"); }
771
    else { SETERRQ(1,"Unable to generate more start vectors"); }
772
  }
689 dsic.upv.es!jroman 773
  t = 1 / norm;
774
  ierr = VecScale(&t,vec);CHKERRQ(ierr);
775
 
776
  if (i!=0) {
777
    ierr = VecDestroy(w);CHKERRQ(ierr);
778
  }
779
 
780
  PetscFunctionReturn(0);
781
}
782