Date: 2013-09-02T10:07:09+00:00

Actual source code: qepsetup.c

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

      4:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      5:    SLEPc - Scalable Library for Eigenvalue Problem Computations
      6:    Copyright (c) 2002-2013, 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/qepimpl.h>       /*I "slepcqep.h" I*/
     25: #include <slepc-private/ipimpl.h>

     29: /*@
     30:    QEPSetUp - Sets up all the internal data structures necessary for the
     31:    execution of the QEP solver.

     33:    Collective on QEP

     35:    Input Parameter:
     36: .  qep   - solver context

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

     43:    Level: advanced

     45: .seealso: QEPCreate(), QEPSolve(), QEPDestroy()
     46: @*/
     47: PetscErrorCode QEPSetUp(QEP qep)
     48: {
     50:   PetscBool      khas,mhas,islinear,flg;
     51:   PetscReal      knorm,mnorm;
     52:   Mat            mat[3];

     56:   if (qep->setupcalled) return(0);
     57:   PetscLogEventBegin(QEP_SetUp,qep,0,0,0);

     59:   /* reset the convergence flag from the previous solves */
     60:   qep->reason = QEP_CONVERGED_ITERATING;

     62:   /* Set default solver type (QEPSetFromOptions was not called) */
     63:   if (!((PetscObject)qep)->type_name) {
     64:     QEPSetType(qep,QEPLINEAR);
     65:   }
     66:   PetscObjectTypeCompare((PetscObject)qep,QEPLINEAR,&islinear);
     67:   if (!islinear) {
     68:     if (!qep->st) { QEPGetST(qep,&qep->st); }
     69:     if (!((PetscObject)qep->st)->type_name) {
     70:       STSetType(qep->st,STSHIFT);
     71:     }
     72:   }
     73:   if (!qep->ip) { QEPGetIP(qep,&qep->ip); }
     74:   if (!((PetscObject)qep->ip)->type_name) {
     75:     IPSetType_Default(qep->ip);
     76:   }
     77:   if (!qep->ds) { QEPGetDS(qep,&qep->ds); }
     78:   DSReset(qep->ds);
     79:   if (!((PetscObject)qep->rand)->type_name) {
     80:     PetscRandomSetFromOptions(qep->rand);
     81:   }

     83:   /* Check matrices, transfer them to ST */
     84:   if (!qep->M || !qep->C || !qep->K) SETERRQ(PetscObjectComm((PetscObject)qep),PETSC_ERR_ARG_WRONGSTATE,"QEPSetOperators must be called first");
     85:   if (!islinear) {
     86:     mat[0] = qep->K;
     87:     mat[1] = qep->C;
     88:     mat[2] = qep->M;
     89:     STSetOperators(qep->st,3,mat);
     90:   }

     92:   /* Set problem dimensions */
     93:   MatGetSize(qep->M,&qep->n,NULL);
     94:   MatGetLocalSize(qep->M,&qep->nloc,NULL);
     95:   VecDestroy(&qep->t);
     96:   SlepcMatGetVecsTemplate(qep->M,&qep->t,NULL);
     97:   PetscLogObjectParent(qep,qep->t);

     99:   /* Set default problem type */
    100:   if (!qep->problem_type) {
    101:     QEPSetProblemType(qep,QEP_GENERAL);
    102:   }

    104:   /* Compute scaling factor if not set by user */
    105:   if (qep->sfactor==0.0) {
    106:     MatHasOperation(qep->K,MATOP_NORM,&khas);
    107:     MatHasOperation(qep->M,MATOP_NORM,&mhas);
    108:     if (khas && mhas) {
    109:       MatNorm(qep->K,NORM_INFINITY,&knorm);
    110:       MatNorm(qep->M,NORM_INFINITY,&mnorm);
    111:       qep->sfactor = PetscSqrtReal(knorm/mnorm);
    112:     } else qep->sfactor = 1.0;
    113:   }

    115:   /* Call specific solver setup */
    116:   (*qep->ops->setup)(qep);

    118:   /* set tolerance if not yet set */
    119:   if (qep->tol==PETSC_DEFAULT) qep->tol = SLEPC_DEFAULT_TOL;

    121:   /* set eigenvalue comparison */
    122:   switch (qep->which) {
    123:     case QEP_LARGEST_MAGNITUDE:
    124:       qep->comparison    = SlepcCompareLargestMagnitude;
    125:       qep->comparisonctx = NULL;
    126:       break;
    127:     case QEP_SMALLEST_MAGNITUDE:
    128:       qep->comparison    = SlepcCompareSmallestMagnitude;
    129:       qep->comparisonctx = NULL;
    130:       break;
    131:     case QEP_LARGEST_REAL:
    132:       qep->comparison    = SlepcCompareLargestReal;
    133:       qep->comparisonctx = NULL;
    134:       break;
    135:     case QEP_SMALLEST_REAL:
    136:       qep->comparison    = SlepcCompareSmallestReal;
    137:       qep->comparisonctx = NULL;
    138:       break;
    139:     case QEP_LARGEST_IMAGINARY:
    140:       qep->comparison    = SlepcCompareLargestImaginary;
    141:       qep->comparisonctx = NULL;
    142:       break;
    143:     case QEP_SMALLEST_IMAGINARY:
    144:       qep->comparison    = SlepcCompareSmallestImaginary;
    145:       qep->comparisonctx = NULL;
    146:       break;
    147:     case QEP_TARGET_MAGNITUDE:
    148:       qep->comparison    = SlepcCompareTargetMagnitude;
    149:       qep->comparisonctx = &qep->target;
    150:       break;
    151:     case QEP_TARGET_REAL:
    152:       qep->comparison    = SlepcCompareTargetReal;
    153:       qep->comparisonctx = &qep->target;
    154:       break;
    155:     case QEP_TARGET_IMAGINARY:
    156:       qep->comparison    = SlepcCompareTargetImaginary;
    157:       qep->comparisonctx = &qep->target;
    158:       break;
    159:   }

    161:   if (qep->ncv > 2*qep->n) SETERRQ(PetscObjectComm((PetscObject)qep),PETSC_ERR_ARG_OUTOFRANGE,"ncv must be twice the problem size at most");
    162:   if (qep->nev > qep->ncv) SETERRQ(PetscObjectComm((PetscObject)qep),PETSC_ERR_ARG_OUTOFRANGE,"nev bigger than ncv");

    164:   /* Setup ST */
    165:   if (!islinear) {
    166:     PetscObjectTypeCompareAny((PetscObject)qep->st,&flg,STSHIFT,STSINVERT,"");
    167:     if (!flg) SETERRQ(PetscObjectComm((PetscObject)qep),PETSC_ERR_SUP,"Only STSHIFT and STSINVERT spectral transformations can be used in QEP");
    168:     STSetUp(qep->st);
    169:   }

    171:   /* process initial vectors */
    172:   if (qep->nini<0) {
    173:     qep->nini = -qep->nini;
    174:     if (qep->nini>qep->ncv) SETERRQ(PetscObjectComm((PetscObject)qep),1,"The number of initial vectors is larger than ncv");
    175:     IPOrthonormalizeBasis_Private(qep->ip,&qep->nini,&qep->IS,qep->V);
    176:   }
    177:   if (qep->ninil<0) {
    178:     if (!qep->leftvecs) { PetscInfo(qep,"Ignoring initial left vectors\n"); }
    179:     else {
    180:       qep->ninil = -qep->ninil;
    181:       if (qep->ninil>qep->ncv) SETERRQ(PetscObjectComm((PetscObject)qep),1,"The number of initial left vectors is larger than ncv");
    182:       IPOrthonormalizeBasis_Private(qep->ip,&qep->ninil,&qep->ISL,qep->W);
    183:     }
    184:   }
    185:   PetscLogEventEnd(QEP_SetUp,qep,0,0,0);
    186:   qep->setupcalled = 1;
    187:   return(0);
    188: }

    192: /*@
    193:    QEPSetOperators - Sets the matrices associated with the quadratic eigenvalue problem.

    195:    Collective on QEP and Mat

    197:    Input Parameters:
    198: +  qep - the eigenproblem solver context
    199: .  M   - the first coefficient matrix
    200: .  C   - the second coefficient matrix
    201: -  K   - the third coefficient matrix

    203:    Notes:
    204:    The quadratic eigenproblem is defined as (l^2*M + l*C + K)*x = 0, where l is
    205:    the eigenvalue and x is the eigenvector.

    207:    Level: beginner

    209: .seealso: QEPSolve(), QEPGetOperators()
    210: @*/
    211: PetscErrorCode QEPSetOperators(QEP qep,Mat M,Mat C,Mat K)
    212: {
    214:   PetscInt       m,n,m0;

    225:   /* Check for square matrices */
    226:   MatGetSize(M,&m,&n);
    227:   if (m!=n) SETERRQ(PetscObjectComm((PetscObject)qep),PETSC_ERR_ARG_WRONG,"M is a non-square matrix");
    228:   m0=m;
    229:   MatGetSize(C,&m,&n);
    230:   if (m!=n) SETERRQ(PetscObjectComm((PetscObject)qep),PETSC_ERR_ARG_WRONG,"C is a non-square matrix");
    231:   if (m!=m0) SETERRQ(PetscObjectComm((PetscObject)qep),PETSC_ERR_ARG_INCOMP,"Dimensions of M and C do not match");
    232:   MatGetSize(K,&m,&n);
    233:   if (m!=n) SETERRQ(PetscObjectComm((PetscObject)qep),PETSC_ERR_ARG_WRONG,"K is a non-square matrix");
    234:   if (m!=m0) SETERRQ(PetscObjectComm((PetscObject)qep),PETSC_ERR_ARG_INCOMP,"Dimensions of M and K do not match");

    236:   /* Store a copy of the matrices */
    237:   if (qep->setupcalled) { QEPReset(qep); }
    238:   PetscObjectReference((PetscObject)M);
    239:   MatDestroy(&qep->M);
    240:   qep->M = M;
    241:   PetscObjectReference((PetscObject)C);
    242:   MatDestroy(&qep->C);
    243:   qep->C = C;
    244:   PetscObjectReference((PetscObject)K);
    245:   MatDestroy(&qep->K);
    246:   qep->K = K;
    247:   return(0);
    248: }

    252: /*@
    253:    QEPGetOperators - Gets the matrices associated with the quadratic eigensystem.

    255:    Collective on QEP and Mat

    257:    Input Parameter:
    258: .  qep - the QEP context

    260:    Output Parameters:
    261: +  M   - the first coefficient matrix
    262: .  C   - the second coefficient matrix
    263: -  K   - the third coefficient matrix

    265:    Level: intermediate

    267: .seealso: QEPSolve(), QEPSetOperators()
    268: @*/
    269: PetscErrorCode QEPGetOperators(QEP qep,Mat *M,Mat *C,Mat *K)
    270: {
    276:   return(0);
    277: }

    281: /*@
    282:    QEPSetInitialSpace - Specify a basis of vectors that constitute the initial
    283:    space, that is, the subspace from which the solver starts to iterate.

    285:    Collective on QEP and Vec

    287:    Input Parameter:
    288: +  qep   - the quadratic eigensolver context
    289: .  n     - number of vectors
    290: -  is    - set of basis vectors of the initial space

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

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

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

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

    305:    Level: intermediate

    307: .seealso: QEPSetInitialSpaceLeft()
    308: @*/
    309: PetscErrorCode QEPSetInitialSpace(QEP qep,PetscInt n,Vec *is)
    310: {

    316:   if (n<0) SETERRQ(PetscObjectComm((PetscObject)qep),PETSC_ERR_ARG_OUTOFRANGE,"Argument n cannot be negative");
    317:   SlepcBasisReference_Private(n,is,&qep->nini,&qep->IS);
    318:   if (n>0) qep->setupcalled = 0;
    319:   return(0);
    320: }

    324: /*@
    325:    QEPSetInitialSpaceLeft - Specify a basis of vectors that constitute the initial
    326:    left space, that is, the subspace from which the solver starts to iterate for
    327:    building the left subspace (in methods that work with two subspaces).

    329:    Collective on QEP and Vec

    331:    Input Parameter:
    332: +  qep   - the quadratic eigensolver context
    333: .  n     - number of vectors
    334: -  is    - set of basis vectors of the initial left space

    336:    Notes:
    337:    Some solvers start to iterate on a single vector (initial left vector). In that case,
    338:    the other vectors are ignored.

    340:    These vectors do not persist from one QEPSolve() call to the other, so the
    341:    initial left space should be set every time.

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

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

    349:    Level: intermediate

    351: .seealso: QEPSetInitialSpace()
    352: @*/
    353: PetscErrorCode QEPSetInitialSpaceLeft(QEP qep,PetscInt n,Vec *is)
    354: {

    360:   if (n<0) SETERRQ(PetscObjectComm((PetscObject)qep),PETSC_ERR_ARG_OUTOFRANGE,"Argument n cannot be negative");
    361:   SlepcBasisReference_Private(n,is,&qep->ninil,&qep->ISL);
    362:   if (n>0) qep->setupcalled = 0;
    363:   return(0);
    364: }

    368: /*
    369:   QEPAllocateSolution - Allocate memory storage for common variables such
    370:   as eigenvalues and eigenvectors. All vectors in V (and W) share a
    371:   contiguous chunk of memory.
    372: */
    373: PetscErrorCode QEPAllocateSolution(QEP qep)
    374: {
    376:   PetscInt       newc,cnt;

    379:   if (qep->allocated_ncv != qep->ncv) {
    380:     newc = PetscMax(0,qep->ncv-qep->allocated_ncv);
    381:     QEPFreeSolution(qep);
    382:     cnt = 0;
    383:     PetscMalloc(qep->ncv*sizeof(PetscScalar),&qep->eigr);
    384:     PetscMalloc(qep->ncv*sizeof(PetscScalar),&qep->eigi);
    385:     cnt += 2*newc*sizeof(PetscScalar);
    386:     PetscMalloc(qep->ncv*sizeof(PetscReal),&qep->errest);
    387:     PetscMalloc(qep->ncv*sizeof(PetscInt),&qep->perm);
    388:     cnt += 2*newc*sizeof(PetscReal);
    389:     PetscLogObjectMemory(qep,cnt);
    390:     VecDuplicateVecs(qep->t,qep->ncv,&qep->V);
    391:     PetscLogObjectParents(qep,qep->ncv,qep->V);
    392:     qep->allocated_ncv = qep->ncv;
    393:   }
    394:   return(0);
    395: }

    399: /*
    400:   QEPFreeSolution - Free memory storage. This routine is related to
    401:   QEPAllocateSolution().
    402: */
    403: PetscErrorCode QEPFreeSolution(QEP qep)
    404: {

    408:   if (qep->allocated_ncv > 0) {
    409:     PetscFree(qep->eigr);
    410:     PetscFree(qep->eigi);
    411:     PetscFree(qep->errest);
    412:     PetscFree(qep->perm);
    413:     VecDestroyVecs(qep->allocated_ncv,&qep->V);
    414:     qep->allocated_ncv = 0;
    415:   }
    416:   return(0);
    417: }