Date: 2013-09-02T10:06:01+00:00

Actual source code: stsles.c

      1: /*
      2:     The ST (spectral transformation) interface routines related to the
      3:     KSP object associated to it.

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

      9:    This file is part of SLEPc.

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

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

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

     25: #include <slepc-private/stimpl.h>            /*I "slepcst.h" I*/
     26: #include <slepcsys.h>

     30: /*@
     31:    STMatMult - Computes the matrix-vector product y = T[k] x, where T[k] is
     32:    the k-th matrix of the spectral transformation.

     34:    Collective on ST

     36:    Input Parameters:
     37: +  st - the spectral transformation context
     38: .  k  - index of matrix to use
     39: -  x  - the vector to be multiplied

     41:    Output Parameter:
     42: .  y - the result

     44:    Level: developer

     46: .seealso: STMatMultTranspose()
     47: @*/
     48: PetscErrorCode STMatMult(ST st,PetscInt k,Vec x,Vec y)
     49: {

     53:   if (k<0 || k>=PetscMax(2,st->nmat)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"k must be between 0 and %d",st->nmat);
     54:   if (x == y) SETERRQ(PetscObjectComm((PetscObject)st),PETSC_ERR_ARG_IDN,"x and y must be different vectors");

     56:   if (!st->setupcalled) { STSetUp(st); }
     57:   if (!st->T[k]) {
     58:     /* T[k]=NULL means identity matrix */
     59:     VecCopy(x,y);
     60:   } else {
     61:     MatMult(st->T[k],x,y);
     62:   }
     63:   return(0);
     64: }

     68: /*@
     69:    STMatMultTranspose - Computes the matrix-vector product y = T[k]' x, where T[k] is
     70:    the k-th matrix of the spectral transformation.

     72:    Collective on ST

     74:    Input Parameters:
     75: +  st - the spectral transformation context
     76: .  k  - index of matrix to use
     77: -  x  - the vector to be multiplied

     79:    Output Parameter:
     80: .  y - the result

     82:    Level: developer

     84: .seealso: STMatMult()
     85: @*/
     86: PetscErrorCode STMatMultTranspose(ST st,PetscInt k,Vec x,Vec y)
     87: {

     91:   if (k<0 || k>=PetscMax(2,st->nmat)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"k must be between 0 and %d",st->nmat);
     92:   if (x == y) SETERRQ(PetscObjectComm((PetscObject)st),PETSC_ERR_ARG_IDN,"x and y must be different vectors");

     94:   if (!st->setupcalled) { STSetUp(st); }
     95:   if (!st->T[k]) {
     96:     /* T[k]=NULL means identity matrix */
     97:     VecCopy(x,y);
     98:   } else {
     99:     MatMultTranspose(st->T[k],x,y);
    100:   }
    101:   return(0);
    102: }

    106: /*@
    107:    STMatSolve - Solves T[k] x = b, where T[k] is the k-th matrix of
    108:    the spectral transformation, using a KSP object stored internally.

    110:    Collective on ST

    112:    Input Parameters:
    113: +  st - the spectral transformation context
    114: .  k  - index of matrix to use
    115: -  b  - right hand side vector

    117:    Output Parameter:
    118: .  x - computed solution

    120:    Level: developer

    122: .seealso: STMatSolveTranspose()
    123: @*/
    124: PetscErrorCode STMatSolve(ST st,PetscInt k,Vec b,Vec x)
    125: {
    126:   PetscErrorCode     ierr;
    127:   PetscInt           its;
    128:   PetscBool          flg;
    129:   KSPConvergedReason reason;

    132:   if (k<0 || k>=PetscMax(2,st->nmat)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"k must be between 0 and %d",st->nmat);
    133:   if (x == b) SETERRQ(PetscObjectComm((PetscObject)st),PETSC_ERR_ARG_IDN,"x and b must be different vectors");

    135:   if (!st->setupcalled) { STSetUp(st); }
    136:   PetscObjectTypeCompareAny((PetscObject)st,&flg,STFOLD,STPRECOND,STSHELL,"");
    137:   if (!flg && !st->T[k]) {
    138:     /* T[k]=NULL means identity matrix */
    139:     VecCopy(b,x);
    140:     return(0);
    141:   }
    142:   if (!st->ksp) { STGetKSP(st,&st->ksp); }
    143:   if (!flg && k!=st->kspidx) {
    144:     /* change of coefficient matrix; should not happen normally */
    145:     KSPSetOperators(st->ksp,st->T[k],st->T[k],DIFFERENT_NONZERO_PATTERN);
    146:     KSPSetUp(st->ksp);
    147:     st->kspidx = k;
    148:   }
    149:   KSPSolve(st->ksp,b,x);
    150:   KSPGetConvergedReason(st->ksp,&reason);
    151:   if (reason<0) SETERRQ1(PetscObjectComm((PetscObject)st),PETSC_ERR_NOT_CONVERGED,"KSP did not converge (reason=%s)",KSPConvergedReasons[reason]);
    152:   KSPGetIterationNumber(st->ksp,&its);
    153:   st->lineariterations += its;
    154:   PetscInfo1(st,"Linear solve iterations=%D\n",its);
    155:   return(0);
    156: }

    160: /*@
    161:    STMatSolveTranspose - Solves T[k]' x = b, where T[k] is the k-th matrix of
    162:    the spectral transformation, using a KSP object stored internally.

    164:    Collective on ST

    166:    Input Parameters:
    167: .  st - the spectral transformation context
    168: .  b  - right hand side vector

    170:    Output Parameter:
    171: .  x - computed solution

    173:    Level: developer

    175: .seealso: STMatSolve()
    176: @*/
    177: PetscErrorCode STMatSolveTranspose(ST st,PetscInt k,Vec b,Vec x)
    178: {
    179:   PetscErrorCode     ierr;
    180:   PetscInt           its;
    181:   PetscBool          flg;
    182:   KSPConvergedReason reason;

    185:   if (k<0 || k>=PetscMax(2,st->nmat)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"k must be between 0 and %d",st->nmat);
    186:   PetscObjectTypeCompareAny((PetscObject)st,&flg,STFOLD,STPRECOND,STSHELL,"");
    187:   if (x == b) SETERRQ(PetscObjectComm((PetscObject)st),PETSC_ERR_ARG_IDN,"x and b must be different vectors");

    189:   if (!st->setupcalled) { STSetUp(st); }
    190:   if (!flg && !st->T[k]) {
    191:     /* T[k]=NULL means identity matrix */
    192:     VecCopy(b,x);
    193:     return(0);
    194:   }
    195:   if (!st->ksp) { STGetKSP(st,&st->ksp); }
    196:   if (!flg && k!=st->kspidx) {
    197:     /* change of coefficient matrix; should not happen normally */
    198:     KSPSetOperators(st->ksp,st->T[k],st->T[k],DIFFERENT_NONZERO_PATTERN);
    199:     KSPSetUp(st->ksp);
    200:     st->kspidx = k;
    201:   }
    202:   KSPSolveTranspose(st->ksp,b,x);
    203:   KSPGetConvergedReason(st->ksp,&reason);
    204:   if (reason<0) SETERRQ1(PetscObjectComm((PetscObject)st),PETSC_ERR_NOT_CONVERGED,"KSP did not converge (reason=%s)",KSPConvergedReasons[reason]);
    205:   KSPGetIterationNumber(st->ksp,&its);
    206:   st->lineariterations += its;
    207:   PetscInfo1(st,"Linear solve iterations=%D\n",its);
    208:   return(0);
    209: }

    213: /*
    214:    STMatSetHermitian - Sets the Hermitian flag to the ST matrix.

    216:    Input Parameters:
    217: .  st - the spectral transformation context
    218: .  M  - matrix
    219: */
    220: PetscErrorCode STMatSetHermitian(ST st,Mat M)
    221: {
    222: #if defined(PETSC_USE_COMPLEX)
    224:   PetscBool      set,aherm,mherm;
    225:   PetscInt       i;
    226: #endif

    229: #if defined(PETSC_USE_COMPLEX)
    230:   mherm = PETSC_FALSE;
    231:   for (i=0;i<st->nmat;i++) {
    232:     MatIsHermitianKnown(st->A[i],&set,&aherm);
    233:     if (!set) aherm = PETSC_FALSE;
    234:     mherm = (mherm && aherm)? PETSC_TRUE: PETSC_FALSE;
    235:     if (PetscRealPart(st->sigma)==0.0) break;
    236:   }
    237:   mherm = (mherm && PetscImaginaryPart(st->sigma)==0.0)? PETSC_TRUE: PETSC_FALSE;
    238:   MatSetOption(M,MAT_HERMITIAN,mherm);
    239: #endif
    240:   return(0);
    241: }

    245: /*@
    246:    STSetKSP - Sets the KSP object associated with the spectral
    247:    transformation.

    249:    Collective on ST

    251:    Input Parameters:
    252: +  st   - the spectral transformation context
    253: -  ksp  - the linear system context

    255:    Level: advanced

    257: @*/
    258: PetscErrorCode STSetKSP(ST st,KSP ksp)
    259: {

    266:   PetscObjectReference((PetscObject)ksp);
    267:   KSPDestroy(&st->ksp);
    268:   st->ksp = ksp;
    269:   PetscLogObjectParent(st,st->ksp);
    270:   return(0);
    271: }

    275: /*@
    276:    STGetKSP - Gets the KSP object associated with the spectral
    277:    transformation.

    279:    Not Collective

    281:    Input Parameter:
    282: .  st - the spectral transformation context

    284:    Output Parameter:
    285: .  ksp  - the linear system context

    287:    Notes:
    288:    On output, the value of ksp can be NULL if the combination of
    289:    eigenproblem type and selected transformation does not require to
    290:    solve a linear system of equations.

    292:    Level: intermediate

    294: @*/
    295: PetscErrorCode STGetKSP(ST st,KSP* ksp)
    296: {

    302:   if (!st->ksp) {
    303:     KSPCreate(PetscObjectComm((PetscObject)st),&st->ksp);
    304:     KSPSetOptionsPrefix(st->ksp,((PetscObject)st)->prefix);
    305:     KSPAppendOptionsPrefix(st->ksp,"st_");
    306:     PetscObjectIncrementTabLevel((PetscObject)st->ksp,(PetscObject)st,1);
    307:     PetscLogObjectParent(st,st->ksp);
    308:     KSPSetTolerances(st->ksp,SLEPC_DEFAULT_TOL,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);
    309:   }
    310:   *ksp = st->ksp;
    311:   return(0);
    312: }

    316: /*@
    317:    STGetOperationCounters - Gets the total number of operator applications
    318:    and linear solver iterations used by the ST object.

    320:    Not Collective

    322:    Input Parameter:
    323: .  st - the spectral transformation context

    325:    Output Parameter:
    326: +  ops  - number of operator applications
    327: -  lits - number of linear solver iterations

    329:    Notes:
    330:    Any output parameter may be NULL on input if not needed.

    332:    Level: intermediate

    334: .seealso: STResetOperationCounters()
    335: @*/
    336: PetscErrorCode STGetOperationCounters(ST st,PetscInt* ops,PetscInt* lits)
    337: {
    340:   if (ops) *ops = st->applys;
    341:   if (lits) *lits = st->lineariterations;
    342:   return(0);
    343: }

    347: /*@
    348:    STResetOperationCounters - Resets the counters for operator applications,
    349:    inner product operations and total number of linear iterations used by
    350:    the ST object.

    352:    Logically Collective on ST

    354:    Input Parameter:
    355: .  st - the spectral transformation context

    357:    Level: intermediate

    359: .seealso: STGetOperationCounters()
    360: @*/
    361: PetscErrorCode STResetOperationCounters(ST st)
    362: {
    365:   st->lineariterations = 0;
    366:   st->applys = 0;
    367:   return(0);
    368: }

    372: PetscErrorCode STCheckNullSpace_Default(ST st,PetscInt n,const Vec V[])
    373: {
    375:   PetscInt       i,c;
    376:   PetscReal      norm;
    377:   Vec            *T,w;
    378:   Mat            A;
    379:   PC             pc;
    380:   MatNullSpace   nullsp;

    383:   PetscMalloc(n*sizeof(Vec),&T);
    384:   if (!st->ksp) { STGetKSP(st,&st->ksp); }
    385:   KSPGetPC(st->ksp,&pc);
    386:   PCGetOperators(pc,&A,NULL,NULL);
    387:   MatGetVecs(A,NULL,&w);
    388:   c = 0;
    389:   for (i=0;i<n;i++) {
    390:     MatMult(A,V[i],w);
    391:     VecNorm(w,NORM_2,&norm);
    392:     if (norm < 1e-8) {
    393:       PetscInfo2(st,"Vector %D norm=%g\n",i,(double)norm);
    394:       T[c] = V[i];
    395:       c++;
    396:     }
    397:   }
    398:   VecDestroy(&w);
    399:   if (c>0) {
    400:     MatNullSpaceCreate(PetscObjectComm((PetscObject)st),PETSC_FALSE,c,T,&nullsp);
    401:     KSPSetNullSpace(st->ksp,nullsp);
    402:     MatNullSpaceDestroy(&nullsp);
    403:   }
    404:   PetscFree(T);
    405:   return(0);
    406: }

    410: /*@
    411:    STCheckNullSpace - Given a set of vectors, this function tests each of
    412:    them to be a nullspace vector of the coefficient matrix of the associated
    413:    KSP object. All these nullspace vectors are passed to the KSP object.

    415:    Collective on ST

    417:    Input Parameters:
    418: +  st - the spectral transformation context
    419: .  n  - number of vectors
    420: -  V  - vectors to be checked

    422:    Note:
    423:    This function allows to handle singular pencils and to solve some problems
    424:    in which the nullspace is important (see the users guide for details).

    426:    Level: developer

    428: .seealso: EPSSetDeflationSpace()
    429: @*/
    430: PetscErrorCode STCheckNullSpace(ST st,PetscInt n,const Vec V[])
    431: {

    437:   if (n>0 && st->ops->checknullspace) {
    440:     (*st->ops->checknullspace)(st,n,V);
    441:   }
    442:   return(0);
    443: }