Date: 2015-09-03T15:04:05+00:00

Actual source code: bvops.c
slepc-3.6.1 2015-09-03
Report Typos and Errors

      1: /*
      2:    BV operations, except those involving global communication.

      4:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      5:    SLEPc - Scalable Library for Eigenvalue Problem Computations
      6:    Copyright (c) 2002-2015, Universitat Politecnica de Valencia, Spain

      8:    This file is part of SLEPc.

     10:    SLEPc is free software: you can redistribute it and/or modify it under  the
     11:    terms of version 3 of the GNU Lesser General Public License as published by
     12:    the Free Software Foundation.

     14:    SLEPc  is  distributed in the hope that it will be useful, but WITHOUT  ANY
     15:    WARRANTY;  without even the implied warranty of MERCHANTABILITY or  FITNESS
     16:    FOR  A  PARTICULAR PURPOSE. See the GNU Lesser General Public  License  for
     17:    more details.

     19:    You  should have received a copy of the GNU Lesser General  Public  License
     20:    along with SLEPc. If not, see <http://www.gnu.org/licenses/>.
     21:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     22: */

     24: #include <slepc/private/bvimpl.h>      /*I "slepcbv.h" I*/

     28: /*@
     29:    BVMult - Computes Y = beta*Y + alpha*X*Q.

     31:    Logically Collective on BV

     33:    Input Parameters:
     34: +  Y,X        - basis vectors
     35: .  alpha,beta - scalars
     36: -  Q          - a sequential dense matrix

     38:    Output Parameter:
     39: .  Y          - the modified basis vectors

     41:    Notes:
     42:    X and Y must be different objects. The case X=Y can be addressed with
     43:    BVMultInPlace().

     45:    The matrix Q must be a sequential dense Mat, with all entries equal on
     46:    all processes (otherwise each process will compute a different update).
     47:    The dimensions of Q must be at least m,n where m is the number of active
     48:    columns of X and n is the number of active columns of Y.

     50:    The leading columns of Y are not modified. Also, if X has leading
     51:    columns specified, then these columns do not participate in the computation.
     52:    Hence, only rows (resp. columns) of Q starting from lx (resp. ly) are used,
     53:    where lx (resp. ly) is the number of leading columns of X (resp. Y).

     55:    Level: intermediate

     57: .seealso: BVMultVec(), BVMultColumn(), BVMultInPlace(), BVSetActiveColumns()
     58: @*/
     59: PetscErrorCode BVMult(BV Y,PetscScalar alpha,PetscScalar beta,BV X,Mat Q)
     60: {
     62:   PetscBool      match;
     63:   PetscInt       m,n;

     72:   BVCheckSizes(Y,1);
     74:   BVCheckSizes(X,4);
     77:   if (X==Y) SETERRQ(PetscObjectComm((PetscObject)Y),PETSC_ERR_ARG_WRONG,"X and Y arguments must be different");
     78:   PetscObjectTypeCompare((PetscObject)Q,MATSEQDENSE,&match);
     79:   if (!match) SETERRQ(PetscObjectComm((PetscObject)Y),PETSC_ERR_SUP,"Mat argument must be of type seqdense");

     81:   MatGetSize(Q,&m,&n);
     82:   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);
     83:   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);
     84:   if (X->n!=Y->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Mismatching local dimension X %D, Y %D",X->n,Y->n);
     85:   if (!X->n) return(0);

     87:   PetscLogEventBegin(BV_Mult,X,Y,0,0);
     88:   (*Y->ops->mult)(Y,alpha,beta,X,Q);
     89:   PetscLogEventEnd(BV_Mult,X,Y,0,0);
     90:   PetscObjectStateIncrease((PetscObject)Y);
     91:   return(0);
     92: }

     96: /*@
     97:    BVMultVec - Computes y = beta*y + alpha*X*q.

     99:    Logically Collective on BV and Vec

    101:    Input Parameters:
    102: +  X          - a basis vectors object
    103: .  alpha,beta - scalars
    104: .  y          - a vector
    105: -  q          - an array of scalars

    107:    Output Parameter:
    108: .  y          - the modified vector

    110:    Notes:
    111:    This operation is the analogue of BVMult() but with a BV and a Vec,
    112:    instead of two BV. Note that arguments are listed in different order
    113:    with respect to BVMult().

    115:    If X has leading columns specified, then these columns do not participate
    116:    in the computation.

    118:    The length of array q must be equal to the number of active columns of X
    119:    minus the number of leading columns, i.e. the first entry of q multiplies
    120:    the first non-leading column.

    122:    Level: intermediate

    124: .seealso: BVMult(), BVMultColumn(), BVMultInPlace(), BVSetActiveColumns()
    125: @*/
    126: PetscErrorCode BVMultVec(BV X,PetscScalar alpha,PetscScalar beta,Vec y,PetscScalar *q)
    127: {
    129:   PetscInt       n,N;

    138:   BVCheckSizes(X,1);

    142:   VecGetSize(y,&N);
    143:   VecGetLocalSize(y,&n);
    144:   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);
    145:   if (!X->n) return(0);

    147:   PetscLogEventBegin(BV_Mult,X,y,0,0);
    148:   (*X->ops->multvec)(X,alpha,beta,y,q);
    149:   PetscLogEventEnd(BV_Mult,X,y,0,0);
    150:   return(0);
    151: }

    155: /*@
    156:    BVMultColumn - Computes y = beta*y + alpha*X*q, where y is the j-th column
    157:    of X.

    159:    Logically Collective on BV

    161:    Input Parameters:
    162: +  X          - a basis vectors object
    163: .  alpha,beta - scalars
    164: .  j          - the column index
    165: -  q          - an array of scalars

    167:    Notes:
    168:    This operation is equivalent to BVMultVec() but it uses column j of X
    169:    rather than taking a Vec as an argument. The number of active columns of
    170:    X is set to j before the computation, and restored afterwards.
    171:    If X has leading columns specified, then these columns do not participate
    172:    in the computation. Therefore, the length of array q must be equal to j
    173:    minus the number of leading columns.

    175:    Level: advanced

    177: .seealso: BVMult(), BVMultVec(), BVMultInPlace(), BVSetActiveColumns()
    178: @*/
    179: PetscErrorCode BVMultColumn(BV X,PetscScalar alpha,PetscScalar beta,PetscInt j,PetscScalar *q)
    180: {
    182:   PetscInt       ksave;
    183:   Vec            y;

    192:   BVCheckSizes(X,1);

    194:   if (j<0) SETERRQ(PetscObjectComm((PetscObject)X),PETSC_ERR_ARG_OUTOFRANGE,"Index j must be non-negative");
    195:   if (j>=X->m) SETERRQ2(PetscObjectComm((PetscObject)X),PETSC_ERR_ARG_OUTOFRANGE,"Index j=%D but BV only has %D columns",j,X->m);

    197:   PetscLogEventBegin(BV_Mult,X,0,0,0);
    198:   ksave = X->k;
    199:   X->k = j;
    200:   BVGetColumn(X,j,&y);
    201:   (*X->ops->multvec)(X,alpha,beta,y,q);
    202:   BVRestoreColumn(X,j,&y);
    203:   X->k = ksave;
    204:   PetscLogEventEnd(BV_Mult,X,0,0,0);
    205:   return(0);
    206: }

    210: /*@
    211:    BVMultInPlace - Update a set of vectors as V(:,s:e-1) = V*Q(:,s:e-1).

    213:    Logically Collective on BV

    215:    Input Parameters:
    216: +  Q - a sequential dense matrix
    217: .  s - first column of V to be overwritten
    218: -  e - first column of V not to be overwritten

    220:    Input/Output Parameter:
    221: +  V - basis vectors

    223:    Notes:
    224:    The matrix Q must be a sequential dense Mat, with all entries equal on
    225:    all processes (otherwise each process will compute a different update).

    227:    This function computes V(:,s:e-1) = V*Q(:,s:e-1), that is, given a set of
    228:    vectors V, columns from s to e-1 are overwritten with columns from s to
    229:    e-1 of the matrix-matrix product V*Q. Only columns s to e-1 of Q are
    230:    referenced.

    232:    Level: intermediate

    234: .seealso: BVMult(), BVMultVec(), BVMultInPlaceTranspose(), BVSetActiveColumns()
    235: @*/
    236: PetscErrorCode BVMultInPlace(BV V,Mat Q,PetscInt s,PetscInt e)
    237: {
    239:   PetscBool      match;
    240:   PetscInt       m,n;

    248:   BVCheckSizes(V,1);
    250:   PetscObjectTypeCompare((PetscObject)Q,MATSEQDENSE,&match);
    251:   if (!match) SETERRQ(PetscObjectComm((PetscObject)V),PETSC_ERR_SUP,"Mat argument must be of type seqdense");

    253:   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);
    254:   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);
    255:   MatGetSize(Q,&m,&n);
    256:   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);
    257:   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);
    258:   if (s>=e || !V->n) return(0);

    260:   PetscLogEventBegin(BV_Mult,V,Q,0,0);
    261:   (*V->ops->multinplace)(V,Q,s,e);
    262:   PetscLogEventEnd(BV_Mult,V,Q,0,0);
    263:   PetscObjectStateIncrease((PetscObject)V);
    264:   return(0);
    265: }

    269: /*@
    270:    BVMultInPlaceTranspose - Update a set of vectors as V(:,s:e-1) = V*Q'(:,s:e-1).

    272:    Logically Collective on BV

    274:    Input Parameters:
    275: +  Q - a sequential dense matrix
    276: .  s - first column of V to be overwritten
    277: -  e - first column of V not to be overwritten

    279:    Input/Output Parameter:
    280: +  V - basis vectors

    282:    Notes:
    283:    This is a variant of BVMultInPlace() where the conjugate transpose
    284:    of Q is used.

    286:    Level: intermediate

    288: .seealso: BVMultInPlace()
    289: @*/
    290: PetscErrorCode BVMultInPlaceTranspose(BV V,Mat Q,PetscInt s,PetscInt e)
    291: {
    293:   PetscBool      match;
    294:   PetscInt       m,n;

    302:   BVCheckSizes(V,1);
    304:   PetscObjectTypeCompare((PetscObject)Q,MATSEQDENSE,&match);
    305:   if (!match) SETERRQ(PetscObjectComm((PetscObject)V),PETSC_ERR_SUP,"Mat argument must be of type seqdense");

    307:   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);
    308:   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);
    309:   MatGetSize(Q,&m,&n);
    310:   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);
    311:   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);
    312:   if (s>=e || !V->n) return(0);

    314:   PetscLogEventBegin(BV_Mult,V,Q,0,0);
    315:   (*V->ops->multinplacetrans)(V,Q,s,e);
    316:   PetscLogEventEnd(BV_Mult,V,Q,0,0);
    317:   PetscObjectStateIncrease((PetscObject)V);
    318:   return(0);
    319: }

    323: /*@
    324:    BVScale - Multiply the BV entries by a scalar value.

    326:    Logically Collective on BV

    328:    Input Parameters:
    329: +  bv    - basis vectors
    330: -  alpha - scaling factor

    332:    Note:
    333:    All active columns (except the leading ones) are scaled.

    335:    Level: intermediate

    337: .seealso: BVScaleColumn(), BVSetActiveColumns()
    338: @*/
    339: PetscErrorCode BVScale(BV bv,PetscScalar alpha)
    340: {

    347:   BVCheckSizes(bv,1);
    348:   if (!bv->n || alpha == (PetscScalar)1.0) return(0);

    350:   PetscLogEventBegin(BV_Scale,bv,0,0,0);
    351:   (*bv->ops->scale)(bv,-1,alpha);
    352:   PetscLogEventEnd(BV_Scale,bv,0,0,0);
    353:   PetscObjectStateIncrease((PetscObject)bv);
    354:   return(0);
    355: }

    359: /*@
    360:    BVScaleColumn - Scale one column of a BV.

    362:    Logically Collective on BV

    364:    Input Parameters:
    365: +  bv    - basis vectors
    366: .  j     - column number to be scaled
    367: -  alpha - scaling factor

    369:    Level: intermediate

    371: .seealso: BVScale(), BVSetActiveColumns()
    372: @*/
    373: PetscErrorCode BVScaleColumn(BV bv,PetscInt j,PetscScalar alpha)
    374: {

    382:   BVCheckSizes(bv,1);

    384:   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);
    385:   if (!bv->n || alpha == (PetscScalar)1.0) return(0);

    387:   PetscLogEventBegin(BV_Scale,bv,0,0,0);
    388:   (*bv->ops->scale)(bv,j,alpha);
    389:   PetscLogEventEnd(BV_Scale,bv,0,0,0);
    390:   PetscObjectStateIncrease((PetscObject)bv);
    391:   return(0);
    392: }

    396: /*@
    397:    BVSetRandom - Set the columns of a BV to random numbers.

    399:    Logically Collective on BV

    401:    Input Parameters:
    402: +  bv   - basis vectors
    403: -  rctx - the random number context, formed by PetscRandomCreate(), or NULL and
    404:           it will create one internally.

    406:    Note:
    407:    All active columns (except the leading ones) are modified.

    409:    Level: advanced

    411: .seealso: BVSetRandomColumn(), BVSetActiveColumns()
    412: @*/
    413: PetscErrorCode BVSetRandom(BV bv,PetscRandom rctx)
    414: {
    416:   PetscRandom    rand=NULL;
    417:   PetscInt       i,low,high,k;
    418:   PetscScalar    *px,t;
    419:   Vec            x;

    424:   else {
    425:     PetscRandomCreate(PetscObjectComm((PetscObject)bv),&rand);
    426:     PetscRandomSetSeed(rand,0x12345678);
    427:     PetscRandomSetFromOptions(rand);
    428:     rctx = rand;
    429:   }
    431:   BVCheckSizes(bv,1);

    433:   PetscLogEventBegin(BV_SetRandom,bv,rctx,0,0);
    434:   for (k=bv->l;k<bv->k;k++) {
    435:     BVGetColumn(bv,k,&x);
    436:     VecGetOwnershipRange(x,&low,&high);
    437:     VecGetArray(x,&px);
    438:     for (i=0;i<bv->N;i++) {
    439:       PetscRandomGetValue(rctx,&t);
    440:       if (i>=low && i<high) px[i-low] = t;
    441:     }
    442:     VecRestoreArray(x,&px);
    443:     BVRestoreColumn(bv,k,&x);
    444:   }
    445:   PetscLogEventEnd(BV_SetRandom,bv,rctx,0,0);
    446:   PetscRandomDestroy(&rand);
    447:   PetscObjectStateIncrease((PetscObject)bv);
    448:   return(0);
    449: }

    453: /*@
    454:    BVSetRandomColumn - Set one column of a BV to random numbers.

    456:    Logically Collective on BV

    458:    Input Parameters:
    459: +  bv   - basis vectors
    460: .  j    - column number to be set
    461: -  rctx - the random number context, formed by PetscRandomCreate(), or NULL and
    462:           it will create one internally.

    464:    Note:
    465:    This operation is analogue to VecSetRandom - the difference is that the
    466:    generated random vector is the same irrespective of the size of the
    467:    communicator (if all processes pass a PetscRandom context initialized
    468:    with the same seed).

    470:    Level: advanced

    472: .seealso: BVSetRandom(), BVSetActiveColumns()
    473: @*/
    474: PetscErrorCode BVSetRandomColumn(BV bv,PetscInt j,PetscRandom rctx)
    475: {
    477:   PetscRandom    rand=NULL;
    478:   PetscInt       i,low,high;
    479:   PetscScalar    *px,t;
    480:   Vec            x;

    486:   else {
    487:     PetscRandomCreate(PetscObjectComm((PetscObject)bv),&rand);
    488:     PetscRandomSetSeed(rand,0x12345678);
    489:     PetscRandomSetFromOptions(rand);
    490:     rctx = rand;
    491:   }
    493:   BVCheckSizes(bv,1);
    494:   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);

    496:   PetscLogEventBegin(BV_SetRandom,bv,rctx,0,0);
    497:   BVGetColumn(bv,j,&x);
    498:   VecGetOwnershipRange(x,&low,&high);
    499:   VecGetArray(x,&px);
    500:   for (i=0;i<bv->N;i++) {
    501:     PetscRandomGetValue(rctx,&t);
    502:     if (i>=low && i<high) px[i-low] = t;
    503:   }
    504:   VecRestoreArray(x,&px);
    505:   BVRestoreColumn(bv,j,&x);
    506:   PetscLogEventEnd(BV_SetRandom,bv,rctx,0,0);
    507:   PetscRandomDestroy(&rand);
    508:   PetscObjectStateIncrease((PetscObject)bv);
    509:   return(0);
    510: }

    514: /*@
    515:    BVMatMult - Computes the matrix-vector product for each column, Y=A*V.

    517:    Neighbor-wise Collective on Mat and BV

    519:    Input Parameters:
    520: +  V - basis vectors context
    521: -  A - the matrix

    523:    Output Parameter:
    524: .  Y - the result

    526:    Note:
    527:    Both V and Y must be distributed in the same manner. Only active columns
    528:    (excluding the leading ones) are processed.
    529:    In the result Y, columns are overwritten starting from the leading ones.

    531:    It is possible to choose whether the computation is done column by column
    532:    or as a Mat-Mat product, see BVSetMatMultMethod().

    534:    Level: beginner

    536: .seealso: BVCopy(), BVSetActiveColumns(), BVMatMultColumn(), BVMatMultHermitianTranspose(), BVSetMatMultMethod()
    537: @*/
    538: PetscErrorCode BVMatMult(BV V,Mat A,BV Y)
    539: {

    545:   BVCheckSizes(V,1);
    550:   BVCheckSizes(Y,3);
    553:   if (V->n!=Y->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Mismatching local dimension V %D, Y %D",V->n,Y->n);
    554:   if (V->k-V->l>Y->m-Y->l) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Y has %D non-leading columns, not enough to store %D columns",Y->m-Y->l,V->k-V->l);

    556:   PetscLogEventBegin(BV_MatMult,V,A,Y,0);
    557:   (*V->ops->matmult)(V,A,Y);
    558:   PetscLogEventEnd(BV_MatMult,V,A,Y,0);
    559:   return(0);
    560: }

    564: /*@
    565:    BVMatMultHermitianTranspose - Computes the matrix-vector product with the
    566:    conjugate transpose of a matrix for each column, Y=A^H*V.

    568:    Neighbor-wise Collective on Mat and BV

    570:    Input Parameters:
    571: +  V - basis vectors context
    572: -  A - the matrix

    574:    Output Parameter:
    575: .  Y - the result

    577:    Note:
    578:    Both V and Y must be distributed in the same manner. Only active columns
    579:    (excluding the leading ones) are processed.
    580:    In the result Y, columns are overwritten starting from the leading ones.

    582:    As opposed to BVMatMult(), this operation is always done column by column,
    583:    with a sequence of calls to MatMultHermitianTranspose().

    585:    Level: beginner

    587: .seealso: BVCopy(), BVSetActiveColumns(), BVMatMult(), BVMatMultColumn()
    588: @*/
    589: PetscErrorCode BVMatMultHermitianTranspose(BV V,Mat A,BV Y)
    590: {
    592:   PetscInt       j;
    593:   Vec            z,f;

    598:   BVCheckSizes(V,1);
    603:   BVCheckSizes(Y,3);
    606:   if (V->n!=Y->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Mismatching local dimension V %D, Y %D",V->n,Y->n);
    607:   if (V->k-V->l>Y->m-Y->l) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Y has %D non-leading columns, not enough to store %D columns",Y->m-Y->l,V->k-V->l);

    609:   PetscLogEventBegin(BV_MatMult,V,A,Y,0);
    610:   for (j=0;j<V->k-V->l;j++) {
    611:     BVGetColumn(V,V->l+j,&z);
    612:     BVGetColumn(Y,Y->l+j,&f);
    613:     MatMultHermitianTranspose(A,z,f);
    614:     BVRestoreColumn(V,V->l+j,&z);
    615:     BVRestoreColumn(Y,Y->l+j,&f);
    616:   }
    617:   PetscLogEventEnd(BV_MatMult,V,A,Y,0);
    618:   return(0);
    619: }

    623: /*@
    624:    BVMatMultColumn - Computes the matrix-vector product for a specified
    625:    column, storing the result in the next column: v_{j+1}=A*v_j.

    627:    Neighbor-wise Collective on Mat and BV

    629:    Input Parameters:
    630: +  V - basis vectors context
    631: .  A - the matrix
    632: -  j - the column

    634:    Output Parameter:
    635: .  Y - the result

    637:    Level: beginner

    639: .seealso: BVMatMult()
    640: @*/
    641: PetscErrorCode BVMatMultColumn(BV V,Mat A,PetscInt j)
    642: {
    644:   Vec            vj,vj1;

    649:   BVCheckSizes(V,1);
    652:   if (j<0) SETERRQ(PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_OUTOFRANGE,"Index j must be non-negative");
    653:   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);

    655:   PetscLogEventBegin(BV_MatMult,V,A,0,0);
    656:   BVGetColumn(V,j,&vj);
    657:   BVGetColumn(V,j+1,&vj1);
    658:   MatMult(A,vj,vj1);
    659:   BVRestoreColumn(V,j,&vj);
    660:   BVRestoreColumn(V,j+1,&vj1);
    661:   PetscLogEventEnd(BV_MatMult,V,A,0,0);
    662:   return(0);
    663: }

    667: /*@C
    668:    BVAXPY - Computes Y = Y + alpha*X.

    670:    Logically Collective on BV

    672:    Input Parameters:
    673: +  Y,X   - basis vectors
    674: -  alpha - scalar

    676:    Output Parameter:
    677: .  Y     - the modified basis vectors

    679:    Notes:
    680:    X and Y must be different objects, with compatible dimensions.
    681:    The effect is the same as doing a VecAXPY for each of the active
    682:    columns (excluding the leading ones).

    684:    Level: intermediate

    686: .seealso: BVMult(), BVSetActiveColumns()
    687: @*/
    688: PetscErrorCode BVAXPY(BV Y,PetscScalar alpha,BV X)
    689: {

    697:   BVCheckSizes(Y,1);
    699:   BVCheckSizes(X,3);
    701:   if (X==Y) SETERRQ(PetscObjectComm((PetscObject)Y),PETSC_ERR_ARG_WRONG,"X and Y arguments must be different");
    702:   if (X->n!=Y->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Mismatching local dimension X %D, Y %D",X->n,Y->n);
    703:   if (X->k-X->l!=Y->k-Y->l) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Y has %D non-leading columns, while X has %D",Y->m-Y->l,X->k-X->l);
    704:   if (!X->n) return(0);

    706:   PetscLogEventBegin(BV_AXPY,X,Y,0,0);
    707:   (*Y->ops->axpy)(Y,alpha,X);
    708:   PetscLogEventEnd(BV_AXPY,X,Y,0,0);
    709:   PetscObjectStateIncrease((PetscObject)Y);
    710:   return(0);
    711: }