Date: 2023-11-27T17:19:25+00:00

Actual source code: bvbasic.c
slepc-3.20.1 2023-11-27
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:    Basic BV routines
     12: */

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

     16: PetscBool         BVRegisterAllCalled = PETSC_FALSE;
     17: PetscFunctionList BVList = NULL;

     19: /*@C
     20:    BVSetType - Selects the type for the BV object.

     22:    Logically Collective

     24:    Input Parameters:
     25: +  bv   - the basis vectors context
     26: -  type - a known type

     28:    Options Database Key:
     29: .  -bv_type <type> - Sets BV type

     31:    Level: intermediate

     33: .seealso: BVGetType()
     34: @*/
     35: PetscErrorCode BVSetType(BV bv,BVType type)
     36: {
     37:   PetscErrorCode (*r)(BV);
     38:   PetscBool      match;

     40:   PetscFunctionBegin;
     42:   PetscAssertPointer(type,2);

     44:   PetscCall(PetscObjectTypeCompare((PetscObject)bv,type,&match));
     45:   if (match) PetscFunctionReturn(PETSC_SUCCESS);
     46:   PetscCall(PetscStrcmp(type,BVTENSOR,&match));
     47:   PetscCheck(!match,PetscObjectComm((PetscObject)bv),PETSC_ERR_ORDER,"Use BVCreateTensor() to create a BV of type tensor");

     49:   PetscCall(PetscFunctionListFind(BVList,type,&r));
     50:   PetscCheck(r,PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested BV type %s",type);

     52:   PetscTryTypeMethod(bv,destroy);
     53:   PetscCall(PetscMemzero(bv->ops,sizeof(struct _BVOps)));

     55:   PetscCall(PetscObjectChangeTypeName((PetscObject)bv,type));
     56:   if (bv->n < 0 && bv->N < 0) {
     57:     bv->ops->create = r;
     58:   } else {
     59:     PetscCall(PetscLogEventBegin(BV_Create,bv,0,0,0));
     60:     PetscCall((*r)(bv));
     61:     PetscCall(PetscLogEventEnd(BV_Create,bv,0,0,0));
     62:   }
     63:   PetscFunctionReturn(PETSC_SUCCESS);
     64: }

     66: /*@C
     67:    BVGetType - Gets the BV type name (as a string) from the BV context.

     69:    Not Collective

     71:    Input Parameter:
     72: .  bv - the basis vectors context

     74:    Output Parameter:
     75: .  type - name of the type of basis vectors

     77:    Level: intermediate

     79: .seealso: BVSetType()
     80: @*/
     81: PetscErrorCode BVGetType(BV bv,BVType *type)
     82: {
     83:   PetscFunctionBegin;
     85:   PetscAssertPointer(type,2);
     86:   *type = ((PetscObject)bv)->type_name;
     87:   PetscFunctionReturn(PETSC_SUCCESS);
     88: }

     90: /*@
     91:    BVSetSizes - Sets the local and global sizes, and the number of columns.

     93:    Collective

     95:    Input Parameters:
     96: +  bv - the basis vectors
     97: .  n  - the local size (or PETSC_DECIDE to have it set)
     98: .  N  - the global size (or PETSC_DECIDE)
     99: -  m  - the number of columns

    101:    Notes:
    102:    n and N cannot be both PETSC_DECIDE.
    103:    If one processor calls this with N of PETSC_DECIDE then all processors must,
    104:    otherwise the program will hang.

    106:    Level: beginner

    108: .seealso: BVSetSizesFromVec(), BVGetSizes(), BVResize()
    109: @*/
    110: PetscErrorCode BVSetSizes(BV bv,PetscInt n,PetscInt N,PetscInt m)
    111: {
    112:   PetscInt       ma;

    114:   PetscFunctionBegin;
    118:   PetscCheck(N<0 || n<=N,PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_INCOMP,"Local size %" PetscInt_FMT " cannot be larger than global size %" PetscInt_FMT,n,N);
    119:   PetscCheck(m>0,PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_INCOMP,"Number of columns %" PetscInt_FMT " must be positive",m);
    120:   PetscCheck((bv->n<0 && bv->N<0) || (bv->n==n && bv->N==N),PetscObjectComm((PetscObject)bv),PETSC_ERR_SUP,"Cannot change/reset vector sizes to %" PetscInt_FMT " local %" PetscInt_FMT " global after previously setting them to %" PetscInt_FMT " local %" PetscInt_FMT " global",n,N,bv->n,bv->N);
    121:   PetscCheck(bv->m<=0 || bv->m==m,PetscObjectComm((PetscObject)bv),PETSC_ERR_SUP,"Cannot change the number of columns to %" PetscInt_FMT " after previously setting it to %" PetscInt_FMT "; use BVResize()",m,bv->m);
    122:   bv->n = n;
    123:   bv->N = N;
    124:   bv->m = m;
    125:   bv->k = m;
    126:   if (!bv->t) {  /* create template vector and get actual dimensions */
    127:     PetscCall(VecCreate(PetscObjectComm((PetscObject)bv),&bv->t));
    128:     PetscCall(VecSetSizes(bv->t,bv->n,bv->N));
    129:     PetscCall(VecSetFromOptions(bv->t));
    130:     PetscCall(VecGetSize(bv->t,&bv->N));
    131:     PetscCall(VecGetLocalSize(bv->t,&bv->n));
    132:     if (bv->matrix) {  /* check compatible dimensions of user-provided matrix */
    133:       PetscCall(MatGetLocalSize(bv->matrix,&ma,NULL));
    134:       PetscCheck(bv->n==ma,PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_INCOMP,"Local dimension %" PetscInt_FMT " does not match that of matrix given at BVSetMatrix %" PetscInt_FMT,bv->n,ma);
    135:     }
    136:   }
    137:   if (bv->ops->create) {
    138:     PetscCall(PetscLogEventBegin(BV_Create,bv,0,0,0));
    139:     PetscUseTypeMethod(bv,create);
    140:     PetscCall(PetscLogEventEnd(BV_Create,bv,0,0,0));
    141:     bv->ops->create = NULL;
    142:     bv->defersfo = PETSC_FALSE;
    143:   }
    144:   PetscFunctionReturn(PETSC_SUCCESS);
    145: }

    147: /*@
    148:    BVSetSizesFromVec - Sets the local and global sizes, and the number of columns.
    149:    Local and global sizes are specified indirectly by passing a template vector.

    151:    Collective

    153:    Input Parameters:
    154: +  bv - the basis vectors
    155: .  t  - the template vector
    156: -  m  - the number of columns

    158:    Level: beginner

    160: .seealso: BVSetSizes(), BVGetSizes(), BVResize()
    161: @*/
    162: PetscErrorCode BVSetSizesFromVec(BV bv,Vec t,PetscInt m)
    163: {
    164:   PetscInt       ma;

    166:   PetscFunctionBegin;
    169:   PetscCheckSameComm(bv,1,t,2);
    171:   PetscCheck(m>0,PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_INCOMP,"Number of columns %" PetscInt_FMT " must be positive",m);
    172:   PetscCheck(!bv->t,PetscObjectComm((PetscObject)bv),PETSC_ERR_SUP,"Template vector was already set by a previous call to BVSetSizes/FromVec");
    173:   PetscCall(VecGetSize(t,&bv->N));
    174:   PetscCall(VecGetLocalSize(t,&bv->n));
    175:   if (bv->matrix) {  /* check compatible dimensions of user-provided matrix */
    176:     PetscCall(MatGetLocalSize(bv->matrix,&ma,NULL));
    177:     PetscCheck(bv->n==ma,PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_INCOMP,"Local dimension %" PetscInt_FMT " does not match that of matrix given at BVSetMatrix %" PetscInt_FMT,bv->n,ma);
    178:   }
    179:   bv->m = m;
    180:   bv->k = m;
    181:   bv->t = t;
    182:   PetscCall(PetscObjectReference((PetscObject)t));
    183:   if (bv->ops->create) {
    184:     PetscUseTypeMethod(bv,create);
    185:     bv->ops->create = NULL;
    186:     bv->defersfo = PETSC_FALSE;
    187:   }
    188:   PetscFunctionReturn(PETSC_SUCCESS);
    189: }

    191: /*@
    192:    BVGetSizes - Returns the local and global sizes, and the number of columns.

    194:    Not Collective

    196:    Input Parameter:
    197: .  bv - the basis vectors

    199:    Output Parameters:
    200: +  n  - the local size
    201: .  N  - the global size
    202: -  m  - the number of columns

    204:    Note:
    205:    Normal usage requires that bv has already been given its sizes, otherwise
    206:    the call fails. However, this function can also be used to determine if
    207:    a BV object has been initialized completely (sizes and type). For this,
    208:    call with n=NULL and N=NULL, then a return value of m=0 indicates that
    209:    the BV object is not ready for use yet.

    211:    Level: beginner

    213: .seealso: BVSetSizes(), BVSetSizesFromVec()
    214: @*/
    215: PetscErrorCode BVGetSizes(BV bv,PetscInt *n,PetscInt *N,PetscInt *m)
    216: {
    217:   PetscFunctionBegin;
    218:   if (!bv) {
    219:     if (m && !n && !N) *m = 0;
    220:     PetscFunctionReturn(PETSC_SUCCESS);
    221:   }
    223:   if (n || N) BVCheckSizes(bv,1);
    224:   if (n) *n = bv->n;
    225:   if (N) *N = bv->N;
    226:   if (m) *m = bv->m;
    227:   if (m && !n && !N && !((PetscObject)bv)->type_name) *m = 0;
    228:   PetscFunctionReturn(PETSC_SUCCESS);
    229: }

    231: /*@
    232:    BVSetNumConstraints - Set the number of constraints.

    234:    Logically Collective

    236:    Input Parameters:
    237: +  V  - basis vectors
    238: -  nc - number of constraints

    240:    Notes:
    241:    This function sets the number of constraints to nc and marks all remaining
    242:    columns as regular. Normal user would call BVInsertConstraints() instead.

    244:    If nc is smaller than the previously set value, then some of the constraints
    245:    are discarded. In particular, using nc=0 removes all constraints preserving
    246:    the content of regular columns.

    248:    Level: developer

    250: .seealso: BVInsertConstraints()
    251: @*/
    252: PetscErrorCode BVSetNumConstraints(BV V,PetscInt nc)
    253: {
    254:   PetscInt       total,diff,i;
    255:   Vec            x,y;

    257:   PetscFunctionBegin;
    260:   PetscCheck(nc>=0,PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_OUTOFRANGE,"Number of constraints (given %" PetscInt_FMT ") cannot be negative",nc);
    262:   BVCheckSizes(V,1);
    263:   PetscCheck(V->ci[0]==-V->nc-1 && V->ci[1]==-V->nc-1,PetscObjectComm((PetscObject)V),PETSC_ERR_SUP,"Cannot call BVSetNumConstraints after BVGetColumn");

    265:   diff = nc-V->nc;
    266:   if (!diff) PetscFunctionReturn(PETSC_SUCCESS);
    267:   total = V->nc+V->m;
    268:   PetscCheck(total-nc>0,PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_OUTOFRANGE,"Not enough columns for the given nc value");
    269:   if (diff<0) {  /* lessen constraints, shift contents of BV */
    270:     for (i=0;i<V->m;i++) {
    271:       PetscCall(BVGetColumn(V,i,&x));
    272:       PetscCall(BVGetColumn(V,i+diff,&y));
    273:       PetscCall(VecCopy(x,y));
    274:       PetscCall(BVRestoreColumn(V,i,&x));
    275:       PetscCall(BVRestoreColumn(V,i+diff,&y));
    276:     }
    277:   }
    278:   V->nc = nc;
    279:   V->ci[0] = -V->nc-1;
    280:   V->ci[1] = -V->nc-1;
    281:   V->m = total-nc;
    282:   V->l = PetscMin(V->l,V->m);
    283:   V->k = PetscMin(V->k,V->m);
    284:   PetscCall(PetscObjectStateIncrease((PetscObject)V));
    285:   PetscFunctionReturn(PETSC_SUCCESS);
    286: }

    288: /*@
    289:    BVGetNumConstraints - Returns the number of constraints.

    291:    Not Collective

    293:    Input Parameter:
    294: .  bv - the basis vectors

    296:    Output Parameters:
    297: .  nc - the number of constraints

    299:    Level: advanced

    301: .seealso: BVGetSizes(), BVInsertConstraints()
    302: @*/
    303: PetscErrorCode BVGetNumConstraints(BV bv,PetscInt *nc)
    304: {
    305:   PetscFunctionBegin;
    307:   PetscAssertPointer(nc,2);
    308:   *nc = bv->nc;
    309:   PetscFunctionReturn(PETSC_SUCCESS);
    310: }

    312: /*@
    313:    BVResize - Change the number of columns.

    315:    Collective

    317:    Input Parameters:
    318: +  bv   - the basis vectors
    319: .  m    - the new number of columns
    320: -  copy - a flag indicating whether current values should be kept

    322:    Note:
    323:    Internal storage is reallocated. If the copy flag is set to true, then
    324:    the contents are copied to the leading part of the new space.

    326:    Level: advanced

    328: .seealso: BVSetSizes(), BVSetSizesFromVec()
    329: @*/
    330: PetscErrorCode BVResize(BV bv,PetscInt m,PetscBool copy)
    331: {
    332:   PetscScalar       *array;
    333:   const PetscScalar *omega;
    334:   Vec               v;

    336:   PetscFunctionBegin;
    341:   PetscCheck(m>0,PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_INCOMP,"Number of columns %" PetscInt_FMT " must be positive",m);
    342:   PetscCheck(!bv->nc || bv->issplit,PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_WRONGSTATE,"Cannot resize a BV with constraints");
    343:   if (bv->m == m) PetscFunctionReturn(PETSC_SUCCESS);
    344:   BVCheckOp(bv,1,resize);

    346:   PetscCall(PetscLogEventBegin(BV_Create,bv,0,0,0));
    347:   PetscUseTypeMethod(bv,resize,m,copy);
    348:   PetscCall(VecDestroy(&bv->buffer));
    349:   PetscCall(BVDestroy(&bv->cached));
    350:   PetscCall(PetscFree2(bv->h,bv->c));
    351:   if (bv->omega) {
    352:     if (bv->cuda) {
    353: #if defined(PETSC_HAVE_CUDA)
    354:       PetscCall(VecCreateSeqCUDA(PETSC_COMM_SELF,m,&v));
    355: #else
    356:       SETERRQ(PetscObjectComm((PetscObject)bv),PETSC_ERR_PLIB,"Something wrong happened");
    357: #endif
    358:     } else PetscCall(VecCreateSeq(PETSC_COMM_SELF,m,&v));
    359:     if (copy) {
    360:       PetscCall(VecGetArray(v,&array));
    361:       PetscCall(VecGetArrayRead(bv->omega,&omega));
    362:       PetscCall(PetscArraycpy(array,omega,PetscMin(m,bv->m)));
    363:       PetscCall(VecRestoreArrayRead(bv->omega,&omega));
    364:       PetscCall(VecRestoreArray(v,&array));
    365:     } else PetscCall(VecSet(v,1.0));
    366:     PetscCall(VecDestroy(&bv->omega));
    367:     bv->omega = v;
    368:   }
    369:   bv->m = m;
    370:   bv->k = PetscMin(bv->k,m);
    371:   bv->l = PetscMin(bv->l,m);
    372:   PetscCall(PetscLogEventEnd(BV_Create,bv,0,0,0));
    373:   PetscCall(PetscObjectStateIncrease((PetscObject)bv));
    374:   PetscFunctionReturn(PETSC_SUCCESS);
    375: }

    377: /*@
    378:    BVSetActiveColumns - Specify the columns that will be involved in operations.

    380:    Logically Collective

    382:    Input Parameters:
    383: +  bv - the basis vectors context
    384: .  l  - number of leading columns
    385: -  k  - number of active columns

    387:    Notes:
    388:    In operations such as BVMult() or BVDot(), only the first k columns are
    389:    considered. This is useful when the BV is filled from left to right, so
    390:    the last m-k columns do not have relevant information.

    392:    Also in operations such as BVMult() or BVDot(), the first l columns are
    393:    normally not included in the computation. See the manpage of each
    394:    operation.

    396:    In orthogonalization operations, the first l columns are treated
    397:    differently, they participate in the orthogonalization but the computed
    398:    coefficients are not stored.

    400:    Level: intermediate

    402: .seealso: BVGetActiveColumns(), BVSetSizes()
    403: @*/
    404: PetscErrorCode BVSetActiveColumns(BV bv,PetscInt l,PetscInt k)
    405: {
    406:   PetscFunctionBegin;
    410:   BVCheckSizes(bv,1);
    411:   if (PetscUnlikely(k==PETSC_DECIDE || k==PETSC_DEFAULT)) {
    412:     bv->k = bv->m;
    413:   } else {
    414:     PetscCheck(k>=0 && k<=bv->m,PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of k (%" PetscInt_FMT "). Must be between 0 and m (%" PetscInt_FMT ")",k,bv->m);
    415:     bv->k = k;
    416:   }
    417:   if (PetscUnlikely(l==PETSC_DECIDE || l==PETSC_DEFAULT)) {
    418:     bv->l = 0;
    419:   } else {
    420:     PetscCheck(l>=0 && l<=bv->k,PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of l (%" PetscInt_FMT "). Must be between 0 and k (%" PetscInt_FMT ")",l,bv->k);
    421:     bv->l = l;
    422:   }
    423:   PetscFunctionReturn(PETSC_SUCCESS);
    424: }

    426: /*@
    427:    BVGetActiveColumns - Returns the current active dimensions.

    429:    Not Collective

    431:    Input Parameter:
    432: .  bv - the basis vectors context

    434:    Output Parameters:
    435: +  l  - number of leading columns
    436: -  k  - number of active columns

    438:    Level: intermediate

    440: .seealso: BVSetActiveColumns()
    441: @*/
    442: PetscErrorCode BVGetActiveColumns(BV bv,PetscInt *l,PetscInt *k)
    443: {
    444:   PetscFunctionBegin;
    446:   if (l) *l = bv->l;
    447:   if (k) *k = bv->k;
    448:   PetscFunctionReturn(PETSC_SUCCESS);
    449: }

    451: /*@
    452:    BVSetMatrix - Specifies the inner product to be used in orthogonalization.

    454:    Collective

    456:    Input Parameters:
    457: +  bv    - the basis vectors context
    458: .  B     - a symmetric matrix (may be NULL)
    459: -  indef - a flag indicating if the matrix is indefinite

    461:    Notes:
    462:    This is used to specify a non-standard inner product, whose matrix
    463:    representation is given by B. Then, all inner products required during
    464:    orthogonalization are computed as (x,y)_B=y^H*B*x rather than the
    465:    standard form (x,y)=y^H*x.

    467:    Matrix B must be real symmetric (or complex Hermitian). A genuine inner
    468:    product requires that B is also positive (semi-)definite. However, we
    469:    also allow for an indefinite B (setting indef=PETSC_TRUE), in which
    470:    case the orthogonalization uses an indefinite inner product.

    472:    This affects operations BVDot(), BVNorm(), BVOrthogonalize(), and variants.

    474:    Setting B=NULL has the same effect as if the identity matrix was passed.

    476:    Level: advanced

    478: .seealso: BVGetMatrix(), BVDot(), BVNorm(), BVOrthogonalize(), BVSetDefiniteTolerance()
    479: @*/
    480: PetscErrorCode BVSetMatrix(BV bv,Mat B,PetscBool indef)
    481: {
    482:   PetscInt       m,n;

    484:   PetscFunctionBegin;
    487:   if (B!=bv->matrix || (B && ((PetscObject)B)->id!=((PetscObject)bv->matrix)->id) || indef!=bv->indef) {
    488:     if (B) {
    490:       PetscCall(MatGetLocalSize(B,&m,&n));
    491:       PetscCheck(m==n,PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_SIZ,"Matrix must be square");
    492:       PetscCheck(!bv->m || bv->n==n,PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_INCOMP,"Mismatching local dimension BV %" PetscInt_FMT ", Mat %" PetscInt_FMT,bv->n,n);
    493:     }
    494:     if (B) PetscCall(PetscObjectReference((PetscObject)B));
    495:     PetscCall(MatDestroy(&bv->matrix));
    496:     bv->matrix = B;
    497:     bv->indef  = indef;
    498:     PetscCall(PetscObjectStateIncrease((PetscObject)bv));
    499:     if (bv->Bx) PetscCall(PetscObjectStateIncrease((PetscObject)bv->Bx));
    500:     if (bv->cached) PetscCall(PetscObjectStateIncrease((PetscObject)bv->cached));
    501:   }
    502:   PetscFunctionReturn(PETSC_SUCCESS);
    503: }

    505: /*@
    506:    BVGetMatrix - Retrieves the matrix representation of the inner product.

    508:    Not Collective

    510:    Input Parameter:
    511: .  bv    - the basis vectors context

    513:    Output Parameters:
    514: +  B     - the matrix of the inner product (may be NULL)
    515: -  indef - the flag indicating if the matrix is indefinite

    517:    Level: advanced

    519: .seealso: BVSetMatrix()
    520: @*/
    521: PetscErrorCode BVGetMatrix(BV bv,Mat *B,PetscBool *indef)
    522: {
    523:   PetscFunctionBegin;
    525:   if (B)     *B     = bv->matrix;
    526:   if (indef) *indef = bv->indef;
    527:   PetscFunctionReturn(PETSC_SUCCESS);
    528: }

    530: /*@
    531:    BVApplyMatrix - Multiplies a vector by the matrix representation of the
    532:    inner product.

    534:    Neighbor-wise Collective

    536:    Input Parameters:
    537: +  bv - the basis vectors context
    538: -  x  - the vector

    540:    Output Parameter:
    541: .  y  - the result

    543:    Note:
    544:    If no matrix was specified this function copies the vector.

    546:    Level: advanced

    548: .seealso: BVSetMatrix(), BVApplyMatrixBV()
    549: @*/
    550: PetscErrorCode BVApplyMatrix(BV bv,Vec x,Vec y)
    551: {
    552:   PetscFunctionBegin;
    556:   if (bv->matrix) {
    557:     PetscCall(BV_IPMatMult(bv,x));
    558:     PetscCall(VecCopy(bv->Bx,y));
    559:   } else PetscCall(VecCopy(x,y));
    560:   PetscFunctionReturn(PETSC_SUCCESS);
    561: }

    563: /*@
    564:    BVApplyMatrixBV - Multiplies the BV vectors by the matrix representation
    565:    of the inner product.

    567:    Neighbor-wise Collective

    569:    Input Parameter:
    570: .  X - the basis vectors context

    572:    Output Parameter:
    573: .  Y - the basis vectors to store the result (optional)

    575:    Note:
    576:    This function computes Y = B*X, where B is the matrix given with
    577:    BVSetMatrix(). This operation is computed as in BVMatMult().
    578:    If no matrix was specified, then it just copies Y = X.

    580:    If no Y is given, the result is stored internally in the cached BV.

    582:    Level: developer

    584: .seealso: BVSetMatrix(), BVApplyMatrix(), BVMatMult(), BVGetCachedBV()
    585: @*/
    586: PetscErrorCode BVApplyMatrixBV(BV X,BV Y)
    587: {
    588:   PetscFunctionBegin;
    590:   if (Y) {
    592:     if (X->matrix) PetscCall(BVMatMult(X,X->matrix,Y));
    593:     else PetscCall(BVCopy(X,Y));
    594:   } else PetscCall(BV_IPMatMultBV(X));
    595:   PetscFunctionReturn(PETSC_SUCCESS);
    596: }

    598: /*@
    599:    BVSetSignature - Sets the signature matrix to be used in orthogonalization.

    601:    Logically Collective

    603:    Input Parameters:
    604: +  bv    - the basis vectors context
    605: -  omega - a vector representing the diagonal of the signature matrix

    607:    Note:
    608:    The signature matrix Omega = V'*B*V is relevant only for an indefinite B.

    610:    Level: developer

    612: .seealso: BVSetMatrix(), BVGetSignature()
    613: @*/
    614: PetscErrorCode BVSetSignature(BV bv,Vec omega)
    615: {
    616:   PetscInt          i,n;
    617:   const PetscScalar *pomega;
    618:   PetscScalar       *intern;

    620:   PetscFunctionBegin;
    622:   BVCheckSizes(bv,1);

    626:   PetscCall(VecGetSize(omega,&n));
    627:   PetscCheck(n==bv->k,PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_SIZ,"Vec argument has %" PetscInt_FMT " elements, should be %" PetscInt_FMT,n,bv->k);
    628:   PetscCall(BV_AllocateSignature(bv));
    629:   if (bv->indef) {
    630:     PetscCall(VecGetArrayRead(omega,&pomega));
    631:     PetscCall(VecGetArray(bv->omega,&intern));
    632:     for (i=0;i<n;i++) intern[bv->nc+i] = pomega[i];
    633:     PetscCall(VecRestoreArray(bv->omega,&intern));
    634:     PetscCall(VecRestoreArrayRead(omega,&pomega));
    635:   } else PetscCall(PetscInfo(bv,"Ignoring signature because BV is not indefinite\n"));
    636:   PetscCall(PetscObjectStateIncrease((PetscObject)bv));
    637:   PetscFunctionReturn(PETSC_SUCCESS);
    638: }

    640: /*@
    641:    BVGetSignature - Retrieves the signature matrix from last orthogonalization.

    643:    Not Collective

    645:    Input Parameter:
    646: .  bv    - the basis vectors context

    648:    Output Parameter:
    649: .  omega - a vector representing the diagonal of the signature matrix

    651:    Note:
    652:    The signature matrix Omega = V'*B*V is relevant only for an indefinite B.

    654:    Level: developer

    656: .seealso: BVSetMatrix(), BVSetSignature()
    657: @*/
    658: PetscErrorCode BVGetSignature(BV bv,Vec omega)
    659: {
    660:   PetscInt          i,n;
    661:   PetscScalar       *pomega;
    662:   const PetscScalar *intern;

    664:   PetscFunctionBegin;
    666:   BVCheckSizes(bv,1);

    670:   PetscCall(VecGetSize(omega,&n));
    671:   PetscCheck(n==bv->k,PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_SIZ,"Vec argument has %" PetscInt_FMT " elements, should be %" PetscInt_FMT,n,bv->k);
    672:   if (bv->indef && bv->omega) {
    673:     PetscCall(VecGetArray(omega,&pomega));
    674:     PetscCall(VecGetArrayRead(bv->omega,&intern));
    675:     for (i=0;i<n;i++) pomega[i] = intern[bv->nc+i];
    676:     PetscCall(VecRestoreArrayRead(bv->omega,&intern));
    677:     PetscCall(VecRestoreArray(omega,&pomega));
    678:   } else PetscCall(VecSet(omega,1.0));
    679:   PetscFunctionReturn(PETSC_SUCCESS);
    680: }

    682: /*@
    683:    BVSetBufferVec - Attach a vector object to be used as buffer space for
    684:    several operations.

    686:    Collective

    688:    Input Parameters:
    689: +  bv     - the basis vectors context)
    690: -  buffer - the vector

    692:    Notes:
    693:    Use BVGetBufferVec() to retrieve the vector (for example, to free it
    694:    at the end of the computations).

    696:    The vector must be sequential of length (nc+m)*m, where m is the number
    697:    of columns of bv and nc is the number of constraints.

    699:    Level: developer

    701: .seealso: BVGetBufferVec(), BVSetSizes(), BVGetNumConstraints()
    702: @*/
    703: PetscErrorCode BVSetBufferVec(BV bv,Vec buffer)
    704: {
    705:   PetscInt       ld,n;
    706:   PetscMPIInt    size;

    708:   PetscFunctionBegin;
    711:   BVCheckSizes(bv,1);
    712:   PetscCall(VecGetSize(buffer,&n));
    713:   ld = bv->m+bv->nc;
    714:   PetscCheck(n==ld*bv->m,PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_SIZ,"Buffer size must be %" PetscInt_FMT,ld*bv->m);
    715:   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)buffer),&size));
    716:   PetscCheck(size==1,PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_WRONG,"Buffer must be a sequential vector");

    718:   PetscCall(PetscObjectReference((PetscObject)buffer));
    719:   PetscCall(VecDestroy(&bv->buffer));
    720:   bv->buffer = buffer;
    721:   PetscFunctionReturn(PETSC_SUCCESS);
    722: }

    724: /*@
    725:    BVGetBufferVec - Obtain the buffer vector associated with the BV object.

    727:    Collective

    729:    Input Parameters:
    730: .  bv - the basis vectors context

    732:    Output Parameter:
    733: .  buffer - vector

    735:    Notes:
    736:    The vector is created if not available previously. It is a sequential vector
    737:    of length (nc+m)*m, where m is the number of columns of bv and nc is the number
    738:    of constraints.

    740:    Developer Notes:
    741:    The buffer vector is viewed as a column-major matrix with leading dimension
    742:    ld=nc+m, and m columns at most. In the most common usage, it has the structure
    743: .vb
    744:       | | C |
    745:       |s|---|
    746:       | | H |
    747: .ve
    748:    where H is an upper Hessenberg matrix of order m x (m-1), C contains coefficients
    749:    related to orthogonalization against constraints (first nc rows), and s is the
    750:    first column that contains scratch values computed during Gram-Schmidt
    751:    orthogonalization. In particular, BVDotColumn() and BVMultColumn() use s to
    752:    store the coefficients.

    754:    Level: developer

    756: .seealso: BVSetBufferVec(), BVSetSizes(), BVGetNumConstraints(), BVDotColumn(), BVMultColumn()
    757: @*/
    758: PetscErrorCode BVGetBufferVec(BV bv,Vec *buffer)
    759: {
    760:   PetscInt       ld;

    762:   PetscFunctionBegin;
    764:   PetscAssertPointer(buffer,2);
    765:   BVCheckSizes(bv,1);
    766:   if (!bv->buffer) {
    767:     ld = bv->m+bv->nc;
    768:     PetscCall(VecCreate(PETSC_COMM_SELF,&bv->buffer));
    769:     PetscCall(VecSetSizes(bv->buffer,PETSC_DECIDE,ld*bv->m));
    770:     PetscCall(VecSetType(bv->buffer,((PetscObject)bv->t)->type_name));
    771:   }
    772:   *buffer = bv->buffer;
    773:   PetscFunctionReturn(PETSC_SUCCESS);
    774: }

    776: /*@
    777:    BVSetRandomContext - Sets the PetscRandom object associated with the BV,
    778:    to be used in operations that need random numbers.

    780:    Collective

    782:    Input Parameters:
    783: +  bv   - the basis vectors context
    784: -  rand - the random number generator context

    786:    Level: advanced

    788: .seealso: BVGetRandomContext(), BVSetRandom(), BVSetRandomNormal(), BVSetRandomColumn(), BVSetRandomCond()
    789: @*/
    790: PetscErrorCode BVSetRandomContext(BV bv,PetscRandom rand)
    791: {
    792:   PetscFunctionBegin;
    795:   PetscCheckSameComm(bv,1,rand,2);
    796:   PetscCall(PetscObjectReference((PetscObject)rand));
    797:   PetscCall(PetscRandomDestroy(&bv->rand));
    798:   bv->rand = rand;
    799:   PetscFunctionReturn(PETSC_SUCCESS);
    800: }

    802: /*@
    803:    BVGetRandomContext - Gets the PetscRandom object associated with the BV.

    805:    Collective

    807:    Input Parameter:
    808: .  bv - the basis vectors context

    810:    Output Parameter:
    811: .  rand - the random number generator context

    813:    Level: advanced

    815: .seealso: BVSetRandomContext(), BVSetRandom(), BVSetRandomNormal(), BVSetRandomColumn(), BVSetRandomCond()
    816: @*/
    817: PetscErrorCode BVGetRandomContext(BV bv,PetscRandom* rand)
    818: {
    819:   PetscFunctionBegin;
    821:   PetscAssertPointer(rand,2);
    822:   if (!bv->rand) {
    823:     PetscCall(PetscRandomCreate(PetscObjectComm((PetscObject)bv),&bv->rand));
    824:     if (bv->cuda) PetscCall(PetscRandomSetType(bv->rand,PETSCCURAND));
    825:     if (bv->sfocalled) PetscCall(PetscRandomSetFromOptions(bv->rand));
    826:     if (bv->rrandom) {
    827:       PetscCall(PetscRandomSetSeed(bv->rand,0x12345678));
    828:       PetscCall(PetscRandomSeed(bv->rand));
    829:     }
    830:   }
    831:   *rand = bv->rand;
    832:   PetscFunctionReturn(PETSC_SUCCESS);
    833: }

    835: /*@
    836:    BVSetFromOptions - Sets BV options from the options database.

    838:    Collective

    840:    Input Parameter:
    841: .  bv - the basis vectors context

    843:    Level: beginner

    845: .seealso: BVSetOptionsPrefix()
    846: @*/
    847: PetscErrorCode BVSetFromOptions(BV bv)
    848: {
    849:   char               type[256];
    850:   PetscBool          flg1,flg2,flg3,flg4;
    851:   PetscReal          r;
    852:   BVOrthogType       otype;
    853:   BVOrthogRefineType orefine;
    854:   BVOrthogBlockType  oblock;

    856:   PetscFunctionBegin;
    858:   PetscCall(BVRegisterAll());
    859:   PetscObjectOptionsBegin((PetscObject)bv);
    860:     PetscCall(PetscOptionsFList("-bv_type","Basis Vectors type","BVSetType",BVList,(char*)(((PetscObject)bv)->type_name?((PetscObject)bv)->type_name:BVMAT),type,sizeof(type),&flg1));
    861:     if (flg1) PetscCall(BVSetType(bv,type));
    862:     else if (!((PetscObject)bv)->type_name) PetscCall(BVSetType(bv,BVMAT));

    864:     otype = bv->orthog_type;
    865:     PetscCall(PetscOptionsEnum("-bv_orthog_type","Orthogonalization method","BVSetOrthogonalization",BVOrthogTypes,(PetscEnum)otype,(PetscEnum*)&otype,&flg1));
    866:     orefine = bv->orthog_ref;
    867:     PetscCall(PetscOptionsEnum("-bv_orthog_refine","Iterative refinement mode during orthogonalization","BVSetOrthogonalization",BVOrthogRefineTypes,(PetscEnum)orefine,(PetscEnum*)&orefine,&flg2));
    868:     r = bv->orthog_eta;
    869:     PetscCall(PetscOptionsReal("-bv_orthog_eta","Parameter of iterative refinement during orthogonalization","BVSetOrthogonalization",r,&r,&flg3));
    870:     oblock = bv->orthog_block;
    871:     PetscCall(PetscOptionsEnum("-bv_orthog_block","Block orthogonalization method","BVSetOrthogonalization",BVOrthogBlockTypes,(PetscEnum)oblock,(PetscEnum*)&oblock,&flg4));
    872:     if (flg1 || flg2 || flg3 || flg4) PetscCall(BVSetOrthogonalization(bv,otype,orefine,r,oblock));

    874:     PetscCall(PetscOptionsEnum("-bv_matmult","Method for BVMatMult","BVSetMatMultMethod",BVMatMultTypes,(PetscEnum)bv->vmm,(PetscEnum*)&bv->vmm,NULL));

    876:     PetscCall(PetscOptionsReal("-bv_definite_tol","Tolerance for checking a definite inner product","BVSetDefiniteTolerance",r,&r,&flg1));
    877:     if (flg1) PetscCall(BVSetDefiniteTolerance(bv,r));

    879:     /* undocumented option to generate random vectors that are independent of the number of processes */
    880:     PetscCall(PetscOptionsGetBool(NULL,NULL,"-bv_reproducible_random",&bv->rrandom,NULL));

    882:     if (bv->ops->create) bv->defersfo = PETSC_TRUE;   /* defer call to setfromoptions */
    883:     else PetscTryTypeMethod(bv,setfromoptions,PetscOptionsObject);
    884:     PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)bv,PetscOptionsObject));
    885:   PetscOptionsEnd();
    886:   bv->sfocalled = PETSC_TRUE;
    887:   PetscFunctionReturn(PETSC_SUCCESS);
    888: }

    890: /*@
    891:    BVSetOrthogonalization - Specifies the method used for the orthogonalization of
    892:    vectors (classical or modified Gram-Schmidt with or without refinement), and
    893:    for the block-orthogonalization (simultaneous orthogonalization of a set of
    894:    vectors).

    896:    Logically Collective

    898:    Input Parameters:
    899: +  bv     - the basis vectors context
    900: .  type   - the method of vector orthogonalization
    901: .  refine - type of refinement
    902: .  eta    - parameter for selective refinement
    903: -  block  - the method of block orthogonalization

    905:    Options Database Keys:
    906: +  -bv_orthog_type <type> - Where <type> is cgs for Classical Gram-Schmidt orthogonalization
    907:                          (default) or mgs for Modified Gram-Schmidt orthogonalization
    908: .  -bv_orthog_refine <ref> - Where <ref> is one of never, ifneeded (default) or always
    909: .  -bv_orthog_eta <eta> -  For setting the value of eta
    910: -  -bv_orthog_block <block> - Where <block> is the block-orthogonalization method

    912:    Notes:
    913:    The default settings work well for most problems.

    915:    The parameter eta should be a real value between 0 and 1 (or PETSC_DEFAULT).
    916:    The value of eta is used only when the refinement type is "ifneeded".

    918:    When using several processors, MGS is likely to result in bad scalability.

    920:    If the method set for block orthogonalization is GS, then the computation
    921:    is done column by column with the vector orthogonalization.

    923:    Level: advanced

    925: .seealso: BVOrthogonalizeColumn(), BVGetOrthogonalization(), BVOrthogType, BVOrthogRefineType, BVOrthogBlockType
    926: @*/
    927: PetscErrorCode BVSetOrthogonalization(BV bv,BVOrthogType type,BVOrthogRefineType refine,PetscReal eta,BVOrthogBlockType block)
    928: {
    929:   PetscFunctionBegin;
    935:   switch (type) {
    936:     case BV_ORTHOG_CGS:
    937:     case BV_ORTHOG_MGS:
    938:       bv->orthog_type = type;
    939:       break;
    940:     default:
    941:       SETERRQ(PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_WRONG,"Unknown orthogonalization type");
    942:   }
    943:   switch (refine) {
    944:     case BV_ORTHOG_REFINE_NEVER:
    945:     case BV_ORTHOG_REFINE_IFNEEDED:
    946:     case BV_ORTHOG_REFINE_ALWAYS:
    947:       bv->orthog_ref = refine;
    948:       break;
    949:     default:
    950:       SETERRQ(PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_WRONG,"Unknown refinement type");
    951:   }
    952:   if (eta == (PetscReal)PETSC_DEFAULT) {
    953:     bv->orthog_eta = 0.7071;
    954:   } else {
    955:     PetscCheck(eta>0.0 && eta<=1.0,PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_OUTOFRANGE,"Invalid eta value");
    956:     bv->orthog_eta = eta;
    957:   }
    958:   switch (block) {
    959:     case BV_ORTHOG_BLOCK_GS:
    960:     case BV_ORTHOG_BLOCK_CHOL:
    961:     case BV_ORTHOG_BLOCK_TSQR:
    962:     case BV_ORTHOG_BLOCK_TSQRCHOL:
    963:     case BV_ORTHOG_BLOCK_SVQB:
    964:       bv->orthog_block = block;
    965:       break;
    966:     default:
    967:       SETERRQ(PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_WRONG,"Unknown block orthogonalization type");
    968:   }
    969:   PetscFunctionReturn(PETSC_SUCCESS);
    970: }

    972: /*@
    973:    BVGetOrthogonalization - Gets the orthogonalization settings from the BV object.

    975:    Not Collective

    977:    Input Parameter:
    978: .  bv - basis vectors context

    980:    Output Parameters:
    981: +  type   - the method of vector orthogonalization
    982: .  refine - type of refinement
    983: .  eta    - parameter for selective refinement
    984: -  block  - the method of block orthogonalization

    986:    Level: advanced

    988: .seealso: BVOrthogonalizeColumn(), BVSetOrthogonalization(), BVOrthogType, BVOrthogRefineType, BVOrthogBlockType
    989: @*/
    990: PetscErrorCode BVGetOrthogonalization(BV bv,BVOrthogType *type,BVOrthogRefineType *refine,PetscReal *eta,BVOrthogBlockType *block)
    991: {
    992:   PetscFunctionBegin;
    994:   if (type)   *type   = bv->orthog_type;
    995:   if (refine) *refine = bv->orthog_ref;
    996:   if (eta)    *eta    = bv->orthog_eta;
    997:   if (block)  *block  = bv->orthog_block;
    998:   PetscFunctionReturn(PETSC_SUCCESS);
    999: }

    1001: /*@
    1002:    BVSetMatMultMethod - Specifies the method used for the BVMatMult() operation.

    1004:    Logically Collective

    1006:    Input Parameters:
    1007: +  bv     - the basis vectors context
    1008: -  method - the method for the BVMatMult() operation

    1010:    Options Database Keys:
    1011: .  -bv_matmult <meth> - choose one of the methods: vecs, mat

    1013:    Notes:
    1014:    Allowed values are
    1015: +  BV_MATMULT_VECS - perform a matrix-vector multiply per each column
    1016: .  BV_MATMULT_MAT - carry out a Mat-Mat product with a dense matrix
    1017: -  BV_MATMULT_MAT_SAVE - this case is deprecated

    1019:    The default is BV_MATMULT_MAT except in the case of BVVECS.

    1021:    Level: advanced

    1023: .seealso: BVMatMult(), BVGetMatMultMethod(), BVMatMultType
    1024: @*/
    1025: PetscErrorCode BVSetMatMultMethod(BV bv,BVMatMultType method)
    1026: {
    1027:   PetscFunctionBegin;
    1030:   switch (method) {
    1031:     case BV_MATMULT_VECS:
    1032:     case BV_MATMULT_MAT:
    1033:       bv->vmm = method;
    1034:       break;
    1035:     case BV_MATMULT_MAT_SAVE:
    1036:       PetscCall(PetscInfo(bv,"BV_MATMULT_MAT_SAVE is deprecated, using BV_MATMULT_MAT\n"));
    1037:       bv->vmm = BV_MATMULT_MAT;
    1038:       break;
    1039:     default:
    1040:       SETERRQ(PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_WRONG,"Unknown matmult method");
    1041:   }
    1042:   PetscFunctionReturn(PETSC_SUCCESS);
    1043: }

    1045: /*@
    1046:    BVGetMatMultMethod - Gets the method used for the BVMatMult() operation.

    1048:    Not Collective

    1050:    Input Parameter:
    1051: .  bv - basis vectors context

    1053:    Output Parameter:
    1054: .  method - the method for the BVMatMult() operation

    1056:    Level: advanced

    1058: .seealso: BVMatMult(), BVSetMatMultMethod(), BVMatMultType
    1059: @*/
    1060: PetscErrorCode BVGetMatMultMethod(BV bv,BVMatMultType *method)
    1061: {
    1062:   PetscFunctionBegin;
    1064:   PetscAssertPointer(method,2);
    1065:   *method = bv->vmm;
    1066:   PetscFunctionReturn(PETSC_SUCCESS);
    1067: }

    1069: /*@
    1070:    BVGetColumn - Returns a Vec object that contains the entries of the
    1071:    requested column of the basis vectors object.

    1073:    Logically Collective

    1075:    Input Parameters:
    1076: +  bv - the basis vectors context
    1077: -  j  - the index of the requested column

    1079:    Output Parameter:
    1080: .  v  - vector containing the jth column

    1082:    Notes:
    1083:    The returned Vec must be seen as a reference (not a copy) of the BV
    1084:    column, that is, modifying the Vec will change the BV entries as well.

    1086:    The returned Vec must not be destroyed. BVRestoreColumn() must be
    1087:    called when it is no longer needed. At most, two columns can be fetched,
    1088:    that is, this function can only be called twice before the corresponding
    1089:    BVRestoreColumn() is invoked.

    1091:    A negative index j selects the i-th constraint, where i=-j. Constraints
    1092:    should not be modified.

    1094:    Level: beginner

    1096: .seealso: BVRestoreColumn(), BVInsertConstraints()
    1097: @*/
    1098: PetscErrorCode BVGetColumn(BV bv,PetscInt j,Vec *v)
    1099: {
    1100:   PetscInt       l;

    1102:   PetscFunctionBegin;
    1105:   BVCheckSizes(bv,1);
    1106:   BVCheckOp(bv,1,getcolumn);
    1108:   PetscCheck(j>=0 || -j<=bv->nc,PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_OUTOFRANGE,"You requested constraint %" PetscInt_FMT " but only %" PetscInt_FMT " are available",-j,bv->nc);
    1109:   PetscCheck(j<bv->m,PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_OUTOFRANGE,"You requested column %" PetscInt_FMT " but only %" PetscInt_FMT " are available",j,bv->m);
    1110:   PetscCheck(j!=bv->ci[0] && j!=bv->ci[1],PetscObjectComm((PetscObject)bv),PETSC_ERR_SUP,"Column %" PetscInt_FMT " already fetched in a previous call to BVGetColumn",j);
    1111:   l = BVAvailableVec;
    1112:   PetscCheck(l!=-1,PetscObjectComm((PetscObject)bv),PETSC_ERR_SUP,"Too many requested columns; you must call BVRestoreColumn for one of the previously fetched columns");
    1113:   PetscUseTypeMethod(bv,getcolumn,j,v);
    1114:   bv->ci[l] = j;
    1115:   PetscCall(PetscObjectStateGet((PetscObject)bv->cv[l],&bv->st[l]));
    1116:   PetscCall(PetscObjectGetId((PetscObject)bv->cv[l],&bv->id[l]));
    1117:   *v = bv->cv[l];
    1118:   PetscFunctionReturn(PETSC_SUCCESS);
    1119: }

    1121: /*@
    1122:    BVRestoreColumn - Restore a column obtained with BVGetColumn().

    1124:    Logically Collective

    1126:    Input Parameters:
    1127: +  bv - the basis vectors context
    1128: .  j  - the index of the column
    1129: -  v  - vector obtained with BVGetColumn()

    1131:    Note:
    1132:    The arguments must match the corresponding call to BVGetColumn().

    1134:    Level: beginner

    1136: .seealso: BVGetColumn()
    1137: @*/
    1138: PetscErrorCode BVRestoreColumn(BV bv,PetscInt j,Vec *v)
    1139: {
    1140:   PetscObjectId    id;
    1141:   PetscObjectState st;
    1142:   PetscInt         l;

    1144:   PetscFunctionBegin;
    1147:   BVCheckSizes(bv,1);
    1149:   PetscAssertPointer(v,3);
    1151:   PetscCheck(j>=0 || -j<=bv->nc,PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_OUTOFRANGE,"You requested constraint %" PetscInt_FMT " but only %" PetscInt_FMT " are available",-j,bv->nc);
    1152:   PetscCheck(j<bv->m,PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_OUTOFRANGE,"You requested column %" PetscInt_FMT " but only %" PetscInt_FMT " are available",j,bv->m);
    1153:   PetscCheck(j==bv->ci[0] || j==bv->ci[1],PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_WRONG,"Column %" PetscInt_FMT " has not been fetched with a call to BVGetColumn",j);
    1154:   l = (j==bv->ci[0])? 0: 1;
    1155:   PetscCall(PetscObjectGetId((PetscObject)*v,&id));
    1156:   PetscCheck(id==bv->id[l],PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_WRONG,"Argument 3 is not the same Vec that was obtained with BVGetColumn");
    1157:   PetscCall(PetscObjectStateGet((PetscObject)*v,&st));
    1158:   if (st!=bv->st[l]) PetscCall(PetscObjectStateIncrease((PetscObject)bv));
    1159:   PetscUseTypeMethod(bv,restorecolumn,j,v);
    1160:   bv->ci[l] = -bv->nc-1;
    1161:   bv->st[l] = -1;
    1162:   bv->id[l] = 0;
    1163:   *v = NULL;
    1164:   PetscFunctionReturn(PETSC_SUCCESS);
    1165: }

    1167: /*@C
    1168:    BVGetArray - Returns a pointer to a contiguous array that contains this
    1169:    processor's portion of the BV data.

    1171:    Logically Collective

    1173:    Input Parameters:
    1174: .  bv - the basis vectors context

    1176:    Output Parameter:
    1177: .  a  - location to put pointer to the array

    1179:    Notes:
    1180:    BVRestoreArray() must be called when access to the array is no longer needed.
    1181:    This operation may imply a data copy, for BV types that do not store
    1182:    data contiguously in memory.

    1184:    The pointer will normally point to the first entry of the first column,
    1185:    but if the BV has constraints then these go before the regular columns.

    1187:    Note that for manipulating the pointer to the BV array, one must take into
    1188:    account the leading dimension, which might be different from the local
    1189:    number of rows, see BVGetLeadingDimension().

    1191:    Use BVGetArrayRead() for read-only access.

    1193:    Level: advanced

    1195: .seealso: BVRestoreArray(), BVInsertConstraints(), BVGetLeadingDimension(), BVGetArrayRead()
    1196: @*/
    1197: PetscErrorCode BVGetArray(BV bv,PetscScalar **a)
    1198: {
    1199:   PetscFunctionBegin;
    1202:   BVCheckSizes(bv,1);
    1203:   BVCheckOp(bv,1,getarray);
    1204:   PetscUseTypeMethod(bv,getarray,a);
    1205:   PetscFunctionReturn(PETSC_SUCCESS);
    1206: }

    1208: /*@C
    1209:    BVRestoreArray - Restore the BV object after BVGetArray() has been called.

    1211:    Logically Collective

    1213:    Input Parameters:
    1214: +  bv - the basis vectors context
    1215: -  a  - location of pointer to array obtained from BVGetArray()

    1217:    Note:
    1218:    This operation may imply a data copy, for BV types that do not store
    1219:    data contiguously in memory.

    1221:    Level: advanced

    1223: .seealso: BVGetColumn()
    1224: @*/
    1225: PetscErrorCode BVRestoreArray(BV bv,PetscScalar **a)
    1226: {
    1227:   PetscFunctionBegin;
    1230:   BVCheckSizes(bv,1);
    1231:   PetscTryTypeMethod(bv,restorearray,a);
    1232:   if (a) *a = NULL;
    1233:   PetscCall(PetscObjectStateIncrease((PetscObject)bv));
    1234:   PetscFunctionReturn(PETSC_SUCCESS);
    1235: }

    1237: /*@C
    1238:    BVGetArrayRead - Returns a read-only pointer to a contiguous array that
    1239:    contains this processor's portion of the BV data.

    1241:    Not Collective

    1243:    Input Parameters:
    1244: .  bv - the basis vectors context

    1246:    Output Parameter:
    1247: .  a  - location to put pointer to the array

    1249:    Notes:
    1250:    BVRestoreArrayRead() must be called when access to the array is no
    1251:    longer needed. This operation may imply a data copy, for BV types that
    1252:    do not store data contiguously in memory.

    1254:    The pointer will normally point to the first entry of the first column,
    1255:    but if the BV has constraints then these go before the regular columns.

    1257:    Level: advanced

    1259: .seealso: BVRestoreArray(), BVInsertConstraints(), BVGetLeadingDimension(), BVGetArray()
    1260: @*/
    1261: PetscErrorCode BVGetArrayRead(BV bv,const PetscScalar **a)
    1262: {
    1263:   PetscFunctionBegin;
    1266:   BVCheckSizes(bv,1);
    1267:   BVCheckOp(bv,1,getarrayread);
    1268:   PetscUseTypeMethod(bv,getarrayread,a);
    1269:   PetscFunctionReturn(PETSC_SUCCESS);
    1270: }

    1272: /*@C
    1273:    BVRestoreArrayRead - Restore the BV object after BVGetArrayRead() has
    1274:    been called.

    1276:    Not Collective

    1278:    Input Parameters:
    1279: +  bv - the basis vectors context
    1280: -  a  - location of pointer to array obtained from BVGetArrayRead()

    1282:    Level: advanced

    1284: .seealso: BVGetColumn()
    1285: @*/
    1286: PetscErrorCode BVRestoreArrayRead(BV bv,const PetscScalar **a)
    1287: {
    1288:   PetscFunctionBegin;
    1291:   BVCheckSizes(bv,1);
    1292:   PetscTryTypeMethod(bv,restorearrayread,a);
    1293:   if (a) *a = NULL;
    1294:   PetscFunctionReturn(PETSC_SUCCESS);
    1295: }

    1297: /*@
    1298:    BVCreateVec - Creates a new Vec object with the same type and dimensions
    1299:    as the columns of the basis vectors object.

    1301:    Collective

    1303:    Input Parameter:
    1304: .  bv - the basis vectors context

    1306:    Output Parameter:
    1307: .  v  - the new vector

    1309:    Note:
    1310:    The user is responsible of destroying the returned vector.

    1312:    Level: beginner

    1314: .seealso: BVCreateMat()
    1315: @*/
    1316: PetscErrorCode BVCreateVec(BV bv,Vec *v)
    1317: {
    1318:   PetscFunctionBegin;
    1320:   BVCheckSizes(bv,1);
    1321:   PetscAssertPointer(v,2);
    1322:   PetscCall(VecDuplicate(bv->t,v));
    1323:   PetscFunctionReturn(PETSC_SUCCESS);
    1324: }

    1326: /*@
    1327:    BVCreateMat - Creates a new Mat object of dense type and copies the contents
    1328:    of the BV object.

    1330:    Collective

    1332:    Input Parameter:
    1333: .  bv - the basis vectors context

    1335:    Output Parameter:
    1336: .  A  - the new matrix

    1338:    Notes:
    1339:    The user is responsible of destroying the returned matrix.

    1341:    The matrix contains all columns of the BV, not just the active columns.

    1343:    Level: intermediate

    1345: .seealso: BVCreateFromMat(), BVCreateVec(), BVGetMat()
    1346: @*/
    1347: PetscErrorCode BVCreateMat(BV bv,Mat *A)
    1348: {
    1349:   PetscInt ksave,lsave;
    1350:   Mat      B;
    1351:   VecType  vtype;

    1353:   PetscFunctionBegin;
    1355:   BVCheckSizes(bv,1);
    1356:   PetscAssertPointer(A,2);

    1358:   PetscCall(VecGetType(bv->t,&vtype));
    1359:   PetscCall(MatCreateDenseFromVecType(PetscObjectComm((PetscObject)bv->t),vtype,bv->n,PETSC_DECIDE,bv->N,bv->m,bv->ld,NULL,A));
    1360:   lsave = bv->l;
    1361:   ksave = bv->k;
    1362:   bv->l = 0;
    1363:   bv->k = bv->m;
    1364:   PetscCall(BVGetMat(bv,&B));
    1365:   PetscCall(MatCopy(B,*A,SAME_NONZERO_PATTERN));
    1366:   PetscCall(BVRestoreMat(bv,&B));
    1367:   bv->l = lsave;
    1368:   bv->k = ksave;
    1369:   PetscFunctionReturn(PETSC_SUCCESS);
    1370: }

    1372: PetscErrorCode BVGetMat_Default(BV bv,Mat *A)
    1373: {
    1374:   PetscScalar *vv,*aa;
    1375:   PetscBool   create=PETSC_FALSE;
    1376:   PetscInt    m,cols;
    1377:   VecType     vtype;

    1379:   PetscFunctionBegin;
    1380:   m = bv->k-bv->l;
    1381:   if (!bv->Aget) create=PETSC_TRUE;
    1382:   else {
    1383:     PetscCall(MatDenseGetArray(bv->Aget,&aa));
    1384:     PetscCheck(!aa,PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_WRONGSTATE,"BVGetMat already called on this BV");
    1385:     PetscCall(MatGetSize(bv->Aget,NULL,&cols));
    1386:     if (cols!=m) {
    1387:       PetscCall(MatDestroy(&bv->Aget));
    1388:       create=PETSC_TRUE;
    1389:     }
    1390:   }
    1391:   PetscCall(BVGetArray(bv,&vv));
    1392:   if (create) {
    1393:     PetscCall(VecGetType(bv->t,&vtype));
    1394:     PetscCall(MatCreateDenseFromVecType(PetscObjectComm((PetscObject)bv),vtype,bv->n,PETSC_DECIDE,bv->N,m,bv->ld,vv,&bv->Aget)); /* pass a pointer to avoid allocation of storage */
    1395:     PetscCall(MatDenseReplaceArray(bv->Aget,NULL));  /* replace with a null pointer, the value after BVRestoreMat */
    1396:   }
    1397:   PetscCall(MatDensePlaceArray(bv->Aget,vv+(bv->nc+bv->l)*bv->ld));  /* set the actual pointer */
    1398:   *A = bv->Aget;
    1399:   PetscFunctionReturn(PETSC_SUCCESS);
    1400: }

    1402: /*@
    1403:    BVGetMat - Returns a Mat object of dense type that shares the memory of
    1404:    the BV object.

    1406:    Collective

    1408:    Input Parameter:
    1409: .  bv - the basis vectors context

    1411:    Output Parameter:
    1412: .  A  - the matrix

    1414:    Notes:
    1415:    The returned matrix contains only the active columns. If the content of
    1416:    the Mat is modified, these changes are also done in the BV object. The
    1417:    user must call BVRestoreMat() when no longer needed.

    1419:    This operation implies a call to BVGetArray(), which may result in data
    1420:    copies.

    1422:    Level: advanced

    1424: .seealso: BVRestoreMat(), BVCreateMat(), BVGetArray()
    1425: @*/
    1426: PetscErrorCode BVGetMat(BV bv,Mat *A)
    1427: {
    1428:   PetscFunctionBegin;
    1430:   BVCheckSizes(bv,1);
    1431:   PetscAssertPointer(A,2);
    1432:   PetscUseTypeMethod(bv,getmat,A);
    1433:   PetscFunctionReturn(PETSC_SUCCESS);
    1434: }

    1436: PetscErrorCode BVRestoreMat_Default(BV bv,Mat *A)
    1437: {
    1438:   PetscScalar *vv,*aa;

    1440:   PetscFunctionBegin;
    1441:   PetscCall(MatDenseGetArray(bv->Aget,&aa));
    1442:   vv = aa-(bv->nc+bv->l)*bv->ld;
    1443:   PetscCall(MatDenseResetArray(bv->Aget));
    1444:   PetscCall(BVRestoreArray(bv,&vv));
    1445:   *A = NULL;
    1446:   PetscFunctionReturn(PETSC_SUCCESS);
    1447: }

    1449: /*@
    1450:    BVRestoreMat - Restores the Mat obtained with BVGetMat().

    1452:    Logically Collective

    1454:    Input Parameters:
    1455: +  bv - the basis vectors context
    1456: -  A  - the fetched matrix

    1458:    Note:
    1459:    A call to this function must match a previous call of BVGetMat().
    1460:    The effect is that the contents of the Mat are copied back to the
    1461:    BV internal data structures.

    1463:    Level: advanced

    1465: .seealso: BVGetMat(), BVRestoreArray()
    1466: @*/
    1467: PetscErrorCode BVRestoreMat(BV bv,Mat *A)
    1468: {
    1469:   PetscFunctionBegin;
    1471:   BVCheckSizes(bv,1);
    1472:   PetscAssertPointer(A,2);
    1473:   PetscCheck(bv->Aget,PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_WRONGSTATE,"BVRestoreMat must match a previous call to BVGetMat");
    1474:   PetscCheck(bv->Aget==*A,PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_WRONGSTATE,"Mat argument is not the same as the one obtained with BVGetMat");
    1475:   PetscUseTypeMethod(bv,restoremat,A);
    1476:   PetscFunctionReturn(PETSC_SUCCESS);
    1477: }

    1479: /*
    1480:    Copy all user-provided attributes of V to another BV object W
    1481:  */
    1482: static inline PetscErrorCode BVDuplicate_Private(BV V,BV W)
    1483: {
    1484:   PetscFunctionBegin;
    1485:   W->ld           = V->ld;
    1486:   PetscCall(BVSetType(W,((PetscObject)V)->type_name));
    1487:   W->orthog_type  = V->orthog_type;
    1488:   W->orthog_ref   = V->orthog_ref;
    1489:   W->orthog_eta   = V->orthog_eta;
    1490:   W->orthog_block = V->orthog_block;
    1491:   if (V->matrix) PetscCall(PetscObjectReference((PetscObject)V->matrix));
    1492:   W->matrix       = V->matrix;
    1493:   W->indef        = V->indef;
    1494:   W->vmm          = V->vmm;
    1495:   W->rrandom      = V->rrandom;
    1496:   W->deftol       = V->deftol;
    1497:   if (V->rand) PetscCall(PetscObjectReference((PetscObject)V->rand));
    1498:   W->rand         = V->rand;
    1499:   W->sfocalled    = V->sfocalled;
    1500:   PetscTryTypeMethod(V,duplicate,W);
    1501:   PetscCall(PetscObjectStateIncrease((PetscObject)W));
    1502:   PetscFunctionReturn(PETSC_SUCCESS);
    1503: }

    1505: /*@
    1506:    BVDuplicate - Creates a new basis vector object of the same type and
    1507:    dimensions as an existing one.

    1509:    Collective

    1511:    Input Parameter:
    1512: .  V - basis vectors context

    1514:    Output Parameter:
    1515: .  W - location to put the new BV

    1517:    Notes:
    1518:    The new BV has the same type and dimensions as V, and it shares the same
    1519:    template vector. Also, the inner product matrix and orthogonalization
    1520:    options are copied.

    1522:    BVDuplicate() DOES NOT COPY the entries, but rather allocates storage
    1523:    for the new basis vectors. Use BVCopy() to copy the contents.

    1525:    Level: intermediate

    1527: .seealso: BVDuplicateResize(), BVCreate(), BVSetSizesFromVec(), BVCopy()
    1528: @*/
    1529: PetscErrorCode BVDuplicate(BV V,BV *W)
    1530: {
    1531:   PetscFunctionBegin;
    1534:   BVCheckSizes(V,1);
    1535:   PetscAssertPointer(W,2);
    1536:   PetscCall(BVCreate(PetscObjectComm((PetscObject)V),W));
    1537:   PetscCall(BVSetSizesFromVec(*W,V->t,V->m));
    1538:   PetscCall(BVDuplicate_Private(V,*W));
    1539:   PetscFunctionReturn(PETSC_SUCCESS);
    1540: }

    1542: /*@
    1543:    BVDuplicateResize - Creates a new basis vector object of the same type and
    1544:    dimensions as an existing one, but with possibly different number of columns.

    1546:    Collective

    1548:    Input Parameters:
    1549: +  V - basis vectors context
    1550: -  m - the new number of columns

    1552:    Output Parameter:
    1553: .  W - location to put the new BV

    1555:    Note:
    1556:    This is equivalent of a call to BVDuplicate() followed by BVResize(). The
    1557:    contents of V are not copied to W.

    1559:    Level: intermediate

    1561: .seealso: BVDuplicate(), BVResize()
    1562: @*/
    1563: PetscErrorCode BVDuplicateResize(BV V,PetscInt m,BV *W)
    1564: {
    1565:   PetscFunctionBegin;
    1568:   BVCheckSizes(V,1);
    1570:   PetscAssertPointer(W,3);
    1571:   PetscCall(BVCreate(PetscObjectComm((PetscObject)V),W));
    1572:   PetscCall(BVSetSizesFromVec(*W,V->t,m));
    1573:   PetscCall(BVDuplicate_Private(V,*W));
    1574:   PetscFunctionReturn(PETSC_SUCCESS);
    1575: }

    1577: /*@
    1578:    BVGetCachedBV - Returns a BV object stored internally that holds the
    1579:    result of B*X after a call to BVApplyMatrixBV().

    1581:    Collective

    1583:    Input Parameter:
    1584: .  bv    - the basis vectors context

    1586:    Output Parameter:
    1587: .  cached - the cached BV

    1589:    Note:
    1590:    The cached BV is created if not available previously.

    1592:    Level: developer

    1594: .seealso: BVApplyMatrixBV()
    1595: @*/
    1596: PetscErrorCode BVGetCachedBV(BV bv,BV *cached)
    1597: {
    1598:   PetscFunctionBegin;
    1600:   PetscAssertPointer(cached,2);
    1601:   BVCheckSizes(bv,1);
    1602:   if (!bv->cached) {
    1603:     PetscCall(BVCreate(PetscObjectComm((PetscObject)bv),&bv->cached));
    1604:     PetscCall(BVSetSizesFromVec(bv->cached,bv->t,bv->m));
    1605:     PetscCall(BVDuplicate_Private(bv,bv->cached));
    1606:   }
    1607:   *cached = bv->cached;
    1608:   PetscFunctionReturn(PETSC_SUCCESS);
    1609: }

    1611: /*@
    1612:    BVCopy - Copies a basis vector object into another one, W <- V.

    1614:    Logically Collective

    1616:    Input Parameter:
    1617: .  V - basis vectors context

    1619:    Output Parameter:
    1620: .  W - the copy

    1622:    Note:
    1623:    Both V and W must be distributed in the same manner; local copies are
    1624:    done. Only active columns (excluding the leading ones) are copied.
    1625:    In the destination W, columns are overwritten starting from the leading ones.
    1626:    Constraints are not copied.

    1628:    Level: beginner

    1630: .seealso: BVCopyVec(), BVCopyColumn(), BVDuplicate(), BVSetActiveColumns()
    1631: @*/
    1632: PetscErrorCode BVCopy(BV V,BV W)
    1633: {
    1634:   PetscScalar       *womega;
    1635:   const PetscScalar *vomega;

    1637:   PetscFunctionBegin;
    1640:   BVCheckSizes(V,1);
    1641:   BVCheckOp(V,1,copy);
    1644:   BVCheckSizes(W,2);
    1645:   PetscCheckSameTypeAndComm(V,1,W,2);
    1646:   PetscCheck(V->n==W->n,PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_INCOMP,"Mismatching local dimension V %" PetscInt_FMT ", W %" PetscInt_FMT,V->n,W->n);
    1647:   PetscCheck(V->k-V->l<=W->m-W->l,PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_SIZ,"W has %" PetscInt_FMT " non-leading columns, not enough to store %" PetscInt_FMT " columns",W->m-W->l,V->k-V->l);
    1648:   if (V==W || !V->n) PetscFunctionReturn(PETSC_SUCCESS);

    1650:   PetscCall(PetscLogEventBegin(BV_Copy,V,W,0,0));
    1651:   if (V->indef && V->matrix && V->indef==W->indef && V->matrix==W->matrix) {
    1652:     /* copy signature */
    1653:     PetscCall(BV_AllocateSignature(W));
    1654:     PetscCall(VecGetArrayRead(V->omega,&vomega));
    1655:     PetscCall(VecGetArray(W->omega,&womega));
    1656:     PetscCall(PetscArraycpy(womega+W->nc+W->l,vomega+V->nc+V->l,V->k-V->l));
    1657:     PetscCall(VecRestoreArray(W->omega,&womega));
    1658:     PetscCall(VecRestoreArrayRead(V->omega,&vomega));
    1659:   }
    1660:   PetscUseTypeMethod(V,copy,W);
    1661:   PetscCall(PetscLogEventEnd(BV_Copy,V,W,0,0));
    1662:   PetscCall(PetscObjectStateIncrease((PetscObject)W));
    1663:   PetscFunctionReturn(PETSC_SUCCESS);
    1664: }

    1666: /*@
    1667:    BVCopyVec - Copies one of the columns of a basis vectors object into a Vec.

    1669:    Logically Collective

    1671:    Input Parameters:
    1672: +  V - basis vectors context
    1673: -  j - the column number to be copied

    1675:    Output Parameter:
    1676: .  w - the copied column

    1678:    Note:
    1679:    Both V and w must be distributed in the same manner; local copies are done.

    1681:    Level: beginner

    1683: .seealso: BVCopy(), BVCopyColumn(), BVInsertVec()
    1684: @*/
    1685: PetscErrorCode BVCopyVec(BV V,PetscInt j,Vec w)
    1686: {
    1687:   PetscInt       n,N;
    1688:   Vec            z;

    1690:   PetscFunctionBegin;
    1693:   BVCheckSizes(V,1);
    1696:   PetscCheckSameComm(V,1,w,3);

    1698:   PetscCall(VecGetSize(w,&N));
    1699:   PetscCall(VecGetLocalSize(w,&n));
    1700:   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);

    1702:   PetscCall(PetscLogEventBegin(BV_Copy,V,w,0,0));
    1703:   PetscCall(BVGetColumn(V,j,&z));
    1704:   PetscCall(VecCopy(z,w));
    1705:   PetscCall(BVRestoreColumn(V,j,&z));
    1706:   PetscCall(PetscLogEventEnd(BV_Copy,V,w,0,0));
    1707:   PetscFunctionReturn(PETSC_SUCCESS);
    1708: }

    1710: /*@
    1711:    BVCopyColumn - Copies the values from one of the columns to another one.

    1713:    Logically Collective

    1715:    Input Parameters:
    1716: +  V - basis vectors context
    1717: .  j - the number of the source column
    1718: -  i - the number of the destination column

    1720:    Level: beginner

    1722: .seealso: BVCopy(), BVCopyVec()
    1723: @*/
    1724: PetscErrorCode BVCopyColumn(BV V,PetscInt j,PetscInt i)
    1725: {
    1726:   PetscScalar *omega;

    1728:   PetscFunctionBegin;
    1731:   BVCheckSizes(V,1);
    1734:   if (j==i) PetscFunctionReturn(PETSC_SUCCESS);

    1736:   PetscCall(PetscLogEventBegin(BV_Copy,V,0,0,0));
    1737:   if (V->omega) {
    1738:     PetscCall(VecGetArray(V->omega,&omega));
    1739:     omega[i] = omega[j];
    1740:     PetscCall(VecRestoreArray(V->omega,&omega));
    1741:   }
    1742:   PetscUseTypeMethod(V,copycolumn,j,i);
    1743:   PetscCall(PetscLogEventEnd(BV_Copy,V,0,0,0));
    1744:   PetscCall(PetscObjectStateIncrease((PetscObject)V));
    1745:   PetscFunctionReturn(PETSC_SUCCESS);
    1746: }

    1748: static PetscErrorCode BVGetSplit_Private(BV bv,PetscBool left,BV *split)
    1749: {
    1750:   PetscInt       ncols;

    1752:   PetscFunctionBegin;
    1753:   ncols = left? bv->nc+bv->l: bv->m-bv->l;
    1754:   if (*split && ncols!=(*split)->m) PetscCall(BVDestroy(split));
    1755:   if (!*split) {
    1756:     PetscCall(BVCreate(PetscObjectComm((PetscObject)bv),split));
    1757:     (*split)->issplit = left? 1: 2;
    1758:     (*split)->splitparent = bv;
    1759:     PetscCall(BVSetSizesFromVec(*split,bv->t,ncols));
    1760:     PetscCall(BVDuplicate_Private(bv,*split));
    1761:   }
    1762:   (*split)->l  = 0;
    1763:   (*split)->k  = left? bv->l: bv->k-bv->l;
    1764:   (*split)->nc = left? bv->nc: 0;
    1765:   (*split)->m  = ncols-(*split)->nc;
    1766:   if ((*split)->nc) {
    1767:     (*split)->ci[0] = -(*split)->nc-1;
    1768:     (*split)->ci[1] = -(*split)->nc-1;
    1769:   }
    1770:   if (left) PetscCall(PetscObjectStateGet((PetscObject)*split,&bv->lstate));
    1771:   else PetscCall(PetscObjectStateGet((PetscObject)*split,&bv->rstate));
    1772:   PetscFunctionReturn(PETSC_SUCCESS);
    1773: }

    1775: /*@
    1776:    BVGetSplit - Splits the BV object into two BV objects that share the
    1777:    internal data, one of them containing the leading columns and the other
    1778:    one containing the remaining columns.

    1780:    Collective

    1782:    Input Parameter:
    1783: .  bv - the basis vectors context

    1785:    Output Parameters:
    1786: +  L - left BV containing leading columns (can be NULL)
    1787: -  R - right BV containing remaining columns (can be NULL)

    1789:    Notes:
    1790:    The columns are split in two sets. The leading columns (including the
    1791:    constraints) are assigned to the left BV and the remaining columns
    1792:    are assigned to the right BV. The number of leading columns, as
    1793:    specified with BVSetActiveColumns(), must be between 1 and m-1 (to
    1794:    guarantee that both L and R have at least one column).

    1796:    The returned BV's must be seen as references (not copies) of the input
    1797:    BV, that is, modifying them will change the entries of bv as well.
    1798:    The returned BV's must not be destroyed. BVRestoreSplit() must be called
    1799:    when they are no longer needed.

    1801:    Pass NULL for any of the output BV's that is not needed.

    1803:    Level: advanced

    1805: .seealso: BVRestoreSplit(), BVSetActiveColumns(), BVSetNumConstraints()
    1806: @*/
    1807: PetscErrorCode BVGetSplit(BV bv,BV *L,BV *R)
    1808: {
    1809:   PetscFunctionBegin;
    1812:   BVCheckSizes(bv,1);
    1813:   PetscCheck(bv->l,PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_WRONGSTATE,"Must indicate the number of leading columns with BVSetActiveColumns()");
    1814:   PetscCheck(!bv->lsplit,PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_WRONGSTATE,"Cannot get the split BV's twice before restoring them with BVRestoreSplit()");
    1815:   bv->lsplit = bv->nc+bv->l;
    1816:   PetscCall(BVGetSplit_Private(bv,PETSC_TRUE,&bv->L));
    1817:   PetscCall(BVGetSplit_Private(bv,PETSC_FALSE,&bv->R));
    1818:   if (L) *L = bv->L;
    1819:   if (R) *R = bv->R;
    1820:   PetscFunctionReturn(PETSC_SUCCESS);
    1821: }

    1823: /*@
    1824:    BVRestoreSplit - Restore the BV objects obtained with BVGetSplit().

    1826:    Logically Collective

    1828:    Input Parameters:
    1829: +  bv - the basis vectors context
    1830: .  L  - left BV obtained with BVGetSplit()
    1831: -  R  - right BV obtained with BVGetSplit()

    1833:    Note:
    1834:    The arguments must match the corresponding call to BVGetSplit().

    1836:    Level: advanced

    1838: .seealso: BVGetSplit()
    1839: @*/
    1840: PetscErrorCode BVRestoreSplit(BV bv,BV *L,BV *R)
    1841: {
    1842:   PetscFunctionBegin;
    1845:   BVCheckSizes(bv,1);
    1846:   PetscCheck(bv->lsplit,PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_WRONGSTATE,"Must call BVGetSplit first");
    1847:   PetscCheck(!L || *L==bv->L,PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_WRONG,"Argument 2 is not the same BV that was obtained with BVGetSplit");
    1848:   PetscCheck(!R || *R==bv->R,PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_WRONG,"Argument 3 is not the same BV that was obtained with BVGetSplit");
    1849:   PetscCheck(!L || ((*L)->ci[0]<=(*L)->nc-1 && (*L)->ci[1]<=(*L)->nc-1),PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_WRONGSTATE,"Argument 2 has unrestored columns, use BVRestoreColumn()");
    1850:   PetscCheck(!R || ((*R)->ci[0]<=(*R)->nc-1 && (*R)->ci[1]<=(*R)->nc-1),PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_WRONGSTATE,"Argument 3 has unrestored columns, use BVRestoreColumn()");

    1852:   PetscTryTypeMethod(bv,restoresplit,L,R);
    1853:   bv->lsplit = 0;
    1854:   if (L) *L = NULL;
    1855:   if (R) *R = NULL;
    1856:   PetscFunctionReturn(PETSC_SUCCESS);
    1857: }

    1859: /*@
    1860:    BVSetDefiniteTolerance - Set the tolerance to be used when checking a
    1861:    definite inner product.

    1863:    Logically Collective

    1865:    Input Parameters:
    1866: +  bv     - basis vectors
    1867: -  deftol - the tolerance

    1869:    Options Database Key:
    1870: .  -bv_definite_tol <deftol> - the tolerance

    1872:    Notes:
    1873:    When using a non-standard inner product, see BVSetMatrix(), the solver needs
    1874:    to compute sqrt(z'*B*z) for various vectors z. If the inner product has not
    1875:    been declared indefinite, the value z'*B*z must be positive, but due to
    1876:    rounding error a tiny value may become negative. A tolerance is used to
    1877:    detect this situation. Likewise, in complex arithmetic z'*B*z should be
    1878:    real, and we use the same tolerance to check whether a nonzero imaginary part
    1879:    can be considered negligible.

    1881:    This function sets this tolerance, which defaults to 10*eps, where eps is
    1882:    the machine epsilon. The default value should be good for most applications.

    1884:    Level: advanced

    1886: .seealso: BVSetMatrix()
    1887: @*/
    1888: PetscErrorCode BVSetDefiniteTolerance(BV bv,PetscReal deftol)
    1889: {
    1890:   PetscFunctionBegin;
    1893:   if (deftol == (PetscReal)PETSC_DEFAULT) bv->deftol = 10*PETSC_MACHINE_EPSILON;
    1894:   else {
    1895:     PetscCheck(deftol>0.0,PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of deftol. Must be > 0");
    1896:     bv->deftol = deftol;
    1897:   }
    1898:   PetscFunctionReturn(PETSC_SUCCESS);
    1899: }

    1901: /*@
    1902:    BVGetDefiniteTolerance - Returns the tolerance for checking a definite
    1903:    inner product.

    1905:    Not Collective

    1907:    Input Parameter:
    1908: .  bv - the basis vectors

    1910:    Output Parameter:
    1911: .  deftol - the tolerance

    1913:    Level: advanced

    1915: .seealso: BVSetDefiniteTolerance()
    1916: @*/
    1917: PetscErrorCode BVGetDefiniteTolerance(BV bv,PetscReal *deftol)
    1918: {
    1919:   PetscFunctionBegin;
    1921:   PetscAssertPointer(deftol,2);
    1922:   *deftol = bv->deftol;
    1923:   PetscFunctionReturn(PETSC_SUCCESS);
    1924: }

    1926: /*@
    1927:    BVSetLeadingDimension - Set the leading dimension to be used for storing the BV data.

    1929:    Not Collective

    1931:    Input Parameters:
    1932: +  bv - basis vectors
    1933: -  ld - the leading dimension

    1935:    Notes:
    1936:    This parameter is relevant for BVMAT, though it might be employed in other types
    1937:    as well.

    1939:    When the internal data of the BV is stored as a dense matrix, the leading dimension
    1940:    has the same meaning as in MatDenseSetLDA(), i.e., the distance in number of
    1941:    elements from one entry of the matrix to the one in the next column at the same
    1942:    row. The leading dimension refers to the local array, and hence can be different
    1943:    in different processes.

    1945:    The user does not need to change this parameter. The default value is equal to the
    1946:    number of local rows, but this value may be increased a little to guarantee alignment
    1947:    (especially in the case of GPU storage).

    1949:    Level: advanced

    1951: .seealso: BVGetLeadingDimension()
    1952: @*/
    1953: PetscErrorCode BVSetLeadingDimension(BV bv,PetscInt ld)
    1954: {
    1955:   PetscFunctionBegin;
    1958:   PetscCheck((bv->n<0 && bv->N<0) || !bv->ops->create,PetscObjectComm((PetscObject)bv),PETSC_ERR_ORDER,"Must call BVSetLeadingDimension() before setting the BV type and sizes");
    1959:   if (ld == PETSC_DEFAULT) bv->ld = 0;
    1960:   else {
    1961:     PetscCheck(ld>0,PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of ld. Must be > 0");
    1962:     bv->ld = ld;
    1963:   }
    1964:   PetscFunctionReturn(PETSC_SUCCESS);
    1965: }

    1967: /*@
    1968:    BVGetLeadingDimension - Returns the leading dimension of the BV.

    1970:    Not Collective

    1972:    Input Parameter:
    1973: .  bv - the basis vectors

    1975:    Output Parameter:
    1976: .  ld - the leading dimension

    1978:    Level: advanced

    1980:    Notes:
    1981:    The returned value may be different in different processes.

    1983:    The leading dimension must be used when accessing the internal array via
    1984:    BVGetArray() or BVGetArrayRead().

    1986: .seealso: BVSetLeadingDimension(), BVGetArray(), BVGetArrayRead()
    1987: @*/
    1988: PetscErrorCode BVGetLeadingDimension(BV bv,PetscInt *ld)
    1989: {
    1990:   PetscFunctionBegin;
    1992:   PetscAssertPointer(ld,2);
    1993:   *ld = bv->ld;
    1994:   PetscFunctionReturn(PETSC_SUCCESS);
    1995: }