1: /*
2: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3: SLEPc - Scalable Library for Eigenvalue Problem Computations
4: Copyright (c) 2002-2020, Universitat Politecnica de Valencia, Spain
6: This file is part of SLEPc.
7: SLEPc is distributed under a 2-clause BSD license (see LICENSE).
8: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
9: */
10: /*
11: BV operations, except those involving global communication
12: */
14: #include <slepc/private/bvimpl.h> /*I "slepcbv.h" I*/
15: #include <slepcds.h>
17: /*@
18: BVMult - Computes Y = beta*Y + alpha*X*Q.
20: Logically Collective on Y
22: Input Parameters:
23: + Y,X - basis vectors
24: . alpha,beta - scalars
25: - Q - (optional) sequential dense matrix
27: Output Parameter:
28: . Y - the modified basis vectors
30: Notes:
31: X and Y must be different objects. The case X=Y can be addressed with
32: BVMultInPlace().
34: If matrix Q is NULL, then an AXPY operation Y = beta*Y + alpha*X is done
35: (i.e. results as if Q = identity). If provided,
36: the matrix Q must be a sequential dense Mat, with all entries equal on
37: all processes (otherwise each process will compute a different update).
38: The dimensions of Q must be at least m,n where m is the number of active
39: columns of X and n is the number of active columns of Y.
41: The leading columns of Y are not modified. Also, if X has leading
42: columns specified, then these columns do not participate in the computation.
43: Hence, only rows (resp. columns) of Q starting from lx (resp. ly) are used,
44: where lx (resp. ly) is the number of leading columns of X (resp. Y).
46: Level: intermediate
48: .seealso: BVMultVec(), BVMultColumn(), BVMultInPlace(), BVSetActiveColumns()
49: @*/
50: PetscErrorCode BVMult(BV Y,PetscScalar alpha,PetscScalar beta,BV X,Mat Q) 51: {
53: PetscBool match;
54: PetscInt m,n;
63: BVCheckSizes(Y,1);
64: BVCheckOp(Y,1,mult);
66: BVCheckSizes(X,4);
69: if (X==Y) SETERRQ(PetscObjectComm((PetscObject)Y),PETSC_ERR_ARG_WRONG,"X and Y arguments must be different");
70: if (Q) {
71: PetscObjectTypeCompare((PetscObject)Q,MATSEQDENSE,&match);
72: if (!match) SETERRQ(PetscObjectComm((PetscObject)Y),PETSC_ERR_SUP,"Mat argument must be of type seqdense");
73: MatGetSize(Q,&m,&n);
74: if (m<X->k) SETERRQ2(PetscObjectComm((PetscObject)Y),PETSC_ERR_ARG_SIZ,"Mat argument has %D rows, should have at least %D",m,X->k);
75: if (n<Y->k) SETERRQ2(PetscObjectComm((PetscObject)Y),PETSC_ERR_ARG_SIZ,"Mat argument has %D columns, should have at least %D",n,Y->k);
76: }
77: if (X->n!=Y->n) SETERRQ2(PetscObjectComm((PetscObject)Y),PETSC_ERR_ARG_INCOMP,"Mismatching local dimension X %D, Y %D",X->n,Y->n);
79: PetscLogEventBegin(BV_Mult,X,Y,0,0);
80: (*Y->ops->mult)(Y,alpha,beta,X,Q);
81: PetscLogEventEnd(BV_Mult,X,Y,0,0);
82: PetscObjectStateIncrease((PetscObject)Y);
83: return(0);
84: }
86: /*@
87: BVMultVec - Computes y = beta*y + alpha*X*q.
89: Logically Collective on X
91: Input Parameters:
92: + X - a basis vectors object
93: . alpha,beta - scalars
94: . y - a vector
95: - q - an array of scalars
97: Output Parameter:
98: . y - the modified vector
100: Notes:
101: This operation is the analogue of BVMult() but with a BV and a Vec,
102: instead of two BV. Note that arguments are listed in different order
103: with respect to BVMult().
105: If X has leading columns specified, then these columns do not participate
106: in the computation.
108: The length of array q must be equal to the number of active columns of X
109: minus the number of leading columns, i.e. the first entry of q multiplies
110: the first non-leading column.
112: Level: intermediate
114: .seealso: BVMult(), BVMultColumn(), BVMultInPlace(), BVSetActiveColumns()
115: @*/
116: PetscErrorCode BVMultVec(BV X,PetscScalar alpha,PetscScalar beta,Vec y,PetscScalar q[])117: {
119: PetscInt n,N;
128: BVCheckSizes(X,1);
129: BVCheckOp(X,1,multvec);
133: VecGetSize(y,&N);
134: VecGetLocalSize(y,&n);
135: if (N!=X->N || n!=X->n) SETERRQ4(PetscObjectComm((PetscObject)X),PETSC_ERR_ARG_INCOMP,"Vec sizes (global %D, local %D) do not match BV sizes (global %D, local %D)",N,n,X->N,X->n);
137: PetscLogEventBegin(BV_MultVec,X,y,0,0);
138: (*X->ops->multvec)(X,alpha,beta,y,q);
139: PetscLogEventEnd(BV_MultVec,X,y,0,0);
140: return(0);
141: }
143: /*@
144: BVMultColumn - Computes y = beta*y + alpha*X*q, where y is the j-th column
145: of X.
147: Logically Collective on X
149: Input Parameters:
150: + X - a basis vectors object
151: . alpha,beta - scalars
152: . j - the column index
153: - q - an array of scalars
155: Notes:
156: This operation is equivalent to BVMultVec() but it uses column j of X
157: rather than taking a Vec as an argument. The number of active columns of
158: X is set to j before the computation, and restored afterwards.
159: If X has leading columns specified, then these columns do not participate
160: in the computation. Therefore, the length of array q must be equal to j
161: minus the number of leading columns.
163: Developer Notes:
164: If q is NULL, then the coefficients are taken from position nc+l of the
165: internal buffer vector, see BVGetBufferVec().
167: Level: advanced
169: .seealso: BVMult(), BVMultVec(), BVMultInPlace(), BVSetActiveColumns()
170: @*/
171: PetscErrorCode BVMultColumn(BV X,PetscScalar alpha,PetscScalar beta,PetscInt j,PetscScalar *q)172: {
174: PetscInt ksave;
175: Vec y;
183: BVCheckSizes(X,1);
185: if (j<0) SETERRQ(PetscObjectComm((PetscObject)X),PETSC_ERR_ARG_OUTOFRANGE,"Index j must be non-negative");
186: if (j>=X->m) SETERRQ2(PetscObjectComm((PetscObject)X),PETSC_ERR_ARG_OUTOFRANGE,"Index j=%D but BV only has %D columns",j,X->m);
188: PetscLogEventBegin(BV_MultVec,X,0,0,0);
189: ksave = X->k;
190: X->k = j;
191: if (!q && !X->buffer) { BVGetBufferVec(X,&X->buffer); }
192: BVGetColumn(X,j,&y);
193: (*X->ops->multvec)(X,alpha,beta,y,q);
194: BVRestoreColumn(X,j,&y);
195: X->k = ksave;
196: PetscLogEventEnd(BV_MultVec,X,0,0,0);
197: PetscObjectStateIncrease((PetscObject)X);
198: return(0);
199: }
201: /*@
202: BVMultInPlace - Update a set of vectors as V(:,s:e-1) = V*Q(:,s:e-1).
204: Logically Collective on V
206: Input Parameters:
207: + Q - a sequential dense matrix
208: . s - first column of V to be overwritten
209: - e - first column of V not to be overwritten
211: Input/Output Parameter:
212: . V - basis vectors
214: Notes:
215: The matrix Q must be a sequential dense Mat, with all entries equal on
216: all processes (otherwise each process will compute a different update).
218: This function computes V(:,s:e-1) = V*Q(:,s:e-1), that is, given a set of
219: vectors V, columns from s to e-1 are overwritten with columns from s to
220: e-1 of the matrix-matrix product V*Q. Only columns s to e-1 of Q are
221: referenced.
223: Level: intermediate
225: .seealso: BVMult(), BVMultVec(), BVMultInPlaceTranspose(), BVSetActiveColumns()
226: @*/
227: PetscErrorCode BVMultInPlace(BV V,Mat Q,PetscInt s,PetscInt e)228: {
230: PetscBool match;
231: PetscInt m,n;
239: BVCheckSizes(V,1);
241: PetscObjectTypeCompare((PetscObject)Q,MATSEQDENSE,&match);
242: if (!match) SETERRQ(PetscObjectComm((PetscObject)V),PETSC_ERR_SUP,"Mat argument must be of type seqdense");
244: if (s<V->l || s>V->m) SETERRQ3(PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_OUTOFRANGE,"Argument s has wrong value %D, should be between %D and %D",s,V->l,V->m);
245: if (e<V->l || e>V->m) SETERRQ3(PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_OUTOFRANGE,"Argument e has wrong value %D, should be between %D and %D",e,V->l,V->m);
246: MatGetSize(Q,&m,&n);
247: if (m<V->k) SETERRQ2(PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_SIZ,"Mat argument has %D rows, should have at least %D",m,V->k);
248: if (e>n) SETERRQ2(PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_SIZ,"Mat argument only has %D columns, the requested value of e is larger: %D",n,e);
249: if (s>=e) return(0);
251: PetscLogEventBegin(BV_MultInPlace,V,Q,0,0);
252: (*V->ops->multinplace)(V,Q,s,e);
253: PetscLogEventEnd(BV_MultInPlace,V,Q,0,0);
254: PetscObjectStateIncrease((PetscObject)V);
255: return(0);
256: }
258: /*@
259: BVMultInPlaceTranspose - Update a set of vectors as V(:,s:e-1) = V*Q'(:,s:e-1).
261: Logically Collective on V
263: Input Parameters:
264: + Q - a sequential dense matrix
265: . s - first column of V to be overwritten
266: - e - first column of V not to be overwritten
268: Input/Output Parameter:
269: . V - basis vectors
271: Notes:
272: This is a variant of BVMultInPlace() where the conjugate transpose
273: of Q is used.
275: Level: intermediate
277: .seealso: BVMultInPlace()
278: @*/
279: PetscErrorCode BVMultInPlaceTranspose(BV V,Mat Q,PetscInt s,PetscInt e)280: {
282: PetscBool match;
283: PetscInt m,n;
291: BVCheckSizes(V,1);
293: PetscObjectTypeCompare((PetscObject)Q,MATSEQDENSE,&match);
294: if (!match) SETERRQ(PetscObjectComm((PetscObject)V),PETSC_ERR_SUP,"Mat argument must be of type seqdense");
296: if (s<V->l || s>V->m) SETERRQ3(PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_OUTOFRANGE,"Argument s has wrong value %D, should be between %D and %D",s,V->l,V->m);
297: if (e<V->l || e>V->m) SETERRQ3(PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_OUTOFRANGE,"Argument e has wrong value %D, should be between %D and %D",e,V->l,V->m);
298: MatGetSize(Q,&m,&n);
299: if (n<V->k) SETERRQ2(PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_SIZ,"Mat argument has %D columns, should have at least %D",n,V->k);
300: if (e>m) SETERRQ2(PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_SIZ,"Mat argument only has %D rows, the requested value of e is larger: %D",m,e);
301: if (s>=e || !V->n) return(0);
303: PetscLogEventBegin(BV_MultInPlace,V,Q,0,0);
304: (*V->ops->multinplacetrans)(V,Q,s,e);
305: PetscLogEventEnd(BV_MultInPlace,V,Q,0,0);
306: PetscObjectStateIncrease((PetscObject)V);
307: return(0);
308: }
310: /*@
311: BVScale - Multiply the BV entries by a scalar value.
313: Logically Collective on bv
315: Input Parameters:
316: + bv - basis vectors
317: - alpha - scaling factor
319: Note:
320: All active columns (except the leading ones) are scaled.
322: Level: intermediate
324: .seealso: BVScaleColumn(), BVSetActiveColumns()
325: @*/
326: PetscErrorCode BVScale(BV bv,PetscScalar alpha)327: {
334: BVCheckSizes(bv,1);
335: if (alpha == (PetscScalar)1.0) return(0);
337: PetscLogEventBegin(BV_Scale,bv,0,0,0);
338: if (bv->n) {
339: (*bv->ops->scale)(bv,-1,alpha);
340: }
341: PetscLogEventEnd(BV_Scale,bv,0,0,0);
342: PetscObjectStateIncrease((PetscObject)bv);
343: return(0);
344: }
346: /*@
347: BVScaleColumn - Scale one column of a BV.
349: Logically Collective on bv
351: Input Parameters:
352: + bv - basis vectors
353: . j - column number to be scaled
354: - alpha - scaling factor
356: Level: intermediate
358: .seealso: BVScale(), BVSetActiveColumns()
359: @*/
360: PetscErrorCode BVScaleColumn(BV bv,PetscInt j,PetscScalar alpha)361: {
369: BVCheckSizes(bv,1);
371: if (j<0 || j>=bv->m) SETERRQ2(PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_OUTOFRANGE,"Argument j has wrong value %D, the number of columns is %D",j,bv->m);
372: if (alpha == (PetscScalar)1.0) return(0);
374: PetscLogEventBegin(BV_Scale,bv,0,0,0);
375: if (bv->n) {
376: (*bv->ops->scale)(bv,j,alpha);
377: }
378: PetscLogEventEnd(BV_Scale,bv,0,0,0);
379: PetscObjectStateIncrease((PetscObject)bv);
380: return(0);
381: }
383: PETSC_STATIC_INLINE PetscErrorCode BVSetRandomColumn_Private(BV bv,PetscInt k)384: {
386: PetscInt i,low,high;
387: PetscScalar *px,t;
388: Vec x;
391: BVGetColumn(bv,k,&x);
392: if (bv->rrandom) { /* generate the same vector irrespective of number of processes */
393: VecGetOwnershipRange(x,&low,&high);
394: VecGetArray(x,&px);
395: for (i=0;i<bv->N;i++) {
396: PetscRandomGetValue(bv->rand,&t);
397: if (i>=low && i<high) px[i-low] = t;
398: }
399: VecRestoreArray(x,&px);
400: } else {
401: VecSetRandom(x,bv->rand);
402: }
403: BVRestoreColumn(bv,k,&x);
404: return(0);
405: }
407: /*@
408: BVSetRandom - Set the columns of a BV to random numbers.
410: Logically Collective on bv
412: Input Parameters:
413: . bv - basis vectors
415: Note:
416: All active columns (except the leading ones) are modified.
418: Level: advanced
420: .seealso: BVSetRandomContext(), BVSetRandomColumn(), BVSetRandomCond(), BVSetActiveColumns()
421: @*/
422: PetscErrorCode BVSetRandom(BV bv)423: {
425: PetscInt k;
430: BVCheckSizes(bv,1);
432: BVGetRandomContext(bv,&bv->rand);
433: PetscLogEventBegin(BV_SetRandom,bv,0,0,0);
434: for (k=bv->l;k<bv->k;k++) {
435: BVSetRandomColumn_Private(bv,k);
436: }
437: PetscLogEventEnd(BV_SetRandom,bv,0,0,0);
438: PetscObjectStateIncrease((PetscObject)bv);
439: return(0);
440: }
442: /*@
443: BVSetRandomColumn - Set one column of a BV to random numbers.
445: Logically Collective on bv
447: Input Parameters:
448: + bv - basis vectors
449: - j - column number to be set
451: Level: advanced
453: .seealso: BVSetRandomContext(), BVSetRandom(), BVSetActiveColumns()
454: @*/
455: PetscErrorCode BVSetRandomColumn(BV bv,PetscInt j)456: {
463: BVCheckSizes(bv,1);
464: if (j<0 || j>=bv->m) SETERRQ2(PetscObjectComm((PetscObject)bv),PETSC_ERR_ARG_OUTOFRANGE,"Argument j has wrong value %D, the number of columns is %D",j,bv->m);
466: BVGetRandomContext(bv,&bv->rand);
467: PetscLogEventBegin(BV_SetRandom,bv,0,0,0);
468: BVSetRandomColumn_Private(bv,j);
469: PetscLogEventEnd(BV_SetRandom,bv,0,0,0);
470: PetscObjectStateIncrease((PetscObject)bv);
471: return(0);
472: }
474: /*@
475: BVSetRandomCond - Set the columns of a BV to random numbers, in a way that
476: the generated matrix has a given condition number.
478: Logically Collective on bv
480: Input Parameters:
481: + bv - basis vectors
482: - condn - condition number
484: Note:
485: All active columns (except the leading ones) are modified.
487: Level: advanced
489: .seealso: BVSetRandomContext(), BVSetRandomColumn(), BVSetActiveColumns()
490: @*/
491: PetscErrorCode BVSetRandomCond(BV bv,PetscReal condn)492: {
494: PetscInt k,i;
495: PetscScalar *eig,*d;
496: DS ds;
497: Mat A,X,Xt,M,G;
502: BVCheckSizes(bv,1);
504: BVGetRandomContext(bv,&bv->rand);
505: PetscLogEventBegin(BV_SetRandom,bv,0,0,0);
506: /* B = rand(n,k) */
507: for (k=bv->l;k<bv->k;k++) {
508: BVSetRandomColumn_Private(bv,k);
509: }
510: DSCreate(PetscObjectComm((PetscObject)bv),&ds);
511: DSSetType(ds,DSHEP);
512: DSAllocate(ds,bv->m);
513: DSSetDimensions(ds,bv->k,0,bv->l,bv->k);
514: /* [V,S] = eig(B'*B) */
515: DSGetMat(ds,DS_MAT_A,&A);
516: BVDot(bv,bv,A);
517: DSRestoreMat(ds,DS_MAT_A,&A);
518: PetscMalloc1(bv->m,&eig);
519: DSSolve(ds,eig,NULL);
520: DSSynchronize(ds,eig,NULL);
521: DSVectors(ds,DS_MAT_X,NULL,NULL);
522: /* M = diag(linspace(1/condn,1,n)./sqrt(diag(S)))' */
523: MatCreateSeqDense(PETSC_COMM_SELF,bv->k,bv->k,NULL,&M);
524: MatZeroEntries(M);
525: MatDenseGetArray(M,&d);
526: for (i=0;i<bv->k;i++) d[i+i*bv->m] = (1.0/condn+(1.0-1.0/condn)/(bv->k-1)*i)/PetscSqrtScalar(eig[i]);
527: MatDenseRestoreArray(M,&d);
528: /* G = X*M*X' */
529: MatCreateSeqDense(PETSC_COMM_SELF,bv->k,bv->k,NULL,&Xt);
530: DSGetMat(ds,DS_MAT_X,&X);
531: MatTranspose(X,MAT_REUSE_MATRIX,&Xt);
532: MatProductCreate(Xt,M,NULL,&G);
533: MatProductSetType(G,MATPRODUCT_PtAP);
534: MatProductSetFromOptions(G);
535: MatProductSymbolic(G);
536: MatProductNumeric(G);
537: MatDestroy(&X);
538: MatDestroy(&Xt);
539: MatDestroy(&M);
540: /* B = B*G */
541: BVMultInPlace(bv,G,bv->l,bv->k);
542: MatDestroy(&G);
543: PetscFree(eig);
544: DSDestroy(&ds);
545: PetscLogEventEnd(BV_SetRandom,bv,0,0,0);
546: PetscObjectStateIncrease((PetscObject)bv);
547: return(0);
548: }
550: /*@
551: BVMatMult - Computes the matrix-vector product for each column, Y=A*V.
553: Neighbor-wise Collective on A
555: Input Parameters:
556: + V - basis vectors context
557: - A - the matrix
559: Output Parameter:
560: . Y - the result
562: Notes:
563: Both V and Y must be distributed in the same manner. Only active columns
564: (excluding the leading ones) are processed.
565: In the result Y, columns are overwritten starting from the leading ones.
566: The number of active columns in V and Y should match, although they need
567: not be the same columns.
569: It is possible to choose whether the computation is done column by column
570: or as a Mat-Mat product, see BVSetMatMultMethod().
572: Level: beginner
574: .seealso: BVCopy(), BVSetActiveColumns(), BVMatMultColumn(), BVMatMultTranspose(), BVMatMultHermitianTranspose(), BVSetMatMultMethod()
575: @*/
576: PetscErrorCode BVMatMult(BV V,Mat A,BV Y)577: {
583: BVCheckSizes(V,1);
584: BVCheckOp(V,1,matmult);
589: BVCheckSizes(Y,3);
592: if (V->n!=Y->n) SETERRQ2(PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_INCOMP,"Mismatching local dimension V %D, Y %D",V->n,Y->n);
593: if (V->k-V->l!=Y->k-Y->l) SETERRQ2(PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_SIZ,"Y has %D active columns, should match %D active columns in V",Y->k-Y->l,V->k-V->l);
595: PetscLogEventBegin(BV_MatMult,V,A,Y,0);
596: (*V->ops->matmult)(V,A,Y);
597: PetscLogEventEnd(BV_MatMult,V,A,Y,0);
598: PetscObjectStateIncrease((PetscObject)Y);
599: return(0);
600: }
602: /*@
603: BVMatMultTranspose - Computes the matrix-vector product with the transpose
604: of a matrix for each column, Y=A^T*V.
606: Neighbor-wise Collective on A
608: Input Parameters:
609: + V - basis vectors context
610: - A - the matrix
612: Output Parameter:
613: . Y - the result
615: Notes:
616: Both V and Y must be distributed in the same manner. Only active columns
617: (excluding the leading ones) are processed.
618: In the result Y, columns are overwritten starting from the leading ones.
619: The number of active columns in V and Y should match, although they need
620: not be the same columns.
622: Currently implemented via MatCreateTranspose().
624: Level: beginner
626: .seealso: BVMatMult(), BVMatMultHermitianTranspose()
627: @*/
628: PetscErrorCode BVMatMultTranspose(BV V,Mat A,BV Y)629: {
631: Mat AT;
636: BVCheckSizes(V,1);
641: BVCheckSizes(Y,3);
644: if (V->n!=Y->n) SETERRQ2(PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_INCOMP,"Mismatching local dimension V %D, Y %D",V->n,Y->n);
645: if (V->k-V->l>Y->m-Y->l) SETERRQ2(PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_SIZ,"Y has %D non-leading columns, not enough to store %D columns",Y->m-Y->l,V->k-V->l);
647: MatCreateTranspose(A,&AT);
648: BVMatMult(V,AT,Y);
649: MatDestroy(&AT);
650: return(0);
651: }
653: /*@
654: BVMatMultHermitianTranspose - Computes the matrix-vector product with the
655: conjugate transpose of a matrix for each column, Y=A^H*V.
657: Neighbor-wise Collective on A
659: Input Parameters:
660: + V - basis vectors context
661: - A - the matrix
663: Output Parameter:
664: . Y - the result
666: Note:
667: Both V and Y must be distributed in the same manner. Only active columns
668: (excluding the leading ones) are processed.
669: In the result Y, columns are overwritten starting from the leading ones.
670: The number of active columns in V and Y should match, although they need
671: not be the same columns.
673: Currently implemented via MatCreateHermitianTranspose().
675: Level: beginner
677: .seealso: BVMatMult(), BVMatMultTranspose()
678: @*/
679: PetscErrorCode BVMatMultHermitianTranspose(BV V,Mat A,BV Y)680: {
682: Mat AH;
687: BVCheckSizes(V,1);
692: BVCheckSizes(Y,3);
695: if (V->n!=Y->n) SETERRQ2(PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_INCOMP,"Mismatching local dimension V %D, Y %D",V->n,Y->n);
696: if (V->k-V->l>Y->m-Y->l) SETERRQ2(PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_SIZ,"Y has %D non-leading columns, not enough to store %D columns",Y->m-Y->l,V->k-V->l);
698: MatCreateHermitianTranspose(A,&AH);
699: BVMatMult(V,AH,Y);
700: MatDestroy(&AH);
701: return(0);
702: }
704: /*@
705: BVMatMultColumn - Computes the matrix-vector product for a specified
706: column, storing the result in the next column: v_{j+1}=A*v_j.
708: Neighbor-wise Collective on A
710: Input Parameters:
711: + V - basis vectors context
712: . A - the matrix
713: - j - the column
715: Level: beginner
717: .seealso: BVMatMult(), BVMatMultTransposeColumn(), BVMatMultHermitianTransposeColumn()
718: @*/
719: PetscErrorCode BVMatMultColumn(BV V,Mat A,PetscInt j)720: {
722: Vec vj,vj1;
727: BVCheckSizes(V,1);
731: if (j<0) SETERRQ(PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_OUTOFRANGE,"Index j must be non-negative");
732: if (j+1>=V->m) SETERRQ2(PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_OUTOFRANGE,"Result should go in index j+1=%D but BV only has %D columns",j+1,V->m);
734: PetscLogEventBegin(BV_MatMultVec,V,A,0,0);
735: BVGetColumn(V,j,&vj);
736: BVGetColumn(V,j+1,&vj1);
737: MatMult(A,vj,vj1);
738: BVRestoreColumn(V,j,&vj);
739: BVRestoreColumn(V,j+1,&vj1);
740: PetscLogEventEnd(BV_MatMultVec,V,A,0,0);
741: PetscObjectStateIncrease((PetscObject)V);
742: return(0);
743: }
745: /*@
746: BVMatMultTransposeColumn - Computes the transpose matrix-vector product for a
747: specified column, storing the result in the next column: v_{j+1}=A^T*v_j.
749: Neighbor-wise Collective on A
751: Input Parameters:
752: + V - basis vectors context
753: . A - the matrix
754: - j - the column
756: Level: beginner
758: .seealso: BVMatMult(), BVMatMultColumn(), BVMatMultHermitianTransposeColumn()
759: @*/
760: PetscErrorCode BVMatMultTransposeColumn(BV V,Mat A,PetscInt j)761: {
763: Vec vj,vj1;
768: BVCheckSizes(V,1);
772: if (j<0) SETERRQ(PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_OUTOFRANGE,"Index j must be non-negative");
773: if (j+1>=V->m) SETERRQ2(PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_OUTOFRANGE,"Result should go in index j+1=%D but BV only has %D columns",j+1,V->m);
775: PetscLogEventBegin(BV_MatMultVec,V,A,0,0);
776: BVGetColumn(V,j,&vj);
777: BVGetColumn(V,j+1,&vj1);
778: MatMultTranspose(A,vj,vj1);
779: BVRestoreColumn(V,j,&vj);
780: BVRestoreColumn(V,j+1,&vj1);
781: PetscLogEventEnd(BV_MatMultVec,V,A,0,0);
782: PetscObjectStateIncrease((PetscObject)V);
783: return(0);
784: }
786: /*@
787: BVMatMultHermitianTransposeColumn - Computes the matrix-vector product for a specified
788: column, storing the result in the next column: v_{j+1}=A*v_j.
790: Neighbor-wise Collective on A
792: Input Parameters:
793: + V - basis vectors context
794: . A - the matrix
795: - j - the column
797: Level: beginner
799: .seealso: BVMatMult(), BVMatMultColumn(), BVMatMultTransposeColumn()
800: @*/
801: PetscErrorCode BVMatMultHermitianTransposeColumn(BV V,Mat A,PetscInt j)802: {
804: Vec vj,vj1;
809: BVCheckSizes(V,1);
813: if (j<0) SETERRQ(PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_OUTOFRANGE,"Index j must be non-negative");
814: if (j+1>=V->m) SETERRQ2(PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_OUTOFRANGE,"Result should go in index j+1=%D but BV only has %D columns",j+1,V->m);
816: PetscLogEventBegin(BV_MatMultVec,V,A,0,0);
817: BVGetColumn(V,j,&vj);
818: BVGetColumn(V,j+1,&vj1);
819: MatMultHermitianTranspose(A,vj,vj1);
820: BVRestoreColumn(V,j,&vj);
821: BVRestoreColumn(V,j+1,&vj1);
822: PetscLogEventEnd(BV_MatMultVec,V,A,0,0);
823: PetscObjectStateIncrease((PetscObject)V);
824: return(0);
825: }