Actual source code: contig.c

slepc-3.18.0 2022-10-01
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 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: {
 24:   BV_CONTIGUOUS     *y = (BV_CONTIGUOUS*)Y->data,*x = (BV_CONTIGUOUS*)X->data;
 25:   const PetscScalar *q;
 26:   PetscInt          ldq;

 28:   if (Q) {
 29:     MatDenseGetLDA(Q,&ldq);
 30:     MatDenseGetArrayRead(Q,&q);
 31:     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);
 32:     MatDenseRestoreArrayRead(Q,&q);
 33:   } else 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);
 34:   return 0;
 35: }

 37: PetscErrorCode BVMultVec_Contiguous(BV X,PetscScalar alpha,PetscScalar beta,Vec y,PetscScalar *q)
 38: {
 39:   BV_CONTIGUOUS  *x = (BV_CONTIGUOUS*)X->data;
 40:   PetscScalar    *py,*qq=q;

 42:   VecGetArray(y,&py);
 43:   if (!q) VecGetArray(X->buffer,&qq);
 44:   BVMultVec_BLAS_Private(X,X->n,X->k-X->l,alpha,x->array+(X->nc+X->l)*X->n,qq,beta,py);
 45:   if (!q) VecRestoreArray(X->buffer,&qq);
 46:   VecRestoreArray(y,&py);
 47:   return 0;
 48: }

 50: PetscErrorCode BVMultInPlace_Contiguous(BV V,Mat Q,PetscInt s,PetscInt e)
 51: {
 52:   BV_CONTIGUOUS     *ctx = (BV_CONTIGUOUS*)V->data;
 53:   const PetscScalar *q;
 54:   PetscInt          ldq;

 56:   MatDenseGetLDA(Q,&ldq);
 57:   MatDenseGetArrayRead(Q,&q);
 58:   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);
 59:   MatDenseRestoreArrayRead(Q,&q);
 60:   return 0;
 61: }

 63: PetscErrorCode BVMultInPlaceHermitianTranspose_Contiguous(BV V,Mat Q,PetscInt s,PetscInt e)
 64: {
 65:   BV_CONTIGUOUS     *ctx = (BV_CONTIGUOUS*)V->data;
 66:   const PetscScalar *q;
 67:   PetscInt          ldq;

 69:   MatDenseGetLDA(Q,&ldq);
 70:   MatDenseGetArrayRead(Q,&q);
 71:   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);
 72:   MatDenseRestoreArrayRead(Q,&q);
 73:   return 0;
 74: }

 76: PetscErrorCode BVDot_Contiguous(BV X,BV Y,Mat M)
 77: {
 78:   BV_CONTIGUOUS  *x = (BV_CONTIGUOUS*)X->data,*y = (BV_CONTIGUOUS*)Y->data;
 79:   PetscScalar    *m;
 80:   PetscInt       ldm;

 82:   MatDenseGetLDA(M,&ldm);
 83:   MatDenseGetArray(M,&m);
 84:   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);
 85:   MatDenseRestoreArray(M,&m);
 86:   return 0;
 87: }

 89: PetscErrorCode BVDotVec_Contiguous(BV X,Vec y,PetscScalar *q)
 90: {
 91:   BV_CONTIGUOUS     *x = (BV_CONTIGUOUS*)X->data;
 92:   const PetscScalar *py;
 93:   PetscScalar       *qq=q;
 94:   Vec               z = y;

 96:   if (PetscUnlikely(X->matrix)) {
 97:     BV_IPMatMult(X,y);
 98:     z = X->Bx;
 99:   }
100:   VecGetArrayRead(z,&py);
101:   if (!q) VecGetArray(X->buffer,&qq);
102:   BVDotVec_BLAS_Private(X,X->n,X->k-X->l,x->array+(X->nc+X->l)*X->n,py,qq,x->mpi);
103:   if (!q) VecRestoreArray(X->buffer,&qq);
104:   VecRestoreArrayRead(z,&py);
105:   return 0;
106: }

108: PetscErrorCode BVDotVec_Local_Contiguous(BV X,Vec y,PetscScalar *m)
109: {
110:   BV_CONTIGUOUS  *x = (BV_CONTIGUOUS*)X->data;
111:   PetscScalar    *py;
112:   Vec            z = y;

114:   if (PetscUnlikely(X->matrix)) {
115:     BV_IPMatMult(X,y);
116:     z = X->Bx;
117:   }
118:   VecGetArray(z,&py);
119:   BVDotVec_BLAS_Private(X,X->n,X->k-X->l,x->array+(X->nc+X->l)*X->n,py,m,PETSC_FALSE);
120:   VecRestoreArray(z,&py);
121:   return 0;
122: }

124: PetscErrorCode BVScale_Contiguous(BV bv,PetscInt j,PetscScalar alpha)
125: {
126:   BV_CONTIGUOUS  *ctx = (BV_CONTIGUOUS*)bv->data;

128:   if (PetscUnlikely(j<0)) BVScale_BLAS_Private(bv,(bv->k-bv->l)*bv->n,ctx->array+(bv->nc+bv->l)*bv->n,alpha);
129:   else BVScale_BLAS_Private(bv,bv->n,ctx->array+(bv->nc+j)*bv->n,alpha);
130:   return 0;
131: }

133: PetscErrorCode BVNorm_Contiguous(BV bv,PetscInt j,NormType type,PetscReal *val)
134: {
135:   BV_CONTIGUOUS  *ctx = (BV_CONTIGUOUS*)bv->data;

137:   if (PetscUnlikely(j<0)) BVNorm_LAPACK_Private(bv,bv->n,bv->k-bv->l,ctx->array+(bv->nc+bv->l)*bv->n,type,val,ctx->mpi);
138:   else BVNorm_LAPACK_Private(bv,bv->n,1,ctx->array+(bv->nc+j)*bv->n,type,val,ctx->mpi);
139:   return 0;
140: }

142: PetscErrorCode BVNorm_Local_Contiguous(BV bv,PetscInt j,NormType type,PetscReal *val)
143: {
144:   BV_CONTIGUOUS  *ctx = (BV_CONTIGUOUS*)bv->data;

146:   if (PetscUnlikely(j<0)) BVNorm_LAPACK_Private(bv,bv->n,bv->k-bv->l,ctx->array+(bv->nc+bv->l)*bv->n,type,val,PETSC_FALSE);
147:   else BVNorm_LAPACK_Private(bv,bv->n,1,ctx->array+(bv->nc+j)*bv->n,type,val,PETSC_FALSE);
148:   return 0;
149: }

151: PetscErrorCode BVNormalize_Contiguous(BV bv,PetscScalar *eigi)
152: {
153:   BV_CONTIGUOUS  *ctx = (BV_CONTIGUOUS*)bv->data;
154:   PetscScalar    *wi=NULL;

156:   if (eigi) wi = eigi+bv->l;
157:   BVNormalize_LAPACK_Private(bv,bv->n,bv->k-bv->l,ctx->array+(bv->nc+bv->l)*bv->n,wi,ctx->mpi);
158:   return 0;
159: }

161: PetscErrorCode BVMatMult_Contiguous(BV V,Mat A,BV W)
162: {
163:   BV_CONTIGUOUS  *v = (BV_CONTIGUOUS*)V->data,*w = (BV_CONTIGUOUS*)W->data;
164:   PetscInt       j;
165:   Mat            Vmat,Wmat;

167:   if (V->vmm) {
168:     BVGetMat(V,&Vmat);
169:     BVGetMat(W,&Wmat);
170:     MatProductCreateWithMat(A,Vmat,NULL,Wmat);
171:     MatProductSetType(Wmat,MATPRODUCT_AB);
172:     MatProductSetFromOptions(Wmat);
173:     MatProductSymbolic(Wmat);
174:     MatProductNumeric(Wmat);
175:     MatProductClear(Wmat);
176:     BVRestoreMat(V,&Vmat);
177:     BVRestoreMat(W,&Wmat);
178:   } else {
179:     for (j=0;j<V->k-V->l;j++) MatMult(A,v->V[V->nc+V->l+j],w->V[W->nc+W->l+j]);
180:   }
181:   return 0;
182: }

184: PetscErrorCode BVCopy_Contiguous(BV V,BV W)
185: {
186:   BV_CONTIGUOUS  *v = (BV_CONTIGUOUS*)V->data,*w = (BV_CONTIGUOUS*)W->data;
187:   PetscScalar    *pvc,*pwc;

189:   pvc = v->array+(V->nc+V->l)*V->n;
190:   pwc = w->array+(W->nc+W->l)*W->n;
191:   PetscArraycpy(pwc,pvc,(V->k-V->l)*V->n);
192:   return 0;
193: }

195: PetscErrorCode BVCopyColumn_Contiguous(BV V,PetscInt j,PetscInt i)
196: {
197:   BV_CONTIGUOUS  *v = (BV_CONTIGUOUS*)V->data;

199:   PetscArraycpy(v->array+(V->nc+i)*V->n,v->array+(V->nc+j)*V->n,V->n);
200:   return 0;
201: }

203: PetscErrorCode BVResize_Contiguous(BV bv,PetscInt m,PetscBool copy)
204: {
205:   BV_CONTIGUOUS  *ctx = (BV_CONTIGUOUS*)bv->data;
206:   PetscInt       j,bs;
207:   PetscScalar    *newarray;
208:   Vec            *newV;
209:   char           str[50];

211:   VecGetBlockSize(bv->t,&bs);
212:   PetscMalloc1(m*bv->n,&newarray);
213:   PetscArrayzero(newarray,m*bv->n);
214:   PetscMalloc1(m,&newV);
215:   for (j=0;j<m;j++) {
216:     if (ctx->mpi) VecCreateMPIWithArray(PetscObjectComm((PetscObject)bv->t),bs,bv->n,PETSC_DECIDE,newarray+j*bv->n,newV+j);
217:     else VecCreateSeqWithArray(PetscObjectComm((PetscObject)bv->t),bs,bv->n,newarray+j*bv->n,newV+j);
218:   }
219:   if (((PetscObject)bv)->name) {
220:     for (j=0;j<m;j++) {
221:       PetscSNPrintf(str,sizeof(str),"%s_%" PetscInt_FMT,((PetscObject)bv)->name,j);
222:       PetscObjectSetName((PetscObject)newV[j],str);
223:     }
224:   }
225:   if (copy) PetscArraycpy(newarray,ctx->array,PetscMin(m,bv->m)*bv->n);
226:   VecDestroyVecs(bv->m,&ctx->V);
227:   ctx->V = newV;
228:   PetscFree(ctx->array);
229:   ctx->array = newarray;
230:   return 0;
231: }

233: PetscErrorCode BVGetColumn_Contiguous(BV bv,PetscInt j,Vec *v)
234: {
235:   BV_CONTIGUOUS *ctx = (BV_CONTIGUOUS*)bv->data;
236:   PetscInt      l;

238:   l = BVAvailableVec;
239:   bv->cv[l] = ctx->V[bv->nc+j];
240:   return 0;
241: }

243: PetscErrorCode BVRestoreColumn_Contiguous(BV bv,PetscInt j,Vec *v)
244: {
245:   PetscInt l;

247:   l = (j==bv->ci[0])? 0: 1;
248:   bv->cv[l] = NULL;
249:   return 0;
250: }

252: PetscErrorCode BVGetArray_Contiguous(BV bv,PetscScalar **a)
253: {
254:   BV_CONTIGUOUS *ctx = (BV_CONTIGUOUS*)bv->data;

256:   *a = ctx->array;
257:   return 0;
258: }

260: PetscErrorCode BVGetArrayRead_Contiguous(BV bv,const PetscScalar **a)
261: {
262:   BV_CONTIGUOUS *ctx = (BV_CONTIGUOUS*)bv->data;

264:   *a = ctx->array;
265:   return 0;
266: }

268: PetscErrorCode BVDestroy_Contiguous(BV bv)
269: {
270:   BV_CONTIGUOUS  *ctx = (BV_CONTIGUOUS*)bv->data;

272:   if (!bv->issplit) {
273:     VecDestroyVecs(bv->nc+bv->m,&ctx->V);
274:     PetscFree(ctx->array);
275:   }
276:   PetscFree(bv->data);
277:   return 0;
278: }

280: PetscErrorCode BVView_Contiguous(BV bv,PetscViewer viewer)
281: {
282:   PetscInt          j;
283:   Vec               v;
284:   PetscViewerFormat format;
285:   PetscBool         isascii,ismatlab=PETSC_FALSE;
286:   const char        *bvname,*name;

288:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
289:   if (isascii) {
290:     PetscViewerGetFormat(viewer,&format);
291:     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) return 0;
292:     if (format == PETSC_VIEWER_ASCII_MATLAB) ismatlab = PETSC_TRUE;
293:   }
294:   if (ismatlab) {
295:     PetscObjectGetName((PetscObject)bv,&bvname);
296:     PetscViewerASCIIPrintf(viewer,"%s=[];\n",bvname);
297:   }
298:   for (j=0;j<bv->m;j++) {
299:     BVGetColumn(bv,j,&v);
300:     VecView(v,viewer);
301:     if (ismatlab) {
302:       PetscObjectGetName((PetscObject)v,&name);
303:       PetscViewerASCIIPrintf(viewer,"%s=[%s,%s];clear %s\n",bvname,bvname,name,name);
304:     }
305:     BVRestoreColumn(bv,j,&v);
306:   }
307:   return 0;
308: }

310: SLEPC_EXTERN PetscErrorCode BVCreate_Contiguous(BV bv)
311: {
312:   BV_CONTIGUOUS  *ctx;
313:   PetscInt       j,nloc,bs,lsplit;
314:   PetscBool      seq;
315:   PetscScalar    *aa;
316:   char           str[50];
317:   PetscScalar    *array;
318:   BV             parent;
319:   Vec            *Vpar;

321:   PetscNew(&ctx);
322:   bv->data = (void*)ctx;

324:   PetscObjectTypeCompare((PetscObject)bv->t,VECMPI,&ctx->mpi);
325:   if (!ctx->mpi) {
326:     PetscObjectTypeCompare((PetscObject)bv->t,VECSEQ,&seq);
328:   }

330:   VecGetLocalSize(bv->t,&nloc);
331:   VecGetBlockSize(bv->t,&bs);

333:   if (PetscUnlikely(bv->issplit)) {
334:     /* split BV: share memory and Vecs of the parent BV */
335:     parent = bv->splitparent;
336:     lsplit = parent->lsplit;
337:     Vpar   = ((BV_CONTIGUOUS*)parent->data)->V;
338:     ctx->V = (bv->issplit==1)? Vpar: Vpar+lsplit;
339:     array  = ((BV_CONTIGUOUS*)parent->data)->array;
340:     ctx->array = (bv->issplit==1)? array: array+lsplit*nloc;
341:   } else {
342:     /* regular BV: allocate memory and Vecs for the BV entries */
343:     PetscCalloc1(bv->m*nloc,&ctx->array);
344:     PetscMalloc1(bv->m,&ctx->V);
345:     for (j=0;j<bv->m;j++) {
346:       if (ctx->mpi) VecCreateMPIWithArray(PetscObjectComm((PetscObject)bv->t),bs,nloc,PETSC_DECIDE,ctx->array+j*nloc,ctx->V+j);
347:       else VecCreateSeqWithArray(PetscObjectComm((PetscObject)bv->t),bs,nloc,ctx->array+j*nloc,ctx->V+j);
348:     }
349:   }
350:   if (((PetscObject)bv)->name) {
351:     for (j=0;j<bv->m;j++) {
352:       PetscSNPrintf(str,sizeof(str),"%s_%" PetscInt_FMT,((PetscObject)bv)->name,j);
353:       PetscObjectSetName((PetscObject)ctx->V[j],str);
354:     }
355:   }

357:   if (PetscUnlikely(bv->Acreate)) {
358:     MatDenseGetArray(bv->Acreate,&aa);
359:     PetscArraycpy(ctx->array,aa,bv->m*nloc);
360:     MatDenseRestoreArray(bv->Acreate,&aa);
361:     MatDestroy(&bv->Acreate);
362:   }

364:   bv->ops->mult             = BVMult_Contiguous;
365:   bv->ops->multvec          = BVMultVec_Contiguous;
366:   bv->ops->multinplace      = BVMultInPlace_Contiguous;
367:   bv->ops->multinplacetrans = BVMultInPlaceHermitianTranspose_Contiguous;
368:   bv->ops->dot              = BVDot_Contiguous;
369:   bv->ops->dotvec           = BVDotVec_Contiguous;
370:   bv->ops->dotvec_local     = BVDotVec_Local_Contiguous;
371:   bv->ops->scale            = BVScale_Contiguous;
372:   bv->ops->norm             = BVNorm_Contiguous;
373:   bv->ops->norm_local       = BVNorm_Local_Contiguous;
374:   bv->ops->normalize        = BVNormalize_Contiguous;
375:   bv->ops->matmult          = BVMatMult_Contiguous;
376:   bv->ops->copy             = BVCopy_Contiguous;
377:   bv->ops->copycolumn       = BVCopyColumn_Contiguous;
378:   bv->ops->resize           = BVResize_Contiguous;
379:   bv->ops->getcolumn        = BVGetColumn_Contiguous;
380:   bv->ops->restorecolumn    = BVRestoreColumn_Contiguous;
381:   bv->ops->getarray         = BVGetArray_Contiguous;
382:   bv->ops->getarrayread     = BVGetArrayRead_Contiguous;
383:   bv->ops->getmat           = BVGetMat_Default;
384:   bv->ops->restoremat       = BVRestoreMat_Default;
385:   bv->ops->destroy          = BVDestroy_Contiguous;
386:   bv->ops->view             = BVView_Contiguous;
387:   return 0;
388: }