Actual source code: nepdefault.c

      1: /*
      2:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      3:    SLEPc - Scalable Library for Eigenvalue Problem Computations
      4:    Copyright (c) 2002-, Universitat Politecnica de Valencia, Spain

      6:    This file is part of SLEPc.
      7:    SLEPc is distributed under a 2-clause BSD license (see LICENSE).
      8:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      9: */
     10: /*
     11:    Simple default routines for common NEP operations
     12: */

     14: #include <slepc/private/nepimpl.h>

     16: /*@
     17:    NEPSetWorkVecs - Sets a number of work vectors into a `NEP` object

     19:    Collective

     21:    Input Parameters:
     22: +  nep - the nonlinear eigensolver context
     23: -  nw  - number of work vectors to allocate

     25:    Developer Note:
     26:    This is `SLEPC_EXTERN` because it may be required by user plugin `NEP`
     27:    implementations.

     29:    Level: developer

     31: .seealso: [](ch:nep), `NEPSetUp()`
     32: @*/
     33: PetscErrorCode NEPSetWorkVecs(NEP nep,PetscInt nw)
     34: {
     35:   Vec            t;

     37:   PetscFunctionBegin;
     40:   PetscCheck(nw>0,PetscObjectComm((PetscObject)nep),PETSC_ERR_ARG_OUTOFRANGE,"nw must be > 0: nw = %" PetscInt_FMT,nw);
     41:   if (nep->nwork < nw) {
     42:     PetscCall(VecDestroyVecs(nep->nwork,&nep->work));
     43:     nep->nwork = nw;
     44:     PetscCall(BVGetColumn(nep->V,0,&t));
     45:     PetscCall(VecDuplicateVecs(t,nw,&nep->work));
     46:     PetscCall(BVRestoreColumn(nep->V,0,&t));
     47:   }
     48:   PetscFunctionReturn(PETSC_SUCCESS);
     49: }

     51: /*
     52:   NEPGetDefaultShift - Return the value of sigma to start the nonlinear iteration.
     53:  */
     54: PetscErrorCode NEPGetDefaultShift(NEP nep,PetscScalar *sigma)
     55: {
     56:   PetscFunctionBegin;
     57:   PetscAssertPointer(sigma,2);
     58:   switch (nep->which) {
     59:     case NEP_LARGEST_MAGNITUDE:
     60:     case NEP_LARGEST_IMAGINARY:
     61:     case NEP_ALL:
     62:     case NEP_WHICH_USER:
     63:       *sigma = 1.0;   /* arbitrary value */
     64:       break;
     65:     case NEP_SMALLEST_MAGNITUDE:
     66:     case NEP_SMALLEST_IMAGINARY:
     67:       *sigma = 0.0;
     68:       break;
     69:     case NEP_LARGEST_REAL:
     70:       *sigma = PETSC_MAX_REAL;
     71:       break;
     72:     case NEP_SMALLEST_REAL:
     73:       *sigma = PETSC_MIN_REAL;
     74:       break;
     75:     case NEP_TARGET_MAGNITUDE:
     76:     case NEP_TARGET_REAL:
     77:     case NEP_TARGET_IMAGINARY:
     78:       *sigma = nep->target;
     79:       break;
     80:   }
     81:   PetscFunctionReturn(PETSC_SUCCESS);
     82: }

     84: /*
     85:   NEPConvergedRelative - Checks convergence relative to the eigenvalue.
     86: */
     87: PetscErrorCode NEPConvergedRelative(NEP nep,PetscScalar eigr,PetscScalar eigi,PetscReal res,PetscReal *errest,void *ctx)
     88: {
     89:   PetscReal w;

     91:   PetscFunctionBegin;
     92:   w = SlepcAbsEigenvalue(eigr,eigi);
     93:   *errest = (w!=0.0)? res/w: PETSC_MAX_REAL;
     94:   PetscFunctionReturn(PETSC_SUCCESS);
     95: }

     97: /*
     98:   NEPConvergedAbsolute - Checks convergence absolutely.
     99: */
    100: PetscErrorCode NEPConvergedAbsolute(NEP nep,PetscScalar eigr,PetscScalar eigi,PetscReal res,PetscReal *errest,void *ctx)
    101: {
    102:   PetscFunctionBegin;
    103:   *errest = res;
    104:   PetscFunctionReturn(PETSC_SUCCESS);
    105: }

    107: /*
    108:   NEPConvergedNorm - Checks convergence relative to the matrix norms.
    109: */
    110: PetscErrorCode NEPConvergedNorm(NEP nep,PetscScalar eigr,PetscScalar eigi,PetscReal res,PetscReal *errest,void *ctx)
    111: {
    112:   PetscScalar    s;
    113:   PetscReal      w=0.0;
    114:   PetscInt       j;
    115:   PetscBool      flg;

    117:   PetscFunctionBegin;
    118:   if (nep->fui!=NEP_USER_INTERFACE_SPLIT) {
    119:     PetscCall(NEPComputeFunction(nep,eigr,nep->function,nep->function));
    120:     PetscCall(MatHasOperation(nep->function,MATOP_NORM,&flg));
    121:     PetscCheck(flg,PetscObjectComm((PetscObject)nep),PETSC_ERR_ARG_WRONG,"The computation of backward errors requires a matrix norm operation");
    122:     PetscCall(MatNorm(nep->function,NORM_INFINITY,&w));
    123:   } else {
    124:     /* initialization of matrix norms */
    125:     if (!nep->nrma[0]) {
    126:       for (j=0;j<nep->nt;j++) {
    127:         PetscCall(MatHasOperation(nep->A[j],MATOP_NORM,&flg));
    128:         PetscCheck(flg,PetscObjectComm((PetscObject)nep),PETSC_ERR_ARG_WRONG,"The convergence test related to the matrix norms requires a matrix norm operation");
    129:         PetscCall(MatNorm(nep->A[j],NORM_INFINITY,&nep->nrma[j]));
    130:       }
    131:     }
    132:     for (j=0;j<nep->nt;j++) {
    133:       PetscCall(FNEvaluateFunction(nep->f[j],eigr,&s));
    134:       w = w + nep->nrma[j]*PetscAbsScalar(s);
    135:     }
    136:   }
    137:   *errest = res/w;
    138:   PetscFunctionReturn(PETSC_SUCCESS);
    139: }

    141: /*@C
    142:    NEPStoppingBasic - Default routine to determine whether the outer eigensolver
    143:    iteration must be stopped.

    145:    Collective

    147:    Input Parameters:
    148: +  nep    - the nonlinear eigensolver context
    149: .  its    - current number of iterations
    150: .  max_it - maximum number of iterations
    151: .  nconv  - number of currently converged eigenpairs
    152: .  nev    - number of requested eigenpairs
    153: -  ctx    - context (not used here)

    155:    Output Parameter:
    156: .  reason - result of the stopping test

    158:    Notes:
    159:    `NEPStoppingBasic()` will stop if all requested eigenvalues are converged, or if
    160:    the maximum number of iterations has been reached.

    162:    This is the default stopping test.
    163:    Use `NEPSetStoppingTest()` to provide your own test instead of using this one.

    165:    Level: advanced

    167: .seealso: [](ch:nep), `NEPSetStoppingTest()`, `NEPConvergedReason`, `NEPGetConvergedReason()`
    168: @*/
    169: PetscErrorCode NEPStoppingBasic(NEP nep,PetscInt its,PetscInt max_it,PetscInt nconv,PetscInt nev,NEPConvergedReason *reason,void *ctx)
    170: {
    171:   PetscFunctionBegin;
    172:   *reason = NEP_CONVERGED_ITERATING;
    173:   if (nconv >= nev) {
    174:     PetscCall(PetscInfo(nep,"Nonlinear eigensolver finished successfully: %" PetscInt_FMT " eigenpairs converged at iteration %" PetscInt_FMT "\n",nconv,its));
    175:     *reason = NEP_CONVERGED_TOL;
    176:   } else if (its >= max_it) {
    177:     *reason = NEP_DIVERGED_ITS;
    178:     PetscCall(PetscInfo(nep,"Nonlinear eigensolver iteration reached maximum number of iterations (%" PetscInt_FMT ")\n",its));
    179:   }
    180:   PetscFunctionReturn(PETSC_SUCCESS);
    181: }

    183: PetscErrorCode NEPComputeVectors_Schur(NEP nep)
    184: {
    185:   Mat            Z;

    187:   PetscFunctionBegin;
    188:   PetscCall(DSVectors(nep->ds,DS_MAT_X,NULL,NULL));
    189:   PetscCall(DSGetMat(nep->ds,DS_MAT_X,&Z));
    190:   PetscCall(BVMultInPlace(nep->V,Z,0,nep->nconv));
    191:   PetscCall(DSRestoreMat(nep->ds,DS_MAT_X,&Z));
    192:   PetscCall(BVNormalize(nep->V,nep->eigi));
    193:   PetscFunctionReturn(PETSC_SUCCESS);
    194: }