Date: 2022-03-31T15:28:55+00:00

Actual source code: bvops.c
slepc-3.17.0 2022-03-31
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: }