Actual source code: nleigs-fullb.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:    Full basis for the linearization of the rational approximation of non-linear eigenproblems
     12: */

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

     17: static PetscErrorCode MatMult_FullBasis_Sinvert(Mat M,Vec x,Vec y)
     18: {
     19:   NEP_NLEIGS        *ctx;
     20:   NEP               nep;
     21:   const PetscScalar *px;
     22:   PetscScalar       *beta,*s,*xi,*t,*py,sigma;
     23:   PetscInt          nmat,d,i,k,m;
     24:   Vec               xx,xxx,yy,yyy,w,ww,www;

     26:   PetscFunctionBegin;
     27:   PetscCall(MatShellGetContext(M,&nep));
     28:   ctx = (NEP_NLEIGS*)nep->data;
     29:   beta = ctx->beta; s = ctx->s; xi = ctx->xi;
     30:   sigma = ctx->shifts[0];
     31:   nmat = ctx->nmat;
     32:   d = nmat-1;
     33:   m = nep->nloc;
     34:   PetscCall(PetscMalloc1(ctx->nmat,&t));
     35:   xx = ctx->w[0]; xxx = ctx->w[1]; yy = ctx->w[2]; yyy=ctx->w[3];
     36:   w = nep->work[0]; ww = nep->work[1]; www = nep->work[2];
     37:   PetscCall(VecGetArrayRead(x,&px));
     38:   PetscCall(VecGetArray(y,&py));
     39:   PetscCall(VecPlaceArray(xx,px+(d-1)*m));
     40:   PetscCall(VecPlaceArray(xxx,px+(d-2)*m));
     41:   PetscCall(VecPlaceArray(yy,py+(d-2)*m));
     42:   PetscCall(VecCopy(xxx,yy));
     43:   PetscCall(VecAXPY(yy,beta[d-1]/xi[d-2],xx));
     44:   PetscCall(VecScale(yy,1.0/(s[d-2]-sigma)));
     45:   PetscCall(VecResetArray(xx));
     46:   PetscCall(VecResetArray(xxx));
     47:   PetscCall(VecResetArray(yy));
     48:   for (i=d-3;i>=0;i--) {
     49:     PetscCall(VecPlaceArray(xx,px+(i+1)*m));
     50:     PetscCall(VecPlaceArray(xxx,px+i*m));
     51:     PetscCall(VecPlaceArray(yy,py+i*m));
     52:     PetscCall(VecPlaceArray(yyy,py+(i+1)*m));
     53:     PetscCall(VecCopy(xxx,yy));
     54:     PetscCall(VecAXPY(yy,beta[i+1]/xi[i],xx));
     55:     PetscCall(VecAXPY(yy,-beta[i+1]*(1.0-sigma/xi[i]),yyy));
     56:     PetscCall(VecScale(yy,1.0/(s[i]-sigma)));
     57:     PetscCall(VecResetArray(xx));
     58:     PetscCall(VecResetArray(xxx));
     59:     PetscCall(VecResetArray(yy));
     60:     PetscCall(VecResetArray(yyy));
     61:   }
     62:   if (nep->fui==NEP_USER_INTERFACE_SPLIT) {
     63:     PetscCall(VecZeroEntries(w));
     64:     for (k=0;k<nep->nt;k++) {
     65:       PetscCall(VecZeroEntries(ww));
     66:       PetscCall(VecPlaceArray(xx,px+(d-1)*m));
     67:       PetscCall(VecAXPY(ww,-ctx->coeffD[k+nep->nt*d]/beta[d],xx));
     68:       PetscCall(VecResetArray(xx));
     69:       for (i=0;i<d-1;i++) {
     70:         PetscCall(VecPlaceArray(yy,py+i*m));
     71:         PetscCall(VecAXPY(ww,-ctx->coeffD[nep->nt*i+k],yy));
     72:         PetscCall(VecResetArray(yy));
     73:       }
     74:       PetscCall(MatMult(nep->A[k],ww,www));
     75:       PetscCall(VecAXPY(w,1.0,www));
     76:     }
     77:   } else {
     78:     PetscCall(VecPlaceArray(xx,px+(d-1)*m));
     79:     PetscCall(MatMult(ctx->D[d],xx,w));
     80:     PetscCall(VecScale(w,-1.0/beta[d]));
     81:     PetscCall(VecResetArray(xx));
     82:     for (i=0;i<d-1;i++) {
     83:       PetscCall(VecPlaceArray(yy,py+i*m));
     84:       PetscCall(MatMult(ctx->D[i],yy,ww));
     85:       PetscCall(VecResetArray(yy));
     86:       PetscCall(VecAXPY(w,-1.0,ww));
     87:     }
     88:   }
     89:   PetscCall(VecPlaceArray(yy,py+(d-1)*m));
     90:   PetscCall(KSPSolve(ctx->ksp[0],w,yy));
     91:   PetscCall(NEPNLEIGSEvalNRTFunct(nep,d-1,sigma,t));
     92:   for (i=0;i<d-1;i++) {
     93:     PetscCall(VecPlaceArray(yyy,py+i*m));
     94:     PetscCall(VecAXPY(yyy,t[i],yy));
     95:     PetscCall(VecResetArray(yyy));
     96:   }
     97:   PetscCall(VecScale(yy,t[d-1]));
     98:   PetscCall(VecResetArray(yy));
     99:   PetscCall(VecRestoreArrayRead(x,&px));
    100:   PetscCall(VecRestoreArray(y,&py));
    101:   PetscCall(PetscFree(t));
    102:   PetscFunctionReturn(PETSC_SUCCESS);
    103: }

    105: static PetscErrorCode MatMultTranspose_FullBasis_Sinvert(Mat M,Vec x,Vec y)
    106: {
    107:   NEP_NLEIGS        *ctx;
    108:   NEP               nep;
    109:   const PetscScalar *px;
    110:   PetscScalar       *beta,*s,*xi,*t,*py,sigma;
    111:   PetscInt          nmat,d,i,k,m;
    112:   Vec               xx,yy,yyy,w,z0;

    114:   PetscFunctionBegin;
    115:   PetscCall(MatShellGetContext(M,&nep));
    116:   ctx = (NEP_NLEIGS*)nep->data;
    117:   beta = ctx->beta; s = ctx->s; xi = ctx->xi;
    118:   sigma = ctx->shifts[0];
    119:   nmat = ctx->nmat;
    120:   d = nmat-1;
    121:   m = nep->nloc;
    122:   PetscCall(PetscMalloc1(ctx->nmat,&t));
    123:   xx = ctx->w[0]; yy = ctx->w[1]; yyy=ctx->w[2];
    124:   w = nep->work[0]; z0 = nep->work[1];
    125:   PetscCall(VecGetArrayRead(x,&px));
    126:   PetscCall(VecGetArray(y,&py));
    127:   PetscCall(NEPNLEIGSEvalNRTFunct(nep,d,sigma,t));
    128:   PetscCall(VecPlaceArray(xx,px+(d-1)*m));
    129:   PetscCall(VecCopy(xx,w));
    130:   PetscCall(VecScale(w,t[d-1]));
    131:   PetscCall(VecResetArray(xx));
    132:   for (i=0;i<d-1;i++) {
    133:     PetscCall(VecPlaceArray(xx,px+i*m));
    134:     PetscCall(VecAXPY(w,t[i],xx));
    135:     PetscCall(VecResetArray(xx));
    136:   }
    137:   PetscCall(KSPSolveTranspose(ctx->ksp[0],w,z0));

    139:   PetscCall(VecPlaceArray(yy,py));
    140:   if (nep->fui==NEP_USER_INTERFACE_SPLIT) {
    141:     PetscCall(VecZeroEntries(yy));
    142:     for (k=0;k<nep->nt;k++) {
    143:       PetscCall(MatMult(nep->A[k],z0,w));
    144:       PetscCall(VecAXPY(yy,ctx->coeffD[k],w));
    145:     }
    146:   } else PetscCall(MatMultTranspose(ctx->D[0],z0,yy));
    147:   PetscCall(VecPlaceArray(xx,px));
    148:   PetscCall(VecAXPY(yy,-1.0,xx));
    149:   PetscCall(VecResetArray(xx));
    150:   PetscCall(VecScale(yy,-1.0/(s[0]-sigma)));
    151:   PetscCall(VecResetArray(yy));
    152:   for (i=2;i<d;i++) {
    153:     PetscCall(VecPlaceArray(yy,py+(i-1)*m));
    154:     if (nep->fui==NEP_USER_INTERFACE_SPLIT) {
    155:       PetscCall(VecZeroEntries(yy));
    156:       for (k=0;k<nep->nt;k++) {
    157:         PetscCall(MatMult(nep->A[k],z0,w));
    158:         PetscCall(VecAXPY(yy,ctx->coeffD[k+(i-1)*nep->nt],w));
    159:       }
    160:     } else PetscCall(MatMultTranspose(ctx->D[i-1],z0,yy));
    161:     PetscCall(VecPlaceArray(yyy,py+(i-2)*m));
    162:     PetscCall(VecAXPY(yy,beta[i-1]*(1.0-sigma/xi[i-2]),yyy));
    163:     PetscCall(VecResetArray(yyy));
    164:     PetscCall(VecPlaceArray(xx,px+(i-1)*m));
    165:     PetscCall(VecAXPY(yy,-1.0,xx));
    166:     PetscCall(VecResetArray(xx));
    167:     PetscCall(VecScale(yy,-1.0/(s[i-1]-sigma)));
    168:     PetscCall(VecResetArray(yy));
    169:   }
    170:   PetscCall(VecPlaceArray(yy,py+(d-1)*m));
    171:   if (nep->fui==NEP_USER_INTERFACE_SPLIT) {
    172:     PetscCall(VecZeroEntries(yy));
    173:     for (k=0;k<nep->nt;k++) {
    174:       PetscCall(MatMult(nep->A[k],z0,w));
    175:       PetscCall(VecAXPY(yy,ctx->coeffD[k+d*nep->nt],w));
    176:     }
    177:   } else PetscCall(MatMultTranspose(ctx->D[d],z0,yy));
    178:   PetscCall(VecScale(yy,-1.0/beta[d]));
    179:   PetscCall(VecPlaceArray(yyy,py+(d-2)*m));
    180:   PetscCall(VecAXPY(yy,beta[d-1]/xi[d-2],yyy));
    181:   PetscCall(VecResetArray(yyy));
    182:   PetscCall(VecResetArray(yy));

    184:   for (i=d-2;i>0;i--) {
    185:     PetscCall(VecPlaceArray(yyy,py+(i-1)*m));
    186:     PetscCall(VecPlaceArray(yy,py+i*m));
    187:     PetscCall(VecAXPY(yy,beta[i]/xi[i-1],yyy));
    188:     PetscCall(VecResetArray(yyy));
    189:     PetscCall(VecResetArray(yy));
    190:   }

    192:   PetscCall(VecRestoreArrayRead(x,&px));
    193:   PetscCall(VecRestoreArray(y,&py));
    194:   PetscCall(PetscFree(t));
    195:   PetscFunctionReturn(PETSC_SUCCESS);
    196: }

    198: static PetscErrorCode BackTransform_FullBasis(ST st,PetscInt n,PetscScalar *eigr,PetscScalar *eigi)
    199: {
    200:   NEP            nep;

    202:   PetscFunctionBegin;
    203:   PetscCall(STShellGetContext(st,&nep));
    204:   PetscCall(NEPNLEIGSBackTransform((PetscObject)nep,n,eigr,eigi));
    205:   PetscFunctionReturn(PETSC_SUCCESS);
    206: }

    208: static PetscErrorCode Apply_FullBasis(ST st,Vec x,Vec y)
    209: {
    210:   NEP            nep;
    211:   NEP_NLEIGS     *ctx;

    213:   PetscFunctionBegin;
    214:   PetscCall(STShellGetContext(st,&nep));
    215:   ctx = (NEP_NLEIGS*)nep->data;
    216:   PetscCall(MatMult(ctx->A,x,y));
    217:   PetscFunctionReturn(PETSC_SUCCESS);
    218: }

    220: static PetscErrorCode ApplyTranspose_FullBasis(ST st,Vec x,Vec y)
    221: {
    222:   NEP            nep;
    223:   NEP_NLEIGS     *ctx;

    225:   PetscFunctionBegin;
    226:   PetscCall(STShellGetContext(st,&nep));
    227:   ctx = (NEP_NLEIGS*)nep->data;
    228:   PetscCall(MatMultTranspose(ctx->A,x,y));
    229:   PetscFunctionReturn(PETSC_SUCCESS);
    230: }

    232: PetscErrorCode NEPSetUp_NLEIGS_FullBasis(NEP nep)
    233: {
    234:   NEP_NLEIGS     *ctx=(NEP_NLEIGS*)nep->data;
    235:   ST             st;
    236:   Mat            Q;
    237:   PetscInt       i=0,deg=ctx->nmat-1;
    238:   PetscBool      trackall,istrivial,ks;
    239:   PetscScalar    *epsarray,*neparray;
    240:   Vec            veps,w=NULL;
    241:   EPSWhich       which;

    243:   PetscFunctionBegin;
    244:   PetscCheck(ctx->nshifts==0,PetscObjectComm((PetscObject)nep),PETSC_ERR_SUP,"The full-basis option is not supported with rational Krylov");
    245:   if (!ctx->eps) PetscCall(NEPNLEIGSGetEPS(nep,&ctx->eps));
    246:   PetscCall(EPSGetST(ctx->eps,&st));
    247:   PetscCall(EPSSetTarget(ctx->eps,nep->target));
    248:   PetscCall(STSetDefaultShift(st,nep->target));
    249:   if (!((PetscObject)ctx->eps)->type_name) PetscCall(EPSSetType(ctx->eps,EPSKRYLOVSCHUR));
    250:   else {
    251:     PetscCall(PetscObjectTypeCompare((PetscObject)ctx->eps,EPSKRYLOVSCHUR,&ks));
    252:     PetscCheck(ks,PetscObjectComm((PetscObject)nep),PETSC_ERR_SUP,"Full-basis option only implemented for Krylov-Schur");
    253:   }
    254:   PetscCall(STSetType(st,STSHELL));
    255:   PetscCall(STShellSetContext(st,nep));
    256:   PetscCall(STShellSetBackTransform(st,BackTransform_FullBasis));
    257:   PetscCall(KSPGetOperators(ctx->ksp[0],&Q,NULL));
    258:   PetscCall(MatCreateVecsEmpty(Q,&ctx->w[0],&ctx->w[1]));
    259:   PetscCall(MatCreateVecsEmpty(Q,&ctx->w[2],&ctx->w[3]));
    260:   PetscCall(MatCreateShell(PetscObjectComm((PetscObject)nep),deg*nep->nloc,deg*nep->nloc,deg*nep->n,deg*nep->n,nep,&ctx->A));
    261:   PetscCall(MatShellSetOperation(ctx->A,MATOP_MULT,(PetscErrorCodeFn*)MatMult_FullBasis_Sinvert));
    262:   PetscCall(MatShellSetOperation(ctx->A,MATOP_MULT_TRANSPOSE,(PetscErrorCodeFn*)MatMultTranspose_FullBasis_Sinvert));
    263:   PetscCall(STShellSetApply(st,Apply_FullBasis));
    264:   PetscCall(STShellSetApplyTranspose(st,ApplyTranspose_FullBasis));
    265:   PetscCall(EPSSetOperators(ctx->eps,ctx->A,NULL));
    266:   PetscCall(EPSSetProblemType(ctx->eps,EPS_NHEP));
    267:   switch (nep->which) {
    268:     case NEP_TARGET_MAGNITUDE:   which = EPS_TARGET_MAGNITUDE; break;
    269:     case NEP_TARGET_REAL:        which = EPS_TARGET_REAL; break;
    270:     case NEP_TARGET_IMAGINARY:   which = EPS_TARGET_IMAGINARY; break;
    271:     case NEP_WHICH_USER:         which = EPS_WHICH_USER;
    272:       PetscCall(EPSSetEigenvalueComparison(ctx->eps,nep->sc->comparison,nep->sc->comparisonctx));
    273:       break;
    274:     default: SETERRQ(PetscObjectComm((PetscObject)nep),PETSC_ERR_SUP,"Should set a target selection in NEPSetWhichEigenpairs()");
    275:   }
    276:   PetscCall(EPSSetWhichEigenpairs(ctx->eps,which));
    277:   PetscCall(RGIsTrivial(nep->rg,&istrivial));
    278:   if (!istrivial) PetscCall(EPSSetRG(ctx->eps,nep->rg));
    279:   PetscCall(EPSSetDimensions(ctx->eps,nep->nev,nep->ncv,nep->mpd));
    280:   PetscCall(EPSSetTolerances(ctx->eps,SlepcDefaultTol(nep->tol),nep->max_it));
    281:   PetscCall(EPSSetTwoSided(ctx->eps,nep->twosided));
    282:   /* Transfer the trackall option from pep to eps */
    283:   PetscCall(NEPGetTrackAll(nep,&trackall));
    284:   PetscCall(EPSSetTrackAll(ctx->eps,trackall));

    286:   /* process initial vector */
    287:   if (nep->nini<0) {
    288:     PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)ctx->eps),deg*nep->nloc,deg*nep->n,&veps));
    289:     PetscCall(VecGetArray(veps,&epsarray));
    290:     for (i=0;i<deg;i++) {
    291:       if (i<-nep->nini) {
    292:         PetscCall(VecGetArray(nep->IS[i],&neparray));
    293:         PetscCall(PetscArraycpy(epsarray+i*nep->nloc,neparray,nep->nloc));
    294:         PetscCall(VecRestoreArray(nep->IS[i],&neparray));
    295:       } else {
    296:         if (!w) PetscCall(VecDuplicate(nep->IS[0],&w));
    297:         PetscCall(VecSetRandom(w,NULL));
    298:         PetscCall(VecGetArray(w,&neparray));
    299:         PetscCall(PetscArraycpy(epsarray+i*nep->nloc,neparray,nep->nloc));
    300:         PetscCall(VecRestoreArray(w,&neparray));
    301:       }
    302:     }
    303:     PetscCall(VecRestoreArray(veps,&epsarray));
    304:     PetscCall(EPSSetInitialSpace(ctx->eps,1,&veps));
    305:     PetscCall(VecDestroy(&veps));
    306:     PetscCall(VecDestroy(&w));
    307:     PetscCall(SlepcBasisDestroy_Private(&nep->nini,&nep->IS));
    308:   }

    310:   PetscCall(EPSSetUp(ctx->eps));
    311:   PetscCall(EPSGetDimensions(ctx->eps,NULL,&nep->ncv,&nep->mpd));
    312:   PetscCall(EPSGetTolerances(ctx->eps,NULL,&nep->max_it));
    313:   PetscCall(NEPAllocateSolution(nep,0));
    314:   PetscFunctionReturn(PETSC_SUCCESS);
    315: }

    317: /*
    318:    NEPNLEIGSExtract_None - Extracts the first block of the basis
    319:    and normalizes the columns.
    320: */
    321: static PetscErrorCode NEPNLEIGSExtract_None(NEP nep,EPS eps)
    322: {
    323:   PetscInt          i,k,m,d;
    324:   const PetscScalar *px;
    325:   PetscScalar       sigma=nep->target,*b;
    326:   Mat               A;
    327:   Vec               xxr,xxi=NULL,w,t,xx;
    328:   PetscReal         norm;
    329:   NEP_NLEIGS        *ctx=(NEP_NLEIGS*)nep->data;

    331:   PetscFunctionBegin;
    332:   d = ctx->nmat-1;
    333:   PetscCall(EPSGetOperators(eps,&A,NULL));
    334:   PetscCall(MatCreateVecs(A,&xxr,NULL));
    335: #if !defined(PETSC_USE_COMPLEX)
    336:   PetscCall(VecDuplicate(xxr,&xxi));
    337: #endif
    338:   w = nep->work[0];
    339:   for (i=0;i<nep->nconv;i++) {
    340:     PetscCall(EPSGetEigenvector(eps,i,xxr,xxi));
    341:     PetscCall(VecGetArrayRead(xxr,&px));
    342:     PetscCall(VecPlaceArray(w,px));
    343:     PetscCall(BVInsertVec(nep->V,i,w));
    344:     PetscCall(BVNormColumn(nep->V,i,NORM_2,&norm));
    345:     PetscCall(BVScaleColumn(nep->V,i,1.0/norm));
    346:     PetscCall(VecResetArray(w));
    347:     PetscCall(VecRestoreArrayRead(xxr,&px));
    348:   }
    349:   if (nep->twosided) {
    350:     PetscCall(PetscMalloc1(ctx->nmat,&b));
    351:     PetscCall(NEPNLEIGSEvalNRTFunct(nep,d,sigma,b));
    352:     m = nep->nloc;
    353:     xx = ctx->w[0];
    354:     w = nep->work[0]; t = nep->work[1];
    355:     for (k=0;k<nep->nconv;k++) {
    356:       PetscCall(EPSGetLeftEigenvector(eps,k,xxr,xxi));
    357:       PetscCall(VecGetArrayRead(xxr,&px));
    358:       PetscCall(VecPlaceArray(xx,px+(d-1)*m));
    359:       PetscCall(VecCopy(xx,w));
    360:       PetscCall(VecScale(w,PetscConj(b[d-1])));
    361:       PetscCall(VecResetArray(xx));
    362:       for (i=0;i<d-1;i++) {
    363:         PetscCall(VecPlaceArray(xx,px+i*m));
    364:         PetscCall(VecAXPY(w,PetscConj(b[i]),xx));
    365:         PetscCall(VecResetArray(xx));
    366:       }
    367:       PetscCall(VecConjugate(w));
    368:       PetscCall(KSPSolveTranspose(ctx->ksp[0],w,t));
    369:       PetscCall(VecConjugate(t));
    370:       PetscCall(BVInsertVec(nep->W,k,t));
    371:       PetscCall(BVNormColumn(nep->W,k,NORM_2,&norm));
    372:       PetscCall(BVScaleColumn(nep->W,k,1.0/norm));
    373:       PetscCall(VecRestoreArrayRead(xxr,&px));
    374:     }
    375:     PetscCall(PetscFree(b));
    376:   }
    377:   PetscCall(VecDestroy(&xxr));
    378: #if !defined(PETSC_USE_COMPLEX)
    379:   PetscCall(VecDestroy(&xxi));
    380: #endif
    381:   PetscFunctionReturn(PETSC_SUCCESS);
    382: }

    384: PetscErrorCode NEPSolve_NLEIGS_FullBasis(NEP nep)
    385: {
    386:   NEP_NLEIGS     *ctx = (NEP_NLEIGS*)nep->data;
    387:   PetscInt       i;
    388:   PetscScalar    eigi=0.0;

    390:   PetscFunctionBegin;
    391:   PetscCall(EPSSolve(ctx->eps));
    392:   PetscCall(EPSGetConverged(ctx->eps,&nep->nconv));
    393:   PetscCall(EPSGetIterationNumber(ctx->eps,&nep->its));
    394:   PetscCall(EPSGetConvergedReason(ctx->eps,(EPSConvergedReason*)&nep->reason));

    396:   /* recover eigenvalues */
    397:   for (i=0;i<nep->nconv;i++) {
    398:     PetscCall(EPSGetEigenpair(ctx->eps,i,&nep->eigr[i],&eigi,NULL,NULL));
    399: #if !defined(PETSC_USE_COMPLEX)
    400:     PetscCheck(eigi==0.0,PetscObjectComm((PetscObject)nep),PETSC_ERR_SUP,"Complex value requires complex arithmetic");
    401: #endif
    402:   }
    403:   PetscCall(NEPNLEIGSExtract_None(nep,ctx->eps));
    404:   PetscFunctionReturn(PETSC_SUCCESS);
    405: }

    407: PetscErrorCode NEPNLEIGSSetEPS_NLEIGS(NEP nep,EPS eps)
    408: {
    409:   NEP_NLEIGS     *ctx=(NEP_NLEIGS*)nep->data;

    411:   PetscFunctionBegin;
    412:   PetscCall(PetscObjectReference((PetscObject)eps));
    413:   PetscCall(EPSDestroy(&ctx->eps));
    414:   ctx->eps = eps;
    415:   nep->state = NEP_STATE_INITIAL;
    416:   PetscFunctionReturn(PETSC_SUCCESS);
    417: }

    419: /*@
    420:    NEPNLEIGSSetEPS - Associate an eigensolver object (`EPS`) to the NLEIGS solver.

    422:    Collective

    424:    Input Parameters:
    425: +  nep - the nonlinear eigensolver context
    426: -  eps - the linear eigensolver context

    428:    Note:
    429:    By default, the linear eigensolver is integrated within the NLEIGS method.
    430:    This `EPS` object is used only in the case that the explicit basis
    431:    has been selected with `NEPNLEIGSSetFullBasis()`.

    433:    Level: advanced

    435: .seealso: [](ch:nep), `NEPNLEIGS`, `NEPNLEIGSGetEPS()`, `NEPNLEIGSSetFullBasis()`
    436: @*/
    437: PetscErrorCode NEPNLEIGSSetEPS(NEP nep,EPS eps)
    438: {
    439:   PetscFunctionBegin;
    442:   PetscCheckSameComm(nep,1,eps,2);
    443:   PetscTryMethod(nep,"NEPNLEIGSSetEPS_C",(NEP,EPS),(nep,eps));
    444:   PetscFunctionReturn(PETSC_SUCCESS);
    445: }

    447: static PetscErrorCode EPSMonitor_NLEIGS(EPS eps,PetscInt its,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest,void *ctx)
    448: {
    449:   NEP            nep = (NEP)ctx;
    450:   PetscInt       i,nv = PetscMin(nest,nep->ncv);

    452:   PetscFunctionBegin;
    453:   for (i=0;i<nv;i++) {
    454:     nep->eigr[i]   = eigr[i];
    455:     nep->eigi[i]   = eigi[i];
    456:     nep->errest[i] = errest[i];
    457:   }
    458:   PetscCall(NEPNLEIGSBackTransform((PetscObject)nep,nv,nep->eigr,nep->eigi));
    459:   PetscCall(NEPMonitor(nep,its,nconv,nep->eigr,nep->eigi,nep->errest,nest));
    460:   PetscFunctionReturn(PETSC_SUCCESS);
    461: }

    463: PetscErrorCode NEPNLEIGSGetEPS_NLEIGS(NEP nep,EPS *eps)
    464: {
    465:   NEP_NLEIGS     *ctx=(NEP_NLEIGS*)nep->data;

    467:   PetscFunctionBegin;
    468:   if (!ctx->eps) {
    469:     PetscCall(EPSCreate(PetscObjectComm((PetscObject)nep),&ctx->eps));
    470:     PetscCall(PetscObjectIncrementTabLevel((PetscObject)ctx->eps,(PetscObject)nep,1));
    471:     PetscCall(EPSSetOptionsPrefix(ctx->eps,((PetscObject)nep)->prefix));
    472:     PetscCall(EPSAppendOptionsPrefix(ctx->eps,"nep_nleigs_"));
    473:     PetscCall(PetscObjectSetOptions((PetscObject)ctx->eps,((PetscObject)nep)->options));
    474:     PetscCall(EPSMonitorSet(ctx->eps,EPSMonitor_NLEIGS,nep,NULL));
    475:   }
    476:   *eps = ctx->eps;
    477:   PetscFunctionReturn(PETSC_SUCCESS);
    478: }

    480: /*@
    481:    NEPNLEIGSGetEPS - Retrieve the linear eigensolver object (`EPS`) associated
    482:    to the nonlinear eigenvalue solver.

    484:    Collective

    486:    Input Parameter:
    487: .  nep - the nonlinear eigensolver context

    489:    Output Parameter:
    490: .  eps - the linear eigensolver context

    492:    Note:
    493:    By default, the linear eigensolver is integrated within the NLEIGS method.
    494:    This `EPS` object is used only in the case that the explicit basis
    495:    has been selected with `NEPNLEIGSSetFullBasis()`.

    497:    Level: advanced

    499: .seealso: [](ch:nep), `NEPNLEIGS`, `NEPNLEIGSSetEPS()`, `NEPNLEIGSSetFullBasis()`
    500: @*/
    501: PetscErrorCode NEPNLEIGSGetEPS(NEP nep,EPS *eps)
    502: {
    503:   PetscFunctionBegin;
    505:   PetscAssertPointer(eps,2);
    506:   PetscUseMethod(nep,"NEPNLEIGSGetEPS_C",(NEP,EPS*),(nep,eps));
    507:   PetscFunctionReturn(PETSC_SUCCESS);
    508: }