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 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 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),PETSC_ERR_ORDER,"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),PETSC_ERR_PLIB,"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) SETERRQ2(PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of k (%D). Must be between 0 and m (%D)",k,bv->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) SETERRQ2(PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of l (%D). Must be between 0 and k (%D)",l,bv->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 Parameters:
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 Parameters:
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 Parameters:
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 Parameters:
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);
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, BVOrthogBlockType967: @*/
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 Parameters:
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, BVOrthogBlockType1030: @*/
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(), BVMatMultType1065: @*/
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(), BVMatMultType1102: @*/
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 BV1127: 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 BV1567: 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 Parameters:
1601: + V - basis vectors context
1602: - m - the new number of columns
1604: Output Parameter:
1605: . W - location to put the new BV1607: 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 BV1643: 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 Parameters:
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 Parameters:
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 Parameter:
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: }