Actual source code: contig.c

slepc-3.17.0 2022-03-31
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:   PetscFunctionReturn(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:   PetscFunctionReturn(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:   PetscFunctionReturn(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:   PetscFunctionReturn(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:   PetscFunctionReturn(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:   PetscFunctionReturn(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:   PetscFunctionReturn(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:   PetscFunctionReturn(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:   PetscFunctionReturn(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:   PetscFunctionReturn(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:   PetscFunctionReturn(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:   PetscFunctionReturn(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:   PetscFunctionReturn(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:   PetscFunctionReturn(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:   PetscLogObjectParents(bv,m,newV);
220:   if (((PetscObject)bv)->name) {
221:     for (j=0;j<m;j++) {
222:       PetscSNPrintf(str,sizeof(str),"%s_%" PetscInt_FMT,((PetscObject)bv)->name,j);
223:       PetscObjectSetName((PetscObject)newV[j],str);
224:     }
225:   }
226:   if (copy) PetscArraycpy(newarray,ctx->array,PetscMin(m,bv->m)*bv->n);
227:   VecDestroyVecs(bv->m,&ctx->V);
228:   ctx->V = newV;
229:   PetscFree(ctx->array);
230:   ctx->array = newarray;
231:   PetscFunctionReturn(0);
232: }

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

239:   l = BVAvailableVec;
240:   bv->cv[l] = ctx->V[bv->nc+j];
241:   PetscFunctionReturn(0);
242: }

244: PetscErrorCode BVGetArray_Contiguous(BV bv,PetscScalar **a)
245: {
246:   BV_CONTIGUOUS *ctx = (BV_CONTIGUOUS*)bv->data;

248:   *a = ctx->array;
249:   PetscFunctionReturn(0);
250: }

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

256:   *a = ctx->array;
257:   PetscFunctionReturn(0);
258: }

260: PetscErrorCode BVDestroy_Contiguous(BV bv)
261: {
262:   BV_CONTIGUOUS  *ctx = (BV_CONTIGUOUS*)bv->data;

264:   if (!bv->issplit) {
265:     VecDestroyVecs(bv->nc+bv->m,&ctx->V);
266:     PetscFree(ctx->array);
267:   }
268:   PetscFree(bv->data);
269:   PetscFunctionReturn(0);
270: }

272: SLEPC_EXTERN PetscErrorCode BVCreate_Contiguous(BV bv)
273: {
274:   BV_CONTIGUOUS  *ctx;
275:   PetscInt       j,nloc,bs,lsplit;
276:   PetscBool      seq;
277:   PetscScalar    *aa;
278:   char           str[50];
279:   PetscScalar    *array;
280:   BV             parent;
281:   Vec            *Vpar;

283:   PetscNewLog(bv,&ctx);
284:   bv->data = (void*)ctx;

286:   PetscObjectTypeCompare((PetscObject)bv->t,VECMPI,&ctx->mpi);
287:   if (!ctx->mpi) {
288:     PetscObjectTypeCompare((PetscObject)bv->t,VECSEQ,&seq);
290:   }

292:   VecGetLocalSize(bv->t,&nloc);
293:   VecGetBlockSize(bv->t,&bs);

295:   if (PetscUnlikely(bv->issplit)) {
296:     /* split BV: share memory and Vecs of the parent BV */
297:     parent = bv->splitparent;
298:     lsplit = parent->lsplit;
299:     Vpar   = ((BV_CONTIGUOUS*)parent->data)->V;
300:     ctx->V = (bv->issplit==1)? Vpar: Vpar+lsplit;
301:     array  = ((BV_CONTIGUOUS*)parent->data)->array;
302:     ctx->array = (bv->issplit==1)? array: array+lsplit*nloc;
303:   } else {
304:     /* regular BV: allocate memory and Vecs for the BV entries */
305:     PetscCalloc1(bv->m*nloc,&ctx->array);
306:     PetscMalloc1(bv->m,&ctx->V);
307:     for (j=0;j<bv->m;j++) {
308:       if (ctx->mpi) VecCreateMPIWithArray(PetscObjectComm((PetscObject)bv->t),bs,nloc,PETSC_DECIDE,ctx->array+j*nloc,ctx->V+j);
309:       else VecCreateSeqWithArray(PetscObjectComm((PetscObject)bv->t),bs,nloc,ctx->array+j*nloc,ctx->V+j);
310:     }
311:     PetscLogObjectParents(bv,bv->m,ctx->V);
312:   }
313:   if (((PetscObject)bv)->name) {
314:     for (j=0;j<bv->m;j++) {
315:       PetscSNPrintf(str,sizeof(str),"%s_%" PetscInt_FMT,((PetscObject)bv)->name,j);
316:       PetscObjectSetName((PetscObject)ctx->V[j],str);
317:     }
318:   }

320:   if (PetscUnlikely(bv->Acreate)) {
321:     MatDenseGetArray(bv->Acreate,&aa);
322:     PetscArraycpy(ctx->array,aa,bv->m*nloc);
323:     MatDenseRestoreArray(bv->Acreate,&aa);
324:     MatDestroy(&bv->Acreate);
325:   }

327:   bv->ops->mult             = BVMult_Contiguous;
328:   bv->ops->multvec          = BVMultVec_Contiguous;
329:   bv->ops->multinplace      = BVMultInPlace_Contiguous;
330:   bv->ops->multinplacetrans = BVMultInPlaceHermitianTranspose_Contiguous;
331:   bv->ops->dot              = BVDot_Contiguous;
332:   bv->ops->dotvec           = BVDotVec_Contiguous;
333:   bv->ops->dotvec_local     = BVDotVec_Local_Contiguous;
334:   bv->ops->scale            = BVScale_Contiguous;
335:   bv->ops->norm             = BVNorm_Contiguous;
336:   bv->ops->norm_local       = BVNorm_Local_Contiguous;
337:   bv->ops->normalize        = BVNormalize_Contiguous;
338:   bv->ops->matmult          = BVMatMult_Contiguous;
339:   bv->ops->copy             = BVCopy_Contiguous;
340:   bv->ops->copycolumn       = BVCopyColumn_Contiguous;
341:   bv->ops->resize           = BVResize_Contiguous;
342:   bv->ops->getcolumn        = BVGetColumn_Contiguous;
343:   bv->ops->getarray         = BVGetArray_Contiguous;
344:   bv->ops->getarrayread     = BVGetArrayRead_Contiguous;
345:   bv->ops->destroy          = BVDestroy_Contiguous;
346:   PetscFunctionReturn(0);
347: }