Actual source code: bvbasic.c

slepc-3.15.1 2021-05-28
Report Typos and Errors
  1: /*
  2:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  3:    SLEPc - Scalable Library for Eigenvalue Problem Computations
  4:    Copyright (c) 2002-2021, 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 = 0;

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

 22:    Logically Collective on bv

 24:    Input Parameter:
 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 ierr,(*r)(BV);
 38:   PetscBool      match;


 44:   PetscObjectTypeCompare((PetscObject)bv,type,&match);
 45:   if (match) return(0);
 46:   PetscStrcmp(type,BVTENSOR,&match);
 47:   if (match) SETERRQ(PetscObjectComm((PetscObject)bv),1,"Use BVCreateTensor() to create a BV of type tensor");

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

 52:   if (bv->ops->destroy) { (*bv->ops->destroy)(bv); }
 53:   PetscMemzero(bv->ops,sizeof(struct _BVOps));

 55:   PetscObjectChangeTypeName((PetscObject)bv,type);
 56:   if (bv->n < 0 && bv->N < 0) {
 57:     bv->ops->create = r;
 58:   } else {
 59:     PetscLogEventBegin(BV_Create,bv,0,0,0);
 60:     (*r)(bv);
 61:     PetscLogEventEnd(BV_Create,bv,0,0,0);
 62:   }
 63:   return(0);
 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: .  name - name of the type of basis vectors

 77:    Level: intermediate

 79: .seealso: BVSetType()
 80: @*/
 81: PetscErrorCode BVGetType(BV bv,BVType *type)
 82: {
 86:   *type = ((PetscObject)bv)->type_name;
 87:   return(0);
 88: }

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

 93:    Collective on bv

 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: {
113:   PetscInt       ma;

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

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

152:    Collective on bv

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

159:    Level: beginner

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

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

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

196:    Not Collective

198:    Input Parameter:
199: .  bv - the basis vectors

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

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

213:    Level: beginner

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

233: /*@
234:    BVSetNumConstraints - Set the number of constraints.

236:    Logically Collective on V

238:    Input Parameters:
239: +  V  - basis vectors
240: -  nc - number of constraints

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

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

250:    Level: developer

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

263:   if (nc<0) SETERRQ1(PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_OUTOFRANGE,"Number of constraints (given %D) cannot be negative",nc);
265:   BVCheckSizes(V,1);
266:   if (V->ci[0]!=-V->nc-1 || V->ci[1]!=-V->nc-1) SETERRQ(PetscObjectComm((PetscObject)V),PETSC_ERR_SUP,"Cannot call BVSetNumConstraints after BVGetColumn");

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

291: /*@
292:    BVGetNumConstraints - Returns the number of constraints.

294:    Not Collective

296:    Input Parameter:
297: .  bv - the basis vectors

299:    Output Parameters:
300: .  nc - the number of constraints

302:    Level: advanced

304: .seealso: BVGetSizes(), BVInsertConstraints()
305: @*/
306: PetscErrorCode BVGetNumConstraints(BV bv,PetscInt *nc)
307: {
311:   *nc = bv->nc;
312:   return(0);
313: }

315: /*@
316:    BVResize - Change the number of columns.

318:    Collective on bv

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

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

329:    Level: advanced

331: .seealso: BVSetSizes(), BVSetSizesFromVec()
332: @*/
333: PetscErrorCode BVResize(BV bv,PetscInt m,PetscBool copy)
334: {
335:   PetscErrorCode    ierr;
336:   PetscScalar       *array;
337:   const PetscScalar *omega;
338:   Vec               v;

345:   if (m <= 0) SETERRQ1(PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_INCOMP,"Number of columns %D must be positive",m);
346:   if (bv->nc && !bv->issplit) SETERRQ(PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_WRONGSTATE,"Cannot resize a BV with constraints");
347:   if (bv->m == m) return(0);
348:   BVCheckOp(bv,1,resize);

350:   PetscLogEventBegin(BV_Create,bv,0,0,0);
351:   (*bv->ops->resize)(bv,m,copy);
352:   VecDestroy(&bv->buffer);
353:   BVDestroy(&bv->cached);
354:   PetscFree2(bv->h,bv->c);
355:   if (bv->omega) {
356:     if (bv->cuda) {
357: #if defined(PETSC_HAVE_CUDA)
358:       VecCreateSeqCUDA(PETSC_COMM_SELF,m,&v);
359: #else
360:       SETERRQ(PetscObjectComm((PetscObject)bv),1,"Something wrong happened");
361: #endif
362:     } else {
363:       VecCreateSeq(PETSC_COMM_SELF,m,&v);
364:     }
365:     PetscLogObjectParent((PetscObject)bv,(PetscObject)v);
366:     if (copy) {
367:       VecGetArray(v,&array);
368:       VecGetArrayRead(bv->omega,&omega);
369:       PetscArraycpy(array,omega,PetscMin(m,bv->m));
370:       VecRestoreArrayRead(bv->omega,&omega);
371:       VecRestoreArray(v,&array);
372:     } else {
373:       VecSet(v,1.0);
374:     }
375:     VecDestroy(&bv->omega);
376:     bv->omega = v;
377:   }
378:   bv->m = m;
379:   bv->k = PetscMin(bv->k,m);
380:   bv->l = PetscMin(bv->l,m);
381:   PetscLogEventEnd(BV_Create,bv,0,0,0);
382:   PetscObjectStateIncrease((PetscObject)bv);
383:   return(0);
384: }

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

389:    Logically Collective on bv

391:    Input Parameters:
392: +  bv - the basis vectors context
393: .  l  - number of leading columns
394: -  k  - number of active columns

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

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

405:    In orthogonalization operations, the first l columns are treated
406:    differently: they participate in the orthogonalization but the computed
407:    coefficients are not stored.

409:    Level: intermediate

411: .seealso: BVGetActiveColumns(), BVSetSizes()
412: @*/
413: PetscErrorCode BVSetActiveColumns(BV bv,PetscInt l,PetscInt k)
414: {
419:   BVCheckSizes(bv,1);
420:   if (k==PETSC_DECIDE || k==PETSC_DEFAULT) {
421:     bv->k = bv->m;
422:   } else {
423:     if (k<0 || k>bv->m) SETERRQ(PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of k. Must be between 0 and m");
424:     bv->k = k;
425:   }
426:   if (l==PETSC_DECIDE || l==PETSC_DEFAULT) {
427:     bv->l = 0;
428:   } else {
429:     if (l<0 || l>bv->k) SETERRQ(PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of l. Must be between 0 and k");
430:     bv->l = l;
431:   }
432:   return(0);
433: }

435: /*@
436:    BVGetActiveColumns - Returns the current active dimensions.

438:    Not Collective

440:    Input Parameter:
441: .  bv - the basis vectors context

443:    Output Parameter:
444: +  l  - number of leading columns
445: -  k  - number of active columns

447:    Level: intermediate

449: .seealso: BVSetActiveColumns()
450: @*/
451: PetscErrorCode BVGetActiveColumns(BV bv,PetscInt *l,PetscInt *k)
452: {
455:   if (l) *l = bv->l;
456:   if (k) *k = bv->k;
457:   return(0);
458: }

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

463:    Collective on bv

465:    Input Parameters:
466: +  bv    - the basis vectors context
467: .  B     - a symmetric matrix (may be NULL)
468: -  indef - a flag indicating if the matrix is indefinite

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

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

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

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

485:    Level: advanced

487: .seealso: BVGetMatrix(), BVDot(), BVNorm(), BVOrthogonalize(), BVSetDefiniteTolerance()
488: @*/
489: PetscErrorCode BVSetMatrix(BV bv,Mat B,PetscBool indef)
490: {
492:   PetscInt       m,n;

497:   if (B!=bv->matrix || (B && ((PetscObject)B)->id!=((PetscObject)bv->matrix)->id) || indef!=bv->indef) {
498:     if (B) {
500:       MatGetLocalSize(B,&m,&n);
501:       if (m!=n) SETERRQ(PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_SIZ,"Matrix must be square");
502:       if (bv->m && bv->n!=n) SETERRQ2(PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_INCOMP,"Mismatching local dimension BV %D, Mat %D",bv->n,n);
503:     }
504:     if (B) { PetscObjectReference((PetscObject)B); }
505:     MatDestroy(&bv->matrix);
506:     bv->matrix = B;
507:     bv->indef  = indef;
508:     PetscObjectStateIncrease((PetscObject)bv);
509:     if (bv->Bx) { PetscObjectStateIncrease((PetscObject)bv->Bx); }
510:     if (bv->cached) { PetscObjectStateIncrease((PetscObject)bv->cached); }
511:   }
512:   return(0);
513: }

515: /*@
516:    BVGetMatrix - Retrieves the matrix representation of the inner product.

518:    Not collective, though a parallel Mat may be returned

520:    Input Parameter:
521: .  bv    - the basis vectors context

523:    Output Parameter:
524: +  B     - the matrix of the inner product (may be NULL)
525: -  indef - the flag indicating if the matrix is indefinite

527:    Level: advanced

529: .seealso: BVSetMatrix()
530: @*/
531: PetscErrorCode BVGetMatrix(BV bv,Mat *B,PetscBool *indef)
532: {
535:   if (B)     *B     = bv->matrix;
536:   if (indef) *indef = bv->indef;
537:   return(0);
538: }

540: /*@
541:    BVApplyMatrix - Multiplies a vector by the matrix representation of the
542:    inner product.

544:    Neighbor-wise Collective on bv

546:    Input Parameter:
547: +  bv - the basis vectors context
548: -  x  - the vector

550:    Output Parameter:
551: .  y  - the result

553:    Note:
554:    If no matrix was specified this function copies the vector.

556:    Level: advanced

558: .seealso: BVSetMatrix(), BVApplyMatrixBV()
559: @*/
560: PetscErrorCode BVApplyMatrix(BV bv,Vec x,Vec y)
561: {

568:   if (bv->matrix) {
569:     BV_IPMatMult(bv,x);
570:     VecCopy(bv->Bx,y);
571:   } else {
572:     VecCopy(x,y);
573:   }
574:   return(0);
575: }

577: /*@
578:    BVApplyMatrixBV - Multiplies the BV vectors by the matrix representation
579:    of the inner product.

581:    Neighbor-wise Collective on X

583:    Input Parameter:
584: .  X - the basis vectors context

586:    Output Parameter:
587: .  Y - the basis vectors to store the result (optional)

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

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

596:    Level: developer

598: .seealso: BVSetMatrix(), BVApplyMatrix(), BVMatMult(), BVGetCachedBV()
599: @*/
600: PetscErrorCode BVApplyMatrixBV(BV X,BV Y)
601: {

606:   if (Y) {
608:     if (X->matrix) {
609:       BVMatMult(X,X->matrix,Y);
610:     } else {
611:       BVCopy(X,Y);
612:     }
613:   } else {
614:     BV_IPMatMultBV(X);
615:   }
616:   return(0);
617: }

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

622:    Logically Collective on bv

624:    Input Parameter:
625: +  bv    - the basis vectors context
626: -  omega - a vector representing the diagonal of the signature matrix

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

631:    Level: developer

633: .seealso: BVSetMatrix(), BVGetSignature()
634: @*/
635: PetscErrorCode BVSetSignature(BV bv,Vec omega)
636: {
637:   PetscErrorCode    ierr;
638:   PetscInt          i,n;
639:   const PetscScalar *pomega;
640:   PetscScalar       *intern;

644:   BVCheckSizes(bv,1);

648:   VecGetSize(omega,&n);
649:   if (n!=bv->k) SETERRQ2(PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_SIZ,"Vec argument has %D elements, should be %D",n,bv->k);
650:   BV_AllocateSignature(bv);
651:   if (bv->indef) {
652:     VecGetArrayRead(omega,&pomega);
653:     VecGetArray(bv->omega,&intern);
654:     for (i=0;i<n;i++) intern[bv->nc+i] = pomega[i];
655:     VecRestoreArray(bv->omega,&intern);
656:     VecRestoreArrayRead(omega,&pomega);
657:   } else {
658:     PetscInfo(bv,"Ignoring signature because BV is not indefinite\n");
659:   }
660:   PetscObjectStateIncrease((PetscObject)bv);
661:   return(0);
662: }

664: /*@
665:    BVGetSignature - Retrieves the signature matrix from last orthogonalization.

667:    Not collective

669:    Input Parameter:
670: .  bv    - the basis vectors context

672:    Output Parameter:
673: .  omega - a vector representing the diagonal of the signature matrix

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

678:    Level: developer

680: .seealso: BVSetMatrix(), BVSetSignature()
681: @*/
682: PetscErrorCode BVGetSignature(BV bv,Vec omega)
683: {
684:   PetscErrorCode    ierr;
685:   PetscInt          i,n;
686:   PetscScalar       *pomega;
687:   const PetscScalar *intern;

691:   BVCheckSizes(bv,1);

695:   VecGetSize(omega,&n);
696:   if (n!=bv->k) SETERRQ2(PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_SIZ,"Vec argument has %D elements, should be %D",n,bv->k);
697:   if (bv->indef && bv->omega) {
698:     VecGetArray(omega,&pomega);
699:     VecGetArrayRead(bv->omega,&intern);
700:     for (i=0;i<n;i++) pomega[i] = intern[bv->nc+i];
701:     VecRestoreArrayRead(bv->omega,&intern);
702:     VecRestoreArray(omega,&pomega);
703:   } else {
704:     VecSet(omega,1.0);
705:   }
706:   return(0);
707: }

709: /*@
710:    BVSetBufferVec - Attach a vector object to be used as buffer space for
711:    several operations.

713:    Collective on bv

715:    Input Parameters:
716: +  bv     - the basis vectors context)
717: -  buffer - the vector

719:    Notes:
720:    Use BVGetBufferVec() to retrieve the vector (for example, to free it
721:    at the end of the computations).

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

726:    Level: developer

728: .seealso: BVGetBufferVec(), BVSetSizes(), BVGetNumConstraints()
729: @*/
730: PetscErrorCode BVSetBufferVec(BV bv,Vec buffer)
731: {
733:   PetscInt       ld,n;
734:   PetscMPIInt    size;

739:   BVCheckSizes(bv,1);
740:   VecGetSize(buffer,&n);
741:   ld = bv->m+bv->nc;
742:   if (n != ld*bv->m) SETERRQ1(PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_SIZ,"Buffer size must be %d",ld*bv->m);
743:   MPI_Comm_size(PetscObjectComm((PetscObject)buffer),&size);CHKERRMPI(ierr);
744:   if (size>1) SETERRQ(PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_WRONG,"Buffer must be a sequential vector");

746:   PetscObjectReference((PetscObject)buffer);
747:   VecDestroy(&bv->buffer);
748:   bv->buffer = buffer;
749:   PetscLogObjectParent((PetscObject)bv,(PetscObject)bv->buffer);
750:   return(0);
751: }

753: /*@
754:    BVGetBufferVec - Obtain the buffer vector associated with the BV object.

756:    Not Collective, but Vec returned is parallel if BV is parallel

758:    Input Parameters:
759: .  bv - the basis vectors context

761:    Output Parameter:
762: .  buffer - vector

764:    Notes:
765:    The vector is created if not available previously. It is a sequential vector
766:    of length (nc+m)*m, where m is the number of columns of bv and nc is the number
767:    of constraints.

769:    Developer Notes:
770:    The buffer vector is viewed as a column-major matrix with leading dimension
771:    ld=nc+m, and m columns at most. In the most common usage, it has the structure
772: .vb
773:       | | C |
774:       |s|---|
775:       | | H |
776: .ve
777:    where H is an upper Hessenberg matrix of order m x (m-1), C contains coefficients
778:    related to orthogonalization against constraints (first nc rows), and s is the
779:    first column that contains scratch values computed during Gram-Schmidt
780:    orthogonalization. In particular, BVDotColumn() and BVMultColumn() use s to
781:    store the coefficients.

783:    Level: developer

785: .seealso: BVSetBufferVec(), BVSetSizes(), BVGetNumConstraints(), BVDotColumn(), BVMultColumn()
786: @*/
787: PetscErrorCode BVGetBufferVec(BV bv,Vec *buffer)
788: {
790:   PetscInt       ld;

795:   BVCheckSizes(bv,1);
796:   if (!bv->buffer) {
797:     ld = bv->m+bv->nc;
798:     VecCreate(PETSC_COMM_SELF,&bv->buffer);
799:     VecSetSizes(bv->buffer,PETSC_DECIDE,ld*bv->m);
800:     VecSetType(bv->buffer,((PetscObject)bv->t)->type_name);
801:     PetscLogObjectParent((PetscObject)bv,(PetscObject)bv->buffer);
802:   }
803:   *buffer = bv->buffer;
804:   return(0);
805: }

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

811:    Collective on bv

813:    Input Parameters:
814: +  bv   - the basis vectors context
815: -  rand - the random number generator context

817:    Level: advanced

819: .seealso: BVGetRandomContext(), BVSetRandom(), BVSetRandomNormal(), BVSetRandomColumn(), BVSetRandomCond()
820: @*/
821: PetscErrorCode BVSetRandomContext(BV bv,PetscRandom rand)
822: {

829:   PetscObjectReference((PetscObject)rand);
830:   PetscRandomDestroy(&bv->rand);
831:   bv->rand = rand;
832:   PetscLogObjectParent((PetscObject)bv,(PetscObject)bv->rand);
833:   return(0);
834: }

836: /*@
837:    BVGetRandomContext - Gets the PetscRandom object associated with the BV.

839:    Not Collective

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

844:    Output Parameter:
845: .  rand - the random number generator context

847:    Level: advanced

849: .seealso: BVSetRandomContext(), BVSetRandom(), BVSetRandomNormal(), BVSetRandomColumn(), BVSetRandomCond()
850: @*/
851: PetscErrorCode BVGetRandomContext(BV bv,PetscRandom* rand)
852: {

858:   if (!bv->rand) {
859:     PetscRandomCreate(PetscObjectComm((PetscObject)bv),&bv->rand);
860:     PetscLogObjectParent((PetscObject)bv,(PetscObject)bv->rand);
861:     if (bv->cuda) { PetscRandomSetType(bv->rand,PETSCCURAND); }
862:     if (bv->sfocalled) { PetscRandomSetFromOptions(bv->rand); }
863:     if (bv->rrandom) {
864:       PetscRandomSetSeed(bv->rand,0x12345678);
865:       PetscRandomSeed(bv->rand);
866:     }
867:   }
868:   *rand = bv->rand;
869:   return(0);
870: }

872: /*@
873:    BVSetFromOptions - Sets BV options from the options database.

875:    Collective on bv

877:    Input Parameter:
878: .  bv - the basis vectors context

880:    Level: beginner
881: @*/
882: PetscErrorCode BVSetFromOptions(BV bv)
883: {
884:   PetscErrorCode     ierr;
885:   char               type[256];
886:   PetscBool          flg1,flg2,flg3,flg4;
887:   PetscReal          r;
888:   BVOrthogType       otype;
889:   BVOrthogRefineType orefine;
890:   BVOrthogBlockType  oblock;

894:   BVRegisterAll();
895:   PetscObjectOptionsBegin((PetscObject)bv);
896:     PetscOptionsFList("-bv_type","Basis Vectors type","BVSetType",BVList,(char*)(((PetscObject)bv)->type_name?((PetscObject)bv)->type_name:BVSVEC),type,sizeof(type),&flg1);
897:     if (flg1) {
898:       BVSetType(bv,type);
899:     } else if (!((PetscObject)bv)->type_name) {
900:       BVSetType(bv,BVSVEC);
901:     }

903:     otype = bv->orthog_type;
904:     PetscOptionsEnum("-bv_orthog_type","Orthogonalization method","BVSetOrthogonalization",BVOrthogTypes,(PetscEnum)otype,(PetscEnum*)&otype,&flg1);
905:     orefine = bv->orthog_ref;
906:     PetscOptionsEnum("-bv_orthog_refine","Iterative refinement mode during orthogonalization","BVSetOrthogonalization",BVOrthogRefineTypes,(PetscEnum)orefine,(PetscEnum*)&orefine,&flg2);
907:     r = bv->orthog_eta;
908:     PetscOptionsReal("-bv_orthog_eta","Parameter of iterative refinement during orthogonalization","BVSetOrthogonalization",r,&r,&flg3);
909:     oblock = bv->orthog_block;
910:     PetscOptionsEnum("-bv_orthog_block","Block orthogonalization method","BVSetOrthogonalization",BVOrthogBlockTypes,(PetscEnum)oblock,(PetscEnum*)&oblock,&flg4);
911:     if (flg1 || flg2 || flg3 || flg4) { BVSetOrthogonalization(bv,otype,orefine,r,oblock); }

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

915:     PetscOptionsReal("-bv_definite_tol","Tolerance for checking a definite inner product","BVSetDefiniteTolerance",r,&r,&flg1);
916:     if (flg1) { BVSetDefiniteTolerance(bv,r); }

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

921:     if (bv->ops->create) bv->defersfo = PETSC_TRUE;   /* defer call to setfromoptions */
922:     else if (bv->ops->setfromoptions) {
923:       (*bv->ops->setfromoptions)(PetscOptionsObject,bv);
924:     }
925:     PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject)bv);
926:   PetscOptionsEnd();
927:   bv->sfocalled = PETSC_TRUE;
928:   return(0);
929: }

931: /*@
932:    BVSetOrthogonalization - Specifies the method used for the orthogonalization of
933:    vectors (classical or modified Gram-Schmidt with or without refinement), and
934:    for the block-orthogonalization (simultaneous orthogonalization of a set of
935:    vectors).

937:    Logically Collective on bv

939:    Input Parameters:
940: +  bv     - the basis vectors context
941: .  type   - the method of vector orthogonalization
942: .  refine - type of refinement
943: .  eta    - parameter for selective refinement
944: -  block  - the method of block orthogonalization

946:    Options Database Keys:
947: +  -bv_orthog_type <type> - Where <type> is cgs for Classical Gram-Schmidt orthogonalization
948:                          (default) or mgs for Modified Gram-Schmidt orthogonalization
949: .  -bv_orthog_refine <ref> - Where <ref> is one of never, ifneeded (default) or always
950: .  -bv_orthog_eta <eta> -  For setting the value of eta
951: -  -bv_orthog_block <block> - Where <block> is the block-orthogonalization method

953:    Notes:
954:    The default settings work well for most problems.

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

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

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

964:    Level: advanced

966: .seealso: BVOrthogonalizeColumn(), BVGetOrthogonalization(), BVOrthogType, BVOrthogRefineType, BVOrthogBlockType
967: @*/
968: PetscErrorCode BVSetOrthogonalization(BV bv,BVOrthogType type,BVOrthogRefineType refine,PetscReal eta,BVOrthogBlockType block)
969: {
976:   switch (type) {
977:     case BV_ORTHOG_CGS:
978:     case BV_ORTHOG_MGS:
979:       bv->orthog_type = type;
980:       break;
981:     default:
982:       SETERRQ(PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_WRONG,"Unknown orthogonalization type");
983:   }
984:   switch (refine) {
985:     case BV_ORTHOG_REFINE_NEVER:
986:     case BV_ORTHOG_REFINE_IFNEEDED:
987:     case BV_ORTHOG_REFINE_ALWAYS:
988:       bv->orthog_ref = refine;
989:       break;
990:     default:
991:       SETERRQ(PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_WRONG,"Unknown refinement type");
992:   }
993:   if (eta == PETSC_DEFAULT) {
994:     bv->orthog_eta = 0.7071;
995:   } else {
996:     if (eta <= 0.0 || eta > 1.0) SETERRQ(PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_OUTOFRANGE,"Invalid eta value");
997:     bv->orthog_eta = eta;
998:   }
999:   switch (block) {
1000:     case BV_ORTHOG_BLOCK_GS:
1001:     case BV_ORTHOG_BLOCK_CHOL:
1002:     case BV_ORTHOG_BLOCK_TSQR:
1003:     case BV_ORTHOG_BLOCK_TSQRCHOL:
1004:     case BV_ORTHOG_BLOCK_SVQB:
1005:       bv->orthog_block = block;
1006:       break;
1007:     default:
1008:       SETERRQ(PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_WRONG,"Unknown block orthogonalization type");
1009:   }
1010:   return(0);
1011: }

1013: /*@
1014:    BVGetOrthogonalization - Gets the orthogonalization settings from the BV object.

1016:    Not Collective

1018:    Input Parameter:
1019: .  bv - basis vectors context

1021:    Output Parameter:
1022: +  type   - the method of vector orthogonalization
1023: .  refine - type of refinement
1024: .  eta    - parameter for selective refinement
1025: -  block  - the method of block orthogonalization

1027:    Level: advanced

1029: .seealso: BVOrthogonalizeColumn(), BVSetOrthogonalization(), BVOrthogType, BVOrthogRefineType, BVOrthogBlockType
1030: @*/
1031: PetscErrorCode BVGetOrthogonalization(BV bv,BVOrthogType *type,BVOrthogRefineType *refine,PetscReal *eta,BVOrthogBlockType *block)
1032: {
1035:   if (type)   *type   = bv->orthog_type;
1036:   if (refine) *refine = bv->orthog_ref;
1037:   if (eta)    *eta    = bv->orthog_eta;
1038:   if (block)  *block  = bv->orthog_block;
1039:   return(0);
1040: }

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

1045:    Logically Collective on bv

1047:    Input Parameters:
1048: +  bv     - the basis vectors context
1049: -  method - the method for the BVMatMult() operation

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

1054:    Notes:
1055:    Allowed values are
1056: +  BV_MATMULT_VECS - perform a matrix-vector multiply per each column
1057: .  BV_MATMULT_MAT - carry out a Mat-Mat product with a dense matrix
1058: -  BV_MATMULT_MAT_SAVE - this case is deprecated

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

1062:    Level: advanced

1064: .seealso: BVMatMult(), BVGetMatMultMethod(), BVMatMultType
1065: @*/
1066: PetscErrorCode BVSetMatMultMethod(BV bv,BVMatMultType method)
1067: {

1073:   switch (method) {
1074:     case BV_MATMULT_VECS:
1075:     case BV_MATMULT_MAT:
1076:       bv->vmm = method;
1077:       break;
1078:     case BV_MATMULT_MAT_SAVE:
1079:       PetscInfo(bv,"BV_MATMULT_MAT_SAVE is deprecated, using BV_MATMULT_MAT\n");
1080:       bv->vmm = BV_MATMULT_MAT;
1081:       break;
1082:     default:
1083:       SETERRQ(PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_WRONG,"Unknown matmult method");
1084:   }
1085:   return(0);
1086: }

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

1091:    Not Collective

1093:    Input Parameter:
1094: .  bv - basis vectors context

1096:    Output Parameter:
1097: .  method - the method for the BVMatMult() operation

1099:    Level: advanced

1101: .seealso: BVMatMult(), BVSetMatMultMethod(), BVMatMultType
1102: @*/
1103: PetscErrorCode BVGetMatMultMethod(BV bv,BVMatMultType *method)
1104: {
1108:   *method = bv->vmm;
1109:   return(0);
1110: }

1112: /*@
1113:    BVGetColumn - Returns a Vec object that contains the entries of the
1114:    requested column of the basis vectors object.

1116:    Logically Collective on bv

1118:    Input Parameters:
1119: +  bv - the basis vectors context
1120: -  j  - the index of the requested column

1122:    Output Parameter:
1123: .  v  - vector containing the jth column

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

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

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

1137:    Level: beginner

1139: .seealso: BVRestoreColumn(), BVInsertConstraints()
1140: @*/
1141: PetscErrorCode BVGetColumn(BV bv,PetscInt j,Vec *v)
1142: {
1144:   PetscInt       l;

1149:   BVCheckSizes(bv,1);
1150:   BVCheckOp(bv,1,getcolumn);
1152:   if (j<0 && -j>bv->nc) SETERRQ2(PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_OUTOFRANGE,"You requested constraint %D but only %D are available",-j,bv->nc);
1153:   if (j>=bv->m) SETERRQ2(PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_OUTOFRANGE,"You requested column %D but only %D are available",j,bv->m);
1154:   if (j==bv->ci[0] || j==bv->ci[1]) SETERRQ1(PetscObjectComm((PetscObject)bv),PETSC_ERR_SUP,"Column %D already fetched in a previous call to BVGetColumn",j);
1155:   l = BVAvailableVec;
1156:   if (l==-1) SETERRQ(PetscObjectComm((PetscObject)bv),PETSC_ERR_SUP,"Too many requested columns; you must call BVRestoreColumn for one of the previously fetched columns");
1157:   (*bv->ops->getcolumn)(bv,j,v);
1158:   bv->ci[l] = j;
1159:   PetscObjectStateGet((PetscObject)bv->cv[l],&bv->st[l]);
1160:   PetscObjectGetId((PetscObject)bv->cv[l],&bv->id[l]);
1161:   *v = bv->cv[l];
1162:   return(0);
1163: }

1165: /*@
1166:    BVRestoreColumn - Restore a column obtained with BVGetColumn().

1168:    Logically Collective on bv

1170:    Input Parameters:
1171: +  bv - the basis vectors context
1172: .  j  - the index of the column
1173: -  v  - vector obtained with BVGetColumn()

1175:    Note:
1176:    The arguments must match the corresponding call to BVGetColumn().

1178:    Level: beginner

1180: .seealso: BVGetColumn()
1181: @*/
1182: PetscErrorCode BVRestoreColumn(BV bv,PetscInt j,Vec *v)
1183: {
1184:   PetscErrorCode   ierr;
1185:   PetscObjectId    id;
1186:   PetscObjectState st;
1187:   PetscInt         l;

1192:   BVCheckSizes(bv,1);
1196:   if (j<0 && -j>bv->nc) SETERRQ2(PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_OUTOFRANGE,"You requested constraint %D but only %D are available",-j,bv->nc);
1197:   if (j>=bv->m) SETERRQ2(PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_OUTOFRANGE,"You requested column %D but only %D are available",j,bv->m);
1198:   if (j!=bv->ci[0] && j!=bv->ci[1]) SETERRQ1(PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_WRONG,"Column %D has not been fetched with a call to BVGetColumn",j);
1199:   l = (j==bv->ci[0])? 0: 1;
1200:   PetscObjectGetId((PetscObject)*v,&id);
1201:   if (id!=bv->id[l]) SETERRQ(PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_WRONG,"Argument 3 is not the same Vec that was obtained with BVGetColumn");
1202:   PetscObjectStateGet((PetscObject)*v,&st);
1203:   if (st!=bv->st[l]) {
1204:     PetscObjectStateIncrease((PetscObject)bv);
1205:   }
1206:   if (bv->ops->restorecolumn) {
1207:     (*bv->ops->restorecolumn)(bv,j,v);
1208:   } else bv->cv[l] = NULL;
1209:   bv->ci[l] = -bv->nc-1;
1210:   bv->st[l] = -1;
1211:   bv->id[l] = 0;
1212:   *v = NULL;
1213:   return(0);
1214: }

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

1220:    Logically Collective on bv

1222:    Input Parameters:
1223: .  bv - the basis vectors context

1225:    Output Parameter:
1226: .  a  - location to put pointer to the array

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

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

1236:    Level: advanced

1238: .seealso: BVRestoreArray(), BVInsertConstraints()
1239: @*/
1240: PetscErrorCode BVGetArray(BV bv,PetscScalar **a)
1241: {

1247:   BVCheckSizes(bv,1);
1248:   BVCheckOp(bv,1,getarray);
1249:   (*bv->ops->getarray)(bv,a);
1250:   return(0);
1251: }

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

1256:    Logically Collective on bv

1258:    Input Parameters:
1259: +  bv - the basis vectors context
1260: -  a  - location of pointer to array obtained from BVGetArray()

1262:    Note:
1263:    This operation may imply a data copy, for BV types that do not store
1264:    data contiguously in memory.

1266:    Level: advanced

1268: .seealso: BVGetColumn()
1269: @*/
1270: PetscErrorCode BVRestoreArray(BV bv,PetscScalar **a)
1271: {

1277:   BVCheckSizes(bv,1);
1278:   if (bv->ops->restorearray) {
1279:     (*bv->ops->restorearray)(bv,a);
1280:   }
1281:   if (a) *a = NULL;
1282:   PetscObjectStateIncrease((PetscObject)bv);
1283:   return(0);
1284: }

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

1290:    Not Collective

1292:    Input Parameters:
1293: .  bv - the basis vectors context

1295:    Output Parameter:
1296: .  a  - location to put pointer to the array

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

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

1306:    Level: advanced

1308: .seealso: BVRestoreArray(), BVInsertConstraints()
1309: @*/
1310: PetscErrorCode BVGetArrayRead(BV bv,const PetscScalar **a)
1311: {

1317:   BVCheckSizes(bv,1);
1318:   BVCheckOp(bv,1,getarrayread);
1319:   (*bv->ops->getarrayread)(bv,a);
1320:   return(0);
1321: }

1323: /*@C
1324:    BVRestoreArrayRead - Restore the BV object after BVGetArrayRead() has
1325:    been called.

1327:    Not Collective

1329:    Input Parameters:
1330: +  bv - the basis vectors context
1331: -  a  - location of pointer to array obtained from BVGetArrayRead()

1333:    Level: advanced

1335: .seealso: BVGetColumn()
1336: @*/
1337: PetscErrorCode BVRestoreArrayRead(BV bv,const PetscScalar **a)
1338: {

1344:   BVCheckSizes(bv,1);
1345:   if (bv->ops->restorearrayread) {
1346:     (*bv->ops->restorearrayread)(bv,a);
1347:   }
1348:   if (a) *a = NULL;
1349:   return(0);
1350: }

1352: /*@
1353:    BVCreateVec - Creates a new Vec object with the same type and dimensions
1354:    as the columns of the basis vectors object.

1356:    Collective on bv

1358:    Input Parameter:
1359: .  bv - the basis vectors context

1361:    Output Parameter:
1362: .  v  - the new vector

1364:    Note:
1365:    The user is responsible of destroying the returned vector.

1367:    Level: beginner

1369: .seealso: BVCreateMat()
1370: @*/
1371: PetscErrorCode BVCreateVec(BV bv,Vec *v)
1372: {

1377:   BVCheckSizes(bv,1);
1379:   VecDuplicate(bv->t,v);
1380:   return(0);
1381: }

1383: /*@
1384:    BVCreateMat - Creates a new Mat object of dense type and copies the contents
1385:    of the BV object.

1387:    Collective on bv

1389:    Input Parameter:
1390: .  bv - the basis vectors context

1392:    Output Parameter:
1393: .  A  - the new matrix

1395:    Notes:
1396:    The user is responsible of destroying the returned matrix.

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

1400:    Level: intermediate

1402: .seealso: BVCreateFromMat(), BVCreateVec(), BVGetMat()
1403: @*/
1404: PetscErrorCode BVCreateMat(BV bv,Mat *A)
1405: {
1406:   PetscErrorCode    ierr;
1407:   PetscScalar       *aa;
1408:   const PetscScalar *vv;

1412:   BVCheckSizes(bv,1);

1415:   MatCreateDense(PetscObjectComm((PetscObject)bv->t),bv->n,PETSC_DECIDE,bv->N,bv->m,NULL,A);
1416:   MatDenseGetArrayWrite(*A,&aa);
1417:   BVGetArrayRead(bv,&vv);
1418:   PetscArraycpy(aa,vv,bv->m*bv->n);
1419:   BVRestoreArrayRead(bv,&vv);
1420:   MatDenseRestoreArrayWrite(*A,&aa);
1421:   MatAssemblyBegin(*A,MAT_FINAL_ASSEMBLY);
1422:   MatAssemblyEnd(*A,MAT_FINAL_ASSEMBLY);
1423:   return(0);
1424: }

1426: /*@
1427:    BVGetMat - Returns a Mat object of dense type that shares the memory of
1428:    the BV object.

1430:    Collective on bv

1432:    Input Parameter:
1433: .  bv - the basis vectors context

1435:    Output Parameter:
1436: .  A  - the matrix

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

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

1446:    Level: advanced

1448: .seealso: BVRestoreMat(), BVCreateMat(), BVGetArray()
1449: @*/
1450: PetscErrorCode BVGetMat(BV bv,Mat *A)
1451: {
1453:   PetscScalar    *vv,*aa;
1454:   PetscBool      create=PETSC_FALSE;
1455:   PetscInt       m,cols;

1459:   BVCheckSizes(bv,1);
1461:   if (bv->ops->getmat) {
1462:     (*bv->ops->getmat)(bv,A);
1463:   } else {
1464:     m = bv->k-bv->l;
1465:     if (!bv->Aget) create=PETSC_TRUE;
1466:     else {
1467:       MatDenseGetArray(bv->Aget,&aa);
1468:       if (aa) SETERRQ(PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_WRONGSTATE,"BVGetMat already called on this BV");
1469:       MatGetSize(bv->Aget,NULL,&cols);
1470:       if (cols!=m) {
1471:         MatDestroy(&bv->Aget);
1472:         create=PETSC_TRUE;
1473:       }
1474:     }
1475:     BVGetArray(bv,&vv);
1476:     if (create) {
1477:       MatCreateDense(PetscObjectComm((PetscObject)bv),bv->n,PETSC_DECIDE,bv->N,m,vv,&bv->Aget); /* pass a pointer to avoid allocation of storage */
1478:       MatDenseReplaceArray(bv->Aget,NULL);  /* replace with a null pointer, the value after BVRestoreMat */
1479:       PetscLogObjectParent((PetscObject)bv,(PetscObject)bv->Aget);
1480:     }
1481:     MatDensePlaceArray(bv->Aget,vv+(bv->nc+bv->l)*bv->n);  /* set the actual pointer */
1482:     *A = bv->Aget;
1483:   }
1484:   return(0);
1485: }

1487: /*@
1488:    BVRestoreMat - Restores the Mat obtained with BVGetMat().

1490:    Logically Collective on bv

1492:    Input Parameters:
1493: +  bv - the basis vectors context
1494: -  A  - the fetched matrix

1496:    Note:
1497:    A call to this function must match a previous call of BVGetMat().
1498:    The effect is that the contents of the Mat are copied back to the
1499:    BV internal data structures.

1501:    Level: advanced

1503: .seealso: BVGetMat(), BVRestoreArray()
1504: @*/
1505: PetscErrorCode BVRestoreMat(BV bv,Mat *A)
1506: {
1508:   PetscScalar    *vv,*aa;

1512:   BVCheckSizes(bv,1);
1514:   if (!bv->Aget) SETERRQ(PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_WRONGSTATE,"BVRestoreMat must match a previous call to BVGetMat");
1515:   if (bv->Aget!=*A) SETERRQ(PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_WRONGSTATE,"Mat argument is not the same as the one obtained with BVGetMat");
1516:   if (bv->ops->restoremat) {
1517:     (*bv->ops->restoremat)(bv,A);
1518:   } else {
1519:     MatDenseGetArray(bv->Aget,&aa);
1520:     vv = aa-(bv->nc+bv->l)*bv->n;
1521:     MatDenseResetArray(bv->Aget);
1522:     BVRestoreArray(bv,&vv);
1523:     *A = NULL;
1524:   }
1525:   return(0);
1526: }

1528: /*
1529:    Copy all user-provided attributes of V to another BV object W
1530:  */
1531: PETSC_STATIC_INLINE PetscErrorCode BVDuplicate_Private(BV V,BV W)
1532: {

1536:   BVSetType(W,((PetscObject)V)->type_name);
1537:   W->orthog_type  = V->orthog_type;
1538:   W->orthog_ref   = V->orthog_ref;
1539:   W->orthog_eta   = V->orthog_eta;
1540:   W->orthog_block = V->orthog_block;
1541:   if (V->matrix) { PetscObjectReference((PetscObject)V->matrix); }
1542:   W->matrix       = V->matrix;
1543:   W->indef        = V->indef;
1544:   W->vmm          = V->vmm;
1545:   W->rrandom      = V->rrandom;
1546:   W->deftol       = V->deftol;
1547:   if (V->rand) { PetscObjectReference((PetscObject)V->rand); }
1548:   W->rand         = V->rand;
1549:   W->sfocalled    = V->sfocalled;
1550:   if (V->ops->duplicate) { (*V->ops->duplicate)(V,W); }
1551:   PetscObjectStateIncrease((PetscObject)W);
1552:   return(0);
1553: }

1555: /*@
1556:    BVDuplicate - Creates a new basis vector object of the same type and
1557:    dimensions as an existing one.

1559:    Collective on V

1561:    Input Parameter:
1562: .  V - basis vectors context

1564:    Output Parameter:
1565: .  W - location to put the new BV

1567:    Notes:
1568:    The new BV has the same type and dimensions as V, and it shares the same
1569:    template vector. Also, the inner product matrix and orthogonalization
1570:    options are copied.

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

1575:    Level: intermediate

1577: .seealso: BVDuplicateResize(), BVCreate(), BVSetSizesFromVec(), BVCopy()
1578: @*/
1579: PetscErrorCode BVDuplicate(BV V,BV *W)
1580: {

1586:   BVCheckSizes(V,1);
1588:   BVCreate(PetscObjectComm((PetscObject)V),W);
1589:   BVSetSizesFromVec(*W,V->t,V->m);
1590:   BVDuplicate_Private(V,*W);
1591:   return(0);
1592: }

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

1598:    Collective on V

1600:    Input Parameter:
1601: +  V - basis vectors context
1602: -  m - the new number of columns

1604:    Output Parameter:
1605: .  W - location to put the new BV

1607:    Note:
1608:    This is equivalent of a call to BVDuplicate() followed by BVResize(). The
1609:    contents of V are not copied to W.

1611:    Level: intermediate

1613: .seealso: BVDuplicate(), BVResize()
1614: @*/
1615: PetscErrorCode BVDuplicateResize(BV V,PetscInt m,BV *W)
1616: {

1622:   BVCheckSizes(V,1);
1625:   BVCreate(PetscObjectComm((PetscObject)V),W);
1626:   BVSetSizesFromVec(*W,V->t,m);
1627:   BVDuplicate_Private(V,*W);
1628:   return(0);
1629: }

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

1635:    Not collective

1637:    Input Parameter:
1638: .  bv    - the basis vectors context

1640:    Output Parameter:
1641: .  cached - the cached BV

1643:    Note:
1644:    The cached BV is created if not available previously.

1646:    Level: developer

1648: .seealso: BVApplyMatrixBV()
1649: @*/
1650: PetscErrorCode BVGetCachedBV(BV bv,BV *cached)
1651: {

1657:   BVCheckSizes(bv,1);
1658:   if (!bv->cached) {
1659:     BVCreate(PetscObjectComm((PetscObject)bv),&bv->cached);
1660:     BVSetSizesFromVec(bv->cached,bv->t,bv->m);
1661:     BVDuplicate_Private(bv,bv->cached);
1662:     PetscLogObjectParent((PetscObject)bv,(PetscObject)bv->cached);
1663:   }
1664:   *cached = bv->cached;
1665:   return(0);
1666: }

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

1671:    Logically Collective on V

1673:    Input Parameter:
1674: .  V - basis vectors context

1676:    Output Parameter:
1677: .  W - the copy

1679:    Note:
1680:    Both V and W must be distributed in the same manner; local copies are
1681:    done. Only active columns (excluding the leading ones) are copied.
1682:    In the destination W, columns are overwritten starting from the leading ones.
1683:    Constraints are not copied.

1685:    Level: beginner

1687: .seealso: BVCopyVec(), BVCopyColumn(), BVDuplicate(), BVSetActiveColumns()
1688: @*/
1689: PetscErrorCode BVCopy(BV V,BV W)
1690: {
1691:   PetscErrorCode    ierr;
1692:   PetscScalar       *womega;
1693:   const PetscScalar *vomega;

1698:   BVCheckSizes(V,1);
1699:   BVCheckOp(V,1,copy);
1702:   BVCheckSizes(W,2);
1704:   if (V->n!=W->n) SETERRQ2(PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_INCOMP,"Mismatching local dimension V %D, W %D",V->n,W->n);
1705:   if (V->k-V->l>W->m-W->l) SETERRQ2(PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_SIZ,"W has %D non-leading columns, not enough to store %D columns",W->m-W->l,V->k-V->l);
1706:   if (V==W || !V->n) return(0);

1708:   PetscLogEventBegin(BV_Copy,V,W,0,0);
1709:   if (V->indef && V->matrix && V->indef==W->indef && V->matrix==W->matrix) {
1710:     /* copy signature */
1711:     BV_AllocateSignature(W);
1712:     VecGetArrayRead(V->omega,&vomega);
1713:     VecGetArray(W->omega,&womega);
1714:     PetscArraycpy(womega+W->nc+W->l,vomega+V->nc+V->l,V->k-V->l);
1715:     VecRestoreArray(W->omega,&womega);
1716:     VecRestoreArrayRead(V->omega,&vomega);
1717:   }
1718:   (*V->ops->copy)(V,W);
1719:   PetscLogEventEnd(BV_Copy,V,W,0,0);
1720:   PetscObjectStateIncrease((PetscObject)W);
1721:   return(0);
1722: }

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

1727:    Logically Collective on V

1729:    Input Parameter:
1730: +  V - basis vectors context
1731: -  j - the column number to be copied

1733:    Output Parameter:
1734: .  w - the copied column

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

1739:    Level: beginner

1741: .seealso: BVCopy(), BVCopyColumn(), BVInsertVec()
1742: @*/
1743: PetscErrorCode BVCopyVec(BV V,PetscInt j,Vec w)
1744: {
1746:   PetscInt       n,N;
1747:   Vec            z;

1752:   BVCheckSizes(V,1);

1757:   VecGetSize(w,&N);
1758:   VecGetLocalSize(w,&n);
1759:   if (N!=V->N || n!=V->n) SETERRQ4(PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_INCOMP,"Vec sizes (global %D, local %D) do not match BV sizes (global %D, local %D)",N,n,V->N,V->n);

1761:   PetscLogEventBegin(BV_Copy,V,w,0,0);
1762:   BVGetColumn(V,j,&z);
1763:   VecCopy(z,w);
1764:   BVRestoreColumn(V,j,&z);
1765:   PetscLogEventEnd(BV_Copy,V,w,0,0);
1766:   return(0);
1767: }

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

1772:    Logically Collective on V

1774:    Input Parameter:
1775: +  V - basis vectors context
1776: .  j - the number of the source column
1777: -  i - the number of the destination column

1779:    Level: beginner

1781: .seealso: BVCopy(), BVCopyVec()
1782: @*/
1783: PetscErrorCode BVCopyColumn(BV V,PetscInt j,PetscInt i)
1784: {
1786:   Vec            z,w;
1787:   PetscScalar    *omega;

1792:   BVCheckSizes(V,1);
1795:   if (j==i) return(0);

1797:   PetscLogEventBegin(BV_Copy,V,0,0,0);
1798:   if (V->omega) {
1799:     VecGetArray(V->omega,&omega);
1800:     omega[i] = omega[j];
1801:     VecRestoreArray(V->omega,&omega);
1802:   }
1803:   if (V->ops->copycolumn) {
1804:     (*V->ops->copycolumn)(V,j,i);
1805:   } else {
1806:     BVGetColumn(V,j,&z);
1807:     BVGetColumn(V,i,&w);
1808:     VecCopy(z,w);
1809:     BVRestoreColumn(V,j,&z);
1810:     BVRestoreColumn(V,i,&w);
1811:   }
1812:   PetscLogEventEnd(BV_Copy,V,0,0,0);
1813:   PetscObjectStateIncrease((PetscObject)V);
1814:   return(0);
1815: }

1817: static PetscErrorCode BVGetSplit_Private(BV bv,PetscBool left,BV *split)
1818: {
1820:   PetscInt       ncols;

1823:   ncols = left? bv->nc+bv->l: bv->m-bv->l;
1824:   if (*split && ncols!=(*split)->m) { BVDestroy(split); }
1825:   if (!*split) {
1826:     BVCreate(PetscObjectComm((PetscObject)bv),split);
1827:     PetscLogObjectParent((PetscObject)bv,(PetscObject)*split);
1828:     (*split)->issplit = left? 1: 2;
1829:     (*split)->splitparent = bv;
1830:     BVSetSizesFromVec(*split,bv->t,ncols);
1831:     BVDuplicate_Private(bv,*split);
1832:   }
1833:   (*split)->l  = 0;
1834:   (*split)->k  = left? bv->l: bv->k-bv->l;
1835:   (*split)->nc = left? bv->nc: 0;
1836:   (*split)->m  = ncols-(*split)->nc;
1837:   if ((*split)->nc) {
1838:     (*split)->ci[0] = -(*split)->nc-1;
1839:     (*split)->ci[1] = -(*split)->nc-1;
1840:   }
1841:   if (left) {
1842:     PetscObjectStateGet((PetscObject)*split,&bv->lstate);
1843:   } else {
1844:     PetscObjectStateGet((PetscObject)*split,&bv->rstate);
1845:   }
1846:   return(0);
1847: }

1849: /*@
1850:    BVGetSplit - Splits the BV object into two BV objects that share the
1851:    internal data, one of them containing the leading columns and the other
1852:    one containing the remaining columns.

1854:    Logically Collective on bv

1856:    Input Parameters:
1857: .  bv - the basis vectors context

1859:    Output Parameters:
1860: +  L - left BV containing leading columns (can be NULL)
1861: -  R - right BV containing remaining columns (can be NULL)

1863:    Notes:
1864:    The columns are split in two sets. The leading columns (including the
1865:    constraints) are assigned to the left BV and the remaining columns
1866:    are assigned to the right BV. The number of leading columns, as
1867:    specified with BVSetActiveColumns(), must be between 1 and m-1 (to
1868:    guarantee that both L and R have at least one column).

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

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

1877:    Level: advanced

1879: .seealso: BVRestoreSplit(), BVSetActiveColumns(), BVSetNumConstraints()
1880: @*/
1881: PetscErrorCode BVGetSplit(BV bv,BV *L,BV *R)
1882: {

1888:   BVCheckSizes(bv,1);
1889:   if (!bv->l) SETERRQ(PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_WRONGSTATE,"Must indicate the number of leading columns with BVSetActiveColumns()");
1890:   if (bv->lsplit) SETERRQ(PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_WRONGSTATE,"Cannot get the split BV's twice before restoring them with BVRestoreSplit()");
1891:   bv->lsplit = bv->nc+bv->l;
1892:   BVGetSplit_Private(bv,PETSC_TRUE,&bv->L);
1893:   BVGetSplit_Private(bv,PETSC_FALSE,&bv->R);
1894:   if (L) *L = bv->L;
1895:   if (R) *R = bv->R;
1896:   return(0);
1897: }

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

1902:    Logically Collective on bv

1904:    Input Parameters:
1905: +  bv - the basis vectors context
1906: .  L  - left BV obtained with BVGetSplit()
1907: -  R  - right BV obtained with BVGetSplit()

1909:    Note:
1910:    The arguments must match the corresponding call to BVGetSplit().

1912:    Level: advanced

1914: .seealso: BVGetSplit()
1915: @*/
1916: PetscErrorCode BVRestoreSplit(BV bv,BV *L,BV *R)
1917: {

1923:   BVCheckSizes(bv,1);
1924:   if (!bv->lsplit) SETERRQ(PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_WRONGSTATE,"Must call BVGetSplit first");
1925:   if (L && *L!=bv->L) SETERRQ(PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_WRONG,"Argument 2 is not the same BV that was obtained with BVGetSplit");
1926:   if (R && *R!=bv->R) SETERRQ(PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_WRONG,"Argument 3 is not the same BV that was obtained with BVGetSplit");
1927:   if (L && ((*L)->ci[0]>(*L)->nc-1 || (*L)->ci[1]>(*L)->nc-1)) SETERRQ(PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_WRONGSTATE,"Argument 2 has unrestored columns, use BVRestoreColumn()");
1928:   if (R && ((*R)->ci[0]>(*R)->nc-1 || (*R)->ci[1]>(*R)->nc-1)) SETERRQ(PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_WRONGSTATE,"Argument 3 has unrestored columns, use BVRestoreColumn()");

1930:   if (bv->ops->restoresplit) {
1931:     (*bv->ops->restoresplit)(bv,L,R);
1932:   }
1933:   bv->lsplit = 0;
1934:   if (L) *L = NULL;
1935:   if (R) *R = NULL;
1936:   return(0);
1937: }

1939: /*@
1940:    BVSetDefiniteTolerance - Set the tolerance to be used when checking a
1941:    definite inner product.

1943:    Logically Collective on bv

1945:    Input Parameters:
1946: +  bv     - basis vectors
1947: -  deftol - the tolerance

1949:    Options Database Key:
1950: .  -bv_definite_tol <deftol> - the tolerance

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

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

1964:    Level: advanced

1966: .seealso: BVSetMatrix()
1967: @*/
1968: PetscErrorCode BVSetDefiniteTolerance(BV bv,PetscReal deftol)
1969: {
1973:   if (deftol == PETSC_DEFAULT) bv->deftol = 10*PETSC_MACHINE_EPSILON;
1974:   else {
1975:     if (deftol<=0.0) SETERRQ(PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of deftol. Must be > 0");
1976:     bv->deftol = deftol;
1977:   }
1978:   return(0);
1979: }

1981: /*@
1982:    BVGetDefiniteTolerance - Returns the tolerance for checking a definite
1983:    inner product.

1985:    Not Collective

1987:    Input Parameter:
1988: .  bv - the basis vectors

1990:    Output Parameters:
1991: .  deftol - the tolerance

1993:    Level: advanced

1995: .seealso: BVGetDefiniteTolerance()
1996: @*/
1997: PetscErrorCode BVGetDefiniteTolerance(BV bv,PetscReal *deftol)
1998: {
2002:   *deftol = bv->deftol;
2003:   return(0);
2004: }