Actual source code: bvmat.c

      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 with a dense Mat
     12: */

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

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

     24:   PetscFunctionBegin;
     25:   PetscCall(MatDenseGetArrayRead(x->A,&px));
     26:   PetscCall(MatDenseGetArray(y->A,&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(MatDenseRestoreArrayRead(x->A,&px));
     34:   PetscCall(MatDenseRestoreArray(y->A,&py));
     35:   PetscFunctionReturn(PETSC_SUCCESS);
     36: }

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

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

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

     62:   PetscFunctionBegin;
     63:   if (s>=e || !V->n) PetscFunctionReturn(PETSC_SUCCESS);
     64:   PetscCall(MatDenseGetLDA(Q,&ldq));
     65:   PetscCall(MatDenseGetArray(ctx->A,&pv));
     66:   PetscCall(MatDenseGetArrayRead(Q,&q));
     67:   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));
     68:   PetscCall(MatDenseRestoreArrayRead(Q,&q));
     69:   PetscCall(MatDenseRestoreArray(ctx->A,&pv));
     70:   PetscFunctionReturn(PETSC_SUCCESS);
     71: }

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

     80:   PetscFunctionBegin;
     81:   if (s>=e || !V->n) PetscFunctionReturn(PETSC_SUCCESS);
     82:   PetscCall(MatDenseGetLDA(Q,&ldq));
     83:   PetscCall(MatDenseGetArray(ctx->A,&pv));
     84:   PetscCall(MatDenseGetArrayRead(Q,&q));
     85:   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));
     86:   PetscCall(MatDenseRestoreArrayRead(Q,&q));
     87:   PetscCall(MatDenseRestoreArray(ctx->A,&pv));
     88:   PetscFunctionReturn(PETSC_SUCCESS);
     89: }

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

     98:   PetscFunctionBegin;
     99:   PetscCall(MatDenseGetLDA(M,&ldm));
    100:   PetscCall(MatDenseGetArrayRead(x->A,&px));
    101:   PetscCall(MatDenseGetArrayRead(y->A,&py));
    102:   PetscCall(MatDenseGetArray(M,&m));
    103:   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));
    104:   PetscCall(MatDenseRestoreArray(M,&m));
    105:   PetscCall(MatDenseRestoreArrayRead(x->A,&px));
    106:   PetscCall(MatDenseRestoreArrayRead(y->A,&py));
    107:   PetscFunctionReturn(PETSC_SUCCESS);
    108: }

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

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

    132: static PetscErrorCode BVDotVec_Local_Mat(BV X,Vec y,PetscScalar *m)
    133: {
    134:   BV_MAT            *x = (BV_MAT*)X->data;
    135:   const PetscScalar *px,*py;
    136:   Vec               z = y;

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

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

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

    165: static PetscErrorCode BVNorm_Mat(BV bv,PetscInt j,NormType type,PetscReal *val)
    166: {
    167:   BV_MAT            *ctx = (BV_MAT*)bv->data;
    168:   const PetscScalar *array;

    170:   PetscFunctionBegin;
    171:   PetscCall(MatDenseGetArrayRead(ctx->A,&array));
    172:   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));
    173:   else PetscCall(BVNorm_LAPACK_Private(bv,bv->n,1,array+(bv->nc+j)*bv->ld,bv->ld,type,val,ctx->mpi));
    174:   PetscCall(MatDenseRestoreArrayRead(ctx->A,&array));
    175:   PetscFunctionReturn(PETSC_SUCCESS);
    176: }

    178: static PetscErrorCode BVNorm_Local_Mat(BV bv,PetscInt j,NormType type,PetscReal *val)
    179: {
    180:   BV_MAT            *ctx = (BV_MAT*)bv->data;
    181:   const PetscScalar *array;

    183:   PetscFunctionBegin;
    184:   PetscCall(MatDenseGetArrayRead(ctx->A,&array));
    185:   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));
    186:   else PetscCall(BVNorm_LAPACK_Private(bv,bv->n,1,array+(bv->nc+j)*bv->ld,bv->ld,type,val,PETSC_FALSE));
    187:   PetscCall(MatDenseRestoreArrayRead(ctx->A,&array));
    188:   PetscFunctionReturn(PETSC_SUCCESS);
    189: }

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

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

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

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

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

    241:   PetscFunctionBegin;
    242:   PetscCall(MatDenseGetArrayRead(v->A,&pv));
    243:   PetscCall(MatDenseGetArray(w->A,&pw));
    244:   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));
    245:   PetscCall(MatDenseRestoreArrayRead(v->A,&pv));
    246:   PetscCall(MatDenseRestoreArray(w->A,&pw));
    247:   PetscFunctionReturn(PETSC_SUCCESS);
    248: }

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

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

    262: static PetscErrorCode BVResize_Mat(BV bv,PetscInt m,PetscBool copy)
    263: {
    264:   BV_MAT            *ctx = (BV_MAT*)bv->data;
    265:   Mat               A,Msrc,Mdst;
    266:   char              str[50];

    268:   PetscFunctionBegin;
    269:   PetscCall(MatCreateDenseFromVecType(PetscObjectComm((PetscObject)bv),bv->vtype,bv->n,PETSC_DECIDE,bv->N,m,bv->ld,NULL,&A));
    270:   if (((PetscObject)bv)->name) {
    271:     PetscCall(PetscSNPrintf(str,sizeof(str),"%s_0",((PetscObject)bv)->name));
    272:     PetscCall(PetscObjectSetName((PetscObject)A,str));
    273:   }
    274:   if (copy) {
    275:     PetscCall(MatDenseGetSubMatrix(ctx->A,PETSC_DECIDE,PETSC_DECIDE,PETSC_DECIDE,PetscMin(m,bv->m),&Msrc));
    276:     PetscCall(MatDenseGetSubMatrix(A,PETSC_DECIDE,PETSC_DECIDE,PETSC_DECIDE,PetscMin(m,bv->m),&Mdst));
    277:     PetscCall(MatCopy(Msrc,Mdst,SAME_NONZERO_PATTERN));
    278:     PetscCall(MatDenseRestoreSubMatrix(ctx->A,&Msrc));
    279:     PetscCall(MatDenseRestoreSubMatrix(A,&Mdst));
    280:   }
    281:   PetscCall(MatDestroy(&ctx->A));
    282:   ctx->A = A;
    283:   PetscFunctionReturn(PETSC_SUCCESS);
    284: }

    286: static PetscErrorCode BVGetColumn_Mat(BV bv,PetscInt j,Vec *v)
    287: {
    288:   BV_MAT         *ctx = (BV_MAT*)bv->data;
    289:   PetscScalar    *pA;
    290:   PetscInt       l;

    292:   PetscFunctionBegin;
    293:   l = BVAvailableVec;
    294:   PetscCall(MatDenseGetArray(ctx->A,&pA));
    295:   PetscCall(VecPlaceArray(bv->cv[l],pA+(bv->nc+j)*bv->ld));
    296:   PetscFunctionReturn(PETSC_SUCCESS);
    297: }

    299: static PetscErrorCode BVRestoreColumn_Mat(BV bv,PetscInt j,Vec *v)
    300: {
    301:   BV_MAT         *ctx = (BV_MAT*)bv->data;
    302:   PetscScalar    *pA;
    303:   PetscInt       l;

    305:   PetscFunctionBegin;
    306:   l = (j==bv->ci[0])? 0: 1;
    307:   PetscCall(VecResetArray(bv->cv[l]));
    308:   PetscCall(MatDenseRestoreArray(ctx->A,&pA));
    309:   PetscFunctionReturn(PETSC_SUCCESS);
    310: }

    312: static PetscErrorCode BVGetArray_Mat(BV bv,PetscScalar **a)
    313: {
    314:   BV_MAT         *ctx = (BV_MAT*)bv->data;

    316:   PetscFunctionBegin;
    317:   PetscCall(MatDenseGetArray(ctx->A,a));
    318:   PetscFunctionReturn(PETSC_SUCCESS);
    319: }

    321: static PetscErrorCode BVRestoreArray_Mat(BV bv,PetscScalar **a)
    322: {
    323:   BV_MAT         *ctx = (BV_MAT*)bv->data;

    325:   PetscFunctionBegin;
    326:   if (a) PetscCall(MatDenseRestoreArray(ctx->A,a));
    327:   PetscFunctionReturn(PETSC_SUCCESS);
    328: }

    330: static PetscErrorCode BVGetArrayRead_Mat(BV bv,const PetscScalar **a)
    331: {
    332:   BV_MAT         *ctx = (BV_MAT*)bv->data;

    334:   PetscFunctionBegin;
    335:   PetscCall(MatDenseGetArrayRead(ctx->A,a));
    336:   PetscFunctionReturn(PETSC_SUCCESS);
    337: }

    339: static PetscErrorCode BVRestoreArrayRead_Mat(BV bv,const PetscScalar **a)
    340: {
    341:   BV_MAT         *ctx = (BV_MAT*)bv->data;

    343:   PetscFunctionBegin;
    344:   if (a) PetscCall(MatDenseRestoreArrayRead(ctx->A,a));
    345:   PetscFunctionReturn(PETSC_SUCCESS);
    346: }

    348: static PetscErrorCode BVView_Mat(BV bv,PetscViewer viewer)
    349: {
    350:   Mat               A;
    351:   PetscViewerFormat format;
    352:   PetscBool         isascii;
    353:   const char        *bvname,*name;

    355:   PetscFunctionBegin;
    356:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii));
    357:   if (isascii) {
    358:     PetscCall(PetscViewerGetFormat(viewer,&format));
    359:     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscFunctionReturn(PETSC_SUCCESS);
    360:   }
    361:   PetscCall(BVGetMat(bv,&A));
    362:   PetscCall(MatView(A,viewer));
    363:   if (format == PETSC_VIEWER_ASCII_MATLAB) {
    364:     PetscCall(PetscObjectGetName((PetscObject)A,&name));
    365:     PetscCall(PetscObjectGetName((PetscObject)bv,&bvname));
    366:     PetscCall(PetscViewerASCIIPrintf(viewer,"%s=%s;clear %s\n",bvname,name,name));
    367:     if (bv->nc) PetscCall(PetscViewerASCIIPrintf(viewer,"%s=%s(:,%" PetscInt_FMT ":end);\n",bvname,bvname,bv->nc+1));
    368:   }
    369:   PetscCall(BVRestoreMat(bv,&A));
    370:   PetscFunctionReturn(PETSC_SUCCESS);
    371: }

    373: static PetscErrorCode BVDestroy_Mat(BV bv)
    374: {
    375:   BV_MAT         *ctx = (BV_MAT*)bv->data;

    377:   PetscFunctionBegin;
    378:   PetscCall(MatDestroy(&ctx->A));
    379:   PetscCall(VecDestroy(&bv->cv[0]));
    380:   PetscCall(VecDestroy(&bv->cv[1]));
    381:   PetscCall(PetscFree(bv->data));
    382:   PetscFunctionReturn(PETSC_SUCCESS);
    383: }

    385: /*MC
    386:    BVMAT - BVMAT = "mat" - A basis vectors object represented by a dense `Mat`.

    388:    Level: beginner

    390: .seealso: [](sec:bv), `BV`, `BVType`, `BVSetType()`
    391: M*/

    393: SLEPC_EXTERN PetscErrorCode BVCreate_Mat(BV bv)
    394: {
    395:   BV_MAT         *ctx;
    396:   PetscInt       nloc,lsplit;
    397:   PetscBool      seq;
    398:   char           str[50];
    399:   PetscScalar    *array,*ptr=NULL;
    400:   BV             parent;
    401:   Mat            Apar;

    403:   PetscFunctionBegin;
    404:   PetscCall(PetscNew(&ctx));
    405:   bv->data = (void*)ctx;

    407:   PetscCall(PetscStrcmpAny(bv->vtype,&bv->cuda,VECSEQCUDA,VECMPICUDA,""));
    408:   PetscCall(PetscStrcmpAny(bv->vtype,&bv->hip,VECSEQHIP,VECMPIHIP,""));
    409:   PetscCall(PetscStrcmpAny(bv->vtype,&ctx->mpi,VECMPI,VECMPICUDA,VECMPIHIP,""));

    411:   PetscCall(PetscStrcmp(bv->vtype,VECSEQ,&seq));
    412:   PetscCheck(seq || ctx->mpi || bv->cuda || bv->hip,PetscObjectComm((PetscObject)bv),PETSC_ERR_SUP,"BVMAT does not support the requested vector type: %s",bv->vtype);

    414:   PetscCall(PetscLayoutGetLocalSize(bv->map,&nloc));
    415:   PetscCall(BV_SetDefaultLD(bv,nloc));

    417:   if (PetscUnlikely(bv->issplit)) {
    418:     /* split BV: share the memory of the parent BV */
    419:     parent = bv->splitparent;
    420:     lsplit = parent->lsplit;
    421:     Apar = ((BV_MAT*)parent->data)->A;
    422:     if (bv->cuda) {
    423: #if defined(PETSC_HAVE_CUDA)
    424:       PetscCall(MatDenseCUDAGetArray(Apar,&array));
    425:       if (bv->issplit>0) ptr = (bv->issplit==1)? array: array+lsplit*bv->ld;
    426:       else ptr = (bv->issplit==1)? array: array-lsplit;
    427:       PetscCall(MatDenseCUDARestoreArray(Apar,&array));
    428: #endif
    429:     } else if (bv->hip) {
    430: #if defined(PETSC_HAVE_HIP)
    431:       PetscCall(MatDenseHIPGetArray(Apar,&array));
    432:       if (bv->issplit>0) ptr = (bv->issplit==1)? array: array+lsplit*bv->ld;
    433:       else ptr = (bv->issplit==1)? array: array-lsplit;
    434:       PetscCall(MatDenseHIPRestoreArray(Apar,&array));
    435: #endif
    436:     } else {
    437:       PetscCall(MatDenseGetArray(Apar,&array));
    438:       if (bv->issplit>0) ptr = (bv->issplit==1)? array: array+lsplit*bv->ld;
    439:       else ptr = (bv->issplit==-1)? array: array-lsplit;
    440:       PetscCall(MatDenseRestoreArray(Apar,&array));
    441:     }
    442:   }

    444:   PetscCall(MatCreateDenseFromVecType(PetscObjectComm((PetscObject)bv),bv->vtype,nloc,PETSC_DECIDE,bv->N,bv->m,bv->ld,ptr,&ctx->A));
    445:   if (((PetscObject)bv)->name) {
    446:     PetscCall(PetscSNPrintf(str,sizeof(str),"%s_0",((PetscObject)bv)->name));
    447:     PetscCall(PetscObjectSetName((PetscObject)ctx->A,str));
    448:   }

    450:   if (PetscUnlikely(bv->Acreate)) {
    451:     PetscCall(MatConvert(bv->Acreate,bv->cuda?MATDENSECUDA:bv->hip?MATDENSEHIP:MATDENSE,MAT_REUSE_MATRIX,&ctx->A));
    452:     PetscCall(MatDestroy(&bv->Acreate));
    453:   }

    455:   PetscCall(BVCreateVecEmpty(bv,&bv->cv[0]));
    456:   PetscCall(BVCreateVecEmpty(bv,&bv->cv[1]));

    458:   if (bv->cuda) {
    459: #if defined(PETSC_HAVE_CUDA)
    460:     bv->ops->mult             = BVMult_Mat_CUDA;
    461:     bv->ops->multvec          = BVMultVec_Mat_CUDA;
    462:     bv->ops->multinplace      = BVMultInPlace_Mat_CUDA;
    463:     bv->ops->multinplacetrans = BVMultInPlaceHermitianTranspose_Mat_CUDA;
    464:     bv->ops->dot              = BVDot_Mat_CUDA;
    465:     bv->ops->dotvec           = BVDotVec_Mat_CUDA;
    466:     bv->ops->dotvec_local     = BVDotVec_Local_Mat_CUDA;
    467:     bv->ops->scale            = BVScale_Mat_CUDA;
    468:     bv->ops->norm             = BVNorm_Mat_CUDA;
    469:     bv->ops->norm_local       = BVNorm_Local_Mat_CUDA;
    470:     bv->ops->normalize        = BVNormalize_Mat_CUDA;
    471:     bv->ops->matmult          = BVMatMult_Mat_CUDA;
    472:     bv->ops->copy             = BVCopy_Mat_CUDA;
    473:     bv->ops->copycolumn       = BVCopyColumn_Mat_CUDA;
    474:     bv->ops->getcolumn        = BVGetColumn_Mat_CUDA;
    475:     bv->ops->restorecolumn    = BVRestoreColumn_Mat_CUDA;
    476:     bv->ops->restoresplit     = BVRestoreSplit_Mat_CUDA;
    477:     bv->ops->restoresplitrows = BVRestoreSplitRows_Mat_CUDA;
    478:     bv->ops->getmat           = BVGetMat_Mat_CUDA;
    479:     bv->ops->restoremat       = BVRestoreMat_Mat_CUDA;
    480: #endif
    481:   } else if (bv->hip) {
    482: #if defined(PETSC_HAVE_HIP)
    483:     bv->ops->mult             = BVMult_Mat_HIP;
    484:     bv->ops->multvec          = BVMultVec_Mat_HIP;
    485:     bv->ops->multinplace      = BVMultInPlace_Mat_HIP;
    486:     bv->ops->multinplacetrans = BVMultInPlaceHermitianTranspose_Mat_HIP;
    487:     bv->ops->dot              = BVDot_Mat_HIP;
    488:     bv->ops->dotvec           = BVDotVec_Mat_HIP;
    489:     bv->ops->dotvec_local     = BVDotVec_Local_Mat_HIP;
    490:     bv->ops->scale            = BVScale_Mat_HIP;
    491:     bv->ops->norm             = BVNorm_Mat_HIP;
    492:     bv->ops->norm_local       = BVNorm_Local_Mat_HIP;
    493:     bv->ops->normalize        = BVNormalize_Mat_HIP;
    494:     bv->ops->matmult          = BVMatMult_Mat_HIP;
    495:     bv->ops->copy             = BVCopy_Mat_HIP;
    496:     bv->ops->copycolumn       = BVCopyColumn_Mat_HIP;
    497:     bv->ops->getcolumn        = BVGetColumn_Mat_HIP;
    498:     bv->ops->restorecolumn    = BVRestoreColumn_Mat_HIP;
    499:     bv->ops->restoresplit     = BVRestoreSplit_Mat_HIP;
    500:     bv->ops->restoresplitrows = BVRestoreSplitRows_Mat_HIP;
    501:     bv->ops->getmat           = BVGetMat_Mat_HIP;
    502:     bv->ops->restoremat       = BVRestoreMat_Mat_HIP;
    503: #endif
    504:   } else {
    505:     bv->ops->mult             = BVMult_Mat;
    506:     bv->ops->multvec          = BVMultVec_Mat;
    507:     bv->ops->multinplace      = BVMultInPlace_Mat;
    508:     bv->ops->multinplacetrans = BVMultInPlaceHermitianTranspose_Mat;
    509:     bv->ops->dot              = BVDot_Mat;
    510:     bv->ops->dotvec           = BVDotVec_Mat;
    511:     bv->ops->dotvec_local     = BVDotVec_Local_Mat;
    512:     bv->ops->scale            = BVScale_Mat;
    513:     bv->ops->norm             = BVNorm_Mat;
    514:     bv->ops->norm_local       = BVNorm_Local_Mat;
    515:     bv->ops->normalize        = BVNormalize_Mat;
    516:     bv->ops->matmult          = BVMatMult_Mat;
    517:     bv->ops->copy             = BVCopy_Mat;
    518:     bv->ops->copycolumn       = BVCopyColumn_Mat;
    519:     bv->ops->getcolumn        = BVGetColumn_Mat;
    520:     bv->ops->restorecolumn    = BVRestoreColumn_Mat;
    521:     bv->ops->getmat           = BVGetMat_Default;
    522:     bv->ops->restoremat       = BVRestoreMat_Default;
    523:   }
    524:   bv->ops->resize           = BVResize_Mat;
    525:   bv->ops->getarray         = BVGetArray_Mat;
    526:   bv->ops->restorearray     = BVRestoreArray_Mat;
    527:   bv->ops->getarrayread     = BVGetArrayRead_Mat;
    528:   bv->ops->restorearrayread = BVRestoreArrayRead_Mat;
    529:   bv->ops->destroy          = BVDestroy_Mat;
    530:   bv->ops->view             = BVView_Mat;
    531:   PetscFunctionReturn(PETSC_SUCCESS);
    532: }