Date: 2016-03-29T14:58:53+00:00

Actual source code: pepsetup.c
slepc-3.6.3 2016-03-29
Report Typos and Errors

      1: /*
      2:       PEP routines related to problem setup.

      4:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      5:    SLEPc - Scalable Library for Eigenvalue Problem Computations
      6:    Copyright (c) 2002-2015, Universitat Politecnica de Valencia, Spain

      8:    This file is part of SLEPc.

     10:    SLEPc is free software: you can redistribute it and/or modify it under  the
     11:    terms of version 3 of the GNU Lesser General Public License as published by
     12:    the Free Software Foundation.

     14:    SLEPc  is  distributed in the hope that it will be useful, but WITHOUT  ANY
     15:    WARRANTY;  without even the implied warranty of MERCHANTABILITY or  FITNESS
     16:    FOR  A  PARTICULAR PURPOSE. See the GNU Lesser General Public  License  for
     17:    more details.

     19:    You  should have received a copy of the GNU Lesser General  Public  License
     20:    along with SLEPc. If not, see <http://www.gnu.org/licenses/>.
     21:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     22: */

     24: #include <slepc/private/pepimpl.h>       /*I "slepcpep.h" I*/

     28: /*@
     29:    PEPSetUp - Sets up all the internal data structures necessary for the
     30:    execution of the PEP solver.

     32:    Collective on PEP

     34:    Input Parameter:
     35: .  pep   - solver context

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

     42:    Level: developer

     44: .seealso: PEPCreate(), PEPSolve(), PEPDestroy()
     45: @*/
     46: PetscErrorCode PEPSetUp(PEP pep)
     47: {
     49:   SlepcSC        sc;
     50:   PetscBool      islinear,istrivial,flg;
     51:   PetscInt       k;

     55:   if (pep->state) return(0);
     56:   PetscLogEventBegin(PEP_SetUp,pep,0,0,0);

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

     61:   /* set default solver type (PEPSetFromOptions was not called) */
     62:   if (!((PetscObject)pep)->type_name) {
     63:     PEPSetType(pep,PEPTOAR);
     64:   }
     65:   if (!pep->st) { PEPGetST(pep,&pep->st); }
     66:   PetscObjectTypeCompare((PetscObject)pep,PEPLINEAR,&islinear);
     67:   if (!((PetscObject)pep->st)->type_name) {
     68:     STSetType(pep->st,STSHIFT);
     69:   }
     70:   if (!pep->ds) { PEPGetDS(pep,&pep->ds); }
     71:   DSReset(pep->ds);
     72:   if (!pep->rg) { PEPGetRG(pep,&pep->rg); }
     73:   if (!((PetscObject)pep->rg)->type_name) {
     74:     RGSetType(pep->rg,RGINTERVAL);
     75:   }
     76:   if (!((PetscObject)pep->rand)->type_name) {
     77:     PetscRandomSetFromOptions(pep->rand);
     78:   }

     80:   /* check matrices, transfer them to ST */
     81:   if (!pep->A) SETERRQ(PetscObjectComm((PetscObject)pep),PETSC_ERR_ARG_WRONGSTATE,"PEPSetOperators must be called first");
     82:   STSetOperators(pep->st,pep->nmat,pep->A);

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

     88:   /* set default problem type */
     89:   if (!pep->problem_type) {
     90:     PEPSetProblemType(pep,PEP_GENERAL);
     91:   }

     93:   /* call specific solver setup */
     94:   (*pep->ops->setup)(pep);

     96:   /* set tolerance if not yet set */
     97:   if (pep->tol==PETSC_DEFAULT) pep->tol = SLEPC_DEFAULT_TOL;
     98:   if (pep->refine) {
     99:     if (pep->rtol==PETSC_DEFAULT) pep->rtol = pep->tol;
    100:     if (pep->rits==PETSC_DEFAULT) pep->rits = (pep->refine==PEP_REFINE_SIMPLE)? 10: 1;
    101:   }

    103:   /* set default extraction */
    104:   if (!pep->extract) {
    105:     pep->extract = (pep->basis==PEP_BASIS_MONOMIAL)? PEP_EXTRACT_NORM: PEP_EXTRACT_NONE;
    106:   }

    108:   /* fill sorting criterion context */
    109:   switch (pep->which) {
    110:     case PEP_LARGEST_MAGNITUDE:
    111:       pep->sc->comparison    = SlepcCompareLargestMagnitude;
    112:       pep->sc->comparisonctx = NULL;
    113:       break;
    114:     case PEP_SMALLEST_MAGNITUDE:
    115:       pep->sc->comparison    = SlepcCompareSmallestMagnitude;
    116:       pep->sc->comparisonctx = NULL;
    117:       break;
    118:     case PEP_LARGEST_REAL:
    119:       pep->sc->comparison    = SlepcCompareLargestReal;
    120:       pep->sc->comparisonctx = NULL;
    121:       break;
    122:     case PEP_SMALLEST_REAL:
    123:       pep->sc->comparison    = SlepcCompareSmallestReal;
    124:       pep->sc->comparisonctx = NULL;
    125:       break;
    126:     case PEP_LARGEST_IMAGINARY:
    127:       pep->sc->comparison    = SlepcCompareLargestImaginary;
    128:       pep->sc->comparisonctx = NULL;
    129:       break;
    130:     case PEP_SMALLEST_IMAGINARY:
    131:       pep->sc->comparison    = SlepcCompareSmallestImaginary;
    132:       pep->sc->comparisonctx = NULL;
    133:       break;
    134:     case PEP_TARGET_MAGNITUDE:
    135:       pep->sc->comparison    = SlepcCompareTargetMagnitude;
    136:       pep->sc->comparisonctx = &pep->target;
    137:       break;
    138:     case PEP_TARGET_REAL:
    139:       pep->sc->comparison    = SlepcCompareTargetReal;
    140:       pep->sc->comparisonctx = &pep->target;
    141:       break;
    142:     case PEP_TARGET_IMAGINARY:
    143:       pep->sc->comparison    = SlepcCompareTargetImaginary;
    144:       pep->sc->comparisonctx = &pep->target;
    145:       break;
    146:     case PEP_WHICH_USER:
    147:       break;
    148:   }
    149:   pep->sc->map    = NULL;
    150:   pep->sc->mapobj = NULL;

    152:   /* fill sorting criterion for DS */
    153:   DSGetSlepcSC(pep->ds,&sc);
    154:   RGIsTrivial(pep->rg,&istrivial);
    155:   sc->rg            = istrivial? NULL: pep->rg;
    156:   sc->comparison    = pep->sc->comparison;
    157:   sc->comparisonctx = pep->sc->comparisonctx;
    158:   sc->map           = SlepcMap_ST;
    159:   sc->mapobj        = (PetscObject)pep->st;

    161:   /* setup ST */
    162:   PetscObjectTypeCompareAny((PetscObject)pep->st,&flg,STSHIFT,STSINVERT,"");
    163:   if (!flg) SETERRQ(PetscObjectComm((PetscObject)pep),PETSC_ERR_SUP,"Only STSHIFT and STSINVERT spectral transformations can be used in PEP");
    164:   STSetUp(pep->st);
    165:   /* compute matrix coefficients */
    166:   STGetTransform(pep->st,&flg);
    167:   if (!flg) {
    168:     if (pep->solvematcoeffs) { STMatSetUp(pep->st,1.0,pep->solvematcoeffs); }
    169:   } else {
    170:     if (pep->basis!=PEP_BASIS_MONOMIAL) SETERRQ(PetscObjectComm((PetscObject)pep),PETSC_ERR_SUP,"Cannot use ST-transform with non-monomial basis in PEP");
    171:   }

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

    176:   /* build balancing matrix if required */
    177:   if (pep->scale==PEP_SCALE_DIAGONAL || pep->scale==PEP_SCALE_BOTH) {
    178:     if (!pep->Dl) {
    179:       BVCreateVec(pep->V,&pep->Dl);
    180:       PetscLogObjectParent((PetscObject)pep,(PetscObject)pep->Dl);
    181:     }
    182:     if (!pep->Dr) {
    183:       BVCreateVec(pep->V,&pep->Dr);
    184:       PetscLogObjectParent((PetscObject)pep,(PetscObject)pep->Dr);
    185:     }
    186:     PEPBuildDiagonalScaling(pep);
    187:   }

    189:   if (pep->conv==PEP_CONV_LINEAR) {
    190:     PEPComputeLinearNorms(pep);
    191:   }

    193:   /* process initial vectors */
    194:   if (pep->nini<0) {
    195:     k = -pep->nini;
    196:     if (k>pep->ncv) SETERRQ(PetscObjectComm((PetscObject)pep),1,"The number of initial vectors is larger than ncv");
    197:     BVInsertVecs(pep->V,0,&k,pep->IS,PETSC_TRUE);
    198:     SlepcBasisDestroy_Private(&pep->nini,&pep->IS);
    199:     pep->nini = k;
    200:   }
    201:   PetscLogEventEnd(PEP_SetUp,pep,0,0,0);
    202:   pep->state = PEP_STATE_SETUP;
    203:   return(0);
    204: }

    208: /*@
    209:    PEPSetOperators - Sets the coefficient matrices associated with the polynomial
    210:    eigenvalue problem.

    212:    Collective on PEP and Mat

    214:    Input Parameters:
    215: +  pep  - the eigenproblem solver context
    216: .  nmat - number of matrices in array A
    217: -  A    - the array of matrices associated with the eigenproblem

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

    225:    Level: beginner

    227: .seealso: PEPSolve(), PEPGetOperators(), PEPGetNumMatrices(), PEPSetBasis()
    228: @*/
    229: PetscErrorCode PEPSetOperators(PEP pep,PetscInt nmat,Mat A[])
    230: {
    232:   PetscInt       i,n,m,m0=0;

    237:   if (nmat <= 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Non-positive value of nmat: %D",nmat);
    238:   if (nmat <= 2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Cannot solve linear eigenproblems with PEP; use EPS instead");

    241:   if (pep->state) { PEPReset(pep); }
    242:   PetscMalloc1(nmat,&pep->A);
    243:   PetscCalloc2(3*nmat,&pep->pbc,nmat,&pep->nrma);
    244:   for (i=0;i<nmat;i++) pep->pbc[i] = 1.0;  /* default to monomial basis */
    245:   PetscLogObjectMemory((PetscObject)pep,nmat*sizeof(Mat)+4*nmat*sizeof(PetscReal)+nmat*sizeof(PetscScalar));
    246:   for (i=0;i<nmat;i++) {
    249:     MatGetSize(A[i],&m,&n);
    250:     if (m!=n) SETERRQ1(PetscObjectComm((PetscObject)pep),PETSC_ERR_ARG_WRONG,"A[%D] is a non-square matrix",i);
    251:     if (!i) m0 = m;
    252:     if (m!=m0) SETERRQ(PetscObjectComm((PetscObject)pep),PETSC_ERR_ARG_INCOMP,"Dimensions of matrices do not match with each other");
    253:     PetscObjectReference((PetscObject)A[i]);
    254:     pep->A[i] = A[i];
    255:   }
    256:   pep->nmat = nmat;
    257:   return(0);
    258: }

    262: /*@
    263:    PEPGetOperators - Gets the matrices associated with the polynomial eigensystem.

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

    267:    Input Parameters:
    268: +  pep - the PEP context
    269: -  k   - the index of the requested matrix (starting in 0)

    271:    Output Parameter:
    272: .  A - the requested matrix

    274:    Level: intermediate

    276: .seealso: PEPSolve(), PEPSetOperators(), PEPGetNumMatrices()
    277: @*/
    278: PetscErrorCode PEPGetOperators(PEP pep,PetscInt k,Mat *A)
    279: {
    283:   if (k<0 || k>=pep->nmat) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"k must be between 0 and %d",pep->nmat-1);
    284:   *A = pep->A[k];
    285:   return(0);
    286: }

    290: /*@
    291:    PEPGetNumMatrices - Returns the number of matrices stored in the PEP.

    293:    Not collective

    295:    Input Parameter:
    296: .  pep - the PEP context

    298:    Output Parameters:
    299: .  nmat - the number of matrices passed in PEPSetOperators()

    301:    Level: intermediate

    303: .seealso: PEPSetOperators()
    304: @*/
    305: PetscErrorCode PEPGetNumMatrices(PEP pep,PetscInt *nmat)
    306: {
    310:   *nmat = pep->nmat;
    311:   return(0);
    312: }

    316: /*@
    317:    PEPSetInitialSpace - Specify a basis of vectors that constitute the initial
    318:    space, that is, the subspace from which the solver starts to iterate.

    320:    Collective on PEP and Vec

    322:    Input Parameter:
    323: +  pep   - the polynomial eigensolver context
    324: .  n     - number of vectors
    325: -  is    - set of basis vectors of the initial space

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

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

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

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

    340:    Level: intermediate
    341: @*/
    342: PetscErrorCode PEPSetInitialSpace(PEP pep,PetscInt n,Vec *is)
    343: {

    349:   if (n<0) SETERRQ(PetscObjectComm((PetscObject)pep),PETSC_ERR_ARG_OUTOFRANGE,"Argument n cannot be negative");
    350:   SlepcBasisReference_Private(n,is,&pep->nini,&pep->IS);
    351:   if (n>0) pep->state = PEP_STATE_INITIAL;
    352:   return(0);
    353: }

    357: /*
    358:   PEPSetDimensions_Default - Set reasonable values for ncv, mpd if not set
    359:   by the user. This is called at setup.
    360:  */
    361: PetscErrorCode PEPSetDimensions_Default(PEP pep,PetscInt nev,PetscInt *ncv,PetscInt *mpd)
    362: {
    364:   PetscBool      krylov;
    365:   PetscInt       dim;

    368:   PetscObjectTypeCompareAny((PetscObject)pep,&krylov,PEPTOAR,PEPQARNOLDI,"");
    369:   dim = krylov?(pep->nmat-1)*pep->n:pep->n;
    370:   if (*ncv) { /* ncv set */
    371:     if (krylov) {
    372:       if (*ncv<nev+1 && !(*ncv==nev && *ncv==dim)) SETERRQ(PetscObjectComm((PetscObject)pep),1,"The value of ncv must be at least nev+1");
    373:     } else {
    374:       if (*ncv<nev) SETERRQ(PetscObjectComm((PetscObject)pep),1,"The value of ncv must be at least nev");
    375:     }
    376:   } else if (*mpd) { /* mpd set */
    377:     *ncv = PetscMin(dim,nev+(*mpd));
    378:   } else { /* neither set: defaults depend on nev being small or large */
    379:     if (nev<500) *ncv = PetscMin(dim,PetscMax(2*nev,nev+15));
    380:     else {
    381:       *mpd = 500;
    382:       *ncv = PetscMin(dim,nev+(*mpd));
    383:     }
    384:   }
    385:   if (!*mpd) *mpd = *ncv;
    386:   return(0);
    387: }

    391: /*@
    392:    PEPAllocateSolution - Allocate memory storage for common variables such
    393:    as eigenvalues and eigenvectors.

    395:    Collective on PEP

    397:    Input Parameters:
    398: +  pep   - eigensolver context
    399: -  extra - number of additional positions, used for methods that require a
    400:            working basis slightly larger than ncv

    402:    Developers Note:
    403:    This is PETSC_EXTERN because it may be required by user plugin PEP
    404:    implementations.

    406:    Level: developer
    407: @*/
    408: PetscErrorCode PEPAllocateSolution(PEP pep,PetscInt extra)
    409: {
    411:   PetscInt       oldsize,newc,requested,requestedbv;
    412:   PetscLogDouble cnt;
    413:   Vec            t;

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

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

    422:   /* allocate space for eigenvalues and friends */
    423:   if (requested != oldsize || !pep->eigr) {
    424:     if (oldsize) {
    425:       PetscFree4(pep->eigr,pep->eigi,pep->errest,pep->perm);
    426:     }
    427:     PetscMalloc4(requested,&pep->eigr,requested,&pep->eigi,requested,&pep->errest,requested,&pep->perm);
    428:     newc = PetscMax(0,requested-oldsize);
    429:     cnt = 2*newc*sizeof(PetscScalar) + newc*sizeof(PetscReal) + newc*sizeof(PetscInt);
    430:     PetscLogObjectMemory((PetscObject)pep,cnt);
    431:   }

    433:   /* allocate V */
    434:   if (!pep->V) { PEPGetBV(pep,&pep->V); }
    435:   if (!oldsize) {
    436:     if (!((PetscObject)(pep->V))->type_name) {
    437:       BVSetType(pep->V,BVSVEC);
    438:     }
    439:     STMatCreateVecs(pep->st,&t,NULL);
    440:     BVSetSizesFromVec(pep->V,t,requestedbv);
    441:     VecDestroy(&t);
    442:   } else {
    443:     BVResize(pep->V,requestedbv,PETSC_FALSE);
    444:   }
    445:   return(0);
    446: }