1: /*
2: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3: SLEPc - Scalable Library for Eigenvalue Problem Computations
4: Copyright (c) 2002-, Universitat Politecnica de Valencia, Spain
6: This file is part of SLEPc.
7: SLEPc is distributed under a 2-clause BSD license (see LICENSE).
8: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
9: */
10: /*
11: BV operations, except those involving global communication
12: */
14: #include <slepc/private/bvimpl.h> 15: #include <slepcds.h> 17: /*@
18: BVMult - Computes Y = beta*Y + alpha*X*Q.
20: Logically Collective on Y
22: Input Parameters:
23: + Y - first basis vectors context (modified on output)
24: . alpha - first scalar
25: . beta - second scalar
26: . X - second basis vectors context
27: - Q - (optional) sequential dense matrix
29: Notes:
30: X and Y must be different objects. The case X=Y can be addressed with
31: BVMultInPlace().
33: If matrix Q is NULL, then an AXPY operation Y = beta*Y + alpha*X is done
34: (i.e. results as if Q = identity). If provided,
35: the matrix Q must be a sequential dense Mat, with all entries equal on
36: all processes (otherwise each process will compute a different update).
37: The dimensions of Q must be at least m,n where m is the number of active
38: columns of X and n is the number of active columns of Y.
40: The leading columns of Y are not modified. Also, if X has leading
41: columns specified, then these columns do not participate in the computation.
42: Hence, only rows (resp. columns) of Q starting from lx (resp. ly) are used,
43: where lx (resp. ly) is the number of leading columns of X (resp. Y).
45: Level: intermediate
47: .seealso: BVMultVec(), BVMultColumn(), BVMultInPlace(), BVSetActiveColumns()
48: @*/
49: PetscErrorCode BVMult(BV Y,PetscScalar alpha,PetscScalar beta,BV X,Mat Q) 50: {
51: PetscInt m,n;
59: BVCheckSizes(Y,1);
60: BVCheckOp(Y,1,mult);
62: BVCheckSizes(X,4);
66: if (Q) {
68: MatGetSize(Q,&m,&n);
71: }
74: PetscLogEventBegin(BV_Mult,X,Y,0,0);
75: (*Y->ops->mult)(Y,alpha,beta,X,Q);
76: PetscLogEventEnd(BV_Mult,X,Y,0,0);
77: PetscObjectStateIncrease((PetscObject)Y);
78: PetscFunctionReturn(0);
79: }
81: /*@
82: BVMultVec - Computes y = beta*y + alpha*X*q.
84: Logically Collective on X
86: Input Parameters:
87: + X - a basis vectors object
88: . alpha - first scalar
89: . beta - second scalar
90: . y - a vector (modified on output)
91: - q - an array of scalars
93: Notes:
94: This operation is the analogue of BVMult() but with a BV and a Vec,
95: instead of two BV. Note that arguments are listed in different order
96: with respect to BVMult().
98: If X has leading columns specified, then these columns do not participate
99: in the computation.
101: The length of array q must be equal to the number of active columns of X
102: minus the number of leading columns, i.e. the first entry of q multiplies
103: the first non-leading column.
105: Level: intermediate
107: .seealso: BVMult(), BVMultColumn(), BVMultInPlace(), BVSetActiveColumns()
108: @*/
109: PetscErrorCode BVMultVec(BV X,PetscScalar alpha,PetscScalar beta,Vec y,PetscScalar q[])110: {
111: PetscInt n,N;
119: BVCheckSizes(X,1);
120: BVCheckOp(X,1,multvec);
124: VecGetSize(y,&N);
125: VecGetLocalSize(y,&n);
128: PetscLogEventBegin(BV_MultVec,X,y,0,0);
129: (*X->ops->multvec)(X,alpha,beta,y,q);
130: PetscLogEventEnd(BV_MultVec,X,y,0,0);
131: PetscFunctionReturn(0);
132: }
134: /*@
135: BVMultColumn - Computes y = beta*y + alpha*X*q, where y is the j-th column
136: of X.
138: Logically Collective on X
140: Input Parameters:
141: + X - a basis vectors object
142: . alpha - first scalar
143: . beta - second scalar
144: . j - the column index
145: - q - an array of scalars
147: Notes:
148: This operation is equivalent to BVMultVec() but it uses column j of X
149: rather than taking a Vec as an argument. The number of active columns of
150: X is set to j before the computation, and restored afterwards.
151: If X has leading columns specified, then these columns do not participate
152: in the computation. Therefore, the length of array q must be equal to j
153: minus the number of leading columns.
155: Developer Notes:
156: If q is NULL, then the coefficients are taken from position nc+l of the
157: internal buffer vector, see BVGetBufferVec().
159: Level: advanced
161: .seealso: BVMult(), BVMultVec(), BVMultInPlace(), BVSetActiveColumns()
162: @*/
163: PetscErrorCode BVMultColumn(BV X,PetscScalar alpha,PetscScalar beta,PetscInt j,PetscScalar *q)164: {
165: PetscInt ksave;
166: Vec y;
173: BVCheckSizes(X,1);
178: PetscLogEventBegin(BV_MultVec,X,0,0,0);
179: ksave = X->k;
180: X->k = j;
181: if (!q && !X->buffer) BVGetBufferVec(X,&X->buffer);
182: BVGetColumn(X,j,&y);
183: (*X->ops->multvec)(X,alpha,beta,y,q);
184: BVRestoreColumn(X,j,&y);
185: X->k = ksave;
186: PetscLogEventEnd(BV_MultVec,X,0,0,0);
187: PetscObjectStateIncrease((PetscObject)X);
188: PetscFunctionReturn(0);
189: }
191: /*@
192: BVMultInPlace - Update a set of vectors as V(:,s:e-1) = V*Q(:,s:e-1).
194: Logically Collective on V
196: Input Parameters:
197: + Q - a sequential dense matrix
198: . s - first column of V to be overwritten
199: - e - first column of V not to be overwritten
201: Input/Output Parameter:
202: . V - basis vectors
204: Notes:
205: The matrix Q must be a sequential dense Mat, with all entries equal on
206: all processes (otherwise each process will compute a different update).
208: This function computes V(:,s:e-1) = V*Q(:,s:e-1), that is, given a set of
209: vectors V, columns from s to e-1 are overwritten with columns from s to
210: e-1 of the matrix-matrix product V*Q. Only columns s to e-1 of Q are
211: referenced.
213: Level: intermediate
215: .seealso: BVMult(), BVMultVec(), BVMultInPlaceHermitianTranspose(), BVSetActiveColumns()
216: @*/
217: PetscErrorCode BVMultInPlace(BV V,Mat Q,PetscInt s,PetscInt e)218: {
219: PetscInt m,n;
226: BVCheckSizes(V,1);
232: MatGetSize(Q,&m,&n);
235: if (s>=e) PetscFunctionReturn(0);
237: PetscLogEventBegin(BV_MultInPlace,V,Q,0,0);
238: (*V->ops->multinplace)(V,Q,s,e);
239: PetscLogEventEnd(BV_MultInPlace,V,Q,0,0);
240: PetscObjectStateIncrease((PetscObject)V);
241: PetscFunctionReturn(0);
242: }
244: /*@
245: BVMultInPlaceHermitianTranspose - Update a set of vectors as V(:,s:e-1) = V*Q'(:,s:e-1).
247: Logically Collective on V
249: Input Parameters:
250: + Q - a sequential dense matrix
251: . s - first column of V to be overwritten
252: - e - first column of V not to be overwritten
254: Input/Output Parameter:
255: . V - basis vectors
257: Notes:
258: This is a variant of BVMultInPlace() where the conjugate transpose
259: of Q is used.
261: Level: intermediate
263: .seealso: BVMultInPlace()
264: @*/
265: PetscErrorCode BVMultInPlaceHermitianTranspose(BV V,Mat Q,PetscInt s,PetscInt e)266: {
267: PetscInt m,n;
274: BVCheckSizes(V,1);
280: MatGetSize(Q,&m,&n);
283: if (s>=e || !V->n) PetscFunctionReturn(0);
285: PetscLogEventBegin(BV_MultInPlace,V,Q,0,0);
286: (*V->ops->multinplacetrans)(V,Q,s,e);
287: PetscLogEventEnd(BV_MultInPlace,V,Q,0,0);
288: PetscObjectStateIncrease((PetscObject)V);
289: PetscFunctionReturn(0);
290: }
292: /*@
293: BVScale - Multiply the BV entries by a scalar value.
295: Logically Collective on bv
297: Input Parameters:
298: + bv - basis vectors
299: - alpha - scaling factor
301: Note:
302: All active columns (except the leading ones) are scaled.
304: Level: intermediate
306: .seealso: BVScaleColumn(), BVSetActiveColumns()
307: @*/
308: PetscErrorCode BVScale(BV bv,PetscScalar alpha)309: {
313: BVCheckSizes(bv,1);
314: if (alpha == (PetscScalar)1.0) PetscFunctionReturn(0);
316: PetscLogEventBegin(BV_Scale,bv,0,0,0);
317: if (bv->n) (*bv->ops->scale)(bv,-1,alpha);
318: PetscLogEventEnd(BV_Scale,bv,0,0,0);
319: PetscObjectStateIncrease((PetscObject)bv);
320: PetscFunctionReturn(0);
321: }
323: /*@
324: BVScaleColumn - Scale one column of a BV.
326: Logically Collective on bv
328: Input Parameters:
329: + bv - basis vectors
330: . j - column number to be scaled
331: - alpha - scaling factor
333: Level: intermediate
335: .seealso: BVScale(), BVSetActiveColumns()
336: @*/
337: PetscErrorCode BVScaleColumn(BV bv,PetscInt j,PetscScalar alpha)338: {
343: BVCheckSizes(bv,1);
346: if (alpha == (PetscScalar)1.0) PetscFunctionReturn(0);
348: PetscLogEventBegin(BV_Scale,bv,0,0,0);
349: if (bv->n) (*bv->ops->scale)(bv,j,alpha);
350: PetscLogEventEnd(BV_Scale,bv,0,0,0);
351: PetscObjectStateIncrease((PetscObject)bv);
352: PetscFunctionReturn(0);
353: }
355: static inline PetscErrorCode BVSetRandomColumn_Private(BV bv,PetscInt k)356: {
357: PetscInt i,low,high;
358: PetscScalar *px,t;
359: Vec x;
361: BVGetColumn(bv,k,&x);
362: if (bv->rrandom) { /* generate the same vector irrespective of number of processes */
363: VecGetOwnershipRange(x,&low,&high);
364: VecGetArray(x,&px);
365: for (i=0;i<bv->N;i++) {
366: PetscRandomGetValue(bv->rand,&t);
367: if (i>=low && i<high) px[i-low] = t;
368: }
369: VecRestoreArray(x,&px);
370: } else VecSetRandom(x,bv->rand);
371: BVRestoreColumn(bv,k,&x);
372: PetscFunctionReturn(0);
373: }
375: static inline PetscErrorCode BVSetRandomNormalColumn_Private(BV bv,PetscInt k,Vec w1,Vec w2)376: {
377: PetscInt i,low,high;
378: PetscScalar *px,s,t;
379: Vec x;
381: BVGetColumn(bv,k,&x);
382: if (bv->rrandom) { /* generate the same vector irrespective of number of processes */
383: VecGetOwnershipRange(x,&low,&high);
384: VecGetArray(x,&px);
385: for (i=0;i<bv->N;i++) {
386: PetscRandomGetValue(bv->rand,&s);
387: PetscRandomGetValue(bv->rand,&t);
388: if (i>=low && i<high) {
389: #if defined(PETSC_USE_COMPLEX)
390: px[i-low] = PetscCMPLX(PetscSqrtReal(-2.0*PetscLogReal(PetscRealPart(s)))*PetscCosReal(2.0*PETSC_PI*PetscRealPart(t)),PetscSqrtReal(-2.0*PetscLogReal(PetscImaginaryPart(s)))*PetscCosReal(2.0*PETSC_PI*PetscImaginaryPart(t)));
391: #else
392: px[i-low] = PetscSqrtReal(-2.0*PetscLogReal(s))*PetscCosReal(2.0*PETSC_PI*t);
393: #endif
394: }
395: }
396: VecRestoreArray(x,&px);
397: } else VecSetRandomNormal(x,bv->rand,w1,w2);
398: BVRestoreColumn(bv,k,&x);
399: PetscFunctionReturn(0);
400: }
402: static inline PetscErrorCode BVSetRandomSignColumn_Private(BV bv,PetscInt k)403: {
404: PetscInt i,low,high;
405: PetscScalar *px,t;
406: Vec x;
408: BVGetColumn(bv,k,&x);
409: VecGetOwnershipRange(x,&low,&high);
410: if (bv->rrandom) { /* generate the same vector irrespective of number of processes */
411: VecGetArray(x,&px);
412: for (i=0;i<bv->N;i++) {
413: PetscRandomGetValue(bv->rand,&t);
414: if (i>=low && i<high) px[i-low] = (PetscRealPart(t)<0.5)? -1.0: 1.0;
415: }
416: VecRestoreArray(x,&px);
417: } else {
418: VecSetRandom(x,bv->rand);
419: VecGetArray(x,&px);
420: for (i=low;i<high;i++) {
421: px[i-low] = (PetscRealPart(px[i-low])<0.5)? -1.0: 1.0;
422: }
423: VecRestoreArray(x,&px);
424: }
425: BVRestoreColumn(bv,k,&x);
426: PetscFunctionReturn(0);
427: }
429: /*@
430: BVSetRandom - Set the columns of a BV to random numbers.
432: Logically Collective on bv
434: Input Parameters:
435: . bv - basis vectors
437: Note:
438: All active columns (except the leading ones) are modified.
440: Level: advanced
442: .seealso: BVSetRandomContext(), BVSetRandomColumn(), BVSetRandomNormal(), BVSetRandomSign(), BVSetRandomCond(), BVSetActiveColumns()
443: @*/
444: PetscErrorCode BVSetRandom(BV bv)445: {
446: PetscInt k;
450: BVCheckSizes(bv,1);
452: BVGetRandomContext(bv,&bv->rand);
453: PetscLogEventBegin(BV_SetRandom,bv,0,0,0);
454: for (k=bv->l;k<bv->k;k++) BVSetRandomColumn_Private(bv,k);
455: PetscLogEventEnd(BV_SetRandom,bv,0,0,0);
456: PetscObjectStateIncrease((PetscObject)bv);
457: PetscFunctionReturn(0);
458: }
460: /*@
461: BVSetRandomColumn - Set one column of a BV to random numbers.
463: Logically Collective on bv
465: Input Parameters:
466: + bv - basis vectors
467: - j - column number to be set
469: Level: advanced
471: .seealso: BVSetRandomContext(), BVSetRandom(), BVSetRandomNormal(), BVSetRandomCond()
472: @*/
473: PetscErrorCode BVSetRandomColumn(BV bv,PetscInt j)474: {
478: BVCheckSizes(bv,1);
481: BVGetRandomContext(bv,&bv->rand);
482: PetscLogEventBegin(BV_SetRandom,bv,0,0,0);
483: BVSetRandomColumn_Private(bv,j);
484: PetscLogEventEnd(BV_SetRandom,bv,0,0,0);
485: PetscObjectStateIncrease((PetscObject)bv);
486: PetscFunctionReturn(0);
487: }
489: /*@
490: BVSetRandomNormal - Set the columns of a BV to random numbers with a normal
491: distribution.
493: Logically Collective on bv
495: Input Parameter:
496: . bv - basis vectors
498: Notes:
499: All active columns (except the leading ones) are modified.
501: Other functions such as BVSetRandom(), BVSetRandomColumn(), and BVSetRandomCond()
502: produce random numbers with a uniform distribution. This function returns values
503: that fit a normal distribution (Gaussian).
505: Developer Notes:
506: The current implementation obtains each of the columns by applying the Box-Muller
507: transform on two random vectors with uniformly distributed entries.
509: Level: advanced
511: .seealso: BVSetRandomContext(), BVSetRandom(), BVSetRandomColumn(), BVSetRandomCond(), BVSetActiveColumns()
512: @*/
513: PetscErrorCode BVSetRandomNormal(BV bv)514: {
515: PetscInt k;
516: Vec w1=NULL,w2=NULL;
520: BVCheckSizes(bv,1);
522: BVGetRandomContext(bv,&bv->rand);
523: if (!bv->rrandom) {
524: BVCreateVec(bv,&w1);
525: BVCreateVec(bv,&w2);
526: }
527: PetscLogEventBegin(BV_SetRandom,bv,0,0,0);
528: for (k=bv->l;k<bv->k;k++) BVSetRandomNormalColumn_Private(bv,k,w1,w2);
529: PetscLogEventEnd(BV_SetRandom,bv,0,0,0);
530: if (!bv->rrandom) {
531: VecDestroy(&w1);
532: VecDestroy(&w2);
533: }
534: PetscObjectStateIncrease((PetscObject)bv);
535: PetscFunctionReturn(0);
536: }
538: /*@
539: BVSetRandomSign - Set the entries of a BV to values 1 or -1 with equal
540: probability.
542: Logically Collective on bv
544: Input Parameter:
545: . bv - basis vectors
547: Notes:
548: All active columns (except the leading ones) are modified.
550: This function is used, e.g., in contour integral methods when estimating
551: the number of eigenvalues enclosed by the contour via an unbiased
552: estimator of tr(f(A)) [Bai et al., JCAM 1996].
554: Developer Notes:
555: The current implementation obtains random numbers and then replaces them
556: with -1 or 1 depending on the value being less than 0.5 or not.
558: Level: advanced
560: .seealso: BVSetRandomContext(), BVSetRandom(), BVSetRandomColumn(), BVSetActiveColumns()
561: @*/
562: PetscErrorCode BVSetRandomSign(BV bv)563: {
564: PetscScalar low,high;
565: PetscInt k;
569: BVCheckSizes(bv,1);
571: BVGetRandomContext(bv,&bv->rand);
572: PetscRandomGetInterval(bv->rand,&low,&high);
574: PetscLogEventBegin(BV_SetRandom,bv,0,0,0);
575: for (k=bv->l;k<bv->k;k++) BVSetRandomSignColumn_Private(bv,k);
576: PetscLogEventEnd(BV_SetRandom,bv,0,0,0);
577: PetscObjectStateIncrease((PetscObject)bv);
578: PetscFunctionReturn(0);
579: }
581: /*@
582: BVSetRandomCond - Set the columns of a BV to random numbers, in a way that
583: the generated matrix has a given condition number.
585: Logically Collective on bv
587: Input Parameters:
588: + bv - basis vectors
589: - condn - condition number
591: Note:
592: All active columns (except the leading ones) are modified.
594: Level: advanced
596: .seealso: BVSetRandomContext(), BVSetRandom(), BVSetRandomColumn(), BVSetRandomNormal(), BVSetActiveColumns()
597: @*/
598: PetscErrorCode BVSetRandomCond(BV bv,PetscReal condn)599: {
600: PetscInt k,i;
601: PetscScalar *eig,*d;
602: DS ds;
603: Mat A,X,Xt,M,G;
607: BVCheckSizes(bv,1);
609: BVGetRandomContext(bv,&bv->rand);
610: PetscLogEventBegin(BV_SetRandom,bv,0,0,0);
611: /* B = rand(n,k) */
612: for (k=bv->l;k<bv->k;k++) BVSetRandomColumn_Private(bv,k);
613: DSCreate(PetscObjectComm((PetscObject)bv),&ds);
614: DSSetType(ds,DSHEP);
615: DSAllocate(ds,bv->m);
616: DSSetDimensions(ds,bv->k,bv->l,bv->k);
617: /* [V,S] = eig(B'*B) */
618: DSGetMat(ds,DS_MAT_A,&A);
619: BVDot(bv,bv,A);
620: DSRestoreMat(ds,DS_MAT_A,&A);
621: PetscMalloc1(bv->m,&eig);
622: DSSolve(ds,eig,NULL);
623: DSSynchronize(ds,eig,NULL);
624: DSVectors(ds,DS_MAT_X,NULL,NULL);
625: /* M = diag(linspace(1/condn,1,n)./sqrt(diag(S)))' */
626: MatCreateSeqDense(PETSC_COMM_SELF,bv->k,bv->k,NULL,&M);
627: MatZeroEntries(M);
628: MatDenseGetArray(M,&d);
629: 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]);
630: MatDenseRestoreArray(M,&d);
631: /* G = X*M*X' */
632: MatCreateSeqDense(PETSC_COMM_SELF,bv->k,bv->k,NULL,&Xt);
633: DSGetMat(ds,DS_MAT_X,&X);
634: MatTranspose(X,MAT_REUSE_MATRIX,&Xt);
635: MatProductCreate(Xt,M,NULL,&G);
636: MatProductSetType(G,MATPRODUCT_PtAP);
637: MatProductSetFromOptions(G);
638: MatProductSymbolic(G);
639: MatProductNumeric(G);
640: MatProductClear(G);
641: MatDestroy(&X);
642: MatDestroy(&Xt);
643: MatDestroy(&M);
644: /* B = B*G */
645: BVMultInPlace(bv,G,bv->l,bv->k);
646: MatDestroy(&G);
647: PetscFree(eig);
648: DSDestroy(&ds);
649: PetscLogEventEnd(BV_SetRandom,bv,0,0,0);
650: PetscObjectStateIncrease((PetscObject)bv);
651: PetscFunctionReturn(0);
652: }
654: /*@
655: BVMatMult - Computes the matrix-vector product for each column, Y=A*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: Notes:
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: It is possible to choose whether the computation is done column by column
674: or as a Mat-Mat product, see BVSetMatMultMethod().
676: Level: beginner
678: .seealso: BVCopy(), BVSetActiveColumns(), BVMatMultColumn(), BVMatMultTranspose(), BVMatMultHermitianTranspose(), BVSetMatMultMethod()
679: @*/
680: PetscErrorCode BVMatMult(BV V,Mat A,BV Y)681: {
682: PetscInt M,N,m,n;
686: BVCheckSizes(V,1);
687: BVCheckOp(V,1,matmult);
692: BVCheckSizes(Y,3);
696: MatGetSize(A,&M,&N);
697: MatGetLocalSize(A,&m,&n);
704: PetscLogEventBegin(BV_MatMult,V,A,Y,0);
705: (*V->ops->matmult)(V,A,Y);
706: PetscLogEventEnd(BV_MatMult,V,A,Y,0);
707: PetscObjectStateIncrease((PetscObject)Y);
708: PetscFunctionReturn(0);
709: }
711: /*@
712: BVMatMultTranspose - Computes the matrix-vector product with the transpose
713: of a matrix for each column, Y=A^T*V.
715: Neighbor-wise Collective on A
717: Input Parameters:
718: + V - basis vectors context
719: - A - the matrix
721: Output Parameter:
722: . Y - the result
724: Notes:
725: Both V and Y must be distributed in the same manner. Only active columns
726: (excluding the leading ones) are processed.
727: In the result Y, columns are overwritten starting from the leading ones.
728: The number of active columns in V and Y should match, although they need
729: not be the same columns.
731: Currently implemented via MatCreateTranspose().
733: Level: beginner
735: .seealso: BVMatMult(), BVMatMultHermitianTranspose()
736: @*/
737: PetscErrorCode BVMatMultTranspose(BV V,Mat A,BV Y)738: {
739: PetscInt M,N,m,n;
740: Mat AT;
744: BVCheckSizes(V,1);
749: BVCheckSizes(Y,3);
753: MatGetSize(A,&M,&N);
754: MatGetLocalSize(A,&m,&n);
761: MatCreateTranspose(A,&AT);
762: BVMatMult(V,AT,Y);
763: MatDestroy(&AT);
764: PetscFunctionReturn(0);
765: }
767: /*@
768: BVMatMultHermitianTranspose - Computes the matrix-vector product with the
769: conjugate transpose of a matrix for each column, Y=A^H*V.
771: Neighbor-wise Collective on A
773: Input Parameters:
774: + V - basis vectors context
775: - A - the matrix
777: Output Parameter:
778: . Y - the result
780: Note:
781: Both V and Y must be distributed in the same manner. Only active columns
782: (excluding the leading ones) are processed.
783: In the result Y, columns are overwritten starting from the leading ones.
784: The number of active columns in V and Y should match, although they need
785: not be the same columns.
787: Currently implemented via MatCreateHermitianTranspose().
789: Level: beginner
791: .seealso: BVMatMult(), BVMatMultTranspose()
792: @*/
793: PetscErrorCode BVMatMultHermitianTranspose(BV V,Mat A,BV Y)794: {
795: PetscInt M,N,m,n;
796: Mat AH;
800: BVCheckSizes(V,1);
805: BVCheckSizes(Y,3);
809: MatGetSize(A,&M,&N);
810: MatGetLocalSize(A,&m,&n);
817: MatCreateHermitianTranspose(A,&AH);
818: BVMatMult(V,AH,Y);
819: MatDestroy(&AH);
820: PetscFunctionReturn(0);
821: }
823: /*@
824: BVMatMultColumn - Computes the matrix-vector product for a specified
825: column, storing the result in the next column v_{j+1}=A*v_j.
827: Neighbor-wise Collective on A
829: Input Parameters:
830: + V - basis vectors context
831: . A - the matrix
832: - j - the column
834: Level: beginner
836: .seealso: BVMatMult(), BVMatMultTransposeColumn(), BVMatMultHermitianTransposeColumn()
837: @*/
838: PetscErrorCode BVMatMultColumn(BV V,Mat A,PetscInt j)839: {
840: Vec vj,vj1;
844: BVCheckSizes(V,1);
851: PetscLogEventBegin(BV_MatMultVec,V,A,0,0);
852: BVGetColumn(V,j,&vj);
853: BVGetColumn(V,j+1,&vj1);
854: MatMult(A,vj,vj1);
855: BVRestoreColumn(V,j,&vj);
856: BVRestoreColumn(V,j+1,&vj1);
857: PetscLogEventEnd(BV_MatMultVec,V,A,0,0);
858: PetscObjectStateIncrease((PetscObject)V);
859: PetscFunctionReturn(0);
860: }
862: /*@
863: BVMatMultTransposeColumn - Computes the transpose matrix-vector product for a
864: specified column, storing the result in the next column v_{j+1}=A^T*v_j.
866: Neighbor-wise Collective on A
868: Input Parameters:
869: + V - basis vectors context
870: . A - the matrix
871: - j - the column
873: Level: beginner
875: .seealso: BVMatMult(), BVMatMultColumn(), BVMatMultHermitianTransposeColumn()
876: @*/
877: PetscErrorCode BVMatMultTransposeColumn(BV V,Mat A,PetscInt j)878: {
879: Vec vj,vj1;
883: BVCheckSizes(V,1);
890: PetscLogEventBegin(BV_MatMultVec,V,A,0,0);
891: BVGetColumn(V,j,&vj);
892: BVGetColumn(V,j+1,&vj1);
893: MatMultTranspose(A,vj,vj1);
894: BVRestoreColumn(V,j,&vj);
895: BVRestoreColumn(V,j+1,&vj1);
896: PetscLogEventEnd(BV_MatMultVec,V,A,0,0);
897: PetscObjectStateIncrease((PetscObject)V);
898: PetscFunctionReturn(0);
899: }
901: /*@
902: BVMatMultHermitianTransposeColumn - Computes the conjugate-transpose matrix-vector
903: product for a specified column, storing the result in the next column v_{j+1}=A^H*v_j.
905: Neighbor-wise Collective on A
907: Input Parameters:
908: + V - basis vectors context
909: . A - the matrix
910: - j - the column
912: Level: beginner
914: .seealso: BVMatMult(), BVMatMultColumn(), BVMatMultTransposeColumn()
915: @*/
916: PetscErrorCode BVMatMultHermitianTransposeColumn(BV V,Mat A,PetscInt j)917: {
918: Vec vj,vj1;
922: BVCheckSizes(V,1);
929: PetscLogEventBegin(BV_MatMultVec,V,A,0,0);
930: BVGetColumn(V,j,&vj);
931: BVGetColumn(V,j+1,&vj1);
932: MatMultHermitianTranspose(A,vj,vj1);
933: BVRestoreColumn(V,j,&vj);
934: BVRestoreColumn(V,j+1,&vj1);
935: PetscLogEventEnd(BV_MatMultVec,V,A,0,0);
936: PetscObjectStateIncrease((PetscObject)V);
937: PetscFunctionReturn(0);
938: }