Date: 2016-03-29T14:57:12+00:00

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

      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-2015, 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*/

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

     33:    Collective on ST

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

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

     43:    Level: developer

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

     56:   STCheckMatrices(st,1);
     57:   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);
     58:   if (x == y) SETERRQ(PetscObjectComm((PetscObject)st),PETSC_ERR_ARG_IDN,"x and y must be different vectors");
     59:   VecLocked(y,3);

     61:   if (!st->setupcalled) { STSetUp(st); }
     62:   VecLockPush(x);
     63:   PetscLogEventBegin(ST_MatMult,st,x,y,0);
     64:   if (!st->T[k]) {
     65:     /* T[k]=NULL means identity matrix */
     66:     VecCopy(x,y);
     67:   } else {
     68:     MatMult(st->T[k],x,y);
     69:   }
     70:   PetscLogEventEnd(ST_MatMult,st,x,y,0);
     71:   VecLockPop(x);
     72:   return(0);
     73: }

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

     81:    Collective on ST

     83:    Input Parameters:
     84: +  st - the spectral transformation context
     85: .  k  - index of matrix to use
     86: -  x  - the vector to be multiplied

     88:    Output Parameter:
     89: .  y - the result

     91:    Level: developer

     93: .seealso: STMatMult()
     94: @*/
     95: PetscErrorCode STMatMultTranspose(ST st,PetscInt k,Vec x,Vec y)
     96: {

    104:   STCheckMatrices(st,1);
    105:   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);
    106:   if (x == y) SETERRQ(PetscObjectComm((PetscObject)st),PETSC_ERR_ARG_IDN,"x and y must be different vectors");
    107:   VecLocked(y,3);

    109:   if (!st->setupcalled) { STSetUp(st); }
    110:   VecLockPush(x);
    111:   PetscLogEventBegin(ST_MatMultTranspose,st,x,y,0);
    112:   if (!st->T[k]) {
    113:     /* T[k]=NULL means identity matrix */
    114:     VecCopy(x,y);
    115:   } else {
    116:     MatMultTranspose(st->T[k],x,y);
    117:   }
    118:   PetscLogEventEnd(ST_MatMultTranspose,st,x,y,0);
    119:   VecLockPop(x);
    120:   return(0);
    121: }

    125: /*@
    126:    STMatSolve - Solves P x = b, where P is the preconditioner matrix of
    127:    the spectral transformation, using a KSP object stored internally.

    129:    Collective on ST

    131:    Input Parameters:
    132: +  st - the spectral transformation context
    133: -  b  - right hand side vector

    135:    Output Parameter:
    136: .  x - computed solution

    138:    Level: developer

    140: .seealso: STMatSolveTranspose()
    141: @*/
    142: PetscErrorCode STMatSolve(ST st,Vec b,Vec x)
    143: {
    145:   PetscInt       its;
    146:   PetscBool      flg;

    152:   STCheckMatrices(st,1);
    153:   if (x == b) SETERRQ(PetscObjectComm((PetscObject)st),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
    154:   VecLocked(x,3);

    156:   if (!st->setupcalled) { STSetUp(st); }
    157:   VecLockPush(b);
    158:   PetscLogEventBegin(ST_MatSolve,st,b,x,0);
    159:   PetscObjectTypeCompareAny((PetscObject)st,&flg,STPRECOND,STSHELL,"");
    160:   if (!flg && !st->P) {
    161:     /* P=NULL means identity matrix */
    162:     VecCopy(b,x);
    163:     return(0);
    164:   }
    165:   if (!st->ksp) { STGetKSP(st,&st->ksp); }
    166:   KSPSolve(st->ksp,b,x);
    167:   KSPGetIterationNumber(st->ksp,&its);
    168:   PetscInfo1(st,"Linear solve iterations=%D\n",its);
    169:   PetscLogEventEnd(ST_MatSolve,st,b,x,0);
    170:   VecLockPop(b);
    171:   return(0);
    172: }

    176: /*@
    177:    STMatSolveTranspose - Solves P' x = b, where P is the preconditioner matrix of
    178:    the spectral transformation, using a KSP object stored internally.

    180:    Collective on ST

    182:    Input Parameters:
    183: .  st - the spectral transformation context
    184: .  b  - right hand side vector

    186:    Output Parameter:
    187: .  x - computed solution

    189:    Level: developer

    191: .seealso: STMatSolve()
    192: @*/
    193: PetscErrorCode STMatSolveTranspose(ST st,Vec b,Vec x)
    194: {
    196:   PetscInt       its;
    197:   PetscBool      flg;

    203:   STCheckMatrices(st,1);
    204:   if (x == b) SETERRQ(PetscObjectComm((PetscObject)st),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
    205:   VecLocked(x,3);

    207:   if (!st->setupcalled) { STSetUp(st); }
    208:   VecLockPush(b);
    209:   PetscLogEventBegin(ST_MatSolveTranspose,st,b,x,0);
    210:   PetscObjectTypeCompareAny((PetscObject)st,&flg,STPRECOND,STSHELL,"");
    211:   if (!flg && !st->P) {
    212:     /* P=NULL means identity matrix */
    213:     VecCopy(b,x);
    214:     return(0);
    215:   }
    216:   if (!st->ksp) { STGetKSP(st,&st->ksp); }
    217:   KSPSolveTranspose(st->ksp,b,x);
    218:   KSPGetIterationNumber(st->ksp,&its);
    219:   PetscInfo1(st,"Linear solve iterations=%D\n",its);
    220:   PetscLogEventEnd(ST_MatSolveTranspose,st,b,x,0);
    221:   VecLockPop(b);
    222:   return(0);
    223: }

    227: /*
    228:    STMatSetHermitian - Sets the Hermitian flag to the ST matrix.

    230:    Input Parameters:
    231: .  st - the spectral transformation context
    232: .  M  - matrix
    233: */
    234: PetscErrorCode STMatSetHermitian(ST st,Mat M)
    235: {
    236: #if defined(PETSC_USE_COMPLEX)
    238:   PetscBool      set,aherm,mherm;
    239:   PetscInt       i;
    240: #endif

    243: #if defined(PETSC_USE_COMPLEX)
    244:   mherm = PETSC_FALSE;
    245:   for (i=0;i<st->nmat;i++) {
    246:     MatIsHermitianKnown(st->A[i],&set,&aherm);
    247:     if (!set) aherm = PETSC_FALSE;
    248:     mherm = (mherm && aherm)? PETSC_TRUE: PETSC_FALSE;
    249:     if (PetscRealPart(st->sigma)==0.0) break;
    250:   }
    251:   mherm = (mherm && PetscImaginaryPart(st->sigma)==0.0)? PETSC_TRUE: PETSC_FALSE;
    252:   MatSetOption(M,MAT_HERMITIAN,mherm);
    253: #endif
    254:   return(0);
    255: }

    259: PetscErrorCode STCheckFactorPackage(ST st)
    260: {
    261:   PetscErrorCode         ierr;
    262:   PC                     pc;
    263:   PetscMPIInt            size;
    264:   PetscBool              flg;
    265:   const MatSolverPackage stype;

    268:   MPI_Comm_size(PetscObjectComm((PetscObject)st),&size);
    269:   if (size==1) return(0);
    270:   KSPGetPC(st->ksp,&pc);
    271:   PCFactorGetMatSolverPackage(pc,&stype);
    272:   if (stype) {   /* currently selected PC is a factorization */
    273:     PetscStrcmp(stype,MATSOLVERPETSC,&flg);
    274:     if (flg) SETERRQ(PetscObjectComm((PetscObject)st),PETSC_ERR_SUP,"You chose to solve linear systems with a factorization, but in parallel runs you need to select an external package; see the users guide for details");
    275:   }
    276:   return(0);
    277: }

    281: /*@
    282:    STSetKSP - Sets the KSP object associated with the spectral
    283:    transformation.

    285:    Collective on ST

    287:    Input Parameters:
    288: +  st   - the spectral transformation context
    289: -  ksp  - the linear system context

    291:    Level: advanced

    293: @*/
    294: PetscErrorCode STSetKSP(ST st,KSP ksp)
    295: {

    302:   PetscObjectReference((PetscObject)ksp);
    303:   KSPDestroy(&st->ksp);
    304:   st->ksp = ksp;
    305:   PetscLogObjectParent((PetscObject)st,(PetscObject)st->ksp);
    306:   return(0);
    307: }

    311: /*@
    312:    STGetKSP - Gets the KSP object associated with the spectral
    313:    transformation.

    315:    Not Collective

    317:    Input Parameter:
    318: .  st - the spectral transformation context

    320:    Output Parameter:
    321: .  ksp  - the linear system context

    323:    Notes:
    324:    On output, the value of ksp can be NULL if the combination of
    325:    eigenproblem type and selected transformation does not require to
    326:    solve a linear system of equations.

    328:    Level: intermediate

    330: @*/
    331: PetscErrorCode STGetKSP(ST st,KSP* ksp)
    332: {

    338:   if (!st->ksp) {
    339:     KSPCreate(PetscObjectComm((PetscObject)st),&st->ksp);
    340:     KSPSetOptionsPrefix(st->ksp,((PetscObject)st)->prefix);
    341:     KSPAppendOptionsPrefix(st->ksp,"st_");
    342:     PetscObjectIncrementTabLevel((PetscObject)st->ksp,(PetscObject)st,1);
    343:     PetscLogObjectParent((PetscObject)st,(PetscObject)st->ksp);
    344:     KSPSetTolerances(st->ksp,SLEPC_DEFAULT_TOL,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);
    345:   }
    346:   *ksp = st->ksp;
    347:   return(0);
    348: }

    352: PetscErrorCode STCheckNullSpace_Default(ST st,BV V)
    353: {
    355:   PetscInt       nc,i,c;
    356:   PetscReal      norm;
    357:   Vec            *T,w,vi;
    358:   Mat            A;
    359:   PC             pc;
    360:   MatNullSpace   nullsp;

    363:   BVGetNumConstraints(V,&nc);
    364:   PetscMalloc1(nc,&T);
    365:   if (!st->ksp) { STGetKSP(st,&st->ksp); }
    366:   KSPGetPC(st->ksp,&pc);
    367:   PCGetOperators(pc,&A,NULL);
    368:   MatCreateVecs(A,NULL,&w);
    369:   c = 0;
    370:   for (i=0;i<nc;i++) {
    371:     BVGetColumn(V,-nc+i,&vi);
    372:     MatMult(A,vi,w);
    373:     VecNorm(w,NORM_2,&norm);
    374:     if (norm < 1e-8) {
    375:       PetscInfo2(st,"Vector %D norm=%g\n",i,(double)norm);
    376:       BVCreateVec(V,T+c);
    377:       VecCopy(vi,T[c]);
    378:       c++;
    379:     }
    380:     BVRestoreColumn(V,-nc+i,&vi);
    381:   }
    382:   VecDestroy(&w);
    383:   if (c>0) {
    384:     MatNullSpaceCreate(PetscObjectComm((PetscObject)st),PETSC_FALSE,c,T,&nullsp);
    385:     MatSetNullSpace(A,nullsp);
    386:     MatNullSpaceDestroy(&nullsp);
    387:     VecDestroyVecs(c,&T);
    388:   } else {
    389:     PetscFree(T);
    390:   }
    391:   return(0);
    392: }

    396: /*@
    397:    STCheckNullSpace - Given a basis vectors object, this function tests each
    398:    of its constraint vectors to be a nullspace vector of the coefficient
    399:    matrix of the associated KSP object. All these nullspace vectors are passed
    400:    to the KSP object.

    402:    Collective on ST

    404:    Input Parameters:
    405: +  st - the spectral transformation context
    406: -  V  - basis vectors to be checked

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

    412:    Level: developer

    414: .seealso: EPSSetDeflationSpace()
    415: @*/
    416: PetscErrorCode STCheckNullSpace(ST st,BV V)
    417: {
    419:   PetscInt       nc;

    427:   BVGetNumConstraints(V,&nc);
    428:   if (nc && st->ops->checknullspace) {
    429:     (*st->ops->checknullspace)(st,V);
    430:   }
    431:   return(0);
    432: }