Actual source code: contig.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 an array of Vecs sharing a contiguous array for elements
     12: */

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

     16: typedef struct {
     17:   Vec         *V;
     18:   PetscScalar *array;
     19:   PetscBool   mpi;
     20: } BV_CONTIGUOUS;

     22: PetscErrorCode BVMult_Contiguous(BV Y,PetscScalar alpha,PetscScalar beta,BV X,Mat Q)
     23: {
     25:   BV_CONTIGUOUS  *y = (BV_CONTIGUOUS*)Y->data,*x = (BV_CONTIGUOUS*)X->data;
     26:   PetscScalar    *q;
     27:   PetscInt       ldq;

     30:   if (Q) {
     31:     MatGetSize(Q,&ldq,NULL);
     32:     MatDenseGetArray(Q,&q);
     33:     BVMult_BLAS_Private(Y,Y->n,Y->k-Y->l,X->k-X->l,ldq,alpha,x->array+(X->nc+X->l)*X->n,q+Y->l*ldq+X->l,beta,y->array+(Y->nc+Y->l)*Y->n);
     34:     MatDenseRestoreArray(Q,&q);
     35:   } else {
     36:     BVAXPY_BLAS_Private(Y,Y->n,Y->k-Y->l,alpha,x->array+(X->nc+X->l)*X->n,beta,y->array+(Y->nc+Y->l)*Y->n);
     37:   }
     38:   return(0);
     39: }

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

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

     56: PetscErrorCode BVMultInPlace_Contiguous(BV V,Mat Q,PetscInt s,PetscInt e)
     57: {
     59:   BV_CONTIGUOUS  *ctx = (BV_CONTIGUOUS*)V->data;
     60:   PetscScalar    *q;
     61:   PetscInt       ldq;

     64:   MatGetSize(Q,&ldq,NULL);
     65:   MatDenseGetArray(Q,&q);
     66:   BVMultInPlace_BLAS_Private(V,V->n,V->k-V->l,ldq,s-V->l,e-V->l,ctx->array+(V->nc+V->l)*V->n,q+V->l*ldq+V->l,PETSC_FALSE);
     67:   MatDenseRestoreArray(Q,&q);
     68:   return(0);
     69: }

     71: PetscErrorCode BVMultInPlaceTranspose_Contiguous(BV V,Mat Q,PetscInt s,PetscInt e)
     72: {
     74:   BV_CONTIGUOUS  *ctx = (BV_CONTIGUOUS*)V->data;
     75:   PetscScalar    *q;
     76:   PetscInt       ldq;

     79:   MatGetSize(Q,&ldq,NULL);
     80:   MatDenseGetArray(Q,&q);
     81:   BVMultInPlace_BLAS_Private(V,V->n,V->k-V->l,ldq,s-V->l,e-V->l,ctx->array+(V->nc+V->l)*V->n,q+V->l*ldq+V->l,PETSC_TRUE);
     82:   MatDenseRestoreArray(Q,&q);
     83:   return(0);
     84: }

     86: PetscErrorCode BVDot_Contiguous(BV X,BV Y,Mat M)
     87: {
     89:   BV_CONTIGUOUS  *x = (BV_CONTIGUOUS*)X->data,*y = (BV_CONTIGUOUS*)Y->data;
     90:   PetscScalar    *m;
     91:   PetscInt       ldm;

     94:   MatGetSize(M,&ldm,NULL);
     95:   MatDenseGetArray(M,&m);
     96:   BVDot_BLAS_Private(X,Y->k-Y->l,X->k-X->l,X->n,ldm,y->array+(Y->nc+Y->l)*Y->n,x->array+(X->nc+X->l)*X->n,m+X->l*ldm+Y->l,x->mpi);
     97:   MatDenseRestoreArray(M,&m);
     98:   return(0);
     99: }

    101: PetscErrorCode BVDotVec_Contiguous(BV X,Vec y,PetscScalar *q)
    102: {
    103:   PetscErrorCode    ierr;
    104:   BV_CONTIGUOUS     *x = (BV_CONTIGUOUS*)X->data;
    105:   const PetscScalar *py;
    106:   PetscScalar       *qq=q;
    107:   Vec               z = y;

    110:   if (X->matrix) {
    111:     BV_IPMatMult(X,y);
    112:     z = X->Bx;
    113:   }
    114:   VecGetArrayRead(z,&py);
    115:   if (!q) { VecGetArray(X->buffer,&qq); }
    116:   BVDotVec_BLAS_Private(X,X->n,X->k-X->l,x->array+(X->nc+X->l)*X->n,py,qq,x->mpi);
    117:   if (!q) { VecRestoreArray(X->buffer,&qq); }
    118:   VecRestoreArrayRead(z,&py);
    119:   return(0);
    120: }

    122: PetscErrorCode BVDotVec_Local_Contiguous(BV X,Vec y,PetscScalar *m)
    123: {
    125:   BV_CONTIGUOUS  *x = (BV_CONTIGUOUS*)X->data;
    126:   PetscScalar    *py;
    127:   Vec            z = y;

    130:   if (X->matrix) {
    131:     BV_IPMatMult(X,y);
    132:     z = X->Bx;
    133:   }
    134:   VecGetArray(z,&py);
    135:   BVDotVec_BLAS_Private(X,X->n,X->k-X->l,x->array+(X->nc+X->l)*X->n,py,m,PETSC_FALSE);
    136:   VecRestoreArray(z,&py);
    137:   return(0);
    138: }

    140: PetscErrorCode BVScale_Contiguous(BV bv,PetscInt j,PetscScalar alpha)
    141: {
    143:   BV_CONTIGUOUS  *ctx = (BV_CONTIGUOUS*)bv->data;

    146:   if (j<0) {
    147:     BVScale_BLAS_Private(bv,(bv->k-bv->l)*bv->n,ctx->array+(bv->nc+bv->l)*bv->n,alpha);
    148:   } else {
    149:     BVScale_BLAS_Private(bv,bv->n,ctx->array+(bv->nc+j)*bv->n,alpha);
    150:   }
    151:   return(0);
    152: }

    154: PetscErrorCode BVNorm_Contiguous(BV bv,PetscInt j,NormType type,PetscReal *val)
    155: {
    157:   BV_CONTIGUOUS  *ctx = (BV_CONTIGUOUS*)bv->data;

    160:   if (j<0) {
    161:     BVNorm_LAPACK_Private(bv,bv->n,bv->k-bv->l,ctx->array+(bv->nc+bv->l)*bv->n,type,val,ctx->mpi);
    162:   } else {
    163:     BVNorm_LAPACK_Private(bv,bv->n,1,ctx->array+(bv->nc+j)*bv->n,type,val,ctx->mpi);
    164:   }
    165:   return(0);
    166: }

    168: PetscErrorCode BVNorm_Local_Contiguous(BV bv,PetscInt j,NormType type,PetscReal *val)
    169: {
    171:   BV_CONTIGUOUS  *ctx = (BV_CONTIGUOUS*)bv->data;

    174:   if (j<0) {
    175:     BVNorm_LAPACK_Private(bv,bv->n,bv->k-bv->l,ctx->array+(bv->nc+bv->l)*bv->n,type,val,PETSC_FALSE);
    176:   } else {
    177:     BVNorm_LAPACK_Private(bv,bv->n,1,ctx->array+(bv->nc+j)*bv->n,type,val,PETSC_FALSE);
    178:   }
    179:   return(0);
    180: }

    182: PetscErrorCode BVMatMult_Contiguous(BV V,Mat A,BV W)
    183: {
    185:   BV_CONTIGUOUS  *v = (BV_CONTIGUOUS*)V->data,*w = (BV_CONTIGUOUS*)W->data;
    186:   PetscInt       j;
    187:   PetscBool      flg;
    188:   Mat            Vmat,Wmat;

    191:   MatHasOperation(A,MATOP_MAT_MULT,&flg);
    192:   if (V->vmm && flg) {
    193:     BVGetMat(V,&Vmat);
    194:     BVGetMat(W,&Wmat);
    195:     MatMatMult(A,Vmat,MAT_REUSE_MATRIX,PETSC_DEFAULT,&Wmat);
    196:     BVRestoreMat(V,&Vmat);
    197:     BVRestoreMat(W,&Wmat);
    198:   } else {
    199:     for (j=0;j<V->k-V->l;j++) {
    200:       MatMult(A,v->V[V->nc+V->l+j],w->V[W->nc+W->l+j]);
    201:     }
    202:   }
    203:   return(0);
    204: }

    206: PetscErrorCode BVCopy_Contiguous(BV V,BV W)
    207: {
    209:   BV_CONTIGUOUS  *v = (BV_CONTIGUOUS*)V->data,*w = (BV_CONTIGUOUS*)W->data;
    210:   PetscScalar    *pvc,*pwc;

    213:   pvc = v->array+(V->nc+V->l)*V->n;
    214:   pwc = w->array+(W->nc+W->l)*W->n;
    215:   PetscMemcpy(pwc,pvc,(V->k-V->l)*V->n*sizeof(PetscScalar));
    216:   return(0);
    217: }

    219: PetscErrorCode BVCopyColumn_Contiguous(BV V,PetscInt j,PetscInt i)
    220: {
    222:   BV_CONTIGUOUS  *v = (BV_CONTIGUOUS*)V->data;

    225:   PetscMemcpy(v->array+(V->nc+i)*V->n,v->array+(V->nc+j)*V->n,V->n*sizeof(PetscScalar));
    226:   return(0);
    227: }

    229: PetscErrorCode BVResize_Contiguous(BV bv,PetscInt m,PetscBool copy)
    230: {
    232:   BV_CONTIGUOUS  *ctx = (BV_CONTIGUOUS*)bv->data;
    233:   PetscInt       j,bs,lsplit;
    234:   PetscScalar    *newarray;
    235:   Vec            *newV;
    236:   char           str[50];
    237:   BV             parent;

    240:   if (bv->issplit==2) {
    241:     parent = bv->splitparent;
    242:     lsplit = parent->lsplit;
    243:     ctx->V = ((BV_CONTIGUOUS*)parent->data)->V+lsplit;
    244:     ctx->array = ((BV_CONTIGUOUS*)parent->data)->array+lsplit*bv->n;
    245:   } else if (!bv->issplit) {
    246:     VecGetBlockSize(bv->t,&bs);
    247:     PetscMalloc1(m*bv->n,&newarray);
    248:     PetscMemzero(newarray,m*bv->n*sizeof(PetscScalar));
    249:     PetscMalloc1(m,&newV);
    250:     for (j=0;j<m;j++) {
    251:       if (ctx->mpi) {
    252:         VecCreateMPIWithArray(PetscObjectComm((PetscObject)bv->t),bs,bv->n,PETSC_DECIDE,newarray+j*bv->n,newV+j);
    253:       } else {
    254:         VecCreateSeqWithArray(PetscObjectComm((PetscObject)bv->t),bs,bv->n,newarray+j*bv->n,newV+j);
    255:       }
    256:     }
    257:     PetscLogObjectParents(bv,m,newV);
    258:     if (((PetscObject)bv)->name) {
    259:       for (j=0;j<m;j++) {
    260:         PetscSNPrintf(str,50,"%s_%d",((PetscObject)bv)->name,(int)j);
    261:         PetscObjectSetName((PetscObject)newV[j],str);
    262:       }
    263:     }
    264:     if (copy) {
    265:       PetscMemcpy(newarray,ctx->array,PetscMin(m,bv->m)*bv->n*sizeof(PetscScalar));
    266:     }
    267:     VecDestroyVecs(bv->m,&ctx->V);
    268:     ctx->V = newV;
    269:     PetscFree(ctx->array);
    270:     ctx->array = newarray;
    271:   }
    272:   return(0);
    273: }

    275: PetscErrorCode BVGetColumn_Contiguous(BV bv,PetscInt j,Vec *v)
    276: {
    277:   BV_CONTIGUOUS *ctx = (BV_CONTIGUOUS*)bv->data;
    278:   PetscInt      l;

    281:   l = BVAvailableVec;
    282:   bv->cv[l] = ctx->V[bv->nc+j];
    283:   return(0);
    284: }

    286: PetscErrorCode BVGetArray_Contiguous(BV bv,PetscScalar **a)
    287: {
    288:   BV_CONTIGUOUS *ctx = (BV_CONTIGUOUS*)bv->data;

    291:   *a = ctx->array;
    292:   return(0);
    293: }

    295: PetscErrorCode BVGetArrayRead_Contiguous(BV bv,const PetscScalar **a)
    296: {
    297:   BV_CONTIGUOUS *ctx = (BV_CONTIGUOUS*)bv->data;

    300:   *a = ctx->array;
    301:   return(0);
    302: }

    304: PetscErrorCode BVDestroy_Contiguous(BV bv)
    305: {
    307:   BV_CONTIGUOUS  *ctx = (BV_CONTIGUOUS*)bv->data;

    310:   if (!bv->issplit) {
    311:     VecDestroyVecs(bv->nc+bv->m,&ctx->V);
    312:     PetscFree(ctx->array);
    313:   }
    314:   PetscFree(bv->data);
    315:   return(0);
    316: }

    318: PETSC_EXTERN PetscErrorCode BVCreate_Contiguous(BV bv)
    319: {
    321:   BV_CONTIGUOUS  *ctx;
    322:   PetscInt       j,nloc,bs,lsplit;
    323:   PetscBool      seq;
    324:   PetscScalar    *aa;
    325:   char           str[50];
    326:   PetscScalar    *array;
    327:   BV             parent;
    328:   Vec            *Vpar;

    331:   PetscNewLog(bv,&ctx);
    332:   bv->data = (void*)ctx;

    334:   PetscObjectTypeCompare((PetscObject)bv->t,VECMPI,&ctx->mpi);
    335:   if (!ctx->mpi) {
    336:     PetscObjectTypeCompare((PetscObject)bv->t,VECSEQ,&seq);
    337:     if (!seq) SETERRQ(PetscObjectComm((PetscObject)bv),PETSC_ERR_SUP,"Cannot create a contiguous BV from a non-standard template vector");
    338:   }

    340:   VecGetLocalSize(bv->t,&nloc);
    341:   VecGetBlockSize(bv->t,&bs);

    343:   if (bv->issplit) {
    344:     /* split BV: share memory and Vecs of the parent BV */
    345:     parent = bv->splitparent;
    346:     lsplit = parent->lsplit;
    347:     Vpar   = ((BV_CONTIGUOUS*)parent->data)->V;
    348:     ctx->V = (bv->issplit==1)? Vpar: Vpar+lsplit;
    349:     array  = ((BV_CONTIGUOUS*)parent->data)->array;
    350:     ctx->array = (bv->issplit==1)? array: array+lsplit*nloc;
    351:   } else {
    352:     /* regular BV: allocate memory and Vecs for the BV entries */
    353:     PetscCalloc1(bv->m*nloc,&ctx->array);
    354:     PetscMalloc1(bv->m,&ctx->V);
    355:     for (j=0;j<bv->m;j++) {
    356:       if (ctx->mpi) {
    357:         VecCreateMPIWithArray(PetscObjectComm((PetscObject)bv->t),bs,nloc,PETSC_DECIDE,ctx->array+j*nloc,ctx->V+j);
    358:       } else {
    359:         VecCreateSeqWithArray(PetscObjectComm((PetscObject)bv->t),bs,nloc,ctx->array+j*nloc,ctx->V+j);
    360:       }
    361:     }
    362:     PetscLogObjectParents(bv,bv->m,ctx->V);
    363:   }
    364:   if (((PetscObject)bv)->name) {
    365:     for (j=0;j<bv->m;j++) {
    366:       PetscSNPrintf(str,50,"%s_%d",((PetscObject)bv)->name,(int)j);
    367:       PetscObjectSetName((PetscObject)ctx->V[j],str);
    368:     }
    369:   }

    371:   if (bv->Acreate) {
    372:     MatDenseGetArray(bv->Acreate,&aa);
    373:     PetscMemcpy(ctx->array,aa,bv->m*nloc*sizeof(PetscScalar));
    374:     MatDenseRestoreArray(bv->Acreate,&aa);
    375:     MatDestroy(&bv->Acreate);
    376:   }

    378:   bv->ops->mult             = BVMult_Contiguous;
    379:   bv->ops->multvec          = BVMultVec_Contiguous;
    380:   bv->ops->multinplace      = BVMultInPlace_Contiguous;
    381:   bv->ops->multinplacetrans = BVMultInPlaceTranspose_Contiguous;
    382:   bv->ops->dot              = BVDot_Contiguous;
    383:   bv->ops->dotvec           = BVDotVec_Contiguous;
    384:   bv->ops->dotvec_local     = BVDotVec_Local_Contiguous;
    385:   bv->ops->scale            = BVScale_Contiguous;
    386:   bv->ops->norm             = BVNorm_Contiguous;
    387:   bv->ops->norm_local       = BVNorm_Local_Contiguous;
    388:   bv->ops->matmult          = BVMatMult_Contiguous;
    389:   bv->ops->copy             = BVCopy_Contiguous;
    390:   bv->ops->copycolumn       = BVCopyColumn_Contiguous;
    391:   bv->ops->resize           = BVResize_Contiguous;
    392:   bv->ops->getcolumn        = BVGetColumn_Contiguous;
    393:   bv->ops->getarray         = BVGetArray_Contiguous;
    394:   bv->ops->getarrayread     = BVGetArrayRead_Contiguous;
    395:   bv->ops->destroy          = BVDestroy_Contiguous;
    396:   return(0);
    397: }