Actual source code: contig.c
slepc-3.17.2 2022-08-09
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: }