Actual source code: svec.c
slepc-3.10.1 2018-10-23
Report Typos and Errors

      1: /*
      2:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      3:    SLEPc - Scalable Library for Eigenvalue Problem Computations
      4:    Copyright (c) 2002-2018, 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 implemented as a single Vec
     12: */

     14: #include <slepc/private/bvimpl.h>
     15: #include "./svecimpl.h"

     17: PetscErrorCode BVMult_Svec(BV Y,PetscScalar alpha,PetscScalar beta,BV X,Mat Q)
     18: {
     19:   PetscErrorCode    ierr;
     20:   BV_SVEC           *y = (BV_SVEC*)Y->data,*x = (BV_SVEC*)X->data;
     21:   const PetscScalar *px;
     22:   PetscScalar       *py,*q;
     23:   PetscInt          ldq;

     26:   VecGetArrayRead(x->v,&px);
     27:   VecGetArray(y->v,&py);
     28:   if (Q) {
     29:     MatGetSize(Q,&ldq,NULL);
     30:     MatDenseGetArray(Q,&q);
     31:     BVMult_BLAS_Private(Y,Y->n,Y->k-Y->l,X->k-X->l,ldq,alpha,px+(X->nc+X->l)*X->n,q+Y->l*ldq+X->l,beta,py+(Y->nc+Y->l)*Y->n);
     32:     MatDenseRestoreArray(Q,&q);
     33:   } else {
     34:     BVAXPY_BLAS_Private(Y,Y->n,Y->k-Y->l,alpha,px+(X->nc+X->l)*X->n,beta,py+(Y->nc+Y->l)*Y->n);
     35:   }
     36:   VecRestoreArrayRead(x->v,&px);
     37:   VecRestoreArray(y->v,&py);
     38:   return(0);
     39: }

     41: PetscErrorCode BVMultVec_Svec(BV X,PetscScalar alpha,PetscScalar beta,Vec y,PetscScalar *q)
     42: {
     44:   BV_SVEC        *x = (BV_SVEC*)X->data;
     45:   PetscScalar    *px,*py,*qq=q;

     48:   VecGetArray(x->v,&px);
     49:   VecGetArray(y,&py);
     50:   if (!q) { VecGetArray(X->buffer,&qq); }
     51:   BVMultVec_BLAS_Private(X,X->n,X->k-X->l,alpha,px+(X->nc+X->l)*X->n,qq,beta,py);
     52:   if (!q) { VecRestoreArray(X->buffer,&qq); }
     53:   VecRestoreArray(x->v,&px);
     54:   VecRestoreArray(y,&py);
     55:   return(0);
     56: }

     58: PetscErrorCode BVMultInPlace_Svec(BV V,Mat Q,PetscInt s,PetscInt e)
     59: {
     61:   BV_SVEC        *ctx = (BV_SVEC*)V->data;
     62:   PetscScalar    *pv,*q;
     63:   PetscInt       ldq;

     66:   MatGetSize(Q,&ldq,NULL);
     67:   VecGetArray(ctx->v,&pv);
     68:   MatDenseGetArray(Q,&q);
     69:   BVMultInPlace_BLAS_Private(V,V->n,V->k-V->l,ldq,s-V->l,e-V->l,pv+(V->nc+V->l)*V->n,q+V->l*ldq+V->l,PETSC_FALSE);
     70:   MatDenseRestoreArray(Q,&q);
     71:   VecRestoreArray(ctx->v,&pv);
     72:   return(0);
     73: }

     75: PetscErrorCode BVMultInPlaceTranspose_Svec(BV V,Mat Q,PetscInt s,PetscInt e)
     76: {
     78:   BV_SVEC        *ctx = (BV_SVEC*)V->data;
     79:   PetscScalar    *pv,*q;
     80:   PetscInt       ldq;

     83:   MatGetSize(Q,&ldq,NULL);
     84:   VecGetArray(ctx->v,&pv);
     85:   MatDenseGetArray(Q,&q);
     86:   BVMultInPlace_BLAS_Private(V,V->n,V->k-V->l,ldq,s-V->l,e-V->l,pv+(V->nc+V->l)*V->n,q+V->l*ldq+V->l,PETSC_TRUE);
     87:   MatDenseRestoreArray(Q,&q);
     88:   VecRestoreArray(ctx->v,&pv);
     89:   return(0);
     90: }

     92: PetscErrorCode BVDot_Svec(BV X,BV Y,Mat M)
     93: {
     94:   PetscErrorCode    ierr;
     95:   BV_SVEC           *x = (BV_SVEC*)X->data,*y = (BV_SVEC*)Y->data;
     96:   const PetscScalar *px,*py;
     97:   PetscScalar       *m;
     98:   PetscInt          ldm;

    101:   MatGetSize(M,&ldm,NULL);
    102:   VecGetArrayRead(x->v,&px);
    103:   VecGetArrayRead(y->v,&py);
    104:   MatDenseGetArray(M,&m);
    105:   BVDot_BLAS_Private(X,Y->k-Y->l,X->k-X->l,X->n,ldm,py+(Y->nc+Y->l)*Y->n,px+(X->nc+X->l)*X->n,m+X->l*ldm+Y->l,x->mpi);
    106:   MatDenseRestoreArray(M,&m);
    107:   VecRestoreArrayRead(x->v,&px);
    108:   VecRestoreArrayRead(y->v,&py);
    109:   return(0);
    110: }

    112: PetscErrorCode BVDotVec_Svec(BV X,Vec y,PetscScalar *q)
    113: {
    114:   PetscErrorCode    ierr;
    115:   BV_SVEC           *x = (BV_SVEC*)X->data;
    116:   const PetscScalar *px,*py;
    117:   PetscScalar       *qq=q;
    118:   Vec               z = y;

    121:   if (X->matrix) {
    122:     BV_IPMatMult(X,y);
    123:     z = X->Bx;
    124:   }
    125:   VecGetArrayRead(x->v,&px);
    126:   VecGetArrayRead(z,&py);
    127:   if (!q) { VecGetArray(X->buffer,&qq); }
    128:   BVDotVec_BLAS_Private(X,X->n,X->k-X->l,px+(X->nc+X->l)*X->n,py,qq,x->mpi);
    129:   if (!q) { VecRestoreArray(X->buffer,&qq); }
    130:   VecRestoreArrayRead(z,&py);
    131:   VecRestoreArrayRead(x->v,&px);
    132:   return(0);
    133: }

    135: PetscErrorCode BVDotVec_Local_Svec(BV X,Vec y,PetscScalar *m)
    136: {
    138:   BV_SVEC        *x = (BV_SVEC*)X->data;
    139:   PetscScalar    *px,*py;
    140:   Vec            z = y;

    143:   if (X->matrix) {
    144:     BV_IPMatMult(X,y);
    145:     z = X->Bx;
    146:   }
    147:   VecGetArray(x->v,&px);
    148:   VecGetArray(z,&py);
    149:   BVDotVec_BLAS_Private(X,X->n,X->k-X->l,px+(X->nc+X->l)*X->n,py,m,PETSC_FALSE);
    150:   VecRestoreArray(z,&py);
    151:   VecRestoreArray(x->v,&px);
    152:   return(0);
    153: }

    155: PetscErrorCode BVScale_Svec(BV bv,PetscInt j,PetscScalar alpha)
    156: {
    158:   BV_SVEC        *ctx = (BV_SVEC*)bv->data;
    159:   PetscScalar    *array;

    162:   VecGetArray(ctx->v,&array);
    163:   if (j<0) {
    164:     BVScale_BLAS_Private(bv,(bv->k-bv->l)*bv->n,array+(bv->nc+bv->l)*bv->n,alpha);
    165:   } else {
    166:     BVScale_BLAS_Private(bv,bv->n,array+(bv->nc+j)*bv->n,alpha);
    167:   }
    168:   VecRestoreArray(ctx->v,&array);
    169:   return(0);
    170: }

    172: PetscErrorCode BVNorm_Svec(BV bv,PetscInt j,NormType type,PetscReal *val)
    173: {
    175:   BV_SVEC        *ctx = (BV_SVEC*)bv->data;
    176:   PetscScalar    *array;

    179:   VecGetArray(ctx->v,&array);
    180:   if (j<0) {
    181:     BVNorm_LAPACK_Private(bv,bv->n,bv->k-bv->l,array+(bv->nc+bv->l)*bv->n,type,val,ctx->mpi);
    182:   } else {
    183:     BVNorm_LAPACK_Private(bv,bv->n,1,array+(bv->nc+j)*bv->n,type,val,ctx->mpi);
    184:   }
    185:   VecRestoreArray(ctx->v,&array);
    186:   return(0);
    187: }

    189: PetscErrorCode BVNorm_Local_Svec(BV bv,PetscInt j,NormType type,PetscReal *val)
    190: {
    192:   BV_SVEC        *ctx = (BV_SVEC*)bv->data;
    193:   PetscScalar    *array;

    196:   VecGetArray(ctx->v,&array);
    197:   if (j<0) {
    198:     BVNorm_LAPACK_Private(bv,bv->n,bv->k-bv->l,array+(bv->nc+bv->l)*bv->n,type,val,PETSC_FALSE);
    199:   } else {
    200:     BVNorm_LAPACK_Private(bv,bv->n,1,array+(bv->nc+j)*bv->n,type,val,PETSC_FALSE);
    201:   }
    202:   VecRestoreArray(ctx->v,&array);
    203:   return(0);
    204: }

    206: PetscErrorCode BVMatMult_Svec(BV V,Mat A,BV W)
    207: {
    208:   PetscErrorCode   ierr;
    209:   BV_SVEC          *v = (BV_SVEC*)V->data,*w = (BV_SVEC*)W->data;
    210:   PetscScalar      *pv,*pw;
    211:   PetscInt         j;
    212:   PetscBool        flg;
    213:   Mat              Vmat,Wmat,aux;
    214:   PetscObjectState Astate;

    217:   MatHasOperation(A,MATOP_MAT_MULT,&flg);
    218:   if (V->vmm && flg) {
    219:     BVGetMat(V,&Vmat);
    220:     BVGetMat(W,&Wmat);
    221:     PetscObjectStateGet((PetscObject)A,&Astate);
    222:     if (V->Amult==A && V->Amultstate==Astate) {
    223:       MatMatMult(A,Vmat,MAT_REUSE_MATRIX,PETSC_DEFAULT,&Wmat);
    224:     } else {
    225:       MatMatMult(A,Vmat,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&aux);
    226:       MatCopy(aux,Wmat,SAME_NONZERO_PATTERN);
    227:       MatDestroy(&aux);
    228:       V->Amult = A;
    229:       V->Amultstate = Astate;
    230:     }
    231:     BVRestoreMat(V,&Vmat);
    232:     BVRestoreMat(W,&Wmat);
    233:   } else {
    234:     VecGetArray(v->v,&pv);
    235:     VecGetArray(w->v,&pw);
    236:     for (j=0;j<V->k-V->l;j++) {
    237:       VecPlaceArray(V->cv[1],pv+(V->nc+V->l+j)*V->n);
    238:       VecPlaceArray(W->cv[1],pw+(W->nc+W->l+j)*W->n);
    239:       MatMult(A,V->cv[1],W->cv[1]);
    240:       VecResetArray(V->cv[1]);
    241:       VecResetArray(W->cv[1]);
    242:     }
    243:     VecRestoreArray(v->v,&pv);
    244:     VecRestoreArray(w->v,&pw);
    245:   }
    246:   return(0);
    247: }

    249: PetscErrorCode BVCopy_Svec(BV V,BV W)
    250: {
    252:   BV_SVEC        *v = (BV_SVEC*)V->data,*w = (BV_SVEC*)W->data;
    253:   PetscScalar    *pv,*pw,*pvc,*pwc;

    256:   VecGetArray(v->v,&pv);
    257:   VecGetArray(w->v,&pw);
    258:   pvc = pv+(V->nc+V->l)*V->n;
    259:   pwc = pw+(W->nc+W->l)*W->n;
    260:   PetscMemcpy(pwc,pvc,(V->k-V->l)*V->n*sizeof(PetscScalar));
    261:   VecRestoreArray(v->v,&pv);
    262:   VecRestoreArray(w->v,&pw);
    263:   return(0);
    264: }

    266: PetscErrorCode BVCopyColumn_Svec(BV V,PetscInt j,PetscInt i)
    267: {
    269:   BV_SVEC        *v = (BV_SVEC*)V->data;
    270:   PetscScalar    *pv;

    273:   VecGetArray(v->v,&pv);
    274:   PetscMemcpy(pv+(V->nc+i)*V->n,pv+(V->nc+j)*V->n,V->n*sizeof(PetscScalar));
    275:   VecRestoreArray(v->v,&pv);
    276:   return(0);
    277: }

    279: PetscErrorCode BVResize_Svec(BV bv,PetscInt m,PetscBool copy)
    280: {
    281:   PetscErrorCode    ierr;
    282:   BV_SVEC           *ctx = (BV_SVEC*)bv->data;
    283:   PetscScalar       *pnew;
    284:   const PetscScalar *pv;
    285:   PetscInt          bs,lsplit;
    286:   Vec               vnew,vpar;
    287:   char              str[50];
    288:   BV                parent;

    291:   if (bv->issplit==2) {
    292:     parent = bv->splitparent;
    293:     lsplit = parent->lsplit;
    294:     vpar = ((BV_SVEC*)parent->data)->v;
    295:     VecGetArrayRead(vpar,&pv);
    296:     VecResetArray(ctx->v);
    297:     VecPlaceArray(ctx->v,pv+lsplit*bv->n);
    298:     VecRestoreArrayRead(vpar,&pv);
    299:   } else if (!bv->issplit) {
    300:     VecGetBlockSize(bv->t,&bs);
    301:     VecCreate(PetscObjectComm((PetscObject)bv->t),&vnew);
    302:     VecSetType(vnew,((PetscObject)bv->t)->type_name);
    303:     VecSetSizes(vnew,m*bv->n,PETSC_DECIDE);
    304:     VecSetBlockSize(vnew,bs);
    305:     PetscLogObjectParent((PetscObject)bv,(PetscObject)vnew);
    306:     if (((PetscObject)bv)->name) {
    307:       PetscSNPrintf(str,50,"%s_0",((PetscObject)bv)->name);
    308:       PetscObjectSetName((PetscObject)vnew,str);
    309:     }
    310:     if (copy) {
    311:       VecGetArrayRead(ctx->v,&pv);
    312:       VecGetArray(vnew,&pnew);
    313:       PetscMemcpy(pnew,pv,PetscMin(m,bv->m)*bv->n*sizeof(PetscScalar));
    314:       VecRestoreArrayRead(ctx->v,&pv);
    315:       VecRestoreArray(vnew,&pnew);
    316:     }
    317:     VecDestroy(&ctx->v);
    318:     ctx->v = vnew;
    319:   }
    320:   return(0);
    321: }

    323: PetscErrorCode BVGetColumn_Svec(BV bv,PetscInt j,Vec *v)
    324: {
    326:   BV_SVEC        *ctx = (BV_SVEC*)bv->data;
    327:   PetscScalar    *pv;
    328:   PetscInt       l;

    331:   l = BVAvailableVec;
    332:   VecGetArray(ctx->v,&pv);
    333:   VecPlaceArray(bv->cv[l],pv+(bv->nc+j)*bv->n);
    334:   return(0);
    335: }

    337: PetscErrorCode BVRestoreColumn_Svec(BV bv,PetscInt j,Vec *v)
    338: {
    340:   BV_SVEC        *ctx = (BV_SVEC*)bv->data;
    341:   PetscInt       l;

    344:   l = (j==bv->ci[0])? 0: 1;
    345:   VecResetArray(bv->cv[l]);
    346:   VecRestoreArray(ctx->v,NULL);
    347:   return(0);
    348: }

    350: PetscErrorCode BVGetArray_Svec(BV bv,PetscScalar **a)
    351: {
    353:   BV_SVEC        *ctx = (BV_SVEC*)bv->data;

    356:   VecGetArray(ctx->v,a);
    357:   return(0);
    358: }

    360: PetscErrorCode BVRestoreArray_Svec(BV bv,PetscScalar **a)
    361: {
    363:   BV_SVEC        *ctx = (BV_SVEC*)bv->data;

    366:   VecRestoreArray(ctx->v,a);
    367:   return(0);
    368: }

    370: PetscErrorCode BVGetArrayRead_Svec(BV bv,const PetscScalar **a)
    371: {
    373:   BV_SVEC        *ctx = (BV_SVEC*)bv->data;

    376:   VecGetArrayRead(ctx->v,a);
    377:   return(0);
    378: }

    380: PetscErrorCode BVRestoreArrayRead_Svec(BV bv,const PetscScalar **a)
    381: {
    383:   BV_SVEC        *ctx = (BV_SVEC*)bv->data;

    386:   VecRestoreArrayRead(ctx->v,a);
    387:   return(0);
    388: }

    390: PetscErrorCode BVView_Svec(BV bv,PetscViewer viewer)
    391: {
    392:   PetscErrorCode    ierr;
    393:   BV_SVEC           *ctx = (BV_SVEC*)bv->data;
    394:   PetscViewerFormat format;
    395:   PetscBool         isascii;
    396:   const char        *bvname,*name;

    399:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
    400:   if (isascii) {
    401:     PetscViewerGetFormat(viewer,&format);
    402:     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) return(0);
    403:     VecView(ctx->v,viewer);
    404:     if (format == PETSC_VIEWER_ASCII_MATLAB) {
    405:       PetscObjectGetName((PetscObject)bv,&bvname);
    406:       PetscObjectGetName((PetscObject)ctx->v,&name);
    407:       PetscViewerASCIIPrintf(viewer,"%s=reshape(%s,%D,%D);clear %s\n",bvname,name,bv->N,bv->nc+bv->m,name);
    408:       if (bv->nc) {
    409:         PetscViewerASCIIPrintf(viewer,"%s=%s(:,%D:end);\n",bvname,bvname,bv->nc+1);
    410:       }
    411:     }
    412:   } else {
    413:     VecView(ctx->v,viewer);
    414:   }
    415:   return(0);
    416: }

    418: PetscErrorCode BVDestroy_Svec(BV bv)
    419: {
    421:   BV_SVEC        *ctx = (BV_SVEC*)bv->data;

    424:   VecDestroy(&ctx->v);
    425:   VecDestroy(&bv->cv[0]);
    426:   VecDestroy(&bv->cv[1]);
    427:   PetscFree(bv->data);
    428:   bv->cuda = PETSC_FALSE;
    429:   return(0);
    430: }

    432: PETSC_EXTERN PetscErrorCode BVCreate_Svec(BV bv)
    433: {
    434:   PetscErrorCode    ierr;
    435:   BV_SVEC           *ctx;
    436:   PetscInt          nloc,N,bs,tglobal,tlocal,lsplit;
    437:   PetscBool         seq;
    438:   PetscScalar       *aa,*vv;
    439:   const PetscScalar *array,*ptr;
    440:   char              str[50];
    441:   BV                parent;
    442:   Vec               vpar;
    443: #if defined(PETSC_HAVE_VECCUDA)
    444:   PetscScalar       *gpuarray,*gptr;
    445: #endif

    448:   PetscNewLog(bv,&ctx);
    449:   bv->data = (void*)ctx;

    451:   PetscObjectTypeCompareAny((PetscObject)bv->t,&bv->cuda,VECSEQCUDA,VECMPICUDA,"");
    452:   PetscObjectTypeCompareAny((PetscObject)bv->t,&ctx->mpi,VECMPI,VECMPICUDA,"");

    454:   PetscObjectTypeCompare((PetscObject)bv->t,VECSEQ,&seq);
    455:   if (!seq && !ctx->mpi && !bv->cuda) SETERRQ(PetscObjectComm((PetscObject)bv),PETSC_ERR_SUP,"BVSVEC does not support the type of the provided template vector");

    457:   VecGetLocalSize(bv->t,&nloc);
    458:   VecGetSize(bv->t,&N);
    459:   VecGetBlockSize(bv->t,&bs);
    460:   tlocal  = bv->m*nloc;
    461:   tglobal = bv->m*N;
    462:   if (tglobal<0) SETERRQ2(PetscObjectComm((PetscObject)bv),1,"The product %D times %D overflows the size of PetscInt; consider reducing the number of columns, or use BVVECS instead",bv->m,N);

    464:   if (bv->issplit) {
    465:     /* split BV: create Vec sharing the memory of the parent BV */
    466:     parent = bv->splitparent;
    467:     lsplit = parent->lsplit;
    468:     vpar = ((BV_SVEC*)parent->data)->v;
    469:     if (bv->cuda) {
    470: #if defined(PETSC_HAVE_VECCUDA)
    471:       VecCUDAGetArrayReadWrite(vpar,&gpuarray);
    472:       gptr = (bv->issplit==1)? gpuarray: gpuarray+lsplit*nloc;
    473:       VecCUDARestoreArrayReadWrite(vpar,&gpuarray);
    474:       if (ctx->mpi) {
    475:         VecCreateMPICUDAWithArray(PetscObjectComm((PetscObject)bv->t),bs,tlocal,bv->m*N,NULL,&ctx->v);
    476:       } else {
    477:         VecCreateSeqCUDAWithArray(PetscObjectComm((PetscObject)bv->t),bs,tlocal,NULL,&ctx->v);
    478:       }
    479:       VecCUDAPlaceArray(ctx->v,gptr);
    480: #endif
    481:     } else {
    482:       VecGetArrayRead(vpar,&array);
    483:       ptr = (bv->issplit==1)? array: array+lsplit*nloc;
    484:       VecRestoreArrayRead(vpar,&array);
    485:       if (ctx->mpi) {
    486:         VecCreateMPIWithArray(PetscObjectComm((PetscObject)bv->t),bs,tlocal,bv->m*N,NULL,&ctx->v);
    487:       } else {
    488:         VecCreateSeqWithArray(PetscObjectComm((PetscObject)bv->t),bs,tlocal,NULL,&ctx->v);
    489:       }
    490:       VecPlaceArray(ctx->v,ptr);
    491:     }
    492:   } else {
    493:     /* regular BV: create Vec to store the BV entries */
    494:     VecCreate(PetscObjectComm((PetscObject)bv->t),&ctx->v);
    495:     VecSetType(ctx->v,((PetscObject)bv->t)->type_name);
    496:     VecSetSizes(ctx->v,tlocal,tglobal);
    497:     VecSetBlockSize(ctx->v,bs);
    498:   }
    499:   PetscLogObjectParent((PetscObject)bv,(PetscObject)ctx->v);
    500:   if (((PetscObject)bv)->name) {
    501:     PetscSNPrintf(str,50,"%s_0",((PetscObject)bv)->name);
    502:     PetscObjectSetName((PetscObject)ctx->v,str);
    503:   }

    505:   if (bv->Acreate) {
    506:     MatDenseGetArray(bv->Acreate,&aa);
    507:     VecGetArray(ctx->v,&vv);
    508:     PetscMemcpy(vv,aa,tlocal*sizeof(PetscScalar));
    509:     VecRestoreArray(ctx->v,&vv);
    510:     MatDenseRestoreArray(bv->Acreate,&aa);
    511:     MatDestroy(&bv->Acreate);
    512:   }

    514:   VecDuplicateEmpty(bv->t,&bv->cv[0]);
    515:   VecDuplicateEmpty(bv->t,&bv->cv[1]);

    517:   if (bv->cuda) {
    518: #if defined(PETSC_HAVE_VECCUDA)
    519:     bv->ops->mult             = BVMult_Svec_CUDA;
    520:     bv->ops->multvec          = BVMultVec_Svec_CUDA;
    521:     bv->ops->multinplace      = BVMultInPlace_Svec_CUDA;
    522:     bv->ops->multinplacetrans = BVMultInPlaceTranspose_Svec_CUDA;
    523:     bv->ops->dot              = BVDot_Svec_CUDA;
    524:     bv->ops->dotvec           = BVDotVec_Svec_CUDA;
    525:     bv->ops->dotvec_local     = BVDotVec_Local_Svec_CUDA;
    526:     bv->ops->scale            = BVScale_Svec_CUDA;
    527:     bv->ops->matmult          = BVMatMult_Svec_CUDA;
    528:     bv->ops->copy             = BVCopy_Svec_CUDA;
    529:     bv->ops->copycolumn       = BVCopyColumn_Svec_CUDA;
    530:     bv->ops->resize           = BVResize_Svec_CUDA;
    531:     bv->ops->getcolumn        = BVGetColumn_Svec_CUDA;
    532:     bv->ops->restorecolumn    = BVRestoreColumn_Svec_CUDA;
    533:     bv->ops->restoresplit     = BVRestoreSplit_Svec_CUDA;
    534: #endif
    535:   } else {
    536:     bv->ops->mult             = BVMult_Svec;
    537:     bv->ops->multvec          = BVMultVec_Svec;
    538:     bv->ops->multinplace      = BVMultInPlace_Svec;
    539:     bv->ops->multinplacetrans = BVMultInPlaceTranspose_Svec;
    540:     bv->ops->dot              = BVDot_Svec;
    541:     bv->ops->dotvec           = BVDotVec_Svec;
    542:     bv->ops->dotvec_local     = BVDotVec_Local_Svec;
    543:     bv->ops->scale            = BVScale_Svec;
    544:     bv->ops->matmult          = BVMatMult_Svec;
    545:     bv->ops->copy             = BVCopy_Svec;
    546:     bv->ops->copycolumn       = BVCopyColumn_Svec;
    547:     bv->ops->resize           = BVResize_Svec;
    548:     bv->ops->getcolumn        = BVGetColumn_Svec;
    549:     bv->ops->restorecolumn    = BVRestoreColumn_Svec;
    550:   }
    551:   bv->ops->norm             = BVNorm_Svec;
    552:   bv->ops->norm_local       = BVNorm_Local_Svec;
    553:   bv->ops->getarray         = BVGetArray_Svec;
    554:   bv->ops->restorearray     = BVRestoreArray_Svec;
    555:   bv->ops->getarrayread     = BVGetArrayRead_Svec;
    556:   bv->ops->restorearrayread = BVRestoreArrayRead_Svec;
    557:   bv->ops->destroy          = BVDestroy_Svec;
    558:   if (!ctx->mpi) bv->ops->view = BVView_Svec;
    559:   return(0);
    560: }