Date: 2022-10-01T06:39:31+00:00

Actual source code: stfunc.c
slepc-3.18.0 2022-10-01
Report Typos and Errors

      1: /*
      2:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      3:    SLEPc - Scalable Library for Eigenvalue Problem Computations
      4:    Copyright (c) 2002-, 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>

     16: PetscClassId     ST_CLASSID = 0;
     17: PetscLogEvent    ST_SetUp = 0,ST_ComputeOperator = 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_",NULL};

     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: {
     32:   PetscFunctionListDestroy(&STList);
     33:   STPackageInitialized = PETSC_FALSE;
     34:   STRegisterAllCalled  = PETSC_FALSE;
     35:   return 0;
     36: }

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

     43:    Level: developer

     45: .seealso: SlepcInitialize()
     46: @*/
     47: PetscErrorCode STInitializePackage(void)
     48: {
     49:   char           logList[256];
     50:   PetscBool      opt,pkg;
     51:   PetscClassId   classids[1];

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

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

     87:    Collective on st

     89:    Input Parameter:
     90: .  st - the spectral transformation context

     92:    Level: advanced

     94: .seealso: STDestroy()
     95: @*/
     96: PetscErrorCode STReset(ST st)
     97: {
     99:   if (!st) return 0;
    100:   STCheckNotSeized(st,1);
    101:   PetscTryTypeMethod(st,reset);
    102:   if (st->ksp) KSPReset(st->ksp);
    103:   MatDestroyMatrices(PetscMax(2,st->nmat),&st->T);
    104:   MatDestroyMatrices(PetscMax(2,st->nmat),&st->A);
    105:   st->nmat = 0;
    106:   PetscFree(st->Astate);
    107:   MatDestroy(&st->Op);
    108:   MatDestroy(&st->P);
    109:   MatDestroy(&st->Pmat);
    110:   MatDestroyMatrices(st->nsplit,&st->Psplit);
    111:   st->nsplit = 0;
    112:   VecDestroyVecs(st->nwork,&st->work);
    113:   st->nwork = 0;
    114:   VecDestroy(&st->wb);
    115:   VecDestroy(&st->wht);
    116:   VecDestroy(&st->D);
    117:   st->state   = ST_STATE_INITIAL;
    118:   st->opready = PETSC_FALSE;
    119:   return 0;
    120: }

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

    125:    Collective on st

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

    130:    Level: beginner

    132: .seealso: STCreate(), STSetUp()
    133: @*/
    134: PetscErrorCode STDestroy(ST *st)
    135: {
    136:   if (!*st) return 0;
    138:   if (--((PetscObject)(*st))->refct > 0) { *st = NULL; return 0; }
    139:   STReset(*st);
    140:   PetscTryTypeMethod(*st,destroy);
    141:   KSPDestroy(&(*st)->ksp);
    142:   PetscHeaderDestroy(st);
    143:   return 0;
    144: }

    146: /*@
    147:    STCreate - Creates a spectral transformation context.

    149:    Collective

    151:    Input Parameter:
    152: .  comm - MPI communicator

    154:    Output Parameter:
    155: .  newst - location to put the spectral transformation context

    157:    Level: beginner

    159: .seealso: STSetUp(), STApply(), STDestroy(), ST
    160: @*/
    161: PetscErrorCode STCreate(MPI_Comm comm,ST *newst)
    162: {
    163:   ST             st;

    166:   *newst = NULL;
    167:   STInitializePackage();
    168:   SlepcHeaderCreate(st,ST_CLASSID,"ST","Spectral Transformation","ST",comm,STDestroy,STView);

    170:   st->A            = NULL;
    171:   st->nmat         = 0;
    172:   st->sigma        = 0.0;
    173:   st->defsigma     = 0.0;
    174:   st->matmode      = ST_MATMODE_COPY;
    175:   st->str          = UNKNOWN_NONZERO_PATTERN;
    176:   st->transform    = PETSC_FALSE;
    177:   st->D            = NULL;
    178:   st->Pmat         = NULL;
    179:   st->Pmat_set     = PETSC_FALSE;
    180:   st->Psplit       = NULL;
    181:   st->nsplit       = 0;
    182:   st->strp         = UNKNOWN_NONZERO_PATTERN;

    184:   st->ksp          = NULL;
    185:   st->usesksp      = PETSC_FALSE;
    186:   st->nwork        = 0;
    187:   st->work         = NULL;
    188:   st->wb           = NULL;
    189:   st->wht          = NULL;
    190:   st->state        = ST_STATE_INITIAL;
    191:   st->Astate       = NULL;
    192:   st->T            = NULL;
    193:   st->Op           = NULL;
    194:   st->opseized     = PETSC_FALSE;
    195:   st->opready      = PETSC_FALSE;
    196:   st->P            = NULL;
    197:   st->M            = NULL;
    198:   st->sigma_set    = PETSC_FALSE;
    199:   st->asymm        = PETSC_FALSE;
    200:   st->aherm        = PETSC_FALSE;
    201:   st->data         = NULL;

    203:   *newst = st;
    204:   return 0;
    205: }

    207: /*
    208:    Checks whether the ST matrices are all symmetric or hermitian.
    209: */
    210: static inline PetscErrorCode STMatIsSymmetricKnown(ST st,PetscBool *symm,PetscBool *herm)
    211: {
    212:   PetscInt       i;
    213:   PetscBool      sbaij=PETSC_FALSE,set,flg=PETSC_FALSE;

    215:   /* check if problem matrices are all sbaij */
    216:   for (i=0;i<st->nmat;i++) {
    217:     PetscObjectTypeCompareAny((PetscObject)st->A[i],&sbaij,MATSEQSBAIJ,MATMPISBAIJ,"");
    218:     if (!sbaij) break;
    219:   }
    220:   /* check if user has set the symmetric flag */
    221:   *symm = PETSC_TRUE;
    222:   for (i=0;i<st->nmat;i++) {
    223:     MatIsSymmetricKnown(st->A[i],&set,&flg);
    224:     if (!set || !flg) { *symm = PETSC_FALSE; break; }
    225:   }
    226:   if (sbaij) *symm = PETSC_TRUE;
    227: #if defined(PETSC_USE_COMPLEX)
    228:   /* check if user has set the hermitian flag */
    229:   *herm = PETSC_TRUE;
    230:   for (i=0;i<st->nmat;i++) {
    231:     MatIsHermitianKnown(st->A[i],&set,&flg);
    232:     if (!set || !flg) { *herm = PETSC_FALSE; break; }
    233:   }
    234: #else
    235:   *herm = *symm;
    236: #endif
    237:   return 0;
    238: }

    240: /*@
    241:    STSetMatrices - Sets the matrices associated with the eigenvalue problem.

    243:    Collective on st

    245:    Input Parameters:
    246: +  st - the spectral transformation context
    247: .  n  - number of matrices in array A
    248: -  A  - the array of matrices associated with the eigensystem

    250:    Notes:
    251:    It must be called before STSetUp(). If it is called again after STSetUp() then
    252:    the ST object is reset.

    254:    Level: intermediate

    256: .seealso: STGetMatrix(), STGetNumMatrices(), STSetUp(), STReset()
    257: @*/
    258: PetscErrorCode STSetMatrices(ST st,PetscInt n,Mat A[])
    259: {
    260:   PetscInt       i;
    261:   PetscBool      same=PETSC_TRUE;

    268:   STCheckNotSeized(st,1);

    271:   if (st->state) {
    272:     if (n!=st->nmat) same = PETSC_FALSE;
    273:     for (i=0;same&&i<n;i++) {
    274:       if (A[i]!=st->A[i]) same = PETSC_FALSE;
    275:     }
    276:     if (!same) STReset(st);
    277:   } else same = PETSC_FALSE;
    278:   if (!same) {
    279:     MatDestroyMatrices(PetscMax(2,st->nmat),&st->A);
    280:     PetscCalloc1(PetscMax(2,n),&st->A);
    281:     PetscFree(st->Astate);
    282:     PetscMalloc1(PetscMax(2,n),&st->Astate);
    283:   }
    284:   for (i=0;i<n;i++) {
    286:     PetscObjectReference((PetscObject)A[i]);
    287:     MatDestroy(&st->A[i]);
    288:     st->A[i] = A[i];
    289:     st->Astate[i] = ((PetscObject)A[i])->state;
    290:   }
    291:   if (n==1) {
    292:     st->A[1] = NULL;
    293:     st->Astate[1] = 0;
    294:   }
    295:   st->nmat = n;
    296:   if (same) st->state = ST_STATE_UPDATED;
    297:   else st->state = ST_STATE_INITIAL;
    299:   st->opready = PETSC_FALSE;
    300:   if (!same) STMatIsSymmetricKnown(st,&st->asymm,&st->aherm);
    301:   return 0;
    302: }

    304: /*@
    305:    STGetMatrix - Gets the matrices associated with the original eigensystem.

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

    309:    Input Parameters:
    310: +  st - the spectral transformation context
    311: -  k  - the index of the requested matrix (starting in 0)

    313:    Output Parameters:
    314: .  A - the requested matrix

    316:    Level: intermediate

    318: .seealso: STSetMatrices(), STGetNumMatrices()
    319: @*/
    320: PetscErrorCode STGetMatrix(ST st,PetscInt k,Mat *A)
    321: {
    325:   STCheckMatrices(st,1);
    328:   *A = st->A[k];
    329:   return 0;
    330: }

    332: /*@
    333:    STGetMatrixTransformed - Gets the matrices associated with the transformed eigensystem.

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

    337:    Input Parameters:
    338: +  st - the spectral transformation context
    339: -  k  - the index of the requested matrix (starting in 0)

    341:    Output Parameters:
    342: .  T - the requested matrix

    344:    Level: developer

    346: .seealso: STGetMatrix(), STGetNumMatrices()
    347: @*/
    348: PetscErrorCode STGetMatrixTransformed(ST st,PetscInt k,Mat *T)
    349: {
    353:   STCheckMatrices(st,1);
    356:   *T = st->T[k];
    357:   return 0;
    358: }

    360: /*@
    361:    STGetNumMatrices - Returns the number of matrices stored in the ST.

    363:    Not collective

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

    368:    Output Parameters:
    369: .  n - the number of matrices passed in STSetMatrices()

    371:    Level: intermediate

    373: .seealso: STSetMatrices()
    374: @*/
    375: PetscErrorCode STGetNumMatrices(ST st,PetscInt *n)
    376: {
    379:   *n = st->nmat;
    380:   return 0;
    381: }

    383: /*@
    384:    STResetMatrixState - Resets the stored state of the matrices in the ST.

    386:    Logically Collective on st

    388:    Input Parameter:
    389: .  st - the spectral transformation context

    391:    Note:
    392:    This is useful in solvers where the user matrices are modified during
    393:    the computation, as in nonlinear inverse iteration. The effect is that
    394:    STGetMatrix() will retrieve the modified matrices as if they were
    395:    the matrices originally provided by the user.

    397:    Level: developer

    399: .seealso: STGetMatrix(), EPSPowerSetNonlinear()
    400: @*/
    401: PetscErrorCode STResetMatrixState(ST st)
    402: {
    403:   PetscInt i;

    406:   for (i=0;i<st->nmat;i++) st->Astate[i] = ((PetscObject)st->A[i])->state;
    407:   return 0;
    408: }

    410: /*@
    411:    STSetPreconditionerMat - Sets the matrix to be used to build the preconditioner.

    413:    Collective on st

    415:    Input Parameters:
    416: +  st  - the spectral transformation context
    417: -  mat - the matrix that will be used in constructing the preconditioner

    419:    Notes:
    420:    This matrix will be passed to the internal KSP object (via the last argument
    421:    of KSPSetOperators()) as the matrix to be used when constructing the preconditioner.
    422:    If no matrix is set or mat is set to NULL, A-sigma*B will be used
    423:    to build the preconditioner, being sigma the value set by STSetShift().

    425:    More precisely, this is relevant for spectral transformations that represent
    426:    a rational matrix function, and use a KSP object for the denominator, called
    427:    K in the description of STGetOperator(). It includes also the STPRECOND case.
    428:    If the user has a good approximation to matrix K that can be used to build a
    429:    cheap preconditioner, it can be passed with this function. Note that it affects
    430:    only the Pmat argument of KSPSetOperators(), not the Amat argument.

    432:    If a preconditioner matrix is set, the default is to use an iterative KSP
    433:    rather than a direct method.

    435:    An alternative to pass an approximation of A-sigma*B with this function is
    436:    to provide approximations of A and B via STSetSplitPreconditioner(). The
    437:    difference is that when sigma changes the preconditioner is recomputed.

    439:    Use NULL to remove a previously set matrix.

    441:    Level: advanced

    443: .seealso: STGetPreconditionerMat(), STSetShift(), STGetOperator(), STSetSplitPreconditioner()
    444: @*/
    445: PetscErrorCode STSetPreconditionerMat(ST st,Mat mat)
    446: {
    448:   if (mat) {
    451:   }
    452:   STCheckNotSeized(st,1);
    454:   if (mat) PetscObjectReference((PetscObject)mat);
    455:   MatDestroy(&st->Pmat);
    456:   st->Pmat     = mat;
    457:   st->Pmat_set = mat? PETSC_TRUE: PETSC_FALSE;
    458:   st->state    = ST_STATE_INITIAL;
    459:   st->opready  = PETSC_FALSE;
    460:   return 0;
    461: }

    463: /*@
    464:    STGetPreconditionerMat - Returns the matrix previously set by STSetPreconditionerMat().

    466:    Not Collective

    468:    Input Parameter:
    469: .  st - the spectral transformation context

    471:    Output Parameter:
    472: .  mat - the matrix that will be used in constructing the preconditioner or
    473:    NULL if no matrix was set by STSetPreconditionerMat().

    475:    Level: advanced

    477: .seealso: STSetPreconditionerMat()
    478: @*/
    479: PetscErrorCode STGetPreconditionerMat(ST st,Mat *mat)
    480: {
    483:   *mat = st->Pmat_set? st->Pmat: NULL;
    484:   return 0;
    485: }

    487: /*@
    488:    STSetSplitPreconditioner - Sets the matrices from which to build the preconditioner
    489:    in split form.

    491:    Collective on st

    493:    Input Parameters:
    494: +  st     - the spectral transformation context
    495: .  n      - number of matrices
    496: .  Psplit - array of matrices
    497: -  strp   - structure flag for Psplit matrices

    499:    Notes:
    500:    The number of matrices passed here must be the same as in STSetMatrices().

    502:    For linear eigenproblems, the preconditioner matrix is computed as
    503:    Pmat(sigma) = A0-sigma*B0, where A0 and B0 are approximations of A and B
    504:    (the eigenproblem matrices) provided via the Psplit array in this function.
    505:    Compared to STSetPreconditionerMat(), this function allows setting a preconditioner
    506:    in a way that is independent of the shift sigma. Whenever the value of sigma
    507:    changes the preconditioner is recomputed.

    509:    Similarly, for polynomial eigenproblems the matrix for the preconditioner
    510:    is expressed as Pmat(sigma) = sum_i Psplit_i*phi_i(sigma), for i=1,...,n, where
    511:    the phi_i's are the polynomial basis functions.

    513:    The structure flag provides information about the relative nonzero pattern of the
    514:    Psplit_i matrices, in the same way as in STSetMatStructure().

    516:    Use n=0 to reset a previously set split preconditioner.

    518:    Level: advanced

    520: .seealso: STGetSplitPreconditionerTerm(), STGetSplitPreconditionerInfo(), STSetPreconditionerMat(), STSetMatrices(), STSetMatStructure()
    521: @*/
    522: PetscErrorCode STSetSplitPreconditioner(ST st,PetscInt n,Mat Psplit[],MatStructure strp)
    523: {
    524:   PetscInt       i,N=0,M,M0=0,mloc,nloc,mloc0=0;

    533:   STCheckNotSeized(st,1);

    535:   for (i=0;i<n;i++) {
    538:     MatGetSize(Psplit[i],&M,&N);
    539:     MatGetLocalSize(Psplit[i],&mloc,&nloc);
    542:     if (!i) { M0 = M; mloc0 = mloc; }
    545:     PetscObjectReference((PetscObject)Psplit[i]);
    546:   }

    548:   if (st->Psplit) MatDestroyMatrices(st->nsplit,&st->Psplit);

    550:   /* allocate space and copy matrices */
    551:   if (n) {
    552:     PetscMalloc1(n,&st->Psplit);
    553:     for (i=0;i<n;i++) st->Psplit[i] = Psplit[i];
    554:   }
    555:   st->nsplit = n;
    556:   st->strp   = strp;
    557:   st->state  = ST_STATE_INITIAL;
    558:   return 0;
    559: }

    561: /*@
    562:    STGetSplitPreconditionerTerm - Gets the matrices associated with
    563:    the split preconditioner.

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

    567:    Input Parameters:
    568: +  st - the spectral transformation context
    569: -  k  - the index of the requested matrix (starting in 0)

    571:    Output Parameter:
    572: .  Psplit - the returned matrix

    574:    Level: advanced

    576: .seealso: STSetSplitPreconditioner(), STGetSplitPreconditionerInfo()
    577: @*/
    578: PetscErrorCode STGetSplitPreconditionerTerm(ST st,PetscInt k,Mat *Psplit)
    579: {
    585:   *Psplit = st->Psplit[k];
    586:   return 0;
    587: }

    589: /*@
    590:    STGetSplitPreconditionerInfo - Returns the number of matrices of the split
    591:    preconditioner, as well as the structure flag.

    593:    Not collective

    595:    Input Parameter:
    596: .  st - the spectral transformation context

    598:    Output Parameters:
    599: +  n    - the number of matrices passed in STSetSplitPreconditioner()
    600: -  strp - the matrix structure flag passed in STSetSplitPreconditioner()

    602:    Level: advanced

    604: .seealso: STSetSplitPreconditioner(), STGetSplitPreconditionerTerm()
    605: @*/
    606: PetscErrorCode STGetSplitPreconditionerInfo(ST st,PetscInt *n,MatStructure *strp)
    607: {
    609:   if (n)    *n    = st->nsplit;
    610:   if (strp) *strp = st->strp;
    611:   return 0;
    612: }

    614: /*@
    615:    STSetShift - Sets the shift associated with the spectral transformation.

    617:    Logically Collective on st

    619:    Input Parameters:
    620: +  st - the spectral transformation context
    621: -  shift - the value of the shift

    623:    Notes:
    624:    In some spectral transformations, changing the shift may have associated
    625:    a lot of work, for example recomputing a factorization.

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

    630:    Level: intermediate

    632: .seealso: EPSSetTarget(), STGetShift(), STSetDefaultShift()
    633: @*/
    634: PetscErrorCode STSetShift(ST st,PetscScalar shift)
    635: {
    639:   if (st->sigma != shift) {
    640:     STCheckNotSeized(st,1);
    641:     if (st->state==ST_STATE_SETUP) PetscTryTypeMethod(st,setshift,shift);
    642:     st->sigma = shift;
    643:   }
    644:   st->sigma_set = PETSC_TRUE;
    645:   return 0;
    646: }

    648: /*@
    649:    STGetShift - Gets the shift associated with the spectral transformation.

    651:    Not Collective

    653:    Input Parameter:
    654: .  st - the spectral transformation context

    656:    Output Parameter:
    657: .  shift - the value of the shift

    659:    Level: intermediate

    661: .seealso: STSetShift()
    662: @*/
    663: PetscErrorCode STGetShift(ST st,PetscScalar* shift)
    664: {
    667:   *shift = st->sigma;
    668:   return 0;
    669: }

    671: /*@
    672:    STSetDefaultShift - Sets the value of the shift that should be employed if
    673:    the user did not specify one.

    675:    Logically Collective on st

    677:    Input Parameters:
    678: +  st - the spectral transformation context
    679: -  defaultshift - the default value of the shift

    681:    Level: developer

    683: .seealso: STSetShift()
    684: @*/
    685: PetscErrorCode STSetDefaultShift(ST st,PetscScalar defaultshift)
    686: {
    689:   if (st->defsigma != defaultshift) {
    690:     st->defsigma = defaultshift;
    691:     st->state    = ST_STATE_INITIAL;
    692:     st->opready  = PETSC_FALSE;
    693:   }
    694:   return 0;
    695: }

    697: /*@
    698:    STScaleShift - Multiply the shift with a given factor.

    700:    Logically Collective on st

    702:    Input Parameters:
    703: +  st     - the spectral transformation context
    704: -  factor - the scaling factor

    706:    Note:
    707:    This function does not update the transformation matrices, as opposed to
    708:    STSetShift().

    710:    Level: developer

    712: .seealso: STSetShift()
    713: @*/
    714: PetscErrorCode STScaleShift(ST st,PetscScalar factor)
    715: {
    718:   st->sigma *= factor;
    719:   return 0;
    720: }

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

    725:    Collective on st

    727:    Input Parameters:
    728: +  st - the spectral transformation context
    729: -  D  - the diagonal matrix (represented as a vector)

    731:    Notes:
    732:    If this matrix is set, STApply will effectively apply D*OP*D^{-1}. Use NULL
    733:    to reset a previously passed D.

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

    738:    Level: developer

    740: .seealso: EPSSetBalance(), STApply(), STGetBalanceMatrix()
    741: @*/
    742: PetscErrorCode STSetBalanceMatrix(ST st,Vec D)
    743: {
    745:   if (st->D == D) return 0;
    746:   STCheckNotSeized(st,1);
    747:   if (D) {
    750:     PetscObjectReference((PetscObject)D);
    751:   }
    752:   VecDestroy(&st->D);
    753:   st->D = D;
    754:   st->state   = ST_STATE_INITIAL;
    755:   st->opready = PETSC_FALSE;
    756:   return 0;
    757: }

    759: /*@
    760:    STGetBalanceMatrix - Gets the balance matrix used by the spectral transformation.

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

    764:    Input Parameter:
    765: .  st - the spectral transformation context

    767:    Output Parameter:
    768: .  D  - the diagonal matrix (represented as a vector)

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

    773:    Level: developer

    775: .seealso: STSetBalanceMatrix()
    776: @*/
    777: PetscErrorCode STGetBalanceMatrix(ST st,Vec *D)
    778: {
    781:   *D = st->D;
    782:   return 0;
    783: }

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

    788:    Collective on st

    790:    Input Parameter:
    791: .  st - the spectral transformation context

    793:    Output Parameters:
    794: +  right - (optional) vector that the matrix can be multiplied against
    795: -  left  - (optional) vector that the matrix vector product can be stored in

    797:    Level: developer

    799: .seealso: STMatCreateVecsEmpty()
    800: @*/
    801: PetscErrorCode STMatCreateVecs(ST st,Vec *right,Vec *left)
    802: {
    803:   STCheckMatrices(st,1);
    804:   MatCreateVecs(st->A[0],right,left);
    805:   return 0;
    806: }

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

    812:    Collective on st

    814:    Input Parameter:
    815: .  st - the spectral transformation context

    817:    Output Parameters:
    818: +  right - (optional) vector that the matrix can be multiplied against
    819: -  left  - (optional) vector that the matrix vector product can be stored in

    821:    Level: developer

    823: .seealso: STMatCreateVecs(), MatCreateVecsEmpty()
    824: @*/
    825: PetscErrorCode STMatCreateVecsEmpty(ST st,Vec *right,Vec *left)
    826: {
    827:   STCheckMatrices(st,1);
    828:   MatCreateVecsEmpty(st->A[0],right,left);
    829:   return 0;
    830: }

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

    835:    Not Collective

    837:    Input Parameter:
    838: .  st - the spectral transformation context

    840:    Output Parameters:
    841: +  m - the number of global rows
    842: -  n - the number of global columns

    844:    Level: developer

    846: .seealso: STMatGetLocalSize()
    847: @*/
    848: PetscErrorCode STMatGetSize(ST st,PetscInt *m,PetscInt *n)
    849: {
    850:   STCheckMatrices(st,1);
    851:   MatGetSize(st->A[0],m,n);
    852:   return 0;
    853: }

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

    858:    Not Collective

    860:    Input Parameter:
    861: .  st - the spectral transformation context

    863:    Output Parameters:
    864: +  m - the number of local rows
    865: -  n - the number of local columns

    867:    Level: developer

    869: .seealso: STMatGetSize()
    870: @*/
    871: PetscErrorCode STMatGetLocalSize(ST st,PetscInt *m,PetscInt *n)
    872: {
    873:   STCheckMatrices(st,1);
    874:   MatGetLocalSize(st->A[0],m,n);
    875:   return 0;
    876: }

    878: /*@C
    879:    STSetOptionsPrefix - Sets the prefix used for searching for all
    880:    ST options in the database.

    882:    Logically Collective on st

    884:    Input Parameters:
    885: +  st     - the spectral transformation context
    886: -  prefix - the prefix string to prepend to all ST option requests

    888:    Notes:
    889:    A hyphen (-) must NOT be given at the beginning of the prefix name.
    890:    The first character of all runtime options is AUTOMATICALLY the
    891:    hyphen.

    893:    Level: advanced

    895: .seealso: STAppendOptionsPrefix(), STGetOptionsPrefix()
    896: @*/
    897: PetscErrorCode STSetOptionsPrefix(ST st,const char *prefix)
    898: {
    900:   if (!st->ksp) STGetKSP(st,&st->ksp);
    901:   KSPSetOptionsPrefix(st->ksp,prefix);
    902:   KSPAppendOptionsPrefix(st->ksp,"st_");
    903:   PetscObjectSetOptionsPrefix((PetscObject)st,prefix);
    904:   return 0;
    905: }

    907: /*@C
    908:    STAppendOptionsPrefix - Appends to the prefix used for searching for all
    909:    ST options in the database.

    911:    Logically Collective on st

    913:    Input Parameters:
    914: +  st     - the spectral transformation context
    915: -  prefix - the prefix string to prepend to all ST option requests

    917:    Notes:
    918:    A hyphen (-) must NOT be given at the beginning of the prefix name.
    919:    The first character of all runtime options is AUTOMATICALLY the
    920:    hyphen.

    922:    Level: advanced

    924: .seealso: STSetOptionsPrefix(), STGetOptionsPrefix()
    925: @*/
    926: PetscErrorCode STAppendOptionsPrefix(ST st,const char *prefix)
    927: {
    929:   PetscObjectAppendOptionsPrefix((PetscObject)st,prefix);
    930:   if (!st->ksp) STGetKSP(st,&st->ksp);
    931:   KSPSetOptionsPrefix(st->ksp,((PetscObject)st)->prefix);
    932:   KSPAppendOptionsPrefix(st->ksp,"st_");
    933:   return 0;
    934: }

    936: /*@C
    937:    STGetOptionsPrefix - Gets the prefix used for searching for all
    938:    ST options in the database.

    940:    Not Collective

    942:    Input Parameters:
    943: .  st - the spectral transformation context

    945:    Output Parameters:
    946: .  prefix - pointer to the prefix string used, is returned

    948:    Note:
    949:    On the Fortran side, the user should pass in a string 'prefix' of
    950:    sufficient length to hold the prefix.

    952:    Level: advanced

    954: .seealso: STSetOptionsPrefix(), STAppendOptionsPrefix()
    955: @*/
    956: PetscErrorCode STGetOptionsPrefix(ST st,const char *prefix[])
    957: {
    960:   PetscObjectGetOptionsPrefix((PetscObject)st,prefix);
    961:   return 0;
    962: }

    964: /*@C
    965:    STView - Prints the ST data structure.

    967:    Collective on st

    969:    Input Parameters:
    970: +  st - the ST context
    971: -  viewer - optional visualization context

    973:    Note:
    974:    The available visualization contexts include
    975: +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
    976: -     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
    977:          output where only the first processor opens
    978:          the file.  All other processors send their
    979:          data to the first processor to print.

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

    984:    Level: beginner

    986: .seealso: EPSView()
    987: @*/
    988: PetscErrorCode STView(ST st,PetscViewer viewer)
    989: {
    990:   STType         cstr;
    991:   char           str[50];
    992:   PetscBool      isascii,isstring;

    995:   if (!viewer) PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)st),&viewer);

    999:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
    1000:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring);
    1001:   if (isascii) {
    1002:     PetscObjectPrintClassNamePrefixType((PetscObject)st,viewer);
    1003:     PetscViewerASCIIPushTab(viewer);
    1004:     PetscTryTypeMethod(st,view,viewer);
    1005:     PetscViewerASCIIPopTab(viewer);
    1006:     SlepcSNPrintfScalar(str,sizeof(str),st->sigma,PETSC_FALSE);
    1007:     PetscViewerASCIIPrintf(viewer,"  shift: %s\n",str);
    1008:     PetscViewerASCIIPrintf(viewer,"  number of matrices: %" PetscInt_FMT "\n",st->nmat);
    1009:     switch (st->matmode) {
    1010:     case ST_MATMODE_COPY:
    1011:       break;
    1012:     case ST_MATMODE_INPLACE:
    1013:       PetscViewerASCIIPrintf(viewer,"  shifting the matrix and unshifting at exit\n");
    1014:       break;
    1015:     case ST_MATMODE_SHELL:
    1016:       PetscViewerASCIIPrintf(viewer,"  using a shell matrix\n");
    1017:       break;
    1018:     }
    1019:     if (st->nmat>1 && st->matmode != ST_MATMODE_SHELL) PetscViewerASCIIPrintf(viewer,"  nonzero pattern of the matrices: %s\n",MatStructures[st->str]);
    1020:     if (st->Psplit) PetscViewerASCIIPrintf(viewer,"  using split preconditioner matrices with %s\n",MatStructures[st->strp]);
    1021:     if (st->transform && st->nmat>2) PetscViewerASCIIPrintf(viewer,"  computing transformed matrices\n");
    1022:   } else if (isstring) {
    1023:     STGetType(st,&cstr);
    1024:     PetscViewerStringSPrintf(viewer," %-7.7s",cstr);
    1025:     PetscTryTypeMethod(st,view,viewer);
    1026:   }
    1027:   if (st->usesksp) {
    1028:     if (!st->ksp) STGetKSP(st,&st->ksp);
    1029:     PetscViewerASCIIPushTab(viewer);
    1030:     KSPView(st->ksp,viewer);
    1031:     PetscViewerASCIIPopTab(viewer);
    1032:   }
    1033:   return 0;
    1034: }

    1036: /*@C
    1037:    STViewFromOptions - View from options

    1039:    Collective on ST

    1041:    Input Parameters:
    1042: +  st   - the spectral transformation context
    1043: .  obj  - optional object
    1044: -  name - command line option

    1046:    Level: intermediate

    1048: .seealso: STView(), STCreate()
    1049: @*/
    1050: PetscErrorCode STViewFromOptions(ST st,PetscObject obj,const char name[])
    1051: {
    1053:   PetscObjectViewFromOptions((PetscObject)st,obj,name);
    1054:   return 0;
    1055: }

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

    1060:    Not collective

    1062:    Input Parameters:
    1063: +  name - name of a new user-defined transformation
    1064: -  function - routine to create method context

    1066:    Notes:
    1067:    STRegister() may be called multiple times to add several user-defined
    1068:    spectral transformations.

    1070:    Sample usage:
    1071: .vb
    1072:     STRegister("my_transform",MyTransformCreate);
    1073: .ve

    1075:    Then, your spectral transform can be chosen with the procedural interface via
    1076: $     STSetType(st,"my_transform")
    1077:    or at runtime via the option
    1078: $     -st_type my_transform

    1080:    Level: advanced

    1082: .seealso: STRegisterAll()
    1083: @*/
    1084: PetscErrorCode STRegister(const char *name,PetscErrorCode (*function)(ST))
    1085: {
    1086:   STInitializePackage();
    1087:   PetscFunctionListAdd(&STList,name,function);
    1088:   return 0;
    1089: }