Actual source code: stfunc.c
slepc-3.10.1 2018-10-23
Report Typos and Errors

      1: /*
      2:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      3:    SLEPc - Scalable Library for Eigenvalue Problem Computations
      4:    Copyright (c) 2002-2018, Universitat Politecnica de Valencia, Spain

      6:    This file is part of SLEPc.
      7:    SLEPc is distributed under a 2-clause BSD license (see LICENSE).
      8:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      9: */
     10: /*
     11:    The ST interface routines, callable by users
     12: */

     14: #include <slepc/private/stimpl.h>            /*I "slepcst.h" I*/

     16: PetscClassId     ST_CLASSID = 0;
     17: PetscLogEvent    ST_SetUp = 0,ST_Apply = 0,ST_ApplyTranspose = 0,ST_MatSetUp = 0,ST_MatMult = 0,ST_MatMultTranspose = 0,ST_MatSolve = 0,ST_MatSolveTranspose = 0;
     18: static PetscBool STPackageInitialized = PETSC_FALSE;

     20: const char *STMatModes[] = {"COPY","INPLACE","SHELL","STMatMode","ST_MATMODE_",0};

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

     26:    Level: developer

     28: .seealso: SlepcFinalize()
     29: @*/
     30: PetscErrorCode STFinalizePackage(void)
     31: {

     35:   PetscFunctionListDestroy(&STList);
     36:   STPackageInitialized = PETSC_FALSE;
     37:   STRegisterAllCalled  = PETSC_FALSE;
     38:   return(0);
     39: }

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

     46:    Level: developer

     48: .seealso: SlepcInitialize()
     49: @*/
     50: PetscErrorCode STInitializePackage(void)
     51: {
     52:   char           logList[256];
     53:   PetscBool      opt,pkg;

     57:   if (STPackageInitialized) return(0);
     58:   STPackageInitialized = PETSC_TRUE;
     59:   /* Register Classes */
     60:   PetscClassIdRegister("Spectral Transform",&ST_CLASSID);
     61:   /* Register Constructors */
     62:   STRegisterAll();
     63:   /* Register Events */
     64:   PetscLogEventRegister("STSetUp",ST_CLASSID,&ST_SetUp);
     65:   PetscLogEventRegister("STApply",ST_CLASSID,&ST_Apply);
     66:   PetscLogEventRegister("STApplyTranspose",ST_CLASSID,&ST_ApplyTranspose);
     67:   PetscLogEventRegister("STMatSetUp",ST_CLASSID,&ST_MatSetUp);
     68:   PetscLogEventRegister("STMatMult",ST_CLASSID,&ST_MatMult);
     69:   PetscLogEventRegister("STMatMultTranspose",ST_CLASSID,&ST_MatMultTranspose);
     70:   PetscLogEventRegister("STMatSolve",ST_CLASSID,&ST_MatSolve);
     71:   PetscLogEventRegister("STMatSolveTranspose",ST_CLASSID,&ST_MatSolveTranspose);
     72:   /* Process info exclusions */
     73:   PetscOptionsGetString(NULL,NULL,"-info_exclude",logList,sizeof(logList),&opt);
     74:   if (opt) {
     75:     PetscStrInList("st",logList,',',&pkg);
     76:     if (pkg) { PetscInfoDeactivateClass(ST_CLASSID); }
     77:   }
     78:   /* Process summary exclusions */
     79:   PetscOptionsGetString(NULL,NULL,"-log_exclude",logList,sizeof(logList),&opt);
     80:   if (opt) {
     81:     PetscStrInList("st",logList,',',&pkg);
     82:     if (pkg) { PetscLogEventDeactivateClass(ST_CLASSID); }
     83:   }
     84:   /* Register package finalizer */
     85:   PetscRegisterFinalize(STFinalizePackage);
     86:   return(0);
     87: }

     89: /*@
     90:    STReset - Resets the ST context to the initial state (prior to setup)
     91:    and destroys any allocated Vecs and Mats.

     93:    Collective on ST

     95:    Input Parameter:
     96: .  st - the spectral transformation context

     98:    Level: advanced

    100: .seealso: STDestroy()
    101: @*/
    102: PetscErrorCode STReset(ST st)
    103: {

    108:   if (!st) return(0);
    109:   if (st->ops->reset) { (*st->ops->reset)(st); }
    110:   if (st->ksp) { KSPReset(st->ksp); }
    111:   MatDestroyMatrices(PetscMax(2,st->nmat),&st->T);
    112:   MatDestroyMatrices(PetscMax(2,st->nmat),&st->A);
    113:   PetscFree(st->Astate);
    114:   MatDestroy(&st->P);
    115:   VecDestroyVecs(st->nwork,&st->work);
    116:   st->nwork = 0;
    117:   VecDestroy(&st->wb);
    118:   VecDestroy(&st->D);
    119:   st->state = ST_STATE_INITIAL;
    120:   return(0);
    121: }

    123: /*@
    124:    STDestroy - Destroys ST context that was created with STCreate().

    126:    Collective on ST

    128:    Input Parameter:
    129: .  st - the spectral transformation context

    131:    Level: beginner

    133: .seealso: STCreate(), STSetUp()
    134: @*/
    135: PetscErrorCode STDestroy(ST *st)
    136: {

    140:   if (!*st) return(0);
    142:   if (--((PetscObject)(*st))->refct > 0) { *st = 0; return(0); }
    143:   STReset(*st);
    144:   if ((*st)->ops->destroy) { (*(*st)->ops->destroy)(*st); }
    145:   KSPDestroy(&(*st)->ksp);
    146:   PetscHeaderDestroy(st);
    147:   return(0);
    148: }

    150: /*@
    151:    STCreate - Creates a spectral transformation context.

    153:    Collective on MPI_Comm

    155:    Input Parameter:
    156: .  comm - MPI communicator

    158:    Output Parameter:
    159: .  st - location to put the spectral transformation context

    161:    Level: beginner

    163: .seealso: STSetUp(), STApply(), STDestroy(), ST
    164: @*/
    165: PetscErrorCode STCreate(MPI_Comm comm,ST *newst)
    166: {
    168:   ST             st;

    172:   *newst = 0;
    173:   STInitializePackage();
    174:   SlepcHeaderCreate(st,ST_CLASSID,"ST","Spectral Transformation","ST",comm,STDestroy,STView);

    176:   st->A            = NULL;
    177:   st->Astate       = NULL;
    178:   st->T            = NULL;
    179:   st->P            = NULL;
    180:   st->nmat         = 0;
    181:   st->sigma        = 0.0;
    182:   st->sigma_set    = PETSC_FALSE;
    183:   st->defsigma     = 0.0;
    184:   st->shift_matrix = ST_MATMODE_COPY;
    185:   st->str          = DIFFERENT_NONZERO_PATTERN;
    186:   st->transform    = PETSC_FALSE;

    188:   st->ksp          = NULL;
    189:   st->nwork        = 0;
    190:   st->work         = NULL;
    191:   st->D            = NULL;
    192:   st->wb           = NULL;
    193:   st->data         = NULL;
    194:   st->state        = ST_STATE_INITIAL;

    196:   *newst = st;
    197:   return(0);
    198: }

    200: /*@
    201:    STSetMatrices - Sets the matrices associated with the eigenvalue problem.

    203:    Collective on ST and Mat

    205:    Input Parameters:
    206: +  st - the spectral transformation context
    207: .  n  - number of matrices in array A
    208: -  A  - the array of matrices associated with the eigensystem

    210:    Notes:
    211:    It must be called before STSetUp(). If it is called again after STSetUp() then
    212:    the ST object is reset.

    214:    Level: intermediate

    216: .seealso: STGetMatrix(), STGetNumMatrices(), STSetUp(), STReset()
    217:  @*/
    218: PetscErrorCode STSetMatrices(ST st,PetscInt n,Mat A[])
    219: {
    220:   PetscInt       i;
    222:   PetscBool      same=PETSC_TRUE;

    227:   if (n <= 0) SETERRQ1(PetscObjectComm((PetscObject)st),PETSC_ERR_ARG_OUTOFRANGE,"Must have one or more matrices, you have %D",n);
    230:   if (st->state) {
    231:     if (n!=st->nmat) same = PETSC_FALSE;
    232:     for (i=0;same&&i<n;i++) {
    233:       if (A[i]!=st->A[i]) same = PETSC_FALSE;
    234:     }
    235:     if (!same) { STReset(st); }
    236:   } else same = PETSC_FALSE;
    237:   if (!same) {
    238:     MatDestroyMatrices(PetscMax(2,st->nmat),&st->A);
    239:     PetscCalloc1(PetscMax(2,n),&st->A);
    240:     PetscLogObjectMemory((PetscObject)st,PetscMax(2,n)*sizeof(Mat));
    241:     PetscFree(st->Astate);
    242:     PetscMalloc1(PetscMax(2,n),&st->Astate);
    243:     PetscLogObjectMemory((PetscObject)st,PetscMax(2,n)*sizeof(PetscInt));
    244:   }
    245:   for (i=0;i<n;i++) {
    247:     PetscObjectReference((PetscObject)A[i]);
    248:     MatDestroy(&st->A[i]);
    249:     st->A[i] = A[i];
    250:     st->Astate[i] = ((PetscObject)A[i])->state;
    251:   }
    252:   if (n==1) {
    253:     st->A[1] = NULL;
    254:     st->Astate[1] = 0;
    255:   }
    256:   st->nmat = n;
    257:   if (same) st->state = ST_STATE_UPDATED;
    258:   else st->state = ST_STATE_INITIAL;
    259:   return(0);
    260: }

    262: /*@
    263:    STGetMatrix - Gets the matrices associated with the original eigensystem.

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

    267:    Input Parameter:
    268: +  st - the spectral transformation context
    269: -  k  - the index of the requested matrix (starting in 0)

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

    274:    Level: intermediate

    276: .seealso: STSetMatrices(), STGetNumMatrices()
    277: @*/
    278: PetscErrorCode STGetMatrix(ST st,PetscInt k,Mat *A)
    279: {
    284:   STCheckMatrices(st,1);
    285:   if (k<0 || k>=st->nmat) SETERRQ1(PetscObjectComm((PetscObject)st),PETSC_ERR_ARG_OUTOFRANGE,"k must be between 0 and %D",st->nmat-1);
    286:   if (((PetscObject)st->A[k])->state!=st->Astate[k]) SETERRQ(PetscObjectComm((PetscObject)st),PETSC_ERR_SUP,"Cannot retrieve original matrices (have been modified)");
    287:   *A = st->A[k];
    288:   return(0);
    289: }

    291: /*@
    292:    STGetMatrixTransformed - Gets the matrices associated with the transformed eigensystem.

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

    296:    Input Parameter:
    297: +  st - the spectral transformation context
    298: -  k  - the index of the requested matrix (starting in 0)

    300:    Output Parameters:
    301: .  T - the requested matrix

    303:    Level: developer

    305: .seealso: STGetMatrix(), STGetNumMatrices()
    306: @*/
    307: PetscErrorCode STGetMatrixTransformed(ST st,PetscInt k,Mat *T)
    308: {
    313:   STCheckMatrices(st,1);
    314:   if (k<0 || k>=st->nmat) SETERRQ1(PetscObjectComm((PetscObject)st),PETSC_ERR_ARG_OUTOFRANGE,"k must be between 0 and %D",st->nmat-1);
    315:   if (!st->T) SETERRQ(PetscObjectComm((PetscObject)st),PETSC_ERR_POINTER,"There are no transformed matrices");
    316:   *T = st->T[k];
    317:   return(0);
    318: }

    320: /*@
    321:    STGetNumMatrices - Returns the number of matrices stored in the ST.

    323:    Not collective

    325:    Input Parameter:
    326: .  st - the spectral transformation context

    328:    Output Parameters:
    329: .  n - the number of matrices passed in STSetMatrices()

    331:    Level: intermediate

    333: .seealso: STSetMatrices()
    334: @*/
    335: PetscErrorCode STGetNumMatrices(ST st,PetscInt *n)
    336: {
    340:   *n = st->nmat;
    341:   return(0);
    342: }

    344: /*@
    345:    STResetMatrixState - Resets the stored state of the matrices in the ST.

    347:    Logically Collective on ST

    349:    Input Parameter:
    350: .  st - the spectral transformation context

    352:    Note:
    353:    This is useful in solvers where the user matrices are modified during
    354:    the computation, as in nonlinear inverse iteration. The effect is that
    355:    STGetMatrix() will retrieve the modified matrices as if they were
    356:    the matrices originally provided by the user.

    358:    Level: developer

    360: .seealso: STGetMatrix(), EPSPowerSetNonlinear()
    361: @*/
    362: PetscErrorCode STResetMatrixState(ST st)
    363: {
    364:   PetscInt i;

    368:   for (i=0;i<st->nmat;i++) st->Astate[i] = ((PetscObject)st->A[i])->state;
    369:   return(0);
    370: }

    372: /*@
    373:    STSetShift - Sets the shift associated with the spectral transformation.

    375:    Logically Collective on ST

    377:    Input Parameters:
    378: +  st - the spectral transformation context
    379: -  shift - the value of the shift

    381:    Notes:
    382:    In some spectral transformations, changing the shift may have associated
    383:    a lot of work, for example recomputing a factorization.

    385:    This function is normally not directly called by users, since the shift is
    386:    indirectly set by EPSSetTarget().

    388:    Level: intermediate

    390: .seealso: EPSSetTarget(), STGetShift(), STSetDefaultShift()
    391: @*/
    392: PetscErrorCode STSetShift(ST st,PetscScalar shift)
    393: {

    400:   if (st->state==ST_STATE_SETUP && st->sigma != shift) {
    401:     if (st->ops->setshift) {
    402:       (*st->ops->setshift)(st,shift);
    403:     }
    404:   }
    405:   st->sigma = shift;
    406:   st->sigma_set = PETSC_TRUE;
    407:   return(0);
    408: }

    410: /*@
    411:    STGetShift - Gets the shift associated with the spectral transformation.

    413:    Not Collective

    415:    Input Parameter:
    416: .  st - the spectral transformation context

    418:    Output Parameter:
    419: .  shift - the value of the shift

    421:    Level: intermediate

    423: .seealso: STSetShift()
    424: @*/
    425: PetscErrorCode STGetShift(ST st,PetscScalar* shift)
    426: {
    430:   *shift = st->sigma;
    431:   return(0);
    432: }

    434: /*@
    435:    STSetDefaultShift - Sets the value of the shift that should be employed if
    436:    the user did not specify one.

    438:    Logically Collective on ST

    440:    Input Parameters:
    441: +  st - the spectral transformation context
    442: -  defaultshift - the default value of the shift

    444:    Level: developer

    446: .seealso: STSetShift()
    447: @*/
    448: PetscErrorCode STSetDefaultShift(ST st,PetscScalar defaultshift)
    449: {
    453:   st->defsigma = defaultshift;
    454:   return(0);
    455: }

    457: /*@
    458:    STScaleShift - Multiply the shift with a given factor.

    460:    Logically Collective on ST

    462:    Input Parameters:
    463: +  st     - the spectral transformation context
    464: -  factor - the scaling factor

    466:    Note:
    467:    This function does not update the transformation matrices, as opposed to
    468:    STSetShift().

    470:    Level: developer

    472: .seealso: STSetShift()
    473: @*/
    474: PetscErrorCode STScaleShift(ST st,PetscScalar factor)
    475: {
    479:   st->sigma *= factor;
    480:   return(0);
    481: }

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

    486:    Collective on ST and Vec

    488:    Input Parameters:
    489: +  st - the spectral transformation context
    490: -  D  - the diagonal matrix (represented as a vector)

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

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

    498:    Level: developer

    500: .seealso: EPSSetBalance(), STApply(), STGetBalanceMatrix()
    501: @*/
    502: PetscErrorCode STSetBalanceMatrix(ST st,Vec D)
    503: {

    510:   PetscObjectReference((PetscObject)D);
    511:   VecDestroy(&st->D);
    512:   st->D = D;
    513:   st->state = ST_STATE_INITIAL;
    514:   return(0);
    515: }

    517: /*@
    518:    STGetBalanceMatrix - Gets the balance matrix used by the spectral transformation.

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

    522:    Input Parameter:
    523: .  st - the spectral transformation context

    525:    Output Parameter:
    526: .  D  - the diagonal matrix (represented as a vector)

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

    531:    Level: developer

    533: .seealso: STSetBalanceMatrix()
    534: @*/
    535: PetscErrorCode STGetBalanceMatrix(ST st,Vec *D)
    536: {
    540:   *D = st->D;
    541:   return(0);
    542: }

    544: /*@C
    545:    STMatCreateVecs - Get vector(s) compatible with the ST matrices.

    547:    Collective on ST

    549:    Input Parameter:
    550: .  st - the spectral transformation context

    552:    Output Parameters:
    553: +  right - (optional) vector that the matrix can be multiplied against
    554: -  left  - (optional) vector that the matrix vector product can be stored in

    556:    Level: developer
    557: @*/
    558: PetscErrorCode STMatCreateVecs(ST st,Vec *right,Vec *left)
    559: {

    563:   STCheckMatrices(st,1);
    564:   MatCreateVecs(st->A[0],right,left);
    565:   return(0);
    566: }

    568: /*@C
    569:    STMatCreateVecsEmpty - Get vector(s) compatible with the ST matrices, i.e. with the same
    570:    parallel layout, but without internal array.

    572:    Collective on ST

    574:    Input Parameter:
    575: .  st - the spectral transformation context

    577:    Output Parameters:
    578: +  right - (optional) vector that the matrix can be multiplied against
    579: -  left  - (optional) vector that the matrix vector product can be stored in

    581:    Level: developer

    583: .seealso: MatCreateVecsEmpty()
    584: @*/
    585: PetscErrorCode STMatCreateVecsEmpty(ST st,Vec *right,Vec *left)
    586: {

    590:   STCheckMatrices(st,1);
    591:   MatCreateVecsEmpty(st->A[0],right,left);
    592:   return(0);
    593: }

    595: /*@
    596:    STMatGetSize - Returns the number of rows and columns of the ST matrices.

    598:    Not Collective

    600:    Input Parameter:
    601: .  st - the spectral transformation context

    603:    Output Parameters:
    604: +  m - the number of global rows
    605: -  n - the number of global columns

    607:    Level: developer
    608: @*/
    609: PetscErrorCode STMatGetSize(ST st,PetscInt *m,PetscInt *n)
    610: {

    614:   STCheckMatrices(st,1);
    615:   MatGetSize(st->A[0],m,n);
    616:   return(0);
    617: }

    619: /*@
    620:    STMatGetLocalSize - Returns the number of local rows and columns of the ST matrices.

    622:    Not Collective

    624:    Input Parameter:
    625: .  st - the spectral transformation context

    627:    Output Parameters:
    628: +  m - the number of local rows
    629: -  n - the number of local columns

    631:    Level: developer
    632: @*/
    633: PetscErrorCode STMatGetLocalSize(ST st,PetscInt *m,PetscInt *n)
    634: {

    638:   STCheckMatrices(st,1);
    639:   MatGetLocalSize(st->A[0],m,n);
    640:   return(0);
    641: }

    643: /*@C
    644:    STSetOptionsPrefix - Sets the prefix used for searching for all
    645:    ST options in the database.

    647:    Logically Collective on ST

    649:    Input Parameters:
    650: +  st     - the spectral transformation context
    651: -  prefix - the prefix string to prepend to all ST option requests

    653:    Notes:
    654:    A hyphen (-) must NOT be given at the beginning of the prefix name.
    655:    The first character of all runtime options is AUTOMATICALLY the
    656:    hyphen.

    658:    Level: advanced

    660: .seealso: STAppendOptionsPrefix(), STGetOptionsPrefix()
    661: @*/
    662: PetscErrorCode STSetOptionsPrefix(ST st,const char *prefix)
    663: {

    668:   if (!st->ksp) { STGetKSP(st,&st->ksp); }
    669:   KSPSetOptionsPrefix(st->ksp,prefix);
    670:   KSPAppendOptionsPrefix(st->ksp,"st_");
    671:   PetscObjectSetOptionsPrefix((PetscObject)st,prefix);
    672:   return(0);
    673: }

    675: /*@C
    676:    STAppendOptionsPrefix - Appends to the prefix used for searching for all
    677:    ST options in the database.

    679:    Logically Collective on ST

    681:    Input Parameters:
    682: +  st     - the spectral transformation context
    683: -  prefix - the prefix string to prepend to all ST option requests

    685:    Notes:
    686:    A hyphen (-) must NOT be given at the beginning of the prefix name.
    687:    The first character of all runtime options is AUTOMATICALLY the
    688:    hyphen.

    690:    Level: advanced

    692: .seealso: STSetOptionsPrefix(), STGetOptionsPrefix()
    693: @*/
    694: PetscErrorCode STAppendOptionsPrefix(ST st,const char *prefix)
    695: {

    700:   PetscObjectAppendOptionsPrefix((PetscObject)st,prefix);
    701:   if (!st->ksp) { STGetKSP(st,&st->ksp); }
    702:   KSPSetOptionsPrefix(st->ksp,((PetscObject)st)->prefix);
    703:   KSPAppendOptionsPrefix(st->ksp,"st_");
    704:   return(0);
    705: }

    707: /*@C
    708:    STGetOptionsPrefix - Gets the prefix used for searching for all
    709:    ST options in the database.

    711:    Not Collective

    713:    Input Parameters:
    714: .  st - the spectral transformation context

    716:    Output Parameters:
    717: .  prefix - pointer to the prefix string used, is returned

    719:    Note:
    720:    On the Fortran side, the user should pass in a string 'prefix' of
    721:    sufficient length to hold the prefix.

    723:    Level: advanced

    725: .seealso: STSetOptionsPrefix(), STAppendOptionsPrefix()
    726: @*/
    727: PetscErrorCode STGetOptionsPrefix(ST st,const char *prefix[])
    728: {

    734:   PetscObjectGetOptionsPrefix((PetscObject)st,prefix);
    735:   return(0);
    736: }

    738: /*@C
    739:    STView - Prints the ST data structure.

    741:    Collective on ST

    743:    Input Parameters:
    744: +  st - the ST context
    745: -  viewer - optional visualization context

    747:    Note:
    748:    The available visualization contexts include
    749: +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
    750: -     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
    751:          output where only the first processor opens
    752:          the file.  All other processors send their
    753:          data to the first processor to print.

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

    758:    Level: beginner

    760: .seealso: EPSView(), PetscViewerASCIIOpen()
    761: @*/
    762: PetscErrorCode STView(ST st,PetscViewer viewer)
    763: {
    765:   STType         cstr;
    766:   const char*    pat=NULL;
    767:   char           str[50];
    768:   PetscBool      isascii,isstring,flg;
    769:   PetscInt       tabs;

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

    777:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
    778:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring);
    779:   if (isascii) {
    780:     PetscViewerASCIIGetTab(viewer,&tabs);
    781:     PetscViewerASCIISetTab(viewer,((PetscObject)st)->tablevel);
    782:     PetscObjectPrintClassNamePrefixType((PetscObject)st,viewer);
    783:     if (st->ops->view) {
    784:       PetscViewerASCIIPushTab(viewer);
    785:       (*st->ops->view)(st,viewer);
    786:       PetscViewerASCIIPopTab(viewer);
    787:     }
    788:     SlepcSNPrintfScalar(str,50,st->sigma,PETSC_FALSE);
    789:     PetscViewerASCIIPrintf(viewer,"  shift: %s\n",str);
    790:     PetscViewerASCIIPrintf(viewer,"  number of matrices: %D\n",st->nmat);
    791:     switch (st->shift_matrix) {
    792:     case ST_MATMODE_COPY:
    793:       break;
    794:     case ST_MATMODE_INPLACE:
    795:       PetscViewerASCIIPrintf(viewer,"  shifting the matrix and unshifting at exit\n");
    796:       break;
    797:     case ST_MATMODE_SHELL:
    798:       PetscViewerASCIIPrintf(viewer,"  using a shell matrix\n");
    799:       break;
    800:     }
    801:     if (st->nmat>1 && st->shift_matrix != ST_MATMODE_SHELL) {
    802:       switch (st->str) {
    803:         case SAME_NONZERO_PATTERN:      pat = "same nonzero pattern";break;
    804:         case DIFFERENT_NONZERO_PATTERN: pat = "different nonzero pattern";break;
    805:         case SUBSET_NONZERO_PATTERN:    pat = "subset nonzero pattern";break;
    806:       }
    807:       PetscViewerASCIIPrintf(viewer,"  all matrices have %s\n",pat);
    808:     }
    809:     if (st->transform && st->nmat>2) {
    810:       PetscViewerASCIIPrintf(viewer,"  computing transformed matrices\n");
    811:     }
    812:     PetscViewerASCIISetTab(viewer,tabs);
    813:   } else if (isstring) {
    814:     STGetType(st,&cstr);
    815:     PetscViewerStringSPrintf(viewer," %-7.7s",cstr);
    816:     if (st->ops->view) { (*st->ops->view)(st,viewer); }
    817:   }
    818:   PetscObjectTypeCompare((PetscObject)st,STSHIFT,&flg);
    819:   if (st->nmat>1 || !flg) {
    820:     if (!st->ksp) { STGetKSP(st,&st->ksp); }
    821:     KSPView(st->ksp,viewer);
    822:   }
    823:   return(0);
    824: }

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

    829:    Not collective

    831:    Input Parameters:
    832: +  name - name of a new user-defined transformation
    833: -  function - routine to create method context

    835:    Notes:
    836:    STRegister() may be called multiple times to add several user-defined
    837:    spectral transformations.

    839:    Sample usage:
    840: .vb
    841:     STRegister("my_transform",MyTransformCreate);
    842: .ve

    844:    Then, your spectral transform can be chosen with the procedural interface via
    845: $     STSetType(st,"my_transform")
    846:    or at runtime via the option
    847: $     -st_type my_transform

    849:    Level: advanced

    851: .seealso: STRegisterAll()
    852: @*/
    853: PetscErrorCode STRegister(const char *name,PetscErrorCode (*function)(ST))
    854: {

    858:   STInitializePackage();
    859:   PetscFunctionListAdd(&STList,name,function);
    860:   return(0);
    861: }