Date: 2023-11-27T17:19:23+00:00

Actual source code: svec.c
slepc-3.20.1 2023-11-27
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 implemented as a single Vec
     12: */

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

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

     24:   PetscFunctionBegin;
     25:   PetscCall(VecGetArrayRead(x->v,&px));
     26:   PetscCall(VecGetArray(y->v,&py));
     27:   if (Q) {
     28:     PetscCall(MatDenseGetLDA(Q,&ldq));
     29:     PetscCall(MatDenseGetArrayRead(Q,&q));
     30:     PetscCall(BVMult_BLAS_Private(Y,Y->n,Y->k-Y->l,X->k-X->l,alpha,px+(X->nc+X->l)*X->ld,X->ld,q+Y->l*ldq+X->l,ldq,beta,py+(Y->nc+Y->l)*Y->ld,Y->ld));
     31:     PetscCall(MatDenseRestoreArrayRead(Q,&q));
     32:   } else PetscCall(BVAXPY_BLAS_Private(Y,Y->n,Y->k-Y->l,alpha,px+(X->nc+X->l)*X->ld,X->ld,beta,py+(Y->nc+Y->l)*Y->ld,Y->ld));
     33:   PetscCall(VecRestoreArrayRead(x->v,&px));
     34:   PetscCall(VecRestoreArray(y->v,&py));
     35:   PetscFunctionReturn(PETSC_SUCCESS);
     36: }

     38: static PetscErrorCode BVMultVec_Svec(BV X,PetscScalar alpha,PetscScalar beta,Vec y,PetscScalar *q)
     39: {
     40:   BV_SVEC        *x = (BV_SVEC*)X->data;
     41:   PetscScalar    *px,*py,*qq=q;

     43:   PetscFunctionBegin;
     44:   PetscCall(VecGetArray(x->v,&px));
     45:   PetscCall(VecGetArray(y,&py));
     46:   if (!q) PetscCall(VecGetArray(X->buffer,&qq));
     47:   PetscCall(BVMultVec_BLAS_Private(X,X->n,X->k-X->l,alpha,px+(X->nc+X->l)*X->ld,X->ld,qq,beta,py));
     48:   if (!q) PetscCall(VecRestoreArray(X->buffer,&qq));
     49:   PetscCall(VecRestoreArray(x->v,&px));
     50:   PetscCall(VecRestoreArray(y,&py));
     51:   PetscFunctionReturn(PETSC_SUCCESS);
     52: }

     54: static PetscErrorCode BVMultInPlace_Svec(BV V,Mat Q,PetscInt s,PetscInt e)
     55: {
     56:   BV_SVEC           *ctx = (BV_SVEC*)V->data;
     57:   PetscScalar       *pv;
     58:   const PetscScalar *q;
     59:   PetscInt          ldq;

     61:   PetscFunctionBegin;
     62:   if (s>=e || !V->n) PetscFunctionReturn(PETSC_SUCCESS);
     63:   PetscCall(MatDenseGetLDA(Q,&ldq));
     64:   PetscCall(VecGetArray(ctx->v,&pv));
     65:   PetscCall(MatDenseGetArrayRead(Q,&q));
     66:   PetscCall(BVMultInPlace_BLAS_Private(V,V->n,V->k-V->l,s-V->l,e-V->l,pv+(V->nc+V->l)*V->ld,V->ld,q+V->l*ldq+V->l,ldq,PETSC_FALSE));
     67:   PetscCall(MatDenseRestoreArrayRead(Q,&q));
     68:   PetscCall(VecRestoreArray(ctx->v,&pv));
     69:   PetscFunctionReturn(PETSC_SUCCESS);
     70: }

     72: static PetscErrorCode BVMultInPlaceHermitianTranspose_Svec(BV V,Mat Q,PetscInt s,PetscInt e)
     73: {
     74:   BV_SVEC           *ctx = (BV_SVEC*)V->data;
     75:   PetscScalar       *pv;
     76:   const PetscScalar *q;
     77:   PetscInt          ldq;

     79:   PetscFunctionBegin;
     80:   if (s>=e || !V->n) PetscFunctionReturn(PETSC_SUCCESS);
     81:   PetscCall(MatDenseGetLDA(Q,&ldq));
     82:   PetscCall(VecGetArray(ctx->v,&pv));
     83:   PetscCall(MatDenseGetArrayRead(Q,&q));
     84:   PetscCall(BVMultInPlace_BLAS_Private(V,V->n,V->k-V->l,s-V->l,e-V->l,pv+(V->nc+V->l)*V->ld,V->ld,q+V->l*ldq+V->l,ldq,PETSC_TRUE));
     85:   PetscCall(MatDenseRestoreArrayRead(Q,&q));
     86:   PetscCall(VecRestoreArray(ctx->v,&pv));
     87:   PetscFunctionReturn(PETSC_SUCCESS);
     88: }

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

     97:   PetscFunctionBegin;
     98:   PetscCall(MatDenseGetLDA(M,&ldm));
     99:   PetscCall(VecGetArrayRead(x->v,&px));
    100:   PetscCall(VecGetArrayRead(y->v,&py));
    101:   PetscCall(MatDenseGetArray(M,&m));
    102:   PetscCall(BVDot_BLAS_Private(X,Y->k-Y->l,X->k-X->l,X->n,py+(Y->nc+Y->l)*Y->ld,Y->ld,px+(X->nc+X->l)*X->ld,X->ld,m+X->l*ldm+Y->l,ldm,x->mpi));
    103:   PetscCall(MatDenseRestoreArray(M,&m));
    104:   PetscCall(VecRestoreArrayRead(x->v,&px));
    105:   PetscCall(VecRestoreArrayRead(y->v,&py));
    106:   PetscFunctionReturn(PETSC_SUCCESS);
    107: }

    109: static PetscErrorCode BVDotVec_Svec(BV X,Vec y,PetscScalar *q)
    110: {
    111:   BV_SVEC           *x = (BV_SVEC*)X->data;
    112:   const PetscScalar *px,*py;
    113:   PetscScalar       *qq=q;
    114:   Vec               z = y;

    116:   PetscFunctionBegin;
    117:   if (PetscUnlikely(X->matrix)) {
    118:     PetscCall(BV_IPMatMult(X,y));
    119:     z = X->Bx;
    120:   }
    121:   PetscCall(VecGetArrayRead(x->v,&px));
    122:   PetscCall(VecGetArrayRead(z,&py));
    123:   if (!q) PetscCall(VecGetArray(X->buffer,&qq));
    124:   PetscCall(BVDotVec_BLAS_Private(X,X->n,X->k-X->l,px+(X->nc+X->l)*X->ld,X->ld,py,qq,x->mpi));
    125:   if (!q) PetscCall(VecRestoreArray(X->buffer,&qq));
    126:   PetscCall(VecRestoreArrayRead(z,&py));
    127:   PetscCall(VecRestoreArrayRead(x->v,&px));
    128:   PetscFunctionReturn(PETSC_SUCCESS);
    129: }

    131: static PetscErrorCode BVDotVec_Local_Svec(BV X,Vec y,PetscScalar *m)
    132: {
    133:   BV_SVEC        *x = (BV_SVEC*)X->data;
    134:   PetscScalar    *px,*py;
    135:   Vec            z = y;

    137:   PetscFunctionBegin;
    138:   if (PetscUnlikely(X->matrix)) {
    139:     PetscCall(BV_IPMatMult(X,y));
    140:     z = X->Bx;
    141:   }
    142:   PetscCall(VecGetArray(x->v,&px));
    143:   PetscCall(VecGetArray(z,&py));
    144:   PetscCall(BVDotVec_BLAS_Private(X,X->n,X->k-X->l,px+(X->nc+X->l)*X->ld,X->ld,py,m,PETSC_FALSE));
    145:   PetscCall(VecRestoreArray(z,&py));
    146:   PetscCall(VecRestoreArray(x->v,&px));
    147:   PetscFunctionReturn(PETSC_SUCCESS);
    148: }

    150: static PetscErrorCode BVScale_Svec(BV bv,PetscInt j,PetscScalar alpha)
    151: {
    152:   BV_SVEC        *ctx = (BV_SVEC*)bv->data;
    153:   PetscScalar    *array;

    155:   PetscFunctionBegin;
    156:   if (!bv->n) PetscFunctionReturn(PETSC_SUCCESS);
    157:   PetscCall(VecGetArray(ctx->v,&array));
    158:   if (PetscUnlikely(j<0)) PetscCall(BVScale_BLAS_Private(bv,(bv->k-bv->l)*bv->ld,array+(bv->nc+bv->l)*bv->ld,alpha));
    159:   else PetscCall(BVScale_BLAS_Private(bv,bv->n,array+(bv->nc+j)*bv->ld,alpha));
    160:   PetscCall(VecRestoreArray(ctx->v,&array));
    161:   PetscFunctionReturn(PETSC_SUCCESS);
    162: }

    164: static PetscErrorCode BVNorm_Svec(BV bv,PetscInt j,NormType type,PetscReal *val)
    165: {
    166:   BV_SVEC        *ctx = (BV_SVEC*)bv->data;
    167:   PetscScalar    *array;

    169:   PetscFunctionBegin;
    170:   PetscCall(VecGetArray(ctx->v,&array));
    171:   if (PetscUnlikely(j<0)) PetscCall(BVNorm_LAPACK_Private(bv,bv->n,bv->k-bv->l,array+(bv->nc+bv->l)*bv->ld,bv->ld,type,val,ctx->mpi));
    172:   else PetscCall(BVNorm_LAPACK_Private(bv,bv->n,1,array+(bv->nc+j)*bv->ld,bv->ld,type,val,ctx->mpi));
    173:   PetscCall(VecRestoreArray(ctx->v,&array));
    174:   PetscFunctionReturn(PETSC_SUCCESS);
    175: }

    177: static PetscErrorCode BVNorm_Local_Svec(BV bv,PetscInt j,NormType type,PetscReal *val)
    178: {
    179:   BV_SVEC        *ctx = (BV_SVEC*)bv->data;
    180:   PetscScalar    *array;

    182:   PetscFunctionBegin;
    183:   PetscCall(VecGetArray(ctx->v,&array));
    184:   if (PetscUnlikely(j<0)) PetscCall(BVNorm_LAPACK_Private(bv,bv->n,bv->k-bv->l,array+(bv->nc+bv->l)*bv->ld,bv->ld,type,val,PETSC_FALSE));
    185:   else PetscCall(BVNorm_LAPACK_Private(bv,bv->n,1,array+(bv->nc+j)*bv->ld,bv->ld,type,val,PETSC_FALSE));
    186:   PetscCall(VecRestoreArray(ctx->v,&array));
    187:   PetscFunctionReturn(PETSC_SUCCESS);
    188: }

    190: static PetscErrorCode BVNormalize_Svec(BV bv,PetscScalar *eigi)
    191: {
    192:   BV_SVEC        *ctx = (BV_SVEC*)bv->data;
    193:   PetscScalar    *array,*wi=NULL;

    195:   PetscFunctionBegin;
    196:   PetscCall(VecGetArray(ctx->v,&array));
    197:   if (eigi) wi = eigi+bv->l;
    198:   PetscCall(BVNormalize_LAPACK_Private(bv,bv->n,bv->k-bv->l,array+(bv->nc+bv->l)*bv->ld,bv->ld,wi,ctx->mpi));
    199:   PetscCall(VecRestoreArray(ctx->v,&array));
    200:   PetscFunctionReturn(PETSC_SUCCESS);
    201: }

    203: static PetscErrorCode BVMatMult_Svec(BV V,Mat A,BV W)
    204: {
    205:   PetscInt       j;
    206:   Mat            Vmat,Wmat;
    207:   Vec            vv,ww;

    209:   PetscFunctionBegin;
    210:   if (V->vmm) {
    211:     PetscCall(BVGetMat(V,&Vmat));
    212:     PetscCall(BVGetMat(W,&Wmat));
    213:     PetscCall(MatProductCreateWithMat(A,Vmat,NULL,Wmat));
    214:     PetscCall(MatProductSetType(Wmat,MATPRODUCT_AB));
    215:     PetscCall(MatProductSetFromOptions(Wmat));
    216:     PetscCall(MatProductSymbolic(Wmat));
    217:     PetscCall(MatProductNumeric(Wmat));
    218:     PetscCall(MatProductClear(Wmat));
    219:     PetscCall(BVRestoreMat(V,&Vmat));
    220:     PetscCall(BVRestoreMat(W,&Wmat));
    221:   } else {
    222:     for (j=0;j<V->k-V->l;j++) {
    223:       PetscCall(BVGetColumn(V,V->l+j,&vv));
    224:       PetscCall(BVGetColumn(W,W->l+j,&ww));
    225:       PetscCall(MatMult(A,vv,ww));
    226:       PetscCall(BVRestoreColumn(V,V->l+j,&vv));
    227:       PetscCall(BVRestoreColumn(W,W->l+j,&ww));
    228:     }
    229:   }
    230:   PetscFunctionReturn(PETSC_SUCCESS);
    231: }

    233: static PetscErrorCode BVCopy_Svec(BV V,BV W)
    234: {
    235:   BV_SVEC           *v = (BV_SVEC*)V->data,*w = (BV_SVEC*)W->data;
    236:   const PetscScalar *pv;
    237:   PetscScalar       *pw;
    238:   PetscInt          j;

    240:   PetscFunctionBegin;
    241:   PetscCall(VecGetArrayRead(v->v,&pv));
    242:   PetscCall(VecGetArray(w->v,&pw));
    243:   for (j=0;j<V->k-V->l;j++) PetscCall(PetscArraycpy(pw+(W->nc+W->l+j)*W->ld,pv+(V->nc+V->l+j)*V->ld,V->n));
    244:   PetscCall(VecRestoreArrayRead(v->v,&pv));
    245:   PetscCall(VecRestoreArray(w->v,&pw));
    246:   PetscFunctionReturn(PETSC_SUCCESS);
    247: }

    249: static PetscErrorCode BVCopyColumn_Svec(BV V,PetscInt j,PetscInt i)
    250: {
    251:   BV_SVEC        *v = (BV_SVEC*)V->data;
    252:   PetscScalar    *pv;

    254:   PetscFunctionBegin;
    255:   PetscCall(VecGetArray(v->v,&pv));
    256:   PetscCall(PetscArraycpy(pv+(V->nc+i)*V->ld,pv+(V->nc+j)*V->ld,V->n));
    257:   PetscCall(VecRestoreArray(v->v,&pv));
    258:   PetscFunctionReturn(PETSC_SUCCESS);
    259: }

    261: static PetscErrorCode BVResize_Svec(BV bv,PetscInt m,PetscBool copy)
    262: {
    263:   BV_SVEC           *ctx = (BV_SVEC*)bv->data;
    264:   PetscScalar       *pnew;
    265:   const PetscScalar *pv;
    266:   PetscInt          bs;
    267:   Vec               vnew;
    268:   char              str[50];

    270:   PetscFunctionBegin;
    271:   PetscCall(VecGetBlockSize(bv->t,&bs));
    272:   PetscCall(VecCreate(PetscObjectComm((PetscObject)bv->t),&vnew));
    273:   PetscCall(VecSetType(vnew,((PetscObject)bv->t)->type_name));
    274:   PetscCall(VecSetSizes(vnew,m*bv->ld,PETSC_DECIDE));
    275:   PetscCall(VecSetBlockSize(vnew,bs));
    276:   if (((PetscObject)bv)->name) {
    277:     PetscCall(PetscSNPrintf(str,sizeof(str),"%s_0",((PetscObject)bv)->name));
    278:     PetscCall(PetscObjectSetName((PetscObject)vnew,str));
    279:   }
    280:   if (copy) {
    281:     PetscCall(VecGetArrayRead(ctx->v,&pv));
    282:     PetscCall(VecGetArray(vnew,&pnew));
    283:     PetscCall(PetscArraycpy(pnew,pv,PetscMin(m,bv->m)*bv->ld));
    284:     PetscCall(VecRestoreArrayRead(ctx->v,&pv));
    285:     PetscCall(VecRestoreArray(vnew,&pnew));
    286:   }
    287:   PetscCall(VecDestroy(&ctx->v));
    288:   ctx->v = vnew;
    289:   PetscFunctionReturn(PETSC_SUCCESS);
    290: }

    292: static PetscErrorCode BVGetColumn_Svec(BV bv,PetscInt j,Vec *v)
    293: {
    294:   BV_SVEC        *ctx = (BV_SVEC*)bv->data;
    295:   PetscScalar    *pv;
    296:   PetscInt       l;

    298:   PetscFunctionBegin;
    299:   l = BVAvailableVec;
    300:   PetscCall(VecGetArray(ctx->v,&pv));
    301:   PetscCall(VecPlaceArray(bv->cv[l],pv+(bv->nc+j)*bv->ld));
    302:   PetscFunctionReturn(PETSC_SUCCESS);
    303: }

    305: static PetscErrorCode BVRestoreColumn_Svec(BV bv,PetscInt j,Vec *v)
    306: {
    307:   BV_SVEC        *ctx = (BV_SVEC*)bv->data;
    308:   PetscInt       l;

    310:   PetscFunctionBegin;
    311:   l = (j==bv->ci[0])? 0: 1;
    312:   PetscCall(VecResetArray(bv->cv[l]));
    313:   PetscCall(VecRestoreArray(ctx->v,NULL));
    314:   PetscFunctionReturn(PETSC_SUCCESS);
    315: }

    317: static PetscErrorCode BVGetArray_Svec(BV bv,PetscScalar **a)
    318: {
    319:   BV_SVEC        *ctx = (BV_SVEC*)bv->data;

    321:   PetscFunctionBegin;
    322:   PetscCall(VecGetArray(ctx->v,a));
    323:   PetscFunctionReturn(PETSC_SUCCESS);
    324: }

    326: static PetscErrorCode BVRestoreArray_Svec(BV bv,PetscScalar **a)
    327: {
    328:   BV_SVEC        *ctx = (BV_SVEC*)bv->data;

    330:   PetscFunctionBegin;
    331:   PetscCall(VecRestoreArray(ctx->v,a));
    332:   PetscFunctionReturn(PETSC_SUCCESS);
    333: }

    335: static PetscErrorCode BVGetArrayRead_Svec(BV bv,const PetscScalar **a)
    336: {
    337:   BV_SVEC        *ctx = (BV_SVEC*)bv->data;

    339:   PetscFunctionBegin;
    340:   PetscCall(VecGetArrayRead(ctx->v,a));
    341:   PetscFunctionReturn(PETSC_SUCCESS);
    342: }

    344: static PetscErrorCode BVRestoreArrayRead_Svec(BV bv,const PetscScalar **a)
    345: {
    346:   BV_SVEC        *ctx = (BV_SVEC*)bv->data;

    348:   PetscFunctionBegin;
    349:   PetscCall(VecRestoreArrayRead(ctx->v,a));
    350:   PetscFunctionReturn(PETSC_SUCCESS);
    351: }

    353: static PetscErrorCode BVView_Svec(BV bv,PetscViewer viewer)
    354: {
    355:   PetscInt          j;
    356:   Vec               v;
    357:   PetscViewerFormat format;
    358:   PetscBool         isascii,ismatlab=PETSC_FALSE;
    359:   const char        *bvname,*name;

    361:   PetscFunctionBegin;
    362:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii));
    363:   if (isascii) {
    364:     PetscCall(PetscViewerGetFormat(viewer,&format));
    365:     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscFunctionReturn(PETSC_SUCCESS);
    366:     if (format == PETSC_VIEWER_ASCII_MATLAB) ismatlab = PETSC_TRUE;
    367:   }
    368:   if (ismatlab) {
    369:     PetscCall(PetscObjectGetName((PetscObject)bv,&bvname));
    370:     PetscCall(PetscViewerASCIIPrintf(viewer,"%s=[];\n",bvname));
    371:   }
    372:   for (j=0;j<bv->m;j++) {
    373:     PetscCall(BVGetColumn(bv,j,&v));
    374:     PetscCall(VecView(v,viewer));
    375:     if (ismatlab) {
    376:       PetscCall(PetscObjectGetName((PetscObject)v,&name));
    377:       PetscCall(PetscViewerASCIIPrintf(viewer,"%s=[%s,%s];clear %s\n",bvname,bvname,name,name));
    378:     }
    379:     PetscCall(BVRestoreColumn(bv,j,&v));
    380:   }
    381:   PetscFunctionReturn(PETSC_SUCCESS);
    382: }

    384: static PetscErrorCode BVDestroy_Svec(BV bv)
    385: {
    386:   BV_SVEC        *ctx = (BV_SVEC*)bv->data;

    388:   PetscFunctionBegin;
    389:   PetscCall(VecDestroy(&ctx->v));
    390:   PetscCall(VecDestroy(&bv->cv[0]));
    391:   PetscCall(VecDestroy(&bv->cv[1]));
    392:   PetscCall(PetscFree(bv->data));
    393:   bv->cuda = PETSC_FALSE;
    394:   PetscFunctionReturn(PETSC_SUCCESS);
    395: }

    397: SLEPC_EXTERN PetscErrorCode BVCreate_Svec(BV bv)
    398: {
    399:   BV_SVEC           *ctx;
    400:   PetscInt          nloc,N,bs,tglobal=0,tlocal,lsplit,j,lda;
    401:   PetscBool         seq,isdense;
    402:   PetscScalar       *vv;
    403:   const PetscScalar *aa,*array,*ptr;
    404:   char              str[50];
    405:   BV                parent;
    406:   Vec               vpar;
    407:   MatType           mtype;

    409:   PetscFunctionBegin;
    410:   PetscCall(PetscNew(&ctx));
    411:   bv->data = (void*)ctx;

    413:   PetscCall(PetscObjectTypeCompareAny((PetscObject)bv->t,&bv->cuda,VECSEQCUDA,VECMPICUDA,""));
    414:   PetscCall(PetscObjectTypeCompareAny((PetscObject)bv->t,&ctx->mpi,VECMPI,VECMPICUDA,""));

    416:   PetscCall(PetscObjectTypeCompare((PetscObject)bv->t,VECSEQ,&seq));
    417:   PetscCheck(seq || ctx->mpi || bv->cuda,PetscObjectComm((PetscObject)bv),PETSC_ERR_SUP,"BVSVEC does not support the type of the provided template vector");

    419:   PetscCall(VecGetLocalSize(bv->t,&nloc));
    420:   PetscCall(VecGetSize(bv->t,&N));
    421:   PetscCall(VecGetBlockSize(bv->t,&bs));
    422:   PetscCall(BV_SetDefaultLD(bv,nloc));
    423:   tlocal = bv->m*bv->ld;
    424:   PetscCall(PetscIntMultError(bv->m,N,&tglobal));  /* just to check integer overflow */

    426:   if (PetscUnlikely(bv->issplit)) {
    427:     /* split BV: create Vec sharing the memory of the parent BV */
    428:     parent = bv->splitparent;
    429:     lsplit = parent->lsplit;
    430:     vpar = ((BV_SVEC*)parent->data)->v;
    431:     if (bv->cuda) {
    432: #if defined(PETSC_HAVE_CUDA)
    433:       PetscCall(VecCUDAGetArrayRead(vpar,&array));
    434:       ptr = (bv->issplit==1)? array: array+lsplit*bv->ld;
    435:       PetscCall(VecCUDARestoreArrayRead(vpar,&array));
    436:       if (ctx->mpi) PetscCall(VecCreateMPICUDAWithArray(PetscObjectComm((PetscObject)bv->t),bs,tlocal,PETSC_DECIDE,NULL,&ctx->v));
    437:       else PetscCall(VecCreateSeqCUDAWithArray(PetscObjectComm((PetscObject)bv->t),bs,tlocal,NULL,&ctx->v));
    438:       PetscCall(VecCUDAPlaceArray(ctx->v,ptr));
    439: #endif
    440:     } else {
    441:       PetscCall(VecGetArrayRead(vpar,&array));
    442:       ptr = (bv->issplit==1)? array: array+lsplit*bv->ld;
    443:       PetscCall(VecRestoreArrayRead(vpar,&array));
    444:       if (ctx->mpi) PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)bv->t),bs,tlocal,PETSC_DECIDE,NULL,&ctx->v));
    445:       else PetscCall(VecCreateSeqWithArray(PetscObjectComm((PetscObject)bv->t),bs,tlocal,NULL,&ctx->v));
    446:       PetscCall(VecPlaceArray(ctx->v,ptr));
    447:     }
    448:   } else {
    449:     /* regular BV: create Vec to store the BV entries */
    450:     PetscCall(VecCreate(PetscObjectComm((PetscObject)bv->t),&ctx->v));
    451:     PetscCall(VecSetType(ctx->v,((PetscObject)bv->t)->type_name));
    452:     PetscCall(VecSetSizes(ctx->v,tlocal,PETSC_DECIDE));
    453:     PetscCall(VecSetBlockSize(ctx->v,bs));
    454:   }
    455:   if (((PetscObject)bv)->name) {
    456:     PetscCall(PetscSNPrintf(str,sizeof(str),"%s_0",((PetscObject)bv)->name));
    457:     PetscCall(PetscObjectSetName((PetscObject)ctx->v,str));
    458:   }

    460:   if (PetscUnlikely(bv->Acreate)) {
    461:     PetscCall(MatGetType(bv->Acreate,&mtype));
    462:     PetscCall(PetscStrcmpAny(mtype,&isdense,MATSEQDENSE,MATMPIDENSE,""));
    463:     PetscCheck(isdense,PetscObjectComm((PetscObject)bv->Acreate),PETSC_ERR_SUP,"BVSVEC requires a dense matrix in BVCreateFromMat()\n");
    464:     PetscCall(MatDenseGetArrayRead(bv->Acreate,&aa));
    465:     PetscCall(MatDenseGetLDA(bv->Acreate,&lda));
    466:     PetscCall(VecGetArray(ctx->v,&vv));
    467:     for (j=0;j<bv->m;j++) PetscCall(PetscArraycpy(vv+j*bv->ld,aa+j*lda,bv->n));
    468:     PetscCall(VecRestoreArray(ctx->v,&vv));
    469:     PetscCall(MatDenseRestoreArrayRead(bv->Acreate,&aa));
    470:     PetscCall(MatDestroy(&bv->Acreate));
    471:   }

    473:   PetscCall(VecDuplicateEmpty(bv->t,&bv->cv[0]));
    474:   PetscCall(VecDuplicateEmpty(bv->t,&bv->cv[1]));

    476:   if (bv->cuda) {
    477: #if defined(PETSC_HAVE_CUDA)
    478:     bv->ops->mult             = BVMult_Svec_CUDA;
    479:     bv->ops->multvec          = BVMultVec_Svec_CUDA;
    480:     bv->ops->multinplace      = BVMultInPlace_Svec_CUDA;
    481:     bv->ops->multinplacetrans = BVMultInPlaceHermitianTranspose_Svec_CUDA;
    482:     bv->ops->dot              = BVDot_Svec_CUDA;
    483:     bv->ops->dotvec           = BVDotVec_Svec_CUDA;
    484:     bv->ops->dotvec_local     = BVDotVec_Local_Svec_CUDA;
    485:     bv->ops->scale            = BVScale_Svec_CUDA;
    486:     bv->ops->matmult          = BVMatMult_Svec_CUDA;
    487:     bv->ops->copy             = BVCopy_Svec_CUDA;
    488:     bv->ops->copycolumn       = BVCopyColumn_Svec_CUDA;
    489:     bv->ops->resize           = BVResize_Svec_CUDA;
    490:     bv->ops->getcolumn        = BVGetColumn_Svec_CUDA;
    491:     bv->ops->restorecolumn    = BVRestoreColumn_Svec_CUDA;
    492:     bv->ops->restoresplit     = BVRestoreSplit_Svec_CUDA;
    493:     bv->ops->getmat           = BVGetMat_Svec_CUDA;
    494:     bv->ops->restoremat       = BVRestoreMat_Svec_CUDA;
    495: #endif
    496:   } else {
    497:     bv->ops->mult             = BVMult_Svec;
    498:     bv->ops->multvec          = BVMultVec_Svec;
    499:     bv->ops->multinplace      = BVMultInPlace_Svec;
    500:     bv->ops->multinplacetrans = BVMultInPlaceHermitianTranspose_Svec;
    501:     bv->ops->dot              = BVDot_Svec;
    502:     bv->ops->dotvec           = BVDotVec_Svec;
    503:     bv->ops->dotvec_local     = BVDotVec_Local_Svec;
    504:     bv->ops->scale            = BVScale_Svec;
    505:     bv->ops->matmult          = BVMatMult_Svec;
    506:     bv->ops->copy             = BVCopy_Svec;
    507:     bv->ops->copycolumn       = BVCopyColumn_Svec;
    508:     bv->ops->resize           = BVResize_Svec;
    509:     bv->ops->getcolumn        = BVGetColumn_Svec;
    510:     bv->ops->restorecolumn    = BVRestoreColumn_Svec;
    511:     bv->ops->getmat           = BVGetMat_Default;
    512:     bv->ops->restoremat       = BVRestoreMat_Default;
    513:   }
    514:   bv->ops->norm             = BVNorm_Svec;
    515:   bv->ops->norm_local       = BVNorm_Local_Svec;
    516:   bv->ops->normalize        = BVNormalize_Svec;
    517:   bv->ops->getarray         = BVGetArray_Svec;
    518:   bv->ops->restorearray     = BVRestoreArray_Svec;
    519:   bv->ops->getarrayread     = BVGetArrayRead_Svec;
    520:   bv->ops->restorearrayread = BVRestoreArrayRead_Svec;
    521:   bv->ops->destroy          = BVDestroy_Svec;
    522:   if (!ctx->mpi) bv->ops->view = BVView_Svec;
    523:   PetscFunctionReturn(PETSC_SUCCESS);
    524: }