Actual source code: bvops.c

slepc-3.17.1 2022-04-11
Report Typos and Errors
  1: /*
  2:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  3:    SLEPc - Scalable Library for Eigenvalue Problem Computations
  4:    Copyright (c) 2002-, Universitat Politecnica de Valencia, Spain

  6:    This file is part of SLEPc.
  7:    SLEPc is distributed under a 2-clause BSD license (see LICENSE).
  8:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  9: */
 10: /*
 11:    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: }