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

Actual source code: pepsetup.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:    PEP routines related to problem setup
     12: */

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

     16: /*
     17:    Let the solver choose the ST type that should be used by default,
     18:    otherwise set it to SHIFT.
     19:    This is called at PEPSetFromOptions (before STSetFromOptions)
     20:    and also at PEPSetUp (in case PEPSetFromOptions was not called).
     21: */
     22: PetscErrorCode PEPSetDefaultST(PEP pep)
     23: {
     24:   if (pep->ops->setdefaultst) (*pep->ops->setdefaultst)(pep);
     25:   if (!((PetscObject)pep->st)->type_name) STSetType(pep->st,STSHIFT);
     26:   PetscFunctionReturn(0);
     27: }

     29: /*
     30:    This is used in Q-Arnoldi and STOAR to set the transform flag by
     31:    default, otherwise the user has to explicitly run with -st_transform
     32: */
     33: PetscErrorCode PEPSetDefaultST_Transform(PEP pep)
     34: {
     35:   STSetTransform(pep->st,PETSC_TRUE);
     36:   PetscFunctionReturn(0);
     37: }

     39: /*@
     40:    PEPSetUp - Sets up all the internal data structures necessary for the
     41:    execution of the PEP solver.

     43:    Collective on pep

     45:    Input Parameter:
     46: .  pep   - solver context

     48:    Notes:
     49:    This function need not be called explicitly in most cases, since PEPSolve()
     50:    calls it. It can be useful when one wants to measure the set-up time
     51:    separately from the solve time.

     53:    Level: developer

     55: .seealso: PEPCreate(), PEPSolve(), PEPDestroy()
     56: @*/
     57: PetscErrorCode PEPSetUp(PEP pep)
     58: {
     59:   SlepcSC        sc;
     60:   PetscBool      istrivial,flg;
     61:   PetscInt       k;
     62:   KSP            ksp;
     63:   PC             pc;
     64:   PetscMPIInt    size;
     65:   MatSolverType  stype;

     68:   if (pep->state) PetscFunctionReturn(0);
     69:   PetscLogEventBegin(PEP_SetUp,pep,0,0,0);

     71:   /* reset the convergence flag from the previous solves */
     72:   pep->reason = PEP_CONVERGED_ITERATING;

     74:   /* set default solver type (PEPSetFromOptions was not called) */
     75:   if (!((PetscObject)pep)->type_name) PEPSetType(pep,PEPTOAR);
     76:   if (!pep->st) PEPGetST(pep,&pep->st);
     77:   PEPSetDefaultST(pep);
     78:   if (!pep->ds) PEPGetDS(pep,&pep->ds);
     79:   if (!pep->rg) PEPGetRG(pep,&pep->rg);
     80:   if (!((PetscObject)pep->rg)->type_name) RGSetType(pep->rg,RGINTERVAL);

     82:   /* check matrices, transfer them to ST */
     84:   STSetMatrices(pep->st,pep->nmat,pep->A);

     86:   /* set problem dimensions */
     87:   MatGetSize(pep->A[0],&pep->n,NULL);
     88:   MatGetLocalSize(pep->A[0],&pep->nloc,NULL);

     90:   /* set default problem type */
     91:   if (!pep->problem_type) PEPSetProblemType(pep,PEP_GENERAL);
     92:   if (pep->nev > (pep->nmat-1)*pep->n) pep->nev = (pep->nmat-1)*pep->n;
     93:   if (pep->ncv > (pep->nmat-1)*pep->n) pep->ncv = (pep->nmat-1)*pep->n;

     95:   /* check consistency of refinement options */
     96:   if (pep->refine) {
     97:     if (!pep->scheme) {  /* set default scheme */
     98:       PEPRefineGetKSP(pep,&ksp);
     99:       KSPGetPC(ksp,&pc);
    100:       PetscObjectTypeCompare((PetscObject)ksp,KSPPREONLY,&flg);
    101:       if (flg) PetscObjectTypeCompareAny((PetscObject)pc,&flg,PCLU,PCCHOLESKY,"");
    102:       pep->scheme = flg? PEP_REFINE_SCHEME_MBE: PEP_REFINE_SCHEME_SCHUR;
    103:     }
    104:     if (pep->scheme==PEP_REFINE_SCHEME_MBE) {
    105:       PEPRefineGetKSP(pep,&ksp);
    106:       KSPGetPC(ksp,&pc);
    107:       PetscObjectTypeCompare((PetscObject)ksp,KSPPREONLY,&flg);
    108:       if (flg) PetscObjectTypeCompareAny((PetscObject)pc,&flg,PCLU,PCCHOLESKY,"");
    110:       MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);
    111:       if (size>1) {   /* currently selected PC is a factorization */
    112:         PCFactorGetMatSolverType(pc,&stype);
    113:         PetscStrcmp(stype,MATSOLVERPETSC,&flg);
    115:       }
    116:     }
    117:     if (pep->scheme==PEP_REFINE_SCHEME_SCHUR) {
    119:     }
    120:   }
    121:   /* call specific solver setup */
    122:   (*pep->ops->setup)(pep);

    124:   /* set tolerance if not yet set */
    125:   if (pep->tol==PETSC_DEFAULT) pep->tol = SLEPC_DEFAULT_TOL;
    126:   if (pep->refine) {
    127:     if (pep->rtol==PETSC_DEFAULT) pep->rtol = PetscMax(pep->tol/1000,PETSC_MACHINE_EPSILON);
    128:     if (pep->rits==PETSC_DEFAULT) pep->rits = (pep->refine==PEP_REFINE_SIMPLE)? 10: 1;
    129:   }

    131:   /* set default extraction */
    132:   if (!pep->extract) {
    133:     pep->extract = (pep->basis==PEP_BASIS_MONOMIAL)? PEP_EXTRACT_NORM: PEP_EXTRACT_NONE;
    134:   }

    136:   /* fill sorting criterion context */
    137:   switch (pep->which) {
    138:     case PEP_LARGEST_MAGNITUDE:
    139:       pep->sc->comparison    = SlepcCompareLargestMagnitude;
    140:       pep->sc->comparisonctx = NULL;
    141:       break;
    142:     case PEP_SMALLEST_MAGNITUDE:
    143:       pep->sc->comparison    = SlepcCompareSmallestMagnitude;
    144:       pep->sc->comparisonctx = NULL;
    145:       break;
    146:     case PEP_LARGEST_REAL:
    147:       pep->sc->comparison    = SlepcCompareLargestReal;
    148:       pep->sc->comparisonctx = NULL;
    149:       break;
    150:     case PEP_SMALLEST_REAL:
    151:       pep->sc->comparison    = SlepcCompareSmallestReal;
    152:       pep->sc->comparisonctx = NULL;
    153:       break;
    154:     case PEP_LARGEST_IMAGINARY:
    155:       pep->sc->comparison    = SlepcCompareLargestImaginary;
    156:       pep->sc->comparisonctx = NULL;
    157:       break;
    158:     case PEP_SMALLEST_IMAGINARY:
    159:       pep->sc->comparison    = SlepcCompareSmallestImaginary;
    160:       pep->sc->comparisonctx = NULL;
    161:       break;
    162:     case PEP_TARGET_MAGNITUDE:
    163:       pep->sc->comparison    = SlepcCompareTargetMagnitude;
    164:       pep->sc->comparisonctx = &pep->target;
    165:       break;
    166:     case PEP_TARGET_REAL:
    167:       pep->sc->comparison    = SlepcCompareTargetReal;
    168:       pep->sc->comparisonctx = &pep->target;
    169:       break;
    170:     case PEP_TARGET_IMAGINARY:
    171: #if defined(PETSC_USE_COMPLEX)
    172:       pep->sc->comparison    = SlepcCompareTargetImaginary;
    173:       pep->sc->comparisonctx = &pep->target;
    174: #endif
    175:       break;
    176:     case PEP_ALL:
    177:       pep->sc->comparison    = SlepcCompareSmallestReal;
    178:       pep->sc->comparisonctx = NULL;
    179:       break;
    180:     case PEP_WHICH_USER:
    181:       break;
    182:   }
    183:   pep->sc->map    = NULL;
    184:   pep->sc->mapobj = NULL;

    186:   /* fill sorting criterion for DS */
    187:   if (pep->which!=PEP_ALL) {
    188:     DSGetSlepcSC(pep->ds,&sc);
    189:     RGIsTrivial(pep->rg,&istrivial);
    190:     sc->rg            = istrivial? NULL: pep->rg;
    191:     sc->comparison    = pep->sc->comparison;
    192:     sc->comparisonctx = pep->sc->comparisonctx;
    193:     sc->map           = SlepcMap_ST;
    194:     sc->mapobj        = (PetscObject)pep->st;
    195:   }
    196:   /* setup ST */
    197:   STSetUp(pep->st);

    199:   /* compute matrix coefficients */
    200:   STGetTransform(pep->st,&flg);
    201:   if (!flg) {
    202:     if (pep->which!=PEP_ALL && pep->solvematcoeffs) STMatSetUp(pep->st,1.0,pep->solvematcoeffs);
    203:   } else {
    205:   }

    207:   /* compute scale factor if no set by user */
    208:   PEPComputeScaleFactor(pep);

    210:   /* build balancing matrix if required */
    211:   if (pep->scale==PEP_SCALE_DIAGONAL || pep->scale==PEP_SCALE_BOTH) {
    212:     if (!pep->Dl) {
    213:       BVCreateVec(pep->V,&pep->Dl);
    214:       PetscLogObjectParent((PetscObject)pep,(PetscObject)pep->Dl);
    215:     }
    216:     if (!pep->Dr) {
    217:       BVCreateVec(pep->V,&pep->Dr);
    218:       PetscLogObjectParent((PetscObject)pep,(PetscObject)pep->Dr);
    219:     }
    220:     PEPBuildDiagonalScaling(pep);
    221:   }

    223:   /* process initial vectors */
    224:   if (pep->nini<0) {
    225:     k = -pep->nini;
    227:     BVInsertVecs(pep->V,0,&k,pep->IS,PETSC_TRUE);
    228:     SlepcBasisDestroy_Private(&pep->nini,&pep->IS);
    229:     pep->nini = k;
    230:   }
    231:   PetscLogEventEnd(PEP_SetUp,pep,0,0,0);
    232:   pep->state = PEP_STATE_SETUP;
    233:   PetscFunctionReturn(0);
    234: }

    236: /*@
    237:    PEPSetOperators - Sets the coefficient matrices associated with the polynomial
    238:    eigenvalue problem.

    240:    Collective on pep

    242:    Input Parameters:
    243: +  pep  - the eigenproblem solver context
    244: .  nmat - number of matrices in array A
    245: -  A    - the array of matrices associated with the eigenproblem

    247:    Notes:
    248:    The polynomial eigenproblem is defined as P(l)*x=0, where l is
    249:    the eigenvalue, x is the eigenvector, and P(l) is defined as
    250:    P(l) = A_0 + l*A_1 + ... + l^d*A_d, with d=nmat-1 (the degree of P).
    251:    For non-monomial bases, this expression is different.

    253:    Level: beginner

    255: .seealso: PEPSolve(), PEPGetOperators(), PEPGetNumMatrices(), PEPSetBasis()
    256: @*/
    257: PetscErrorCode PEPSetOperators(PEP pep,PetscInt nmat,Mat A[])
    258: {
    259:   PetscInt       i,n=0,m,m0=0,mloc,nloc,mloc0=0;

    267:   for (i=0;i<nmat;i++) {
    270:     MatGetSize(A[i],&m,&n);
    271:     MatGetLocalSize(A[i],&mloc,&nloc);
    274:     if (!i) { m0 = m; mloc0 = mloc; }
    277:     PetscObjectReference((PetscObject)A[i]);
    278:   }

    280:   if (pep->state && (n!=pep->n || nloc!=pep->nloc)) PEPReset(pep);
    281:   else if (pep->nmat) {
    282:     MatDestroyMatrices(pep->nmat,&pep->A);
    283:     PetscFree2(pep->pbc,pep->nrma);
    284:     PetscFree(pep->solvematcoeffs);
    285:   }

    287:   PetscMalloc1(nmat,&pep->A);
    288:   PetscCalloc2(3*nmat,&pep->pbc,nmat,&pep->nrma);
    289:   PetscLogObjectMemory((PetscObject)pep,nmat*sizeof(Mat)+4*nmat*sizeof(PetscReal));
    290:   for (i=0;i<nmat;i++) {
    291:     pep->A[i]   = A[i];
    292:     pep->pbc[i] = 1.0;  /* default to monomial basis */
    293:   }
    294:   pep->nmat = nmat;
    295:   pep->state = PEP_STATE_INITIAL;
    296:   PetscFunctionReturn(0);
    297: }

    299: /*@
    300:    PEPGetOperators - Gets the matrices associated with the polynomial eigensystem.

    302:    Not collective, though parallel Mats are returned if the PEP is parallel

    304:    Input Parameters:
    305: +  pep - the PEP context
    306: -  k   - the index of the requested matrix (starting in 0)

    308:    Output Parameter:
    309: .  A - the requested matrix

    311:    Level: intermediate

    313: .seealso: PEPSolve(), PEPSetOperators(), PEPGetNumMatrices()
    314: @*/
    315: PetscErrorCode PEPGetOperators(PEP pep,PetscInt k,Mat *A)
    316: {
    320:   *A = pep->A[k];
    321:   PetscFunctionReturn(0);
    322: }

    324: /*@
    325:    PEPGetNumMatrices - Returns the number of matrices stored in the PEP.

    327:    Not collective

    329:    Input Parameter:
    330: .  pep - the PEP context

    332:    Output Parameters:
    333: .  nmat - the number of matrices passed in PEPSetOperators()

    335:    Level: intermediate

    337: .seealso: PEPSetOperators()
    338: @*/
    339: PetscErrorCode PEPGetNumMatrices(PEP pep,PetscInt *nmat)
    340: {
    343:   *nmat = pep->nmat;
    344:   PetscFunctionReturn(0);
    345: }

    347: /*@C
    348:    PEPSetInitialSpace - Specify a basis of vectors that constitute the initial
    349:    space, that is, the subspace from which the solver starts to iterate.

    351:    Collective on pep

    353:    Input Parameters:
    354: +  pep   - the polynomial eigensolver context
    355: .  n     - number of vectors
    356: -  is    - set of basis vectors of the initial space

    358:    Notes:
    359:    Some solvers start to iterate on a single vector (initial vector). In that case,
    360:    the other vectors are ignored.

    362:    These vectors do not persist from one PEPSolve() call to the other, so the
    363:    initial space should be set every time.

    365:    The vectors do not need to be mutually orthonormal, since they are explicitly
    366:    orthonormalized internally.

    368:    Common usage of this function is when the user can provide a rough approximation
    369:    of the wanted eigenspace. Then, convergence may be faster.

    371:    Level: intermediate

    373: .seealso: PEPSetUp()
    374: @*/
    375: PetscErrorCode PEPSetInitialSpace(PEP pep,PetscInt n,Vec is[])
    376: {
    380:   if (n>0) {
    383:   }
    384:   SlepcBasisReference_Private(n,is,&pep->nini,&pep->IS);
    385:   if (n>0) pep->state = PEP_STATE_INITIAL;
    386:   PetscFunctionReturn(0);
    387: }

    389: /*
    390:   PEPSetDimensions_Default - Set reasonable values for ncv, mpd if not set
    391:   by the user. This is called at setup.
    392:  */
    393: PetscErrorCode PEPSetDimensions_Default(PEP pep,PetscInt nev,PetscInt *ncv,PetscInt *mpd)
    394: {
    395:   PetscBool      krylov;
    396:   PetscInt       dim;

    398:   PetscObjectTypeCompareAny((PetscObject)pep,&krylov,PEPTOAR,PEPSTOAR,PEPQARNOLDI,"");
    399:   dim = (pep->nmat-1)*pep->n;
    400:   if (*ncv!=PETSC_DEFAULT) { /* ncv set */
    401:     if (krylov) {
    403:     } else {
    405:     }
    406:   } else if (*mpd!=PETSC_DEFAULT) { /* mpd set */
    407:     *ncv = PetscMin(dim,nev+(*mpd));
    408:   } else { /* neither set: defaults depend on nev being small or large */
    409:     if (nev<500) *ncv = PetscMin(dim,PetscMax(2*nev,nev+15));
    410:     else {
    411:       *mpd = 500;
    412:       *ncv = PetscMin(dim,nev+(*mpd));
    413:     }
    414:   }
    415:   if (*mpd==PETSC_DEFAULT) *mpd = *ncv;
    416:   PetscFunctionReturn(0);
    417: }

    419: /*@
    420:    PEPAllocateSolution - Allocate memory storage for common variables such
    421:    as eigenvalues and eigenvectors.

    423:    Collective on pep

    425:    Input Parameters:
    426: +  pep   - eigensolver context
    427: -  extra - number of additional positions, used for methods that require a
    428:            working basis slightly larger than ncv

    430:    Developer Notes:
    431:    This is SLEPC_EXTERN because it may be required by user plugin PEP
    432:    implementations.

    434:    Level: developer

    436: .seealso: PEPSetUp()
    437: @*/
    438: PetscErrorCode PEPAllocateSolution(PEP pep,PetscInt extra)
    439: {
    440:   PetscInt       oldsize,newc,requested,requestedbv;
    441:   PetscLogDouble cnt;
    442:   Vec            t;

    444:   requested = (pep->lineariz? pep->ncv: pep->ncv*(pep->nmat-1)) + extra;
    445:   requestedbv = pep->ncv + extra;

    447:   /* oldsize is zero if this is the first time setup is called */
    448:   BVGetSizes(pep->V,NULL,NULL,&oldsize);

    450:   /* allocate space for eigenvalues and friends */
    451:   if (requested != oldsize || !pep->eigr) {
    452:     PetscFree4(pep->eigr,pep->eigi,pep->errest,pep->perm);
    453:     PetscMalloc4(requested,&pep->eigr,requested,&pep->eigi,requested,&pep->errest,requested,&pep->perm);
    454:     newc = PetscMax(0,requested-oldsize);
    455:     cnt = 2*newc*sizeof(PetscScalar) + newc*sizeof(PetscReal) + newc*sizeof(PetscInt);
    456:     PetscLogObjectMemory((PetscObject)pep,cnt);
    457:   }

    459:   /* allocate V */
    460:   if (!pep->V) PEPGetBV(pep,&pep->V);
    461:   if (!oldsize) {
    462:     if (!((PetscObject)(pep->V))->type_name) BVSetType(pep->V,BVSVEC);
    463:     STMatCreateVecsEmpty(pep->st,&t,NULL);
    464:     BVSetSizesFromVec(pep->V,t,requestedbv);
    465:     VecDestroy(&t);
    466:   } else BVResize(pep->V,requestedbv,PETSC_FALSE);
    467:   PetscFunctionReturn(0);
    468: }