Date: 2013-09-02T10:05:53+00:00

Actual source code: stfunc.c

      1: /*
      2:     The ST (spectral transformation) interface routines, callable by users.

      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/stimpl.h>            /*I "slepcst.h" I*/

     26: PetscClassId     ST_CLASSID = 0;
     27: PetscLogEvent    ST_SetUp = 0,ST_Apply = 0,ST_ApplyTranspose = 0;
     28: static PetscBool STPackageInitialized = PETSC_FALSE;

     32: /*@C
     33:    STFinalizePackage - This function destroys everything in the Slepc interface
     34:    to the ST package. It is called from SlepcFinalize().

     36:    Level: developer

     38: .seealso: SlepcFinalize()
     39: @*/
     40: PetscErrorCode STFinalizePackage(void)
     41: {

     45:   PetscFunctionListDestroy(&STList);
     46:   STPackageInitialized = PETSC_FALSE;
     47:   STRegisterAllCalled  = PETSC_FALSE;
     48:   return(0);
     49: }

     53: /*@C
     54:    STInitializePackage - This function initializes everything in the ST package. It is called
     55:    from PetscDLLibraryRegister() when using dynamic libraries, and on the first call to STCreate()
     56:    when using static libraries.

     58:    Level: developer

     60: .seealso: SlepcInitialize()
     61: @*/
     62: PetscErrorCode STInitializePackage(void)
     63: {
     64:   char           logList[256];
     65:   char           *className;
     66:   PetscBool      opt;

     70:   if (STPackageInitialized) return(0);
     71:   STPackageInitialized = PETSC_TRUE;
     72:   /* Register Classes */
     73:   PetscClassIdRegister("Spectral Transform",&ST_CLASSID);
     74:   /* Register Constructors */
     75:   STRegisterAll();
     76:   /* Register Events */
     77:   PetscLogEventRegister("STSetUp",ST_CLASSID,&ST_SetUp);
     78:   PetscLogEventRegister("STApply",ST_CLASSID,&ST_Apply);
     79:   PetscLogEventRegister("STApplyTranspose",ST_CLASSID,&ST_ApplyTranspose);
     80:   /* Process info exclusions */
     81:   PetscOptionsGetString(NULL,"-info_exclude",logList,256,&opt);
     82:   if (opt) {
     83:     PetscStrstr(logList,"st",&className);
     84:     if (className) {
     85:       PetscInfoDeactivateClass(ST_CLASSID);
     86:     }
     87:   }
     88:   /* Process summary exclusions */
     89:   PetscOptionsGetString(NULL,"-log_summary_exclude",logList,256,&opt);
     90:   if (opt) {
     91:     PetscStrstr(logList,"st",&className);
     92:     if (className) {
     93:       PetscLogEventDeactivateClass(ST_CLASSID);
     94:     }
     95:   }
     96:   PetscRegisterFinalize(STFinalizePackage);
     97:   return(0);
     98: }

    102: /*@
    103:    STReset - Resets the ST context and removes any allocated objects.

    105:    Collective on ST

    107:    Input Parameter:
    108: .  st - the spectral transformation context

    110:    Level: advanced

    112: .seealso: STDestroy()
    113: @*/
    114: PetscErrorCode STReset(ST st)
    115: {

    120:   if (st->ops->reset) { (*st->ops->reset)(st); }
    121:   if (st->ksp) { KSPReset(st->ksp); }
    122:   MatDestroyMatrices(PetscMax(2,st->nmat),&st->T);
    123:   VecDestroy(&st->w);
    124:   VecDestroy(&st->wb);
    125:   STResetOperationCounters(st);
    126:   st->kspidx = -1;
    127:   st->setupcalled = 0;
    128:   return(0);
    129: }

    133: /*@C
    134:    STDestroy - Destroys ST context that was created with STCreate().

    136:    Collective on ST

    138:    Input Parameter:
    139: .  st - the spectral transformation context

    141:    Level: beginner

    143: .seealso: STCreate(), STSetUp()
    144: @*/
    145: PetscErrorCode STDestroy(ST *st)
    146: {

    150:   if (!*st) return(0);
    152:   if (--((PetscObject)(*st))->refct > 0) { *st = 0; return(0); }
    153:   STReset(*st);
    154:   MatDestroyMatrices(PetscMax(2,(*st)->nmat),&(*st)->A);
    155:   PetscFree((*st)->Astate);
    156:   if ((*st)->ops->destroy) { (*(*st)->ops->destroy)(*st); }
    157:   VecDestroy(&(*st)->D);
    158:   KSPDestroy(&(*st)->ksp);
    159:   PetscHeaderDestroy(st);
    160:   return(0);
    161: }

    165: /*@C
    166:    STCreate - Creates a spectral transformation context.

    168:    Collective on MPI_Comm

    170:    Input Parameter:
    171: .  comm - MPI communicator

    173:    Output Parameter:
    174: .  st - location to put the spectral transformation context

    176:    Level: beginner

    178: .seealso: STSetUp(), STApply(), STDestroy(), ST
    179: @*/
    180: PetscErrorCode STCreate(MPI_Comm comm,ST *newst)
    181: {
    183:   ST             st;

    187:   *newst = 0;
    188: #if !defined(PETSC_USE_DYNAMIC_LIBRARIES)
    189:   STInitializePackage();
    190: #endif

    192:   SlepcHeaderCreate(st,_p_ST,struct _STOps,ST_CLASSID,"ST","Spectral Transformation","ST",comm,STDestroy,STView);

    194:   st->A            = 0;
    195:   st->Astate       = 0;
    196:   st->T            = 0;
    197:   st->nmat         = 0;
    198:   st->sigma        = 0.0;
    199:   st->sigma_set    = PETSC_FALSE;
    200:   st->defsigma     = 0.0;
    201:   st->data         = 0;
    202:   st->setupcalled  = 0;
    203:   st->ksp          = 0;
    204:   st->kspidx       = -1;
    205:   st->w            = 0;
    206:   st->D            = 0;
    207:   st->wb           = 0;
    208:   st->shift_matrix = ST_MATMODE_COPY;
    209:   st->str          = DIFFERENT_NONZERO_PATTERN;

    211:   *newst = st;
    212:   return(0);
    213: }

    217: /*@
    218:    STSetOperators - Sets the matrices associated with the eigenvalue problem.

    220:    Collective on ST and Mat

    222:    Input Parameters:
    223: +  st - the spectral transformation context
    224: .  n  - number of matrices in array A
    225: -  A  - the array of matrices associated with the eigensystem

    227:    Notes:
    228:    It must be called before STSetUp(). If it is called again after STSetUp() then
    229:    the ST object is reset.

    231:    Level: intermediate

    233: .seealso: STGetOperators(), STGetNumMatrices(), STSetUp(), STReset()
    234:  @*/
    235: PetscErrorCode STSetOperators(ST st,PetscInt n,Mat A[])
    236: {
    237:   PetscInt       i;

    243:   if (n <= 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Must have one or more matrices, you have %D",n);
    246:   if (st->setupcalled) { STReset(st); }
    247:   MatDestroyMatrices(PetscMax(2,st->nmat),&st->A);
    248:   PetscMalloc(PetscMax(2,n)*sizeof(Mat),&st->A);
    249:   PetscLogObjectMemory(st,PetscMax(2,n)*sizeof(Mat));
    250:   PetscFree(st->Astate);
    251:   PetscMalloc(PetscMax(2,n)*sizeof(PetscInt),&st->Astate);
    252:   PetscLogObjectMemory(st,PetscMax(2,n)*sizeof(PetscInt));
    253:   for (i=0;i<n;i++) {
    255:     PetscObjectReference((PetscObject)A[i]);
    256:     st->A[i] = A[i];
    257:     st->Astate[i] = ((PetscObject)A[i])->state;
    258:   }
    259:   if (n==1) {
    260:     st->A[1] = NULL;
    261:     st->Astate[1] = 0;
    262:   }
    263:   st->nmat = n;
    264:   return(0);
    265: }

    269: /*@
    270:    STGetOperators - Gets the matrices associated with the original eigensystem.

    272:    Not collective, though parallel Mats are returned if the ST is parallel

    274:    Input Parameter:
    275: +  st - the spectral transformation context
    276: -  k  - the index of the requested matrix (starting in 0)

    278:    Output Parameters:
    279: .  A - the requested matrix

    281:    Level: intermediate

    283: .seealso: STSetOperators(), STGetNumMatrices()
    284: @*/
    285: PetscErrorCode STGetOperators(ST st,PetscInt k,Mat *A)
    286: {
    290:   if (k<0 || k>=st->nmat) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"k must be between 0 and %d",st->nmat-1);
    291:   if (((PetscObject)st->A[k])->state!=st->Astate[k]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot retrieve original matrices (have been modified)");
    292:   *A = st->A[k];
    293:   return(0);
    294: }

    298: /*@
    299:    STGetNumMatrices - Returns the number of matrices stored in the ST.

    301:    Not collective

    303:    Input Parameter:
    304: .  st - the spectral transformation context

    306:    Output Parameters:
    307: .  n - the number of matrices passed in STSetOperators()

    309:    Level: intermediate

    311: .seealso: STSetOperators()
    312: @*/
    313: PetscErrorCode STGetNumMatrices(ST st,PetscInt *n)
    314: {
    318:   *n = st->nmat;
    319:   return(0);
    320: }

    324: /*@
    325:    STSetShift - Sets the shift associated with the spectral transformation.

    327:    Logically Collective on ST

    329:    Input Parameters:
    330: +  st - the spectral transformation context
    331: -  shift - the value of the shift

    333:    Note:
    334:    In some spectral transformations, changing the shift may have associated
    335:    a lot of work, for example recomputing a factorization.

    337:    Level: beginner

    339: @*/
    340: PetscErrorCode STSetShift(ST st,PetscScalar shift)
    341: {

    347:   if (st->sigma != shift) {
    348:     if (st->ops->setshift) {
    349:       (*st->ops->setshift)(st,shift);
    350:     }
    351:   }
    352:   st->sigma = shift;
    353:   st->sigma_set = PETSC_TRUE;
    354:   return(0);
    355: }

    359: /*@
    360:    STGetShift - Gets the shift associated with the spectral transformation.

    362:    Not Collective

    364:    Input Parameter:
    365: .  st - the spectral transformation context

    367:    Output Parameter:
    368: .  shift - the value of the shift

    370:    Level: beginner

    372: @*/
    373: PetscErrorCode STGetShift(ST st,PetscScalar* shift)
    374: {
    378:   *shift = st->sigma;
    379:   return(0);
    380: }

    384: /*@
    385:    STSetDefaultShift - Sets the value of the shift that should be employed if
    386:    the user did not specify one.

    388:    Logically Collective on ST

    390:    Input Parameters:
    391: +  st - the spectral transformation context
    392: -  defaultshift - the default value of the shift

    394:    Level: developer

    396: @*/
    397: PetscErrorCode STSetDefaultShift(ST st,PetscScalar defaultshift)
    398: {
    402:   st->defsigma = defaultshift;
    403:   return(0);
    404: }

    408: /*@
    409:    STSetBalanceMatrix - Sets the diagonal matrix to be used for balancing.

    411:    Collective on ST and Vec

    413:    Input Parameters:
    414: +  st - the spectral transformation context
    415: -  D  - the diagonal matrix (represented as a vector)

    417:    Notes:
    418:    If this matrix is set, STApply will effectively apply D*OP*D^{-1}.

    420:    Balancing is usually set via EPSSetBalance, but the advanced user may use
    421:    this function to bypass the usual balancing methods.

    423:    Level: developer

    425: .seealso: EPSSetBalance(), STApply(), STGetBalanceMatrix()
    426: @*/
    427: PetscErrorCode STSetBalanceMatrix(ST st,Vec D)
    428: {

    435:   PetscObjectReference((PetscObject)D);
    436:   VecDestroy(&st->D);
    437:   st->D = D;
    438:   st->setupcalled = 0;
    439:   return(0);
    440: }

    444: /*@
    445:    STGetBalanceMatrix - Gets the balance matrix used by the spectral transformation.

    447:    Not collective, but vector is shared by all processors that share the ST

    449:    Input Parameter:
    450: .  st - the spectral transformation context

    452:    Output Parameter:
    453: .  D  - the diagonal matrix (represented as a vector)

    455:    Note:
    456:    If the matrix was not set, a null pointer will be returned.

    458:    Level: developer

    460: .seealso: STSetBalanceMatrix()
    461: @*/
    462: PetscErrorCode STGetBalanceMatrix(ST st,Vec *D)
    463: {
    467:   *D = st->D;
    468:   return(0);
    469: }

    473: /*@C
    474:    STSetOptionsPrefix - Sets the prefix used for searching for all
    475:    ST options in the database.

    477:    Logically Collective on ST

    479:    Input Parameters:
    480: +  st     - the spectral transformation context
    481: -  prefix - the prefix string to prepend to all ST option requests

    483:    Notes:
    484:    A hyphen (-) must NOT be given at the beginning of the prefix name.
    485:    The first character of all runtime options is AUTOMATICALLY the
    486:    hyphen.

    488:    Level: advanced

    490: .seealso: STAppendOptionsPrefix(), STGetOptionsPrefix()
    491: @*/
    492: PetscErrorCode STSetOptionsPrefix(ST st,const char *prefix)
    493: {

    498:   if (!st->ksp) { STGetKSP(st,&st->ksp); }
    499:   KSPSetOptionsPrefix(st->ksp,prefix);
    500:   KSPAppendOptionsPrefix(st->ksp,"st_");
    501:   PetscObjectSetOptionsPrefix((PetscObject)st,prefix);
    502:   return(0);
    503: }

    507: /*@C
    508:    STAppendOptionsPrefix - Appends to the prefix used for searching for all
    509:    ST options in the database.

    511:    Logically Collective on ST

    513:    Input Parameters:
    514: +  st     - the spectral transformation context
    515: -  prefix - the prefix string to prepend to all ST option requests

    517:    Notes:
    518:    A hyphen (-) must NOT be given at the beginning of the prefix name.
    519:    The first character of all runtime options is AUTOMATICALLY the
    520:    hyphen.

    522:    Level: advanced

    524: .seealso: STSetOptionsPrefix(), STGetOptionsPrefix()
    525: @*/
    526: PetscErrorCode STAppendOptionsPrefix(ST st,const char *prefix)
    527: {

    532:   PetscObjectAppendOptionsPrefix((PetscObject)st,prefix);
    533:   if (!st->ksp) { STGetKSP(st,&st->ksp); }
    534:   KSPSetOptionsPrefix(st->ksp,((PetscObject)st)->prefix);
    535:   KSPAppendOptionsPrefix(st->ksp,"st_");
    536:   return(0);
    537: }

    541: /*@C
    542:    STGetOptionsPrefix - Gets the prefix used for searching for all
    543:    ST options in the database.

    545:    Not Collective

    547:    Input Parameters:
    548: .  st - the spectral transformation context

    550:    Output Parameters:
    551: .  prefix - pointer to the prefix string used, is returned

    553:    Notes: On the Fortran side, the user should pass in a string 'prefix' of
    554:    sufficient length to hold the prefix.

    556:    Level: advanced

    558: .seealso: STSetOptionsPrefix(), STAppendOptionsPrefix()
    559: @*/
    560: PetscErrorCode STGetOptionsPrefix(ST st,const char *prefix[])
    561: {

    567:   PetscObjectGetOptionsPrefix((PetscObject)st,prefix);
    568:   return(0);
    569: }

    573: /*@C
    574:    STView - Prints the ST data structure.

    576:    Collective on ST

    578:    Input Parameters:
    579: +  st - the ST context
    580: -  viewer - optional visualization context

    582:    Note:
    583:    The available visualization contexts include
    584: +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
    585: -     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
    586:          output where only the first processor opens
    587:          the file.  All other processors send their
    588:          data to the first processor to print.

    590:    The user can open an alternative visualization contexts with
    591:    PetscViewerASCIIOpen() (output to a specified file).

    593:    Level: beginner

    595: .seealso: EPSView(), PetscViewerASCIIOpen()
    596: @*/
    597: PetscErrorCode STView(ST st,PetscViewer viewer)
    598: {
    600:   STType         cstr;
    601:   const char*    pat;
    602:   char           str[50];
    603:   PetscBool      isascii,isstring,flg;

    607:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)st));

    611:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
    612:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring);
    613:   if (isascii) {
    614:     PetscObjectPrintClassNamePrefixType((PetscObject)st,viewer,"ST Object");
    615:     if (st->ops->view) {
    616:       PetscViewerASCIIPushTab(viewer);
    617:       (*st->ops->view)(st,viewer);
    618:       PetscViewerASCIIPopTab(viewer);
    619:     }
    620:     SlepcSNPrintfScalar(str,50,st->sigma,PETSC_FALSE);
    621:     PetscViewerASCIIPrintf(viewer,"  shift: %s\n",str);
    622:     PetscViewerASCIIPrintf(viewer,"  number of matrices: %D\n",st->nmat);
    623:     switch (st->shift_matrix) {
    624:     case ST_MATMODE_COPY:
    625:       break;
    626:     case ST_MATMODE_INPLACE:
    627:       PetscViewerASCIIPrintf(viewer,"  shifting the matrix and unshifting at exit\n");
    628:       break;
    629:     case ST_MATMODE_SHELL:
    630:       PetscViewerASCIIPrintf(viewer,"  using a shell matrix\n");
    631:       break;
    632:     }
    633:     if (st->nmat>1 && st->shift_matrix != ST_MATMODE_SHELL) {
    634:       switch (st->str) {
    635:         case SAME_NONZERO_PATTERN:      pat = "same nonzero pattern";break;
    636:         case DIFFERENT_NONZERO_PATTERN: pat = "different nonzero pattern";break;
    637:         case SUBSET_NONZERO_PATTERN:    pat = "subset nonzero pattern";break;
    638:         default: SETERRQ(PetscObjectComm((PetscObject)st),1,"Wrong structure flag");
    639:       }
    640:       PetscViewerASCIIPrintf(viewer,"  all matrices have %s\n",pat);
    641:     }
    642:   } else if (isstring) {
    643:     STGetType(st,&cstr);
    644:     PetscViewerStringSPrintf(viewer," %-7.7s",cstr);
    645:     if (st->ops->view) { (*st->ops->view)(st,viewer); }
    646:   }
    647:   PetscObjectTypeCompareAny((PetscObject)st,&flg,STSHIFT,STFOLD,"");
    648:   if (st->nmat>1 || !flg) {
    649:     if (!st->ksp) { STGetKSP(st,&st->ksp); }
    650:     PetscViewerASCIIPushTab(viewer);
    651:     KSPView(st->ksp,viewer);
    652:     PetscViewerASCIIPopTab(viewer);
    653:   }
    654:   return(0);
    655: }

    659: /*@C
    660:    STRegister - Adds a method to the spectral transformation package.

    662:    Not collective

    664:    Input Parameters:
    665: +  name - name of a new user-defined transformation
    666: -  function - routine to create method context

    668:    Notes:
    669:    STRegister() may be called multiple times to add several user-defined
    670:    spectral transformations.

    672:    Sample usage:
    673: .vb
    674:    STRegister("my_solver",MySolverCreate);
    675: .ve

    677:    Then, your solver can be chosen with the procedural interface via
    678: $     STSetType(st,"my_solver")
    679:    or at runtime via the option
    680: $     -st_type my_solver

    682:    Level: advanced

    684: .seealso: STRegisterAll()
    685: @*/
    686: PetscErrorCode STRegister(const char *name,PetscErrorCode (*function)(ST))
    687: {

    691:   PetscFunctionListAdd(&STList,name,function);
    692:   return(0);
    693: }