Actual source code: bvfunc.c

      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:    BV (basis vectors) interface routines, callable by users
     12: */

     14: #include <slepc/private/bvimpl.h>

     16: PetscClassId     BV_CLASSID = 0;
     17: PetscLogEvent    BV_Create = 0,BV_Copy = 0,BV_Mult = 0,BV_MultVec = 0,BV_MultInPlace = 0,BV_Dot = 0,BV_DotVec = 0,BV_Orthogonalize = 0,BV_OrthogonalizeVec = 0,BV_Scale = 0,BV_Norm = 0,BV_NormVec = 0,BV_Normalize = 0,BV_SetRandom = 0,BV_MatMult = 0,BV_MatMultVec = 0,BV_MatProject = 0,BV_SVDAndRank = 0;
     18: static PetscBool BVPackageInitialized = PETSC_FALSE;
     19: MPI_Op MPIU_TSQR = 0,MPIU_LAPY2;

     21: const char *BVOrthogTypes[] = {"CGS","MGS","BVOrthogType","BV_ORTHOG_",NULL};
     22: const char *BVOrthogRefineTypes[] = {"IFNEEDED","NEVER","ALWAYS","BVOrthogRefineType","BV_ORTHOG_REFINE_",NULL};
     23: const char *BVOrthogBlockTypes[] = {"GS","CHOL","TSQR","TSQRCHOL","SVQB","BVOrthogBlockType","BV_ORTHOG_BLOCK_",NULL};
     24: const char *BVMatMultTypes[] = {"VECS","MAT","MAT_SAVE","BVMatMultType","BV_MATMULT_",NULL};
     25: const char *BVSVDMethods[] = {"REFINE","QR","QR_CAA","BVSVDMethod","BV_SVD_METHOD_",NULL};

     27: /*@C
     28:    BVFinalizePackage - This function destroys everything in the SLEPc interface
     29:    to the `BV` package. It is called from `SlepcFinalize()`.

     31:    Level: developer

     33: .seealso: [](sec:bv), `SlepcFinalize()`, `BVInitializePackage()`
     34: @*/
     35: PetscErrorCode BVFinalizePackage(void)
     36: {
     37:   PetscFunctionBegin;
     38:   PetscCall(PetscFunctionListDestroy(&BVList));
     39:   PetscCallMPI(MPI_Op_free(&MPIU_TSQR));
     40:   PetscCallMPI(MPI_Op_free(&MPIU_LAPY2));
     41:   BVPackageInitialized = PETSC_FALSE;
     42:   BVRegisterAllCalled  = PETSC_FALSE;
     43:   PetscFunctionReturn(PETSC_SUCCESS);
     44: }

     46: /*@C
     47:    BVInitializePackage - This function initializes everything in the `BV` package.
     48:    It is called from `PetscDLLibraryRegister_slepc()` when using dynamic libraries, and
     49:    on the first call to `BVCreate()` when using shared or static libraries.

     51:    Note:
     52:    This function never needs to be called by SLEPc users.

     54:    Level: developer

     56: .seealso: [](sec:bv), `BV`, `SlepcInitialize()`, `BVFinalizePackage()`
     57: @*/
     58: PetscErrorCode BVInitializePackage(void)
     59: {
     60:   char           logList[256];
     61:   PetscBool      opt,pkg;
     62:   PetscClassId   classids[1];

     64:   PetscFunctionBegin;
     65:   if (BVPackageInitialized) PetscFunctionReturn(PETSC_SUCCESS);
     66:   BVPackageInitialized = PETSC_TRUE;
     67:   /* Register Classes */
     68:   PetscCall(PetscClassIdRegister("Basis Vectors",&BV_CLASSID));
     69:   /* Register Constructors */
     70:   PetscCall(BVRegisterAll());
     71:   /* Register Events */
     72:   PetscCall(PetscLogEventRegister("BVCreate",BV_CLASSID,&BV_Create));
     73:   PetscCall(PetscLogEventRegister("BVCopy",BV_CLASSID,&BV_Copy));
     74:   PetscCall(PetscLogEventRegister("BVMult",BV_CLASSID,&BV_Mult));
     75:   PetscCall(PetscLogEventRegister("BVMultVec",BV_CLASSID,&BV_MultVec));
     76:   PetscCall(PetscLogEventRegister("BVMultInPlace",BV_CLASSID,&BV_MultInPlace));
     77:   PetscCall(PetscLogEventRegister("BVDot",BV_CLASSID,&BV_Dot));
     78:   PetscCall(PetscLogEventRegister("BVDotVec",BV_CLASSID,&BV_DotVec));
     79:   PetscCall(PetscLogEventRegister("BVOrthogonalize",BV_CLASSID,&BV_Orthogonalize));
     80:   PetscCall(PetscLogEventRegister("BVOrthogonalizeV",BV_CLASSID,&BV_OrthogonalizeVec));
     81:   PetscCall(PetscLogEventRegister("BVScale",BV_CLASSID,&BV_Scale));
     82:   PetscCall(PetscLogEventRegister("BVNorm",BV_CLASSID,&BV_Norm));
     83:   PetscCall(PetscLogEventRegister("BVNormVec",BV_CLASSID,&BV_NormVec));
     84:   PetscCall(PetscLogEventRegister("BVNormalize",BV_CLASSID,&BV_Normalize));
     85:   PetscCall(PetscLogEventRegister("BVSetRandom",BV_CLASSID,&BV_SetRandom));
     86:   PetscCall(PetscLogEventRegister("BVMatMult",BV_CLASSID,&BV_MatMult));
     87:   PetscCall(PetscLogEventRegister("BVMatMultVec",BV_CLASSID,&BV_MatMultVec));
     88:   PetscCall(PetscLogEventRegister("BVMatProject",BV_CLASSID,&BV_MatProject));
     89:   PetscCall(PetscLogEventRegister("BVSVDAndRank",BV_CLASSID,&BV_SVDAndRank));
     90:   /* MPI reduction operation used in BVOrthogonalize */
     91:   PetscCallMPI(MPI_Op_create(SlepcGivensPacked,PETSC_FALSE,&MPIU_TSQR));
     92:   PetscCallMPI(MPI_Op_create(SlepcPythag,PETSC_TRUE,&MPIU_LAPY2));
     93:   /* Process Info */
     94:   classids[0] = BV_CLASSID;
     95:   PetscCall(PetscInfoProcessClass("bv",1,&classids[0]));
     96:   /* Process summary exclusions */
     97:   PetscCall(PetscOptionsGetString(NULL,NULL,"-log_exclude",logList,sizeof(logList),&opt));
     98:   if (opt) {
     99:     PetscCall(PetscStrInList("bv",logList,',',&pkg));
    100:     if (pkg) PetscCall(PetscLogEventDeactivateClass(BV_CLASSID));
    101:   }
    102:   /* Register package finalizer */
    103:   PetscCall(PetscRegisterFinalize(BVFinalizePackage));
    104:   PetscFunctionReturn(PETSC_SUCCESS);
    105: }

    107: /*@
    108:    BVDestroy - Destroys a `BV` context that was created with `BVCreate()`.

    110:    Collective

    112:    Input Parameter:
    113: .  bv - the basis vectors context

    115:    Level: beginner

    117: .seealso: [](sec:bv), `BVCreate()`
    118: @*/
    119: PetscErrorCode BVDestroy(BV *bv)
    120: {
    121:   PetscFunctionBegin;
    122:   if (!*bv) PetscFunctionReturn(PETSC_SUCCESS);
    124:   PetscCheck(!(*bv)->lsplit,PetscObjectComm((PetscObject)*bv),PETSC_ERR_ARG_WRONGSTATE,"Must call BVRestoreSplit before destroying the BV");
    125:   if (--((PetscObject)*bv)->refct > 0) { *bv = NULL; PetscFunctionReturn(PETSC_SUCCESS); }
    126:   PetscTryTypeMethod(*bv,destroy);
    127:   PetscCall(PetscLayoutDestroy(&(*bv)->map));
    128:   PetscCall(PetscFree((*bv)->vtype));
    129:   PetscCall(MatDestroy(&(*bv)->matrix));
    130:   PetscCall(VecDestroy(&(*bv)->Bx));
    131:   PetscCall(VecDestroy(&(*bv)->buffer));
    132:   PetscCall(BVDestroy(&(*bv)->cached));
    133:   PetscCall(BVDestroy(&(*bv)->L));
    134:   PetscCall(BVDestroy(&(*bv)->R));
    135:   PetscCall(PetscFree((*bv)->work));
    136:   PetscCall(PetscFree2((*bv)->h,(*bv)->c));
    137:   PetscCall(VecDestroy(&(*bv)->omega));
    138:   PetscCall(MatDestroy(&(*bv)->Acreate));
    139:   PetscCall(MatDestroy(&(*bv)->Aget));
    140:   PetscCall(MatDestroy(&(*bv)->Abuffer));
    141:   PetscCall(PetscRandomDestroy(&(*bv)->rand));
    142:   PetscCall(PetscHeaderDestroy(bv));
    143:   PetscFunctionReturn(PETSC_SUCCESS);
    144: }

    146: /*@
    147:    BVCreate - Creates a basis vectors context.

    149:    Collective

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

    154:    Output Parameter:
    155: .  newbv - location to put the basis vectors context

    157:    Note:
    158:    A basis vectors object of type `BVTENSOR` should be created using
    159:    the helper function `BVCreateTensor()` instead of this one.

    161:    Level: beginner

    163: .seealso: [](sec:bv), `BV`, `BVDuplicate()`, `BVDestroy()`, `BVCreateTensor()` , `BVCreateFromMat()`
    164: @*/
    165: PetscErrorCode BVCreate(MPI_Comm comm,BV *newbv)
    166: {
    167:   BV             bv;

    169:   PetscFunctionBegin;
    170:   PetscAssertPointer(newbv,2);
    171:   PetscCall(BVInitializePackage());
    172:   PetscCall(SlepcHeaderCreate(bv,BV_CLASSID,"BV","Basis Vectors","BV",comm,BVDestroy,BVView));

    174:   bv->map          = NULL;
    175:   bv->vtype        = NULL;
    176:   bv->n            = -1;
    177:   bv->N            = -1;
    178:   bv->m            = 0;
    179:   bv->l            = 0;
    180:   bv->k            = 0;
    181:   bv->nc           = 0;
    182:   bv->ld           = 0;
    183:   bv->orthog_type  = BV_ORTHOG_CGS;
    184:   bv->orthog_ref   = BV_ORTHOG_REFINE_IFNEEDED;
    185:   bv->orthog_eta   = 0.7071;
    186:   bv->orthog_block = BV_ORTHOG_BLOCK_GS;
    187:   bv->matrix       = NULL;
    188:   bv->indef        = PETSC_FALSE;
    189:   bv->vmm          = BV_MATMULT_MAT;
    190:   bv->rrandom      = PETSC_FALSE;
    191:   bv->deftol       = 10*PETSC_MACHINE_EPSILON;

    193:   bv->buffer       = NULL;
    194:   bv->Abuffer      = NULL;
    195:   bv->Bx           = NULL;
    196:   bv->xid          = 0;
    197:   bv->xstate       = 0;
    198:   bv->cv[0]        = NULL;
    199:   bv->cv[1]        = NULL;
    200:   bv->ci[0]        = -1;
    201:   bv->ci[1]        = -1;
    202:   bv->st[0]        = -1;
    203:   bv->st[1]        = -1;
    204:   bv->id[0]        = 0;
    205:   bv->id[1]        = 0;
    206:   bv->h            = NULL;
    207:   bv->c            = NULL;
    208:   bv->omega        = NULL;
    209:   bv->defersfo     = PETSC_FALSE;
    210:   bv->cached       = NULL;
    211:   bv->bvstate      = 0;
    212:   bv->L            = NULL;
    213:   bv->R            = NULL;
    214:   bv->lstate       = 0;
    215:   bv->rstate       = 0;
    216:   bv->lsplit       = 0;
    217:   bv->issplit      = 0;
    218:   bv->splitparent  = NULL;
    219:   bv->rand         = NULL;
    220:   bv->Acreate      = NULL;
    221:   bv->Aget         = NULL;
    222:   bv->cuda         = PETSC_FALSE;
    223:   bv->hip          = PETSC_FALSE;
    224:   bv->sfocalled    = PETSC_FALSE;
    225:   bv->work         = NULL;
    226:   bv->lwork        = 0;
    227:   bv->data         = NULL;

    229:   *newbv = bv;
    230:   PetscFunctionReturn(PETSC_SUCCESS);
    231: }

    233: /*@
    234:    BVCreateFromMat - Creates a basis vectors object from a dense `Mat` object.

    236:    Collective

    238:    Input Parameter:
    239: .  A - a dense tall-skinny matrix

    241:    Output Parameter:
    242: .  bv - the new basis vectors context

    244:    Notes:
    245:    The matrix values are copied to the `BV` data storage, memory is not shared.

    247:    The communicator of the `BV` object will be the same as `A`, and so will be
    248:    the dimensions.

    250:    Level: intermediate

    252: .seealso: [](sec:bv), `BVCreate()`, `BVDestroy()`, `BVCreateMat()`
    253: @*/
    254: PetscErrorCode BVCreateFromMat(Mat A,BV *bv)
    255: {
    256:   PetscInt  n,N,k;
    257:   VecType   vtype;

    259:   PetscFunctionBegin;

    262:   PetscCall(MatGetSize(A,&N,&k));
    263:   PetscCall(MatGetLocalSize(A,&n,NULL));
    264:   PetscCall(MatGetVecType(A,&vtype));
    265:   PetscCall(BVCreate(PetscObjectComm((PetscObject)A),bv));
    266:   PetscCall(BVSetSizes(*bv,n,N,k));
    267:   PetscCall(BVSetVecType(*bv,vtype));

    269:   (*bv)->Acreate = A;
    270:   PetscCall(PetscObjectReference((PetscObject)A));
    271:   PetscFunctionReturn(PETSC_SUCCESS);
    272: }

    274: /*@
    275:    BVInsertVec - Insert a vector into the specified column.

    277:    Logically Collective

    279:    Input Parameters:
    280: +  V - basis vectors
    281: .  j - the column of `V` to be overwritten
    282: -  w - the vector to be copied

    284:    Level: intermediate

    286: .seealso: [](sec:bv), `BVInsertVecs()`
    287: @*/
    288: PetscErrorCode BVInsertVec(BV V,PetscInt j,Vec w)
    289: {
    290:   PetscInt       n,N;
    291:   Vec            v;

    293:   PetscFunctionBegin;
    298:   BVCheckSizes(V,1);
    299:   PetscCheckSameComm(V,1,w,3);

    301:   PetscCall(VecGetSize(w,&N));
    302:   PetscCall(VecGetLocalSize(w,&n));
    303:   PetscCheck(N==V->N && n==V->n,PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_INCOMP,"Vec sizes (global %" PetscInt_FMT ", local %" PetscInt_FMT ") do not match BV sizes (global %" PetscInt_FMT ", local %" PetscInt_FMT ")",N,n,V->N,V->n);
    304:   PetscCheck(j>=-V->nc && j<V->m,PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_OUTOFRANGE,"Argument j has wrong value %" PetscInt_FMT ", should be between %" PetscInt_FMT " and %" PetscInt_FMT,j,-V->nc,V->m-1);

    306:   PetscCall(BVGetColumn(V,j,&v));
    307:   PetscCall(VecCopy(w,v));
    308:   PetscCall(BVRestoreColumn(V,j,&v));
    309:   PetscCall(PetscObjectStateIncrease((PetscObject)V));
    310:   PetscFunctionReturn(PETSC_SUCCESS);
    311: }

    313: /*@
    314:    BVInsertVecs - Insert a set of vectors into the specified columns.

    316:    Collective

    318:    Input Parameters:
    319: +  V - basis vectors
    320: .  s - first column of `V` to be overwritten
    321: .  W - array of vectors to be copied
    322: -  orth - flag indicating if the vectors must be orthogonalized

    324:    Input/Output Parameter:
    325: .  m - number of input vectors, on output the number of linearly independent
    326:        vectors

    328:    Notes:
    329:    Copies the contents of vectors `W` to `V(:,s:s+n)`. If the orthogonalization
    330:    flag is set, then the vectors are copied one by one and then orthogonalized
    331:    against the previous ones. If any of them is linearly dependent then it
    332:    is discarded and the value of `m` is decreased.

    334:    Level: intermediate

    336: .seealso: [](sec:bv), `BVInsertVec()`, `BVOrthogonalizeColumn()`
    337: @*/
    338: PetscErrorCode BVInsertVecs(BV V,PetscInt s,PetscInt *m,Vec W[],PetscBool orth)
    339: {
    340:   PetscInt       n,N,i,ndep;
    341:   PetscBool      lindep;
    342:   PetscReal      norm;
    343:   Vec            v;

    345:   PetscFunctionBegin;
    348:   PetscAssertPointer(m,3);
    350:   if (!*m) PetscFunctionReturn(PETSC_SUCCESS);
    351:   PetscCheck(*m>0,PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_OUTOFRANGE,"Number of vectors (given %" PetscInt_FMT ") cannot be negative",*m);
    352:   PetscAssertPointer(W,4);
    356:   BVCheckSizes(V,1);
    357:   PetscCheckSameComm(V,1,*W,4);

    359:   PetscCall(VecGetSize(*W,&N));
    360:   PetscCall(VecGetLocalSize(*W,&n));
    361:   PetscCheck(N==V->N && n==V->n,PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_INCOMP,"Vec sizes (global %" PetscInt_FMT ", local %" PetscInt_FMT ") do not match BV sizes (global %" PetscInt_FMT ", local %" PetscInt_FMT ")",N,n,V->N,V->n);
    362:   PetscCheck(s>=0 && s<V->m,PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_OUTOFRANGE,"Argument s has wrong value %" PetscInt_FMT ", should be between 0 and %" PetscInt_FMT,s,V->m-1);
    363:   PetscCheck(s+(*m)<=V->m,PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_OUTOFRANGE,"Too many vectors provided, there is only room for %" PetscInt_FMT,V->m);

    365:   ndep = 0;
    366:   for (i=0;i<*m;i++) {
    367:     PetscCall(BVGetColumn(V,s+i-ndep,&v));
    368:     PetscCall(VecCopy(W[i],v));
    369:     PetscCall(BVRestoreColumn(V,s+i-ndep,&v));
    370:     if (orth) {
    371:       PetscCall(BVOrthogonalizeColumn(V,s+i-ndep,NULL,&norm,&lindep));
    372:       if (norm==0.0 || lindep) {
    373:         PetscCall(PetscInfo(V,"Removing linearly dependent vector %" PetscInt_FMT "\n",i));
    374:         ndep++;
    375:       } else PetscCall(BVScaleColumn(V,s+i-ndep,1.0/norm));
    376:     }
    377:   }
    378:   *m -= ndep;
    379:   PetscCall(PetscObjectStateIncrease((PetscObject)V));
    380:   PetscFunctionReturn(PETSC_SUCCESS);
    381: }

    383: /*@
    384:    BVInsertConstraints - Insert a set of vectors as constraints.

    386:    Collective

    388:    Input Parameters:
    389: +  V - basis vectors
    390: -  C - set of vectors to be inserted as constraints

    392:    Input/Output Parameter:
    393: .  nc - number of input vectors, on output the number of linearly independent
    394:        vectors

    396:    Notes:
    397:    The constraints are relevant only during orthogonalization. Constraint
    398:    vectors span a subspace that is deflated in every orthogonalization
    399:    operation, so they are intended for removing those directions from the
    400:    orthogonal basis computed in regular `BV` columns.

    402:    Constraints are not stored in regular `BV` columns, but in a special part of
    403:    the storage. They can be accessed with negative indices in `BVGetColumn()`.

    405:    This operation is DESTRUCTIVE, meaning that all data contained in the
    406:    columns of `V` is lost. This is typically invoked just after creating the `BV`.
    407:    Once a set of constraints has been set, it is not allowed to call this
    408:    function again.

    410:    The vectors are copied one by one and then orthogonalized against the
    411:    previous ones. If any of them is linearly dependent then it is discarded
    412:    and the value of `nc` is decreased. The behavior is similar to `BVInsertVecs()`.

    414:    Level: advanced

    416: .seealso: [](sec:bv), `BVInsertVecs()`, `BVOrthogonalizeColumn()`, `BVGetColumn()`, `BVGetNumConstraints()`
    417: @*/
    418: PetscErrorCode BVInsertConstraints(BV V,PetscInt *nc,Vec C[])
    419: {
    420:   PetscInt       msave;

    422:   PetscFunctionBegin;
    424:   PetscAssertPointer(nc,2);
    426:   if (!*nc) PetscFunctionReturn(PETSC_SUCCESS);
    427:   PetscCheck(*nc>0,PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_OUTOFRANGE,"Number of constraints (given %" PetscInt_FMT ") cannot be negative",*nc);
    428:   PetscAssertPointer(C,3);
    431:   BVCheckSizes(V,1);
    432:   PetscCheckSameComm(V,1,*C,3);
    433:   PetscCheck(!V->issplit,PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_WRONGSTATE,"Operation not permitted for a BV obtained from BVGetSplit");
    434:   PetscCheck(!V->nc,PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_WRONGSTATE,"Constraints already present in this BV object");
    435:   PetscCheck(V->ci[0]==-1 && V->ci[1]==-1,PetscObjectComm((PetscObject)V),PETSC_ERR_SUP,"Cannot call BVInsertConstraints after BVGetColumn");

    437:   msave = V->m;
    438:   PetscCall(BVResize(V,*nc+V->m,PETSC_FALSE));
    439:   PetscCall(BVInsertVecs(V,0,nc,C,PETSC_TRUE));
    440:   V->nc = *nc;
    441:   V->m  = msave;
    442:   V->ci[0] = -V->nc-1;
    443:   V->ci[1] = -V->nc-1;
    444:   PetscCall(PetscObjectStateIncrease((PetscObject)V));
    445:   PetscFunctionReturn(PETSC_SUCCESS);
    446: }

    448: /*@
    449:    BVSetOptionsPrefix - Sets the prefix used for searching for all
    450:    `BV` options in the database.

    452:    Logically Collective

    454:    Input Parameters:
    455: +  bv     - the basis vectors context
    456: -  prefix - the prefix string to prepend to all `BV` option requests

    458:    Notes:
    459:    A hyphen (-) must NOT be given at the beginning of the prefix name.
    460:    The first character of all runtime options is AUTOMATICALLY the
    461:    hyphen.

    463:    Level: advanced

    465: .seealso: [](sec:bv), `BVAppendOptionsPrefix()`, `BVGetOptionsPrefix()`
    466: @*/
    467: PetscErrorCode BVSetOptionsPrefix(BV bv,const char prefix[])
    468: {
    469:   PetscFunctionBegin;
    471:   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)bv,prefix));
    472:   PetscFunctionReturn(PETSC_SUCCESS);
    473: }

    475: /*@
    476:    BVAppendOptionsPrefix - Appends to the prefix used for searching for all
    477:    `BV` options in the database.

    479:    Logically Collective

    481:    Input Parameters:
    482: +  bv     - the basis vectors context
    483: -  prefix - the prefix string to prepend to all `BV` option requests

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

    490:    Level: advanced

    492: .seealso: [](sec:bv), `BVSetOptionsPrefix()`, `BVGetOptionsPrefix()`
    493: @*/
    494: PetscErrorCode BVAppendOptionsPrefix(BV bv,const char prefix[])
    495: {
    496:   PetscFunctionBegin;
    498:   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)bv,prefix));
    499:   PetscFunctionReturn(PETSC_SUCCESS);
    500: }

    502: /*@
    503:    BVGetOptionsPrefix - Gets the prefix used for searching for all
    504:    `BV` options in the database.

    506:    Not Collective

    508:    Input Parameter:
    509: .  bv - the basis vectors context

    511:    Output Parameter:
    512: .  prefix - pointer to the prefix string used is returned

    514:    Level: advanced

    516: .seealso: [](sec:bv), `BVSetOptionsPrefix()`, `BVAppendOptionsPrefix()`
    517: @*/
    518: PetscErrorCode BVGetOptionsPrefix(BV bv,const char *prefix[])
    519: {
    520:   PetscFunctionBegin;
    522:   PetscAssertPointer(prefix,2);
    523:   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)bv,prefix));
    524:   PetscFunctionReturn(PETSC_SUCCESS);
    525: }

    527: /*@
    528:    BVView - Prints the `BV` data structure.

    530:    Collective

    532:    Input Parameters:
    533: +  bv     - the basis vectors context
    534: -  viewer - optional visualization context

    536:    Notes:
    537:    The available visualization contexts include
    538: +     `PETSC_VIEWER_STDOUT_SELF` - standard output (default)
    539: -     `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard output where only the
    540:          first process opens the file; all other processes send their data to the
    541:          first one to print

    543:    The user can open an alternative visualization context with `PetscViewerASCIIOpen()`
    544:    to output to a specified file.

    546:    Use `BVViewFromOptions()` to allow the user to select many different `PetscViewerType`
    547:    and formats from the options database.

    549:    Level: beginner

    551: .seealso: [](sec:bv), `BVCreate()`
    552: @*/
    553: PetscErrorCode BVView(BV bv,PetscViewer viewer)
    554: {
    555:   PetscBool         isascii;
    556:   PetscViewerFormat format;
    557:   const char        *orthname[2] = {"classical","modified"};
    558:   const char        *refname[3] = {"if needed","never","always"};

    560:   PetscFunctionBegin;
    562:   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)bv),&viewer));

    565:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii));
    566:   if (isascii) {
    567:     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)bv,viewer));
    568:     PetscCall(PetscViewerGetFormat(viewer,&format));
    569:     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
    570:       PetscCall(PetscViewerASCIIPrintf(viewer,"  %" PetscInt_FMT " columns of global length %" PetscInt_FMT "%s\n",bv->m,bv->N,bv->cuda?" (CUDA)":bv->hip?" (HIP)":""));
    571:       if (bv->nc>0) PetscCall(PetscViewerASCIIPrintf(viewer,"  number of constraints: %" PetscInt_FMT "\n",bv->nc));
    572:       PetscCall(PetscViewerASCIIPrintf(viewer,"  vector orthogonalization method: %s Gram-Schmidt\n",orthname[bv->orthog_type]));
    573:       switch (bv->orthog_ref) {
    574:         case BV_ORTHOG_REFINE_IFNEEDED:
    575:           PetscCall(PetscViewerASCIIPrintf(viewer,"  orthogonalization refinement: %s (eta: %g)\n",refname[bv->orthog_ref],(double)bv->orthog_eta));
    576:           break;
    577:         case BV_ORTHOG_REFINE_NEVER:
    578:         case BV_ORTHOG_REFINE_ALWAYS:
    579:           PetscCall(PetscViewerASCIIPrintf(viewer,"  orthogonalization refinement: %s\n",refname[bv->orthog_ref]));
    580:           break;
    581:       }
    582:       PetscCall(PetscViewerASCIIPrintf(viewer,"  block orthogonalization method: %s\n",BVOrthogBlockTypes[bv->orthog_block]));
    583:       if (bv->matrix) {
    584:         if (bv->indef) PetscCall(PetscViewerASCIIPrintf(viewer,"  indefinite inner product\n"));
    585:         else PetscCall(PetscViewerASCIIPrintf(viewer,"  non-standard inner product\n"));
    586:         PetscCall(PetscViewerASCIIPrintf(viewer,"  tolerance for definite inner product: %g\n",(double)bv->deftol));
    587:         PetscCall(PetscViewerASCIIPrintf(viewer,"  inner product matrix:\n"));
    588:         PetscCall(PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_INFO));
    589:         PetscCall(PetscViewerASCIIPushTab(viewer));
    590:         PetscCall(MatView(bv->matrix,viewer));
    591:         PetscCall(PetscViewerASCIIPopTab(viewer));
    592:         PetscCall(PetscViewerPopFormat(viewer));
    593:       }
    594:       switch (bv->vmm) {
    595:         case BV_MATMULT_VECS:
    596:           PetscCall(PetscViewerASCIIPrintf(viewer,"  doing matmult as matrix-vector products\n"));
    597:           break;
    598:         case BV_MATMULT_MAT:
    599:           PetscCall(PetscViewerASCIIPrintf(viewer,"  doing matmult as a single matrix-matrix product\n"));
    600:           break;
    601:         case BV_MATMULT_MAT_SAVE:
    602:           PetscCall(PetscViewerASCIIPrintf(viewer,"  mat_save is deprecated, use mat\n"));
    603:           break;
    604:       }
    605:       if (bv->rrandom) PetscCall(PetscViewerASCIIPrintf(viewer,"  generating random vectors independent of the number of processes\n"));
    606:     }
    607:   }
    608:   PetscTryTypeMethod(bv,view,viewer);
    609:   PetscFunctionReturn(PETSC_SUCCESS);
    610: }

    612: /*@
    613:    BVViewFromOptions - View (print) a `BV` object based on values in the options database.

    615:    Collective

    617:    Input Parameters:
    618: +  bv   - the basis vectors context
    619: .  obj  - optional object that provides the options prefix used to query the options database
    620: -  name - command line option

    622:    Level: intermediate

    624: .seealso: [](sec:bv), `BVView()`, `BVCreate()`, `PetscObjectViewFromOptions()`
    625: @*/
    626: PetscErrorCode BVViewFromOptions(BV bv,PetscObject obj,const char name[])
    627: {
    628:   PetscFunctionBegin;
    630:   PetscCall(PetscObjectViewFromOptions((PetscObject)bv,obj,name));
    631:   PetscFunctionReturn(PETSC_SUCCESS);
    632: }

    634: /*@C
    635:    BVRegister - Adds a new storage format to the `BV` package.

    637:    Not Collective

    639:    Input Parameters:
    640: +  name     - name of a new user-defined `BV`
    641: -  function - routine to create context

    643:    Notes:
    644:    `BVRegister()` may be called multiple times to add several user-defined
    645:    basis vectors.

    647:    Level: advanced

    649: .seealso: [](sec:bv), `BVRegisterAll()`
    650: @*/
    651: PetscErrorCode BVRegister(const char *name,PetscErrorCode (*function)(BV))
    652: {
    653:   PetscFunctionBegin;
    654:   PetscCall(BVInitializePackage());
    655:   PetscCall(PetscFunctionListAdd(&BVList,name,function));
    656:   PetscFunctionReturn(PETSC_SUCCESS);
    657: }

    659: PetscErrorCode BVAllocateWork_Private(BV bv,PetscInt s)
    660: {
    661:   PetscFunctionBegin;
    662:   if (s>bv->lwork) {
    663:     PetscCall(PetscFree(bv->work));
    664:     PetscCall(PetscMalloc1(s,&bv->work));
    665:     bv->lwork = s;
    666:   }
    667:   PetscFunctionReturn(PETSC_SUCCESS);
    668: }

    670: #if defined(PETSC_USE_DEBUG) && !defined(PETSC_CLANG_STATIC_ANALYZER)
    671: /*
    672:    SlepcDebugBVView - partially view a BV object, to be used from within a debugger.

    674:      ini, end: columns to be viewed
    675:      s: name of Matlab variable
    676:      filename: optionally write output to a file
    677:  */
    678: PETSC_UNUSED PetscErrorCode SlepcDebugBVView(BV bv,PetscInt ini,PetscInt end,const char *s,const char *filename)
    679: {
    680:   PetscInt       N,m;
    681:   PetscScalar    *array;

    683:   PetscFunctionBegin;
    684:   PetscCall(BVGetArray(bv,&array));
    685:   PetscCall(BVGetSizes(bv,NULL,&N,&m));
    686:   PetscCall(SlepcDebugViewMatrix(N,end-ini+1,array+ini*N,NULL,bv->ld,s,filename));
    687:   PetscCall(BVRestoreArray(bv,&array));
    688:   PetscFunctionReturn(PETSC_SUCCESS);
    689: }
    690: #endif