Date: 2022-03-31T15:29:09+00:00

Actual source code: ciss.c
slepc-3.17.0 2022-03-31
Report Typos and Errors

      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:    SLEPc eigensolver: "ciss"

     13:    Method: Contour Integral Spectral Slicing

     15:    Algorithm:

     17:        Contour integral based on Sakurai-Sugiura method to construct a
     18:        subspace, with various eigenpair extractions (Rayleigh-Ritz,
     19:        explicit moment).

     21:    Based on code contributed by Y. Maeda, T. Sakurai.

     23:    References:

     25:        [1] T. Sakurai and H. Sugiura, "A projection method for generalized
     26:            eigenvalue problems", J. Comput. Appl. Math. 159:119-128, 2003.

     28:        [2] T. Sakurai and H. Tadano, "CIRR: a Rayleigh-Ritz type method with
     29:            contour integral for generalized eigenvalue problems", Hokkaido
     30:            Math. J. 36:745-757, 2007.
     31: */

     33: #include <slepc/private/epsimpl.h>
     34: #include <slepc/private/slepccontour.h>
     35: #include <slepcblaslapack.h>

     37: typedef struct {
     38:   /* user parameters */
     39:   PetscInt          N;          /* number of integration points (32) */
     40:   PetscInt          L;          /* block size (16) */
     41:   PetscInt          M;          /* moment degree (N/4 = 4) */
     42:   PetscReal         delta;      /* threshold of singular value (1e-12) */
     43:   PetscInt          L_max;      /* maximum number of columns of the source matrix V */
     44:   PetscReal         spurious_threshold; /* discard spurious eigenpairs */
     45:   PetscBool         isreal;     /* A and B are real */
     46:   PetscInt          npart;      /* number of partitions */
     47:   PetscInt          refine_inner;
     48:   PetscInt          refine_blocksize;
     49:   EPSCISSQuadRule   quad;
     50:   EPSCISSExtraction extraction;
     51:   PetscBool         usest;
     52:   /* private data */
     53:   SlepcContourData  contour;
     54:   PetscReal         *sigma;     /* threshold for numerical rank */
     55:   PetscScalar       *weight;
     56:   PetscScalar       *omega;
     57:   PetscScalar       *pp;
     58:   BV                V;
     59:   BV                S;
     60:   BV                pV;
     61:   BV                Y;
     62:   PetscBool         useconj;
     63:   PetscBool         usest_set;  /* whether the user set the usest flag or not */
     64:   PetscObjectId     rgid;
     65:   PetscObjectState  rgstate;
     66: } EPS_CISS;

     68: /*
     69:   Set up KSP solvers for every integration point, only called if !ctx->usest
     70: */
     71: static PetscErrorCode EPSCISSSetUp(EPS eps,Mat A,Mat B,Mat Pa,Mat Pb)
     72: {
     73:   EPS_CISS         *ctx = (EPS_CISS*)eps->data;
     74:   SlepcContourData contour;
     75:   PetscInt         i,p_id,nsplit;
     76:   Mat              Amat,Pmat;
     77:   MatStructure     str,strp;

     79:   if (!ctx->contour || !ctx->contour->ksp) EPSCISSGetKSPs(eps,NULL,NULL);
     80:   contour = ctx->contour;
     81:   STGetMatStructure(eps->st,&str);
     82:   STGetSplitPreconditionerInfo(eps->st,&nsplit,&strp);
     83:   for (i=0;i<contour->npoints;i++) {
     84:     p_id = i*contour->subcomm->n + contour->subcomm->color;
     85:     MatDuplicate(A,MAT_COPY_VALUES,&Amat);
     86:     if (B) MatAXPY(Amat,-ctx->omega[p_id],B,str);
     87:     else MatShift(Amat,-ctx->omega[p_id]);
     88:     if (nsplit) {
     89:       MatDuplicate(Pa,MAT_COPY_VALUES,&Pmat);
     90:       if (Pb) MatAXPY(Pmat,-ctx->omega[p_id],Pb,strp);
     91:       else MatShift(Pmat,-ctx->omega[p_id]);
     92:     } else Pmat = Amat;
     93:     EPS_KSPSetOperators(contour->ksp[i],Amat,Amat);
     94:     MatDestroy(&Amat);
     95:     if (nsplit) MatDestroy(&Pmat);
     96:   }
     97:   PetscFunctionReturn(0);
     98: }

    100: /*
    101:   Y_i = (A-z_i B)^{-1}BV for every integration point, Y=[Y_i] is in the context
    102: */
    103: static PetscErrorCode EPSCISSSolve(EPS eps,Mat B,BV V,PetscInt L_start,PetscInt L_end)
    104: {
    105:   EPS_CISS         *ctx = (EPS_CISS*)eps->data;
    106:   SlepcContourData contour;
    107:   PetscInt         i,p_id;
    108:   Mat              MV,BMV=NULL,MC;
    109:   KSP              ksp;

    111:   if (!ctx->contour || !ctx->contour->ksp) EPSCISSGetKSPs(eps,NULL,NULL);
    112:   contour = ctx->contour;
    113:   BVSetActiveColumns(V,L_start,L_end);
    114:   BVGetMat(V,&MV);
    115:   for (i=0;i<contour->npoints;i++) {
    116:     p_id = i*contour->subcomm->n + contour->subcomm->color;
    117:     if (ctx->usest)  {
    118:       STSetShift(eps->st,ctx->omega[p_id]);
    119:       STGetKSP(eps->st,&ksp);
    120:     } else ksp = contour->ksp[i];
    121:     BVSetActiveColumns(ctx->Y,i*ctx->L+L_start,i*ctx->L+L_end);
    122:     BVGetMat(ctx->Y,&MC);
    123:     if (B) {
    124:       if (!i) {
    125:         MatProductCreate(B,MV,NULL,&BMV);
    126:         MatProductSetType(BMV,MATPRODUCT_AB);
    127:         MatProductSetFromOptions(BMV);
    128:         MatProductSymbolic(BMV);
    129:       }
    130:       MatProductNumeric(BMV);
    131:       KSPMatSolve(ksp,BMV,MC);
    132:     } else KSPMatSolve(ksp,MV,MC);
    133:     BVRestoreMat(ctx->Y,&MC);
    134:     if (ctx->usest && i<contour->npoints-1) KSPReset(ksp);
    135:   }
    136:   MatDestroy(&BMV);
    137:   BVRestoreMat(V,&MV);
    138:   PetscFunctionReturn(0);
    139: }

    141: static PetscErrorCode rescale_eig(EPS eps,PetscInt nv)
    142: {
    143:   EPS_CISS       *ctx = (EPS_CISS*)eps->data;
    144:   PetscInt       i;
    145:   PetscScalar    center;
    146:   PetscReal      radius,a,b,c,d,rgscale;
    147: #if defined(PETSC_USE_COMPLEX)
    148:   PetscReal      start_ang,end_ang,vscale,theta;
    149: #endif
    150:   PetscBool      isring,isellipse,isinterval;

    152:   PetscObjectTypeCompare((PetscObject)eps->rg,RGELLIPSE,&isellipse);
    153:   PetscObjectTypeCompare((PetscObject)eps->rg,RGRING,&isring);
    154:   PetscObjectTypeCompare((PetscObject)eps->rg,RGINTERVAL,&isinterval);
    155:   RGGetScale(eps->rg,&rgscale);
    156:   if (isinterval) {
    157:     RGIntervalGetEndpoints(eps->rg,NULL,NULL,&c,&d);
    158:     if (c==d) {
    159:       for (i=0;i<nv;i++) {
    160: #if defined(PETSC_USE_COMPLEX)
    161:         eps->eigr[i] = PetscRealPart(eps->eigr[i]);
    162: #else
    163:         eps->eigi[i] = 0;
    164: #endif
    165:       }
    166:     }
    167:   }
    168:   if (ctx->extraction == EPS_CISS_EXTRACTION_HANKEL) {
    169:     if (isellipse) {
    170:       RGEllipseGetParameters(eps->rg,&center,&radius,NULL);
    171:       for (i=0;i<nv;i++) eps->eigr[i] = rgscale*(center + radius*eps->eigr[i]);
    172:     } else if (isinterval) {
    173:       RGIntervalGetEndpoints(eps->rg,&a,&b,&c,&d);
    174:       if (ctx->quad == EPS_CISS_QUADRULE_CHEBYSHEV) {
    175:         for (i=0;i<nv;i++) {
    176:           if (c==d) eps->eigr[i] = ((b-a)*(eps->eigr[i]+1.0)/2.0+a)*rgscale;
    177:           if (a==b) {
    178: #if defined(PETSC_USE_COMPLEX)
    179:             eps->eigr[i] = ((d-c)*(eps->eigr[i]+1.0)/2.0+c)*rgscale*PETSC_i;
    180: #else
    181:             SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Integration points on a vertical line require complex arithmetic");
    182: #endif
    183:           }
    184:         }
    185:       } else {
    186:         center = (b+a)/2.0+(d+c)/2.0*PETSC_PI;
    187:         radius = PetscSqrtReal(PetscPowRealInt((b-a)/2.0,2)+PetscPowRealInt((d-c)/2.0,2));
    188:         for (i=0;i<nv;i++) eps->eigr[i] = center + radius*eps->eigr[i];
    189:       }
    190:     } else if (isring) {  /* only supported in complex scalars */
    191: #if defined(PETSC_USE_COMPLEX)
    192:       RGRingGetParameters(eps->rg,&center,&radius,&vscale,&start_ang,&end_ang,NULL);
    193:       if (ctx->quad == EPS_CISS_QUADRULE_CHEBYSHEV) {
    194:         for (i=0;i<nv;i++) {
    195:           theta = (start_ang*2.0+(end_ang-start_ang)*(PetscRealPart(eps->eigr[i])+1.0))*PETSC_PI;
    196:           eps->eigr[i] = rgscale*center + (rgscale*radius+PetscImaginaryPart(eps->eigr[i]))*PetscCMPLX(PetscCosReal(theta),vscale*PetscSinReal(theta));
    197:         }
    198:       } else {
    199:         for (i=0;i<nv;i++) eps->eigr[i] = rgscale*(center + radius*eps->eigr[i]);
    200:       }
    201: #endif
    202:     }
    203:   }
    204:   PetscFunctionReturn(0);
    205: }

    207: PetscErrorCode EPSSetUp_CISS(EPS eps)
    208: {
    209:   EPS_CISS         *ctx = (EPS_CISS*)eps->data;
    210:   SlepcContourData contour;
    211:   PetscBool        istrivial,isring,isellipse,isinterval,flg;
    212:   PetscReal        c,d;
    213:   PetscInt         nsplit;
    214:   PetscRandom      rand;
    215:   PetscObjectId    id;
    216:   PetscObjectState state;
    217:   Mat              A[2],Psplit[2];
    218:   Vec              v0;

    220:   if (eps->ncv==PETSC_DEFAULT) {
    221:     eps->ncv = ctx->L_max*ctx->M;
    222:     if (eps->ncv>eps->n) {
    223:       eps->ncv = eps->n;
    224:       ctx->L_max = eps->ncv/ctx->M;
    226:     }
    227:   } else {
    228:     EPSSetDimensions_Default(eps,eps->nev,&eps->ncv,&eps->mpd);
    229:     ctx->L_max = eps->ncv/ctx->M;
    230:     if (!ctx->L_max) {
    231:       ctx->L_max = 1;
    232:       eps->ncv = ctx->L_max*ctx->M;
    233:     }
    234:   }
    235:   ctx->L = PetscMin(ctx->L,ctx->L_max);
    236:   if (eps->max_it==PETSC_DEFAULT) eps->max_it = 5;
    237:   if (eps->mpd==PETSC_DEFAULT) eps->mpd = eps->ncv;
    238:   if (!eps->which) eps->which = EPS_ALL;
    240:   EPSCheckUnsupported(eps,EPS_FEATURE_BALANCE | EPS_FEATURE_ARBITRARY | EPS_FEATURE_EXTRACTION | EPS_FEATURE_STOPPING | EPS_FEATURE_TWOSIDED);

    242:   /* check region */
    243:   RGIsTrivial(eps->rg,&istrivial);
    245:   RGGetComplement(eps->rg,&flg);
    247:   PetscObjectTypeCompare((PetscObject)eps->rg,RGELLIPSE,&isellipse);
    248:   PetscObjectTypeCompare((PetscObject)eps->rg,RGRING,&isring);
    249:   PetscObjectTypeCompare((PetscObject)eps->rg,RGINTERVAL,&isinterval);

    252:   /* if the region has changed, then reset contour data */
    253:   PetscObjectGetId((PetscObject)eps->rg,&id);
    254:   PetscObjectStateGet((PetscObject)eps->rg,&state);
    255:   if (ctx->rgid && (id != ctx->rgid || state != ctx->rgstate)) {
    256:     SlepcContourDataDestroy(&ctx->contour);
    257:     PetscInfo(eps,"Resetting the contour data structure due to a change of region\n");
    258:     ctx->rgid = id; ctx->rgstate = state;
    259:   }

    261: #if !defined(PETSC_USE_COMPLEX)
    263: #endif
    264:   if (isinterval) {
    265:     RGIntervalGetEndpoints(eps->rg,NULL,NULL,&c,&d);
    266: #if !defined(PETSC_USE_COMPLEX)
    268: #endif
    269:     if (!ctx->quad && c==d) ctx->quad = EPS_CISS_QUADRULE_CHEBYSHEV;
    270:   }
    271:   if (!ctx->quad) ctx->quad = EPS_CISS_QUADRULE_TRAPEZOIDAL;

    273:   /* create contour data structure */
    274:   if (!ctx->contour) {
    275:     RGCanUseConjugates(eps->rg,ctx->isreal,&ctx->useconj);
    276:     SlepcContourDataCreate(ctx->useconj?ctx->N/2:ctx->N,ctx->npart,(PetscObject)eps,&ctx->contour);
    277:   }

    279:   EPSAllocateSolution(eps,0);
    280:   BVGetRandomContext(eps->V,&rand);  /* make sure the random context is available when duplicating */
    281:   if (ctx->weight) PetscFree4(ctx->weight,ctx->omega,ctx->pp,ctx->sigma);
    282:   PetscMalloc4(ctx->N,&ctx->weight,ctx->N+1,&ctx->omega,ctx->N,&ctx->pp,ctx->L_max*ctx->M,&ctx->sigma);
    283:   PetscLogObjectMemory((PetscObject)eps,3*ctx->N*sizeof(PetscScalar)+ctx->L_max*ctx->N*sizeof(PetscReal));

    285:   /* allocate basis vectors */
    286:   BVDestroy(&ctx->S);
    287:   BVDuplicateResize(eps->V,ctx->L*ctx->M,&ctx->S);
    288:   PetscLogObjectParent((PetscObject)eps,(PetscObject)ctx->S);
    289:   BVDestroy(&ctx->V);
    290:   BVDuplicateResize(eps->V,ctx->L,&ctx->V);
    291:   PetscLogObjectParent((PetscObject)eps,(PetscObject)ctx->V);

    293:   STGetMatrix(eps->st,0,&A[0]);
    294:   MatIsShell(A[0],&flg);
    296:   if (eps->isgeneralized) STGetMatrix(eps->st,1,&A[1]);

    298:   if (!ctx->usest_set) ctx->usest = (ctx->npart>1)? PETSC_FALSE: PETSC_TRUE;

    301:   /* check if a user-defined split preconditioner has been set */
    302:   STGetSplitPreconditionerInfo(eps->st,&nsplit,NULL);
    303:   if (nsplit) {
    304:     STGetSplitPreconditionerTerm(eps->st,0,&Psplit[0]);
    305:     if (eps->isgeneralized) STGetSplitPreconditionerTerm(eps->st,1,&Psplit[1]);
    306:   }

    308:   contour = ctx->contour;
    309:   SlepcContourRedundantMat(contour,eps->isgeneralized?2:1,A,nsplit?Psplit:NULL);
    310:   if (contour->pA) {
    311:     BVGetColumn(ctx->V,0,&v0);
    312:     SlepcContourScatterCreate(contour,v0);
    313:     BVRestoreColumn(ctx->V,0,&v0);
    314:     BVDestroy(&ctx->pV);
    315:     BVCreate(PetscObjectComm((PetscObject)contour->xsub),&ctx->pV);
    316:     BVSetSizesFromVec(ctx->pV,contour->xsub,eps->n);
    317:     BVSetFromOptions(ctx->pV);
    318:     BVResize(ctx->pV,ctx->L,PETSC_FALSE);
    319:     PetscLogObjectParent((PetscObject)eps,(PetscObject)ctx->pV);
    320:   }

    322:   EPSCheckDefinite(eps);
    323:   EPSCheckSinvertCondition(eps,ctx->usest," (with the usest flag set)");

    325:   BVDestroy(&ctx->Y);
    326:   if (contour->pA) {
    327:     BVCreate(PetscObjectComm((PetscObject)contour->xsub),&ctx->Y);
    328:     BVSetSizesFromVec(ctx->Y,contour->xsub,eps->n);
    329:     BVSetFromOptions(ctx->Y);
    330:     BVResize(ctx->Y,contour->npoints*ctx->L,PETSC_FALSE);
    331:   } else BVDuplicateResize(eps->V,contour->npoints*ctx->L,&ctx->Y);
    332:   PetscLogObjectParent((PetscObject)eps,(PetscObject)ctx->Y);

    334:   if (ctx->extraction == EPS_CISS_EXTRACTION_HANKEL) DSSetType(eps->ds,DSGNHEP);
    335:   else if (eps->isgeneralized) {
    336:     if (eps->ishermitian && eps->ispositive) DSSetType(eps->ds,DSGHEP);
    337:     else DSSetType(eps->ds,DSGNHEP);
    338:   } else {
    339:     if (eps->ishermitian) DSSetType(eps->ds,DSHEP);
    340:     else DSSetType(eps->ds,DSNHEP);
    341:   }
    342:   DSAllocate(eps->ds,eps->ncv);

    344: #if !defined(PETSC_USE_COMPLEX)
    345:   EPSSetWorkVecs(eps,3);
    346:   if (!eps->ishermitian) PetscInfo(eps,"Warning: complex eigenvalues are not calculated exactly without --with-scalar-type=complex in PETSc\n");
    347: #else
    348:   EPSSetWorkVecs(eps,2);
    349: #endif
    350:   PetscFunctionReturn(0);
    351: }

    353: PetscErrorCode EPSSetUpSort_CISS(EPS eps)
    354: {
    355:   SlepcSC        sc;

    357:   /* fill sorting criterion context */
    358:   eps->sc->comparison    = SlepcCompareSmallestReal;
    359:   eps->sc->comparisonctx = NULL;
    360:   eps->sc->map           = NULL;
    361:   eps->sc->mapobj        = NULL;

    363:   /* fill sorting criterion for DS */
    364:   DSGetSlepcSC(eps->ds,&sc);
    365:   sc->comparison    = SlepcCompareLargestMagnitude;
    366:   sc->comparisonctx = NULL;
    367:   sc->map           = NULL;
    368:   sc->mapobj        = NULL;
    369:   PetscFunctionReturn(0);
    370: }

    372: PetscErrorCode EPSSolve_CISS(EPS eps)
    373: {
    374:   EPS_CISS         *ctx = (EPS_CISS*)eps->data;
    375:   SlepcContourData contour = ctx->contour;
    376:   Mat              A,B,X,M,pA,pB,T,J,Pa=NULL,Pb=NULL;
    377:   BV               V;
    378:   PetscInt         i,j,ld,nmat,L_add=0,nv=0,L_base=ctx->L,inner,nlocal,*inside,nsplit;
    379:   PetscScalar      *Mu,*H0,*H1=NULL,*rr,*temp;
    380:   PetscReal        error,max_error,norm;
    381:   PetscBool        *fl1;
    382:   Vec              si,si1=NULL,w[3];
    383:   PetscRandom      rand;
    384: #if defined(PETSC_USE_COMPLEX)
    385:   PetscBool        isellipse;
    386:   PetscReal        est_eig,eta;
    387: #else
    388:   PetscReal        normi;
    389: #endif

    391:   w[0] = eps->work[0];
    392: #if defined(PETSC_USE_COMPLEX)
    393:   w[1] = NULL;
    394: #else
    395:   w[1] = eps->work[2];
    396: #endif
    397:   w[2] = eps->work[1];
    398:   VecGetLocalSize(w[0],&nlocal);
    399:   DSGetLeadingDimension(eps->ds,&ld);
    400:   RGComputeQuadrature(eps->rg,ctx->quad==EPS_CISS_QUADRULE_CHEBYSHEV?RG_QUADRULE_CHEBYSHEV:RG_QUADRULE_TRAPEZOIDAL,ctx->N,ctx->omega,ctx->pp,ctx->weight);
    401:   STGetNumMatrices(eps->st,&nmat);
    402:   STGetMatrix(eps->st,0,&A);
    403:   if (nmat>1) STGetMatrix(eps->st,1,&B);
    404:   else B = NULL;
    405:   J = (contour->pA && nmat>1)? contour->pA[1]: B;
    406:   V = contour->pA? ctx->pV: ctx->V;
    407:   if (!ctx->usest) {
    408:     T = contour->pA? contour->pA[0]: A;
    409:     STGetSplitPreconditionerInfo(eps->st,&nsplit,NULL);
    410:     if (nsplit) {
    411:       if (contour->pA) {
    412:         Pa = contour->pP[0];
    413:         if (nsplit>1) Pb = contour->pP[1];
    414:       } else {
    415:         STGetSplitPreconditionerTerm(eps->st,0,&Pa);
    416:         if (nsplit>1) STGetSplitPreconditionerTerm(eps->st,1,&Pb);
    417:       }
    418:     }
    419:     EPSCISSSetUp(eps,T,J,Pa,Pb);
    420:   }
    421:   BVSetActiveColumns(ctx->V,0,ctx->L);
    422:   BVSetRandomSign(ctx->V);
    423:   BVGetRandomContext(ctx->V,&rand);

    425:   if (contour->pA) BVScatter(ctx->V,ctx->pV,contour->scatterin,contour->xdup);
    426:   EPSCISSSolve(eps,J,V,0,ctx->L);
    427: #if defined(PETSC_USE_COMPLEX)
    428:   PetscObjectTypeCompare((PetscObject)eps->rg,RGELLIPSE,&isellipse);
    429:   if (isellipse) {
    430:     BVTraceQuadrature(ctx->Y,ctx->V,ctx->L,ctx->L,ctx->weight,contour->scatterin,contour->subcomm,contour->npoints,ctx->useconj,&est_eig);
    431:     PetscInfo(eps,"Estimated eigenvalue count: %f\n",(double)est_eig);
    432:     eta = PetscPowReal(10.0,-PetscLog10Real(eps->tol)/ctx->N);
    433:     L_add = PetscMax(0,(PetscInt)PetscCeilReal((est_eig*eta)/ctx->M)-ctx->L);
    434:     if (L_add>ctx->L_max-ctx->L) {
    435:       PetscInfo(eps,"Number of eigenvalues inside the contour path may be too large\n");
    436:       L_add = ctx->L_max-ctx->L;
    437:     }
    438:   }
    439: #endif
    440:   if (L_add>0) {
    441:     PetscInfo(eps,"Changing L %" PetscInt_FMT " -> %" PetscInt_FMT " by Estimate #Eig\n",ctx->L,ctx->L+L_add);
    442:     BVCISSResizeBases(ctx->S,contour->pA?ctx->pV:ctx->V,ctx->Y,ctx->L,ctx->L+L_add,ctx->M,contour->npoints);
    443:     BVSetActiveColumns(ctx->V,ctx->L,ctx->L+L_add);
    444:     BVSetRandomSign(ctx->V);
    445:     if (contour->pA) BVScatter(ctx->V,ctx->pV,contour->scatterin,contour->xdup);
    446:     ctx->L += L_add;
    447:     EPSCISSSolve(eps,J,V,ctx->L-L_add,ctx->L);
    448:   }
    449:   PetscMalloc2(ctx->L*ctx->L*ctx->M*2,&Mu,ctx->L*ctx->M*ctx->L*ctx->M,&H0);
    450:   for (i=0;i<ctx->refine_blocksize;i++) {
    451:     BVDotQuadrature(ctx->Y,(contour->pA)?ctx->pV:ctx->V,Mu,ctx->M,ctx->L,ctx->L,ctx->weight,ctx->pp,contour->subcomm,contour->npoints,ctx->useconj);
    452:     CISS_BlockHankel(Mu,0,ctx->L,ctx->M,H0);
    453:     PetscLogEventBegin(EPS_CISS_SVD,eps,0,0,0);
    454:     SlepcCISS_BH_SVD(H0,ctx->L*ctx->M,ctx->delta,ctx->sigma,&nv);
    455:     PetscLogEventEnd(EPS_CISS_SVD,eps,0,0,0);
    456:     if (ctx->sigma[0]<=ctx->delta || nv < ctx->L*ctx->M || ctx->L == ctx->L_max) break;
    457:     L_add = L_base;
    458:     if (ctx->L+L_add>ctx->L_max) L_add = ctx->L_max-ctx->L;
    459:     PetscInfo(eps,"Changing L %" PetscInt_FMT " -> %" PetscInt_FMT " by SVD(H0)\n",ctx->L,ctx->L+L_add);
    460:     BVCISSResizeBases(ctx->S,contour->pA?ctx->pV:ctx->V,ctx->Y,ctx->L,ctx->L+L_add,ctx->M,contour->npoints);
    461:     BVSetActiveColumns(ctx->V,ctx->L,ctx->L+L_add);
    462:     BVSetRandomSign(ctx->V);
    463:     if (contour->pA) BVScatter(ctx->V,ctx->pV,contour->scatterin,contour->xdup);
    464:     ctx->L += L_add;
    465:     EPSCISSSolve(eps,J,V,ctx->L-L_add,ctx->L);
    466:     if (L_add) {
    467:       PetscFree2(Mu,H0);
    468:       PetscMalloc2(ctx->L*ctx->L*ctx->M*2,&Mu,ctx->L*ctx->M*ctx->L*ctx->M,&H0);
    469:     }
    470:   }
    471:   if (ctx->extraction == EPS_CISS_EXTRACTION_HANKEL) PetscMalloc1(ctx->L*ctx->M*ctx->L*ctx->M,&H1);

    473:   while (eps->reason == EPS_CONVERGED_ITERATING) {
    474:     eps->its++;
    475:     for (inner=0;inner<=ctx->refine_inner;inner++) {
    476:       if (ctx->extraction == EPS_CISS_EXTRACTION_HANKEL) {
    477:         BVDotQuadrature(ctx->Y,(contour->pA)?ctx->pV:ctx->V,Mu,ctx->M,ctx->L,ctx->L,ctx->weight,ctx->pp,contour->subcomm,contour->npoints,ctx->useconj);
    478:         CISS_BlockHankel(Mu,0,ctx->L,ctx->M,H0);
    479:         PetscLogEventBegin(EPS_CISS_SVD,eps,0,0,0);
    480:         SlepcCISS_BH_SVD(H0,ctx->L*ctx->M,ctx->delta,ctx->sigma,&nv);
    481:         PetscLogEventEnd(EPS_CISS_SVD,eps,0,0,0);
    482:         break;
    483:       } else {
    484:         BVSumQuadrature(ctx->S,ctx->Y,ctx->M,ctx->L,ctx->L,ctx->weight,ctx->pp,contour->scatterin,contour->subcomm,contour->npoints,ctx->useconj);
    485:         BVSetActiveColumns(ctx->S,0,ctx->L);
    486:         BVSetActiveColumns(ctx->V,0,ctx->L);
    487:         BVCopy(ctx->S,ctx->V);
    488:         BVSVDAndRank(ctx->S,ctx->M,ctx->L,ctx->delta,BV_SVD_METHOD_REFINE,H0,ctx->sigma,&nv);
    489:         if (ctx->sigma[0]>ctx->delta && nv==ctx->L*ctx->M && inner!=ctx->refine_inner) {
    490:           if (contour->pA) BVScatter(ctx->V,ctx->pV,contour->scatterin,contour->xdup);
    491:           EPSCISSSolve(eps,J,V,0,ctx->L);
    492:         } else break;
    493:       }
    494:     }
    495:     eps->nconv = 0;
    496:     if (nv == 0) eps->reason = EPS_CONVERGED_TOL;
    497:     else {
    498:       DSSetDimensions(eps->ds,nv,0,0);
    499:       DSSetState(eps->ds,DS_STATE_RAW);

    501:       if (ctx->extraction == EPS_CISS_EXTRACTION_HANKEL) {
    502:         CISS_BlockHankel(Mu,0,ctx->L,ctx->M,H0);
    503:         CISS_BlockHankel(Mu,1,ctx->L,ctx->M,H1);
    504:         DSGetArray(eps->ds,DS_MAT_A,&temp);
    505:         for (j=0;j<nv;j++) {
    506:           for (i=0;i<nv;i++) {
    507:             temp[i+j*ld] = H1[i+j*ctx->L*ctx->M];
    508:           }
    509:         }
    510:         DSRestoreArray(eps->ds,DS_MAT_A,&temp);
    511:         DSGetArray(eps->ds,DS_MAT_B,&temp);
    512:         for (j=0;j<nv;j++) {
    513:           for (i=0;i<nv;i++) {
    514:             temp[i+j*ld] = H0[i+j*ctx->L*ctx->M];
    515:           }
    516:         }
    517:         DSRestoreArray(eps->ds,DS_MAT_B,&temp);
    518:       } else {
    519:         BVSetActiveColumns(ctx->S,0,nv);
    520:         DSGetMat(eps->ds,DS_MAT_A,&pA);
    521:         MatZeroEntries(pA);
    522:         BVMatProject(ctx->S,A,ctx->S,pA);
    523:         DSRestoreMat(eps->ds,DS_MAT_A,&pA);
    524:         if (B) {
    525:           DSGetMat(eps->ds,DS_MAT_B,&pB);
    526:           MatZeroEntries(pB);
    527:           BVMatProject(ctx->S,B,ctx->S,pB);
    528:           DSRestoreMat(eps->ds,DS_MAT_B,&pB);
    529:         }
    530:       }

    532:       DSSolve(eps->ds,eps->eigr,eps->eigi);
    533:       DSSynchronize(eps->ds,eps->eigr,eps->eigi);

    535:       PetscMalloc3(nv,&fl1,nv,&inside,nv,&rr);
    536:       rescale_eig(eps,nv);
    537:       DSVectors(eps->ds,DS_MAT_X,NULL,NULL);
    538:       DSGetMat(eps->ds,DS_MAT_X,&X);
    539:       SlepcCISS_isGhost(X,nv,ctx->sigma,ctx->spurious_threshold,fl1);
    540:       MatDestroy(&X);
    541:       RGCheckInside(eps->rg,nv,eps->eigr,eps->eigi,inside);
    542:       for (i=0;i<nv;i++) {
    543:         if (fl1[i] && inside[i]>=0) {
    544:           rr[i] = 1.0;
    545:           eps->nconv++;
    546:         } else rr[i] = 0.0;
    547:       }
    548:       DSSort(eps->ds,eps->eigr,eps->eigi,rr,NULL,&eps->nconv);
    549:       DSSynchronize(eps->ds,eps->eigr,eps->eigi);
    550:       rescale_eig(eps,nv);
    551:       PetscFree3(fl1,inside,rr);
    552:       BVSetActiveColumns(eps->V,0,nv);
    553:       if (ctx->extraction == EPS_CISS_EXTRACTION_HANKEL) {
    554:         BVSumQuadrature(ctx->S,ctx->Y,ctx->M,ctx->L,ctx->L,ctx->weight,ctx->pp,contour->scatterin,contour->subcomm,contour->npoints,ctx->useconj);
    555:         BVSetActiveColumns(ctx->S,0,ctx->L);
    556:         BVCopy(ctx->S,ctx->V);
    557:         BVSetActiveColumns(ctx->S,0,nv);
    558:       }
    559:       BVCopy(ctx->S,eps->V);

    561:       DSVectors(eps->ds,DS_MAT_X,NULL,NULL);
    562:       DSGetMat(eps->ds,DS_MAT_X,&X);
    563:       BVMultInPlace(ctx->S,X,0,eps->nconv);
    564:       if (eps->ishermitian) BVMultInPlace(eps->V,X,0,eps->nconv);
    565:       MatDestroy(&X);
    566:       max_error = 0.0;
    567:       for (i=0;i<eps->nconv;i++) {
    568:         BVGetColumn(ctx->S,i,&si);
    569: #if !defined(PETSC_USE_COMPLEX)
    570:         if (eps->eigi[i]!=0.0) BVGetColumn(ctx->S,i+1,&si1);
    571: #endif
    572:         EPSComputeResidualNorm_Private(eps,PETSC_FALSE,eps->eigr[i],eps->eigi[i],si,si1,w,&error);
    573:         if (ctx->extraction == EPS_CISS_EXTRACTION_HANKEL) {  /* vector is not normalized */
    574:           VecNorm(si,NORM_2,&norm);
    575: #if !defined(PETSC_USE_COMPLEX)
    576:           if (eps->eigi[i]!=0.0) {
    577:             VecNorm(si1,NORM_2,&normi);
    578:             norm = SlepcAbsEigenvalue(norm,normi);
    579:           }
    580: #endif
    581:           error /= norm;
    582:         }
    583:         (*eps->converged)(eps,eps->eigr[i],eps->eigi[i],error,&error,eps->convergedctx);
    584:         BVRestoreColumn(ctx->S,i,&si);
    585: #if !defined(PETSC_USE_COMPLEX)
    586:         if (eps->eigi[i]!=0.0) {
    587:           BVRestoreColumn(ctx->S,i+1,&si1);
    588:           i++;
    589:         }
    590: #endif
    591:         max_error = PetscMax(max_error,error);
    592:       }

    594:       if (max_error <= eps->tol) eps->reason = EPS_CONVERGED_TOL;
    595:       else if (eps->its >= eps->max_it) eps->reason = EPS_DIVERGED_ITS;
    596:       else {
    597:         if (eps->nconv > ctx->L) nv = eps->nconv;
    598:         else if (ctx->L > nv) nv = ctx->L;
    599:         nv = PetscMin(nv,ctx->L*ctx->M);
    600:         MatCreateSeqDense(PETSC_COMM_SELF,nv,ctx->L,NULL,&M);
    601:         MatSetRandom(M,rand);
    602:         BVSetActiveColumns(ctx->S,0,nv);
    603:         BVMultInPlace(ctx->S,M,0,ctx->L);
    604:         MatDestroy(&M);
    605:         BVSetActiveColumns(ctx->S,0,ctx->L);
    606:         BVSetActiveColumns(ctx->V,0,ctx->L);
    607:         BVCopy(ctx->S,ctx->V);
    608:         if (contour->pA) BVScatter(ctx->V,ctx->pV,contour->scatterin,contour->xdup);
    609:         EPSCISSSolve(eps,J,V,0,ctx->L);
    610:       }
    611:     }
    612:   }
    613:   if (ctx->extraction == EPS_CISS_EXTRACTION_HANKEL) PetscFree(H1);
    614:   PetscFree2(Mu,H0);
    615:   PetscFunctionReturn(0);
    616: }

    618: PetscErrorCode EPSComputeVectors_CISS(EPS eps)
    619: {
    620:   EPS_CISS       *ctx = (EPS_CISS*)eps->data;
    621:   PetscInt       n;
    622:   Mat            Z,B=NULL;

    624:   if (eps->ishermitian) {
    625:     if (eps->isgeneralized && !eps->ispositive) EPSComputeVectors_Indefinite(eps);
    626:     else EPSComputeVectors_Hermitian(eps);
    627:     if (eps->isgeneralized && eps->ispositive && ctx->extraction == EPS_CISS_EXTRACTION_HANKEL) {
    628:       /* normalize to have unit B-norm */
    629:       STGetMatrix(eps->st,1,&B);
    630:       BVSetMatrix(eps->V,B,PETSC_FALSE);
    631:       BVNormalize(eps->V,NULL);
    632:       BVSetMatrix(eps->V,NULL,PETSC_FALSE);
    633:     }
    634:     PetscFunctionReturn(0);
    635:   }
    636:   DSGetDimensions(eps->ds,&n,NULL,NULL,NULL);
    637:   BVSetActiveColumns(eps->V,0,n);

    639:   /* right eigenvectors */
    640:   DSVectors(eps->ds,DS_MAT_X,NULL,NULL);

    642:   /* V = V * Z */
    643:   DSGetMat(eps->ds,DS_MAT_X,&Z);
    644:   BVMultInPlace(eps->V,Z,0,n);
    645:   MatDestroy(&Z);
    646:   BVSetActiveColumns(eps->V,0,eps->nconv);

    648:   /* normalize */
    649:   if (ctx->extraction == EPS_CISS_EXTRACTION_HANKEL) BVNormalize(eps->V,NULL);
    650:   PetscFunctionReturn(0);
    651: }

    653: static PetscErrorCode EPSCISSSetSizes_CISS(EPS eps,PetscInt ip,PetscInt bs,PetscInt ms,PetscInt npart,PetscInt bsmax,PetscBool realmats)
    654: {
    655:   EPS_CISS       *ctx = (EPS_CISS*)eps->data;
    656:   PetscInt       oN,oL,oM,oLmax,onpart;
    657:   PetscMPIInt    size;

    659:   oN = ctx->N;
    660:   if (ip == PETSC_DECIDE || ip == PETSC_DEFAULT) {
    661:     if (ctx->N!=32) { ctx->N =32; ctx->M = ctx->N/4; }
    662:   } else {
    665:     if (ctx->N!=ip) { ctx->N = ip; ctx->M = ctx->N/4; }
    666:   }
    667:   oL = ctx->L;
    668:   if (bs == PETSC_DECIDE || bs == PETSC_DEFAULT) {
    669:     ctx->L = 16;
    670:   } else {
    672:     ctx->L = bs;
    673:   }
    674:   oM = ctx->M;
    675:   if (ms == PETSC_DECIDE || ms == PETSC_DEFAULT) {
    676:     ctx->M = ctx->N/4;
    677:   } else {
    680:     ctx->M = ms;
    681:   }
    682:   onpart = ctx->npart;
    683:   if (npart == PETSC_DECIDE || npart == PETSC_DEFAULT) {
    684:     ctx->npart = 1;
    685:   } else {
    686:     MPI_Comm_size(PetscObjectComm((PetscObject)eps),&size);
    688:     ctx->npart = npart;
    689:   }
    690:   oLmax = ctx->L_max;
    691:   if (bsmax == PETSC_DECIDE || bsmax == PETSC_DEFAULT) {
    692:     ctx->L_max = 64;
    693:   } else {
    695:     ctx->L_max = PetscMax(bsmax,ctx->L);
    696:   }
    697:   if (onpart != ctx->npart || oN != ctx->N || realmats != ctx->isreal) {
    698:     SlepcContourDataDestroy(&ctx->contour);
    699:     PetscInfo(eps,"Resetting the contour data structure due to a change of parameters\n");
    700:     eps->state = EPS_STATE_INITIAL;
    701:   }
    702:   ctx->isreal = realmats;
    703:   if (oL != ctx->L || oM != ctx->M || oLmax != ctx->L_max) eps->state = EPS_STATE_INITIAL;
    704:   PetscFunctionReturn(0);
    705: }

    707: /*@
    708:    EPSCISSSetSizes - Sets the values of various size parameters in the CISS solver.

    710:    Logically Collective on eps

    712:    Input Parameters:
    713: +  eps   - the eigenproblem solver context
    714: .  ip    - number of integration points
    715: .  bs    - block size
    716: .  ms    - moment size
    717: .  npart - number of partitions when splitting the communicator
    718: .  bsmax - max block size
    719: -  realmats - A and B are real

    721:    Options Database Keys:
    722: +  -eps_ciss_integration_points - Sets the number of integration points
    723: .  -eps_ciss_blocksize - Sets the block size
    724: .  -eps_ciss_moments - Sets the moment size
    725: .  -eps_ciss_partitions - Sets the number of partitions
    726: .  -eps_ciss_maxblocksize - Sets the maximum block size
    727: -  -eps_ciss_realmats - A and B are real

    729:    Note:
    730:    The default number of partitions is 1. This means the internal KSP object is shared
    731:    among all processes of the EPS communicator. Otherwise, the communicator is split
    732:    into npart communicators, so that npart KSP solves proceed simultaneously.

    734:    Level: advanced

    736: .seealso: EPSCISSGetSizes()
    737: @*/
    738: PetscErrorCode EPSCISSSetSizes(EPS eps,PetscInt ip,PetscInt bs,PetscInt ms,PetscInt npart,PetscInt bsmax,PetscBool realmats)
    739: {
    747:   PetscTryMethod(eps,"EPSCISSSetSizes_C",(EPS,PetscInt,PetscInt,PetscInt,PetscInt,PetscInt,PetscBool),(eps,ip,bs,ms,npart,bsmax,realmats));
    748:   PetscFunctionReturn(0);
    749: }

    751: static PetscErrorCode EPSCISSGetSizes_CISS(EPS eps,PetscInt *ip,PetscInt *bs,PetscInt *ms,PetscInt *npart,PetscInt *bsmax,PetscBool *realmats)
    752: {
    753:   EPS_CISS *ctx = (EPS_CISS*)eps->data;

    755:   if (ip) *ip = ctx->N;
    756:   if (bs) *bs = ctx->L;
    757:   if (ms) *ms = ctx->M;
    758:   if (npart) *npart = ctx->npart;
    759:   if (bsmax) *bsmax = ctx->L_max;
    760:   if (realmats) *realmats = ctx->isreal;
    761:   PetscFunctionReturn(0);
    762: }

    764: /*@
    765:    EPSCISSGetSizes - Gets the values of various size parameters in the CISS solver.

    767:    Not Collective

    769:    Input Parameter:
    770: .  eps - the eigenproblem solver context

    772:    Output Parameters:
    773: +  ip    - number of integration points
    774: .  bs    - block size
    775: .  ms    - moment size
    776: .  npart - number of partitions when splitting the communicator
    777: .  bsmax - max block size
    778: -  realmats - A and B are real

    780:    Level: advanced

    782: .seealso: EPSCISSSetSizes()
    783: @*/
    784: PetscErrorCode EPSCISSGetSizes(EPS eps,PetscInt *ip,PetscInt *bs,PetscInt *ms,PetscInt *npart,PetscInt *bsmax,PetscBool *realmats)
    785: {
    787:   PetscUseMethod(eps,"EPSCISSGetSizes_C",(EPS,PetscInt*,PetscInt*,PetscInt*,PetscInt*,PetscInt*,PetscBool*),(eps,ip,bs,ms,npart,bsmax,realmats));
    788:   PetscFunctionReturn(0);
    789: }

    791: static PetscErrorCode EPSCISSSetThreshold_CISS(EPS eps,PetscReal delta,PetscReal spur)
    792: {
    793:   EPS_CISS *ctx = (EPS_CISS*)eps->data;

    795:   if (delta == PETSC_DEFAULT) {
    796:     ctx->delta = SLEPC_DEFAULT_TOL*1e-4;
    797:   } else {
    799:     ctx->delta = delta;
    800:   }
    801:   if (spur == PETSC_DEFAULT) {
    802:     ctx->spurious_threshold = PetscSqrtReal(SLEPC_DEFAULT_TOL);
    803:   } else {
    805:     ctx->spurious_threshold = spur;
    806:   }
    807:   PetscFunctionReturn(0);
    808: }

    810: /*@
    811:    EPSCISSSetThreshold - Sets the values of various threshold parameters in
    812:    the CISS solver.

    814:    Logically Collective on eps

    816:    Input Parameters:
    817: +  eps   - the eigenproblem solver context
    818: .  delta - threshold for numerical rank
    819: -  spur  - spurious threshold (to discard spurious eigenpairs)

    821:    Options Database Keys:
    822: +  -eps_ciss_delta - Sets the delta
    823: -  -eps_ciss_spurious_threshold - Sets the spurious threshold

    825:    Level: advanced

    827: .seealso: EPSCISSGetThreshold()
    828: @*/
    829: PetscErrorCode EPSCISSSetThreshold(EPS eps,PetscReal delta,PetscReal spur)
    830: {
    834:   PetscTryMethod(eps,"EPSCISSSetThreshold_C",(EPS,PetscReal,PetscReal),(eps,delta,spur));
    835:   PetscFunctionReturn(0);
    836: }

    838: static PetscErrorCode EPSCISSGetThreshold_CISS(EPS eps,PetscReal *delta,PetscReal *spur)
    839: {
    840:   EPS_CISS *ctx = (EPS_CISS*)eps->data;

    842:   if (delta) *delta = ctx->delta;
    843:   if (spur)  *spur = ctx->spurious_threshold;
    844:   PetscFunctionReturn(0);
    845: }

    847: /*@
    848:    EPSCISSGetThreshold - Gets the values of various threshold parameters
    849:    in the CISS solver.

    851:    Not Collective

    853:    Input Parameter:
    854: .  eps - the eigenproblem solver context

    856:    Output Parameters:
    857: +  delta - threshold for numerical rank
    858: -  spur  - spurious threshold (to discard spurious eigenpairs)

    860:    Level: advanced

    862: .seealso: EPSCISSSetThreshold()
    863: @*/
    864: PetscErrorCode EPSCISSGetThreshold(EPS eps,PetscReal *delta,PetscReal *spur)
    865: {
    867:   PetscUseMethod(eps,"EPSCISSGetThreshold_C",(EPS,PetscReal*,PetscReal*),(eps,delta,spur));
    868:   PetscFunctionReturn(0);
    869: }

    871: static PetscErrorCode EPSCISSSetRefinement_CISS(EPS eps,PetscInt inner,PetscInt blsize)
    872: {
    873:   EPS_CISS *ctx = (EPS_CISS*)eps->data;

    875:   if (inner == PETSC_DEFAULT) {
    876:     ctx->refine_inner = 0;
    877:   } else {
    879:     ctx->refine_inner = inner;
    880:   }
    881:   if (blsize == PETSC_DEFAULT) {
    882:     ctx->refine_blocksize = 0;
    883:   } else {
    885:     ctx->refine_blocksize = blsize;
    886:   }
    887:   PetscFunctionReturn(0);
    888: }

    890: /*@
    891:    EPSCISSSetRefinement - Sets the values of various refinement parameters
    892:    in the CISS solver.

    894:    Logically Collective on eps

    896:    Input Parameters:
    897: +  eps    - the eigenproblem solver context
    898: .  inner  - number of iterative refinement iterations (inner loop)
    899: -  blsize - number of iterative refinement iterations (blocksize loop)

    901:    Options Database Keys:
    902: +  -eps_ciss_refine_inner - Sets number of inner iterations
    903: -  -eps_ciss_refine_blocksize - Sets number of blocksize iterations

    905:    Level: advanced

    907: .seealso: EPSCISSGetRefinement()
    908: @*/
    909: PetscErrorCode EPSCISSSetRefinement(EPS eps,PetscInt inner,PetscInt blsize)
    910: {
    914:   PetscTryMethod(eps,"EPSCISSSetRefinement_C",(EPS,PetscInt,PetscInt),(eps,inner,blsize));
    915:   PetscFunctionReturn(0);
    916: }

    918: static PetscErrorCode EPSCISSGetRefinement_CISS(EPS eps,PetscInt *inner,PetscInt *blsize)
    919: {
    920:   EPS_CISS *ctx = (EPS_CISS*)eps->data;

    922:   if (inner)  *inner = ctx->refine_inner;
    923:   if (blsize) *blsize = ctx->refine_blocksize;
    924:   PetscFunctionReturn(0);
    925: }

    927: /*@
    928:    EPSCISSGetRefinement - Gets the values of various refinement parameters
    929:    in the CISS solver.

    931:    Not Collective

    933:    Input Parameter:
    934: .  eps - the eigenproblem solver context

    936:    Output Parameters:
    937: +  inner  - number of iterative refinement iterations (inner loop)
    938: -  blsize - number of iterative refinement iterations (blocksize loop)

    940:    Level: advanced

    942: .seealso: EPSCISSSetRefinement()
    943: @*/
    944: PetscErrorCode EPSCISSGetRefinement(EPS eps, PetscInt *inner, PetscInt *blsize)
    945: {
    947:   PetscUseMethod(eps,"EPSCISSGetRefinement_C",(EPS,PetscInt*,PetscInt*),(eps,inner,blsize));
    948:   PetscFunctionReturn(0);
    949: }

    951: static PetscErrorCode EPSCISSSetUseST_CISS(EPS eps,PetscBool usest)
    952: {
    953:   EPS_CISS *ctx = (EPS_CISS*)eps->data;

    955:   ctx->usest     = usest;
    956:   ctx->usest_set = PETSC_TRUE;
    957:   eps->state     = EPS_STATE_INITIAL;
    958:   PetscFunctionReturn(0);
    959: }

    961: /*@
    962:    EPSCISSSetUseST - Sets a flag indicating that the CISS solver will
    963:    use the ST object for the linear solves.

    965:    Logically Collective on eps

    967:    Input Parameters:
    968: +  eps    - the eigenproblem solver context
    969: -  usest  - boolean flag to use the ST object or not

    971:    Options Database Keys:
    972: .  -eps_ciss_usest <bool> - whether the ST object will be used or not

    974:    Level: advanced

    976: .seealso: EPSCISSGetUseST()
    977: @*/
    978: PetscErrorCode EPSCISSSetUseST(EPS eps,PetscBool usest)
    979: {
    982:   PetscTryMethod(eps,"EPSCISSSetUseST_C",(EPS,PetscBool),(eps,usest));
    983:   PetscFunctionReturn(0);
    984: }

    986: static PetscErrorCode EPSCISSGetUseST_CISS(EPS eps,PetscBool *usest)
    987: {
    988:   EPS_CISS *ctx = (EPS_CISS*)eps->data;

    990:   *usest = ctx->usest;
    991:   PetscFunctionReturn(0);
    992: }

    994: /*@
    995:    EPSCISSGetUseST - Gets the flag for using the ST object
    996:    in the CISS solver.

    998:    Not Collective

    1000:    Input Parameter:
    1001: .  eps - the eigenproblem solver context

    1003:    Output Parameters:
    1004: .  usest - boolean flag indicating if the ST object is being used

    1006:    Level: advanced

    1008: .seealso: EPSCISSSetUseST()
    1009: @*/
    1010: PetscErrorCode EPSCISSGetUseST(EPS eps,PetscBool *usest)
    1011: {
    1014:   PetscUseMethod(eps,"EPSCISSGetUseST_C",(EPS,PetscBool*),(eps,usest));
    1015:   PetscFunctionReturn(0);
    1016: }

    1018: static PetscErrorCode EPSCISSSetQuadRule_CISS(EPS eps,EPSCISSQuadRule quad)
    1019: {
    1020:   EPS_CISS *ctx = (EPS_CISS*)eps->data;

    1022:   if (ctx->quad != quad) {
    1023:     ctx->quad  = quad;
    1024:     eps->state = EPS_STATE_INITIAL;
    1025:   }
    1026:   PetscFunctionReturn(0);
    1027: }

    1029: /*@
    1030:    EPSCISSSetQuadRule - Sets the quadrature rule used in the CISS solver.

    1032:    Logically Collective on eps

    1034:    Input Parameters:
    1035: +  eps  - the eigenproblem solver context
    1036: -  quad - the quadrature rule

    1038:    Options Database Key:
    1039: .  -eps_ciss_quadrule - Sets the quadrature rule (either 'trapezoidal' or
    1040:                            'chebyshev')

    1042:    Notes:
    1043:    By default, the trapezoidal rule is used (EPS_CISS_QUADRULE_TRAPEZOIDAL).

    1045:    If the 'chebyshev' option is specified (EPS_CISS_QUADRULE_CHEBYSHEV), then
    1046:    Chebyshev points are used as quadrature points.

    1048:    Level: advanced

    1050: .seealso: EPSCISSGetQuadRule(), EPSCISSQuadRule
    1051: @*/
    1052: PetscErrorCode EPSCISSSetQuadRule(EPS eps,EPSCISSQuadRule quad)
    1053: {
    1056:   PetscTryMethod(eps,"EPSCISSSetQuadRule_C",(EPS,EPSCISSQuadRule),(eps,quad));
    1057:   PetscFunctionReturn(0);
    1058: }

    1060: static PetscErrorCode EPSCISSGetQuadRule_CISS(EPS eps,EPSCISSQuadRule *quad)
    1061: {
    1062:   EPS_CISS *ctx = (EPS_CISS*)eps->data;

    1064:   *quad = ctx->quad;
    1065:   PetscFunctionReturn(0);
    1066: }

    1068: /*@
    1069:    EPSCISSGetQuadRule - Gets the quadrature rule used in the CISS solver.

    1071:    Not Collective

    1073:    Input Parameter:
    1074: .  eps - the eigenproblem solver context

    1076:    Output Parameters:
    1077: .  quad - quadrature rule

    1079:    Level: advanced

    1081: .seealso: EPSCISSSetQuadRule() EPSCISSQuadRule
    1082: @*/
    1083: PetscErrorCode EPSCISSGetQuadRule(EPS eps,EPSCISSQuadRule *quad)
    1084: {
    1087:   PetscUseMethod(eps,"EPSCISSGetQuadRule_C",(EPS,EPSCISSQuadRule*),(eps,quad));
    1088:   PetscFunctionReturn(0);
    1089: }

    1091: static PetscErrorCode EPSCISSSetExtraction_CISS(EPS eps,EPSCISSExtraction extraction)
    1092: {
    1093:   EPS_CISS *ctx = (EPS_CISS*)eps->data;

    1095:   if (ctx->extraction != extraction) {
    1096:     ctx->extraction = extraction;
    1097:     eps->state      = EPS_STATE_INITIAL;
    1098:   }
    1099:   PetscFunctionReturn(0);
    1100: }

    1102: /*@
    1103:    EPSCISSSetExtraction - Sets the extraction technique used in the CISS solver.

    1105:    Logically Collective on eps

    1107:    Input Parameters:
    1108: +  eps        - the eigenproblem solver context
    1109: -  extraction - the extraction technique

    1111:    Options Database Key:
    1112: .  -eps_ciss_extraction - Sets the extraction technique (either 'ritz' or
    1113:                            'hankel')

    1115:    Notes:
    1116:    By default, the Rayleigh-Ritz extraction is used (EPS_CISS_EXTRACTION_RITZ).

    1118:    If the 'hankel' option is specified (EPS_CISS_EXTRACTION_HANKEL), then
    1119:    the Block Hankel method is used for extracting eigenpairs.

    1121:    Level: advanced

    1123: .seealso: EPSCISSGetExtraction(), EPSCISSExtraction
    1124: @*/
    1125: PetscErrorCode EPSCISSSetExtraction(EPS eps,EPSCISSExtraction extraction)
    1126: {
    1129:   PetscTryMethod(eps,"EPSCISSSetExtraction_C",(EPS,EPSCISSExtraction),(eps,extraction));
    1130:   PetscFunctionReturn(0);
    1131: }

    1133: static PetscErrorCode EPSCISSGetExtraction_CISS(EPS eps,EPSCISSExtraction *extraction)
    1134: {
    1135:   EPS_CISS *ctx = (EPS_CISS*)eps->data;

    1137:   *extraction = ctx->extraction;
    1138:   PetscFunctionReturn(0);
    1139: }

    1141: /*@
    1142:    EPSCISSGetExtraction - Gets the extraction technique used in the CISS solver.

    1144:    Not Collective

    1146:    Input Parameter:
    1147: .  eps - the eigenproblem solver context

    1149:    Output Parameters:
    1150: .  extraction - extraction technique

    1152:    Level: advanced

    1154: .seealso: EPSCISSSetExtraction() EPSCISSExtraction
    1155: @*/
    1156: PetscErrorCode EPSCISSGetExtraction(EPS eps,EPSCISSExtraction *extraction)
    1157: {
    1160:   PetscUseMethod(eps,"EPSCISSGetExtraction_C",(EPS,EPSCISSExtraction*),(eps,extraction));
    1161:   PetscFunctionReturn(0);
    1162: }

    1164: static PetscErrorCode EPSCISSGetKSPs_CISS(EPS eps,PetscInt *nsolve,KSP **ksp)
    1165: {
    1166:   EPS_CISS         *ctx = (EPS_CISS*)eps->data;
    1167:   SlepcContourData contour;
    1168:   PetscInt         i,nsplit;
    1169:   PC               pc;
    1170:   MPI_Comm         child;

    1172:   if (!ctx->contour) {  /* initialize contour data structure first */
    1173:     RGCanUseConjugates(eps->rg,ctx->isreal,&ctx->useconj);
    1174:     SlepcContourDataCreate(ctx->useconj?ctx->N/2:ctx->N,ctx->npart,(PetscObject)eps,&ctx->contour);
    1175:   }
    1176:   contour = ctx->contour;
    1177:   if (!contour->ksp) {
    1178:     PetscMalloc1(contour->npoints,&contour->ksp);
    1179:     EPSGetST(eps,&eps->st);
    1180:     STGetSplitPreconditionerInfo(eps->st,&nsplit,NULL);
    1181:     PetscSubcommGetChild(contour->subcomm,&child);
    1182:     for (i=0;i<contour->npoints;i++) {
    1183:       KSPCreate(child,&contour->ksp[i]);
    1184:       PetscObjectIncrementTabLevel((PetscObject)contour->ksp[i],(PetscObject)eps,1);
    1185:       KSPSetOptionsPrefix(contour->ksp[i],((PetscObject)eps)->prefix);
    1186:       KSPAppendOptionsPrefix(contour->ksp[i],"eps_ciss_");
    1187:       PetscLogObjectParent((PetscObject)eps,(PetscObject)contour->ksp[i]);
    1188:       PetscObjectSetOptions((PetscObject)contour->ksp[i],((PetscObject)eps)->options);
    1189:       KSPSetErrorIfNotConverged(contour->ksp[i],PETSC_TRUE);
    1190:       KSPSetTolerances(contour->ksp[i],SlepcDefaultTol(eps->tol),PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);
    1191:       KSPGetPC(contour->ksp[i],&pc);
    1192:       if (nsplit) {
    1193:         KSPSetType(contour->ksp[i],KSPBCGS);
    1194:         PCSetType(pc,PCBJACOBI);
    1195:       } else {
    1196:         KSPSetType(contour->ksp[i],KSPPREONLY);
    1197:         PCSetType(pc,PCLU);
    1198:       }
    1199:     }
    1200:   }
    1201:   if (nsolve) *nsolve = contour->npoints;
    1202:   if (ksp)    *ksp    = contour->ksp;
    1203:   PetscFunctionReturn(0);
    1204: }

    1206: /*@C
    1207:    EPSCISSGetKSPs - Retrieve the array of linear solver objects associated with
    1208:    the CISS solver.

    1210:    Not Collective

    1212:    Input Parameter:
    1213: .  eps - the eigenproblem solver solver

    1215:    Output Parameters:
    1216: +  nsolve - number of solver objects
    1217: -  ksp - array of linear solver object

    1219:    Notes:
    1220:    The number of KSP solvers is equal to the number of integration points divided by
    1221:    the number of partitions. This value is halved in the case of real matrices with
    1222:    a region centered at the real axis.

    1224:    Level: advanced

    1226: .seealso: EPSCISSSetSizes()
    1227: @*/
    1228: PetscErrorCode EPSCISSGetKSPs(EPS eps,PetscInt *nsolve,KSP **ksp)
    1229: {
    1231:   PetscUseMethod(eps,"EPSCISSGetKSPs_C",(EPS,PetscInt*,KSP**),(eps,nsolve,ksp));
    1232:   PetscFunctionReturn(0);
    1233: }

    1235: PetscErrorCode EPSReset_CISS(EPS eps)
    1236: {
    1237:   EPS_CISS       *ctx = (EPS_CISS*)eps->data;

    1239:   BVDestroy(&ctx->S);
    1240:   BVDestroy(&ctx->V);
    1241:   BVDestroy(&ctx->Y);
    1242:   if (!ctx->usest) SlepcContourDataReset(ctx->contour);
    1243:   BVDestroy(&ctx->pV);
    1244:   PetscFunctionReturn(0);
    1245: }

    1247: PetscErrorCode EPSSetFromOptions_CISS(PetscOptionItems *PetscOptionsObject,EPS eps)
    1248: {
    1249:   PetscReal         r3,r4;
    1250:   PetscInt          i,i1,i2,i3,i4,i5,i6,i7;
    1251:   PetscBool         b1,b2,flg,flg2,flg3,flg4,flg5,flg6;
    1252:   EPS_CISS          *ctx = (EPS_CISS*)eps->data;
    1253:   EPSCISSQuadRule   quad;
    1254:   EPSCISSExtraction extraction;

    1256:   PetscOptionsHead(PetscOptionsObject,"EPS CISS Options");

    1258:     EPSCISSGetSizes(eps,&i1,&i2,&i3,&i4,&i5,&b1);
    1259:     PetscOptionsInt("-eps_ciss_integration_points","Number of integration points","EPSCISSSetSizes",i1,&i1,&flg);
    1260:     PetscOptionsInt("-eps_ciss_blocksize","Block size","EPSCISSSetSizes",i2,&i2,&flg2);
    1261:     PetscOptionsInt("-eps_ciss_moments","Moment size","EPSCISSSetSizes",i3,&i3,&flg3);
    1262:     PetscOptionsInt("-eps_ciss_partitions","Number of partitions","EPSCISSSetSizes",i4,&i4,&flg4);
    1263:     PetscOptionsInt("-eps_ciss_maxblocksize","Maximum block size","EPSCISSSetSizes",i5,&i5,&flg5);
    1264:     PetscOptionsBool("-eps_ciss_realmats","True if A and B are real","EPSCISSSetSizes",b1,&b1,&flg6);
    1265:     if (flg || flg2 || flg3 || flg4 || flg5 || flg6) EPSCISSSetSizes(eps,i1,i2,i3,i4,i5,b1);

    1267:     EPSCISSGetThreshold(eps,&r3,&r4);
    1268:     PetscOptionsReal("-eps_ciss_delta","Threshold for numerical rank","EPSCISSSetThreshold",r3,&r3,&flg);
    1269:     PetscOptionsReal("-eps_ciss_spurious_threshold","Threshold for the spurious eigenpairs","EPSCISSSetThreshold",r4,&r4,&flg2);
    1270:     if (flg || flg2) EPSCISSSetThreshold(eps,r3,r4);

    1272:     EPSCISSGetRefinement(eps,&i6,&i7);
    1273:     PetscOptionsInt("-eps_ciss_refine_inner","Number of inner iterative refinement iterations","EPSCISSSetRefinement",i6,&i6,&flg);
    1274:     PetscOptionsInt("-eps_ciss_refine_blocksize","Number of blocksize iterative refinement iterations","EPSCISSSetRefinement",i7,&i7,&flg2);
    1275:     if (flg || flg2) EPSCISSSetRefinement(eps,i6,i7);

    1277:     EPSCISSGetUseST(eps,&b2);
    1278:     PetscOptionsBool("-eps_ciss_usest","Use ST for linear solves","EPSCISSSetUseST",b2,&b2,&flg);
    1279:     if (flg) EPSCISSSetUseST(eps,b2);

    1281:     PetscOptionsEnum("-eps_ciss_quadrule","Quadrature rule","EPSCISSSetQuadRule",EPSCISSQuadRules,(PetscEnum)ctx->quad,(PetscEnum*)&quad,&flg);
    1282:     if (flg) EPSCISSSetQuadRule(eps,quad);

    1284:     PetscOptionsEnum("-eps_ciss_extraction","Extraction technique","EPSCISSSetExtraction",EPSCISSExtractions,(PetscEnum)ctx->extraction,(PetscEnum*)&extraction,&flg);
    1285:     if (flg) EPSCISSSetExtraction(eps,extraction);

    1287:   PetscOptionsTail();

    1289:   if (!eps->rg) EPSGetRG(eps,&eps->rg);
    1290:   RGSetFromOptions(eps->rg); /* this is necessary here to set useconj */
    1291:   if (!ctx->contour || !ctx->contour->ksp) EPSCISSGetKSPs(eps,NULL,NULL);
    1292:   for (i=0;i<ctx->contour->npoints;i++) KSPSetFromOptions(ctx->contour->ksp[i]);
    1293:   PetscSubcommSetFromOptions(ctx->contour->subcomm);
    1294:   PetscFunctionReturn(0);
    1295: }

    1297: PetscErrorCode EPSDestroy_CISS(EPS eps)
    1298: {
    1299:   EPS_CISS       *ctx = (EPS_CISS*)eps->data;

    1301:   SlepcContourDataDestroy(&ctx->contour);
    1302:   PetscFree4(ctx->weight,ctx->omega,ctx->pp,ctx->sigma);
    1303:   PetscFree(eps->data);
    1304:   PetscObjectComposeFunction((PetscObject)eps,"EPSCISSSetSizes_C",NULL);
    1305:   PetscObjectComposeFunction((PetscObject)eps,"EPSCISSGetSizes_C",NULL);
    1306:   PetscObjectComposeFunction((PetscObject)eps,"EPSCISSSetThreshold_C",NULL);
    1307:   PetscObjectComposeFunction((PetscObject)eps,"EPSCISSGetThreshold_C",NULL);
    1308:   PetscObjectComposeFunction((PetscObject)eps,"EPSCISSSetRefinement_C",NULL);
    1309:   PetscObjectComposeFunction((PetscObject)eps,"EPSCISSGetRefinement_C",NULL);
    1310:   PetscObjectComposeFunction((PetscObject)eps,"EPSCISSSetUseST_C",NULL);
    1311:   PetscObjectComposeFunction((PetscObject)eps,"EPSCISSGetUseST_C",NULL);
    1312:   PetscObjectComposeFunction((PetscObject)eps,"EPSCISSSetQuadRule_C",NULL);
    1313:   PetscObjectComposeFunction((PetscObject)eps,"EPSCISSGetQuadRule_C",NULL);
    1314:   PetscObjectComposeFunction((PetscObject)eps,"EPSCISSSetExtraction_C",NULL);
    1315:   PetscObjectComposeFunction((PetscObject)eps,"EPSCISSGetExtraction_C",NULL);
    1316:   PetscObjectComposeFunction((PetscObject)eps,"EPSCISSGetKSPs_C",NULL);
    1317:   PetscFunctionReturn(0);
    1318: }

    1320: PetscErrorCode EPSView_CISS(EPS eps,PetscViewer viewer)
    1321: {
    1322:   EPS_CISS       *ctx = (EPS_CISS*)eps->data;
    1323:   PetscBool      isascii;
    1324:   PetscViewer    sviewer;

    1326:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
    1327:   if (isascii) {
    1328:     PetscViewerASCIIPrintf(viewer,"  sizes { integration points: %" PetscInt_FMT ", block size: %" PetscInt_FMT ", moment size: %" PetscInt_FMT ", partitions: %" PetscInt_FMT ", maximum block size: %" PetscInt_FMT " }\n",ctx->N,ctx->L,ctx->M,ctx->npart,ctx->L_max);
    1329:     if (ctx->isreal) PetscViewerASCIIPrintf(viewer,"  exploiting symmetry of integration points\n");
    1330:     PetscViewerASCIIPrintf(viewer,"  threshold { delta: %g, spurious threshold: %g }\n",(double)ctx->delta,(double)ctx->spurious_threshold);
    1331:     PetscViewerASCIIPrintf(viewer,"  iterative refinement { inner: %" PetscInt_FMT ", blocksize: %" PetscInt_FMT " }\n",ctx->refine_inner, ctx->refine_blocksize);
    1332:     PetscViewerASCIIPrintf(viewer,"  extraction: %s\n",EPSCISSExtractions[ctx->extraction]);
    1333:     PetscViewerASCIIPrintf(viewer,"  quadrature rule: %s\n",EPSCISSQuadRules[ctx->quad]);
    1334:     if (ctx->usest) PetscViewerASCIIPrintf(viewer,"  using ST for linear solves\n");
    1335:     else {
    1336:       if (!ctx->contour || !ctx->contour->ksp) EPSCISSGetKSPs(eps,NULL,NULL);
    1337:       PetscViewerASCIIPushTab(viewer);
    1338:       if (ctx->npart>1 && ctx->contour->subcomm) {
    1339:         PetscViewerGetSubViewer(viewer,ctx->contour->subcomm->child,&sviewer);
    1340:         if (!ctx->contour->subcomm->color) KSPView(ctx->contour->ksp[0],sviewer);
    1341:         PetscViewerFlush(sviewer);
    1342:         PetscViewerRestoreSubViewer(viewer,ctx->contour->subcomm->child,&sviewer);
    1343:         PetscViewerFlush(viewer);
    1344:         /* extra call needed because of the two calls to PetscViewerASCIIPushSynchronized() in PetscViewerGetSubViewer() */
    1345:         PetscViewerASCIIPopSynchronized(viewer);
    1346:       } else KSPView(ctx->contour->ksp[0],viewer);
    1347:       PetscViewerASCIIPopTab(viewer);
    1348:     }
    1349:   }
    1350:   PetscFunctionReturn(0);
    1351: }

    1353: PetscErrorCode EPSSetDefaultST_CISS(EPS eps)
    1354: {
    1355:   EPS_CISS       *ctx = (EPS_CISS*)eps->data;
    1356:   PetscBool      usest = ctx->usest;
    1357:   KSP            ksp;
    1358:   PC             pc;

    1360:   if (!((PetscObject)eps->st)->type_name) {
    1361:     if (!ctx->usest_set) usest = (ctx->npart>1)? PETSC_FALSE: PETSC_TRUE;
    1362:     if (usest) STSetType(eps->st,STSINVERT);
    1363:     else {
    1364:       /* we are not going to use ST, so avoid factorizing the matrix */
    1365:       STSetType(eps->st,STSHIFT);
    1366:       if (eps->isgeneralized) {
    1367:         STGetKSP(eps->st,&ksp);
    1368:         KSPGetPC(ksp,&pc);
    1369:         PCSetType(pc,PCNONE);
    1370:       }
    1371:     }
    1372:   }
    1373:   PetscFunctionReturn(0);
    1374: }

    1376: SLEPC_EXTERN PetscErrorCode EPSCreate_CISS(EPS eps)
    1377: {
    1378:   EPS_CISS       *ctx = (EPS_CISS*)eps->data;

    1380:   PetscNewLog(eps,&ctx);
    1381:   eps->data = ctx;

    1383:   eps->useds = PETSC_TRUE;
    1384:   eps->categ = EPS_CATEGORY_CONTOUR;

    1386:   eps->ops->solve          = EPSSolve_CISS;
    1387:   eps->ops->setup          = EPSSetUp_CISS;
    1388:   eps->ops->setupsort      = EPSSetUpSort_CISS;
    1389:   eps->ops->setfromoptions = EPSSetFromOptions_CISS;
    1390:   eps->ops->destroy        = EPSDestroy_CISS;
    1391:   eps->ops->reset          = EPSReset_CISS;
    1392:   eps->ops->view           = EPSView_CISS;
    1393:   eps->ops->computevectors = EPSComputeVectors_CISS;
    1394:   eps->ops->setdefaultst   = EPSSetDefaultST_CISS;

    1396:   PetscObjectComposeFunction((PetscObject)eps,"EPSCISSSetSizes_C",EPSCISSSetSizes_CISS);
    1397:   PetscObjectComposeFunction((PetscObject)eps,"EPSCISSGetSizes_C",EPSCISSGetSizes_CISS);
    1398:   PetscObjectComposeFunction((PetscObject)eps,"EPSCISSSetThreshold_C",EPSCISSSetThreshold_CISS);
    1399:   PetscObjectComposeFunction((PetscObject)eps,"EPSCISSGetThreshold_C",EPSCISSGetThreshold_CISS);
    1400:   PetscObjectComposeFunction((PetscObject)eps,"EPSCISSSetRefinement_C",EPSCISSSetRefinement_CISS);
    1401:   PetscObjectComposeFunction((PetscObject)eps,"EPSCISSGetRefinement_C",EPSCISSGetRefinement_CISS);
    1402:   PetscObjectComposeFunction((PetscObject)eps,"EPSCISSSetUseST_C",EPSCISSSetUseST_CISS);
    1403:   PetscObjectComposeFunction((PetscObject)eps,"EPSCISSGetUseST_C",EPSCISSGetUseST_CISS);
    1404:   PetscObjectComposeFunction((PetscObject)eps,"EPSCISSSetQuadRule_C",EPSCISSSetQuadRule_CISS);
    1405:   PetscObjectComposeFunction((PetscObject)eps,"EPSCISSGetQuadRule_C",EPSCISSGetQuadRule_CISS);
    1406:   PetscObjectComposeFunction((PetscObject)eps,"EPSCISSSetExtraction_C",EPSCISSSetExtraction_CISS);
    1407:   PetscObjectComposeFunction((PetscObject)eps,"EPSCISSGetExtraction_C",EPSCISSGetExtraction_CISS);
    1408:   PetscObjectComposeFunction((PetscObject)eps,"EPSCISSGetKSPs_C",EPSCISSGetKSPs_CISS);

    1410:   /* set default values of parameters */
    1411:   ctx->N                  = 32;
    1412:   ctx->L                  = 16;
    1413:   ctx->M                  = ctx->N/4;
    1414:   ctx->delta              = SLEPC_DEFAULT_TOL*1e-4;
    1415:   ctx->L_max              = 64;
    1416:   ctx->spurious_threshold = PetscSqrtReal(SLEPC_DEFAULT_TOL);
    1417:   ctx->usest              = PETSC_TRUE;
    1418:   ctx->usest_set          = PETSC_FALSE;
    1419:   ctx->isreal             = PETSC_FALSE;
    1420:   ctx->refine_inner       = 0;
    1421:   ctx->refine_blocksize   = 0;
    1422:   ctx->npart              = 1;
    1423:   ctx->quad               = (EPSCISSQuadRule)0;
    1424:   ctx->extraction         = EPS_CISS_EXTRACTION_RITZ;
    1425:   PetscFunctionReturn(0);
    1426: }