Actual source code: bvmat.c
slepc-3.13.0 2020-03-31
1: /*
2: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3: SLEPc - Scalable Library for Eigenvalue Problem Computations
4: Copyright (c) 2002-2020, 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>
16: typedef struct {
17: Mat A;
18: PetscBool mpi;
19: } BV_MAT;
21: PetscErrorCode BVMult_Mat(BV Y,PetscScalar alpha,PetscScalar beta,BV X,Mat Q)
22: {
24: BV_MAT *y = (BV_MAT*)Y->data,*x = (BV_MAT*)X->data;
25: PetscScalar *px,*py,*q;
26: PetscInt ldq;
29: MatDenseGetArray(x->A,&px);
30: MatDenseGetArray(y->A,&py);
31: if (Q) {
32: MatGetSize(Q,&ldq,NULL);
33: MatDenseGetArray(Q,&q);
34: BVMult_BLAS_Private(Y,Y->n,Y->k-Y->l,X->k-X->l,ldq,alpha,px+(X->nc+X->l)*X->n,q+Y->l*ldq+X->l,beta,py+(Y->nc+Y->l)*Y->n);
35: MatDenseRestoreArray(Q,&q);
36: } else {
37: BVAXPY_BLAS_Private(Y,Y->n,Y->k-Y->l,alpha,px+(X->nc+X->l)*X->n,beta,py+(Y->nc+Y->l)*Y->n);
38: }
39: MatDenseRestoreArray(x->A,&px);
40: MatDenseRestoreArray(y->A,&py);
41: return(0);
42: }
44: PetscErrorCode BVMultVec_Mat(BV X,PetscScalar alpha,PetscScalar beta,Vec y,PetscScalar *q)
45: {
47: BV_MAT *x = (BV_MAT*)X->data;
48: PetscScalar *px,*py,*qq=q;
51: MatDenseGetArray(x->A,&px);
52: VecGetArray(y,&py);
53: if (!q) { VecGetArray(X->buffer,&qq); }
54: BVMultVec_BLAS_Private(X,X->n,X->k-X->l,alpha,px+(X->nc+X->l)*X->n,qq,beta,py);
55: if (!q) { VecRestoreArray(X->buffer,&qq); }
56: MatDenseRestoreArray(x->A,&px);
57: VecRestoreArray(y,&py);
58: return(0);
59: }
61: PetscErrorCode BVMultInPlace_Mat(BV V,Mat Q,PetscInt s,PetscInt e)
62: {
64: BV_MAT *ctx = (BV_MAT*)V->data;
65: PetscScalar *pv,*q;
66: PetscInt ldq;
69: MatGetSize(Q,&ldq,NULL);
70: MatDenseGetArray(ctx->A,&pv);
71: MatDenseGetArray(Q,&q);
72: BVMultInPlace_BLAS_Private(V,V->n,V->k-V->l,ldq,s-V->l,e-V->l,pv+(V->nc+V->l)*V->n,q+V->l*ldq+V->l,PETSC_FALSE);
73: MatDenseRestoreArray(Q,&q);
74: MatDenseRestoreArray(ctx->A,&pv);
75: return(0);
76: }
78: PetscErrorCode BVMultInPlaceTranspose_Mat(BV V,Mat Q,PetscInt s,PetscInt e)
79: {
81: BV_MAT *ctx = (BV_MAT*)V->data;
82: PetscScalar *pv,*q;
83: PetscInt ldq;
86: MatGetSize(Q,&ldq,NULL);
87: MatDenseGetArray(ctx->A,&pv);
88: MatDenseGetArray(Q,&q);
89: BVMultInPlace_BLAS_Private(V,V->n,V->k-V->l,ldq,s-V->l,e-V->l,pv+(V->nc+V->l)*V->n,q+V->l*ldq+V->l,PETSC_TRUE);
90: MatDenseRestoreArray(Q,&q);
91: MatDenseRestoreArray(ctx->A,&pv);
92: return(0);
93: }
95: PetscErrorCode BVDot_Mat(BV X,BV Y,Mat M)
96: {
98: BV_MAT *x = (BV_MAT*)X->data,*y = (BV_MAT*)Y->data;
99: PetscScalar *px,*py,*m;
100: PetscInt ldm;
103: MatGetSize(M,&ldm,NULL);
104: MatDenseGetArray(x->A,&px);
105: MatDenseGetArray(y->A,&py);
106: MatDenseGetArray(M,&m);
107: BVDot_BLAS_Private(X,Y->k-Y->l,X->k-X->l,X->n,ldm,py+(Y->nc+Y->l)*Y->n,px+(X->nc+X->l)*X->n,m+X->l*ldm+Y->l,x->mpi);
108: MatDenseRestoreArray(M,&m);
109: MatDenseRestoreArray(x->A,&px);
110: MatDenseRestoreArray(y->A,&py);
111: return(0);
112: }
114: PetscErrorCode BVDotVec_Mat(BV X,Vec y,PetscScalar *q)
115: {
116: PetscErrorCode ierr;
117: BV_MAT *x = (BV_MAT*)X->data;
118: PetscScalar *px,*qq=q;
119: const PetscScalar *py;
120: Vec z = y;
123: if (X->matrix) {
124: BV_IPMatMult(X,y);
125: z = X->Bx;
126: }
127: MatDenseGetArray(x->A,&px);
128: VecGetArrayRead(z,&py);
129: if (!q) { VecGetArray(X->buffer,&qq); }
130: BVDotVec_BLAS_Private(X,X->n,X->k-X->l,px+(X->nc+X->l)*X->n,py,qq,x->mpi);
131: if (!q) { VecRestoreArray(X->buffer,&qq); }
132: VecRestoreArrayRead(z,&py);
133: MatDenseRestoreArray(x->A,&px);
134: return(0);
135: }
137: PetscErrorCode BVDotVec_Local_Mat(BV X,Vec y,PetscScalar *m)
138: {
140: BV_MAT *x = (BV_MAT*)X->data;
141: PetscScalar *px,*py;
142: Vec z = y;
145: if (X->matrix) {
146: BV_IPMatMult(X,y);
147: z = X->Bx;
148: }
149: MatDenseGetArray(x->A,&px);
150: VecGetArray(z,&py);
151: BVDotVec_BLAS_Private(X,X->n,X->k-X->l,px+(X->nc+X->l)*X->n,py,m,PETSC_FALSE);
152: VecRestoreArray(z,&py);
153: MatDenseRestoreArray(x->A,&px);
154: return(0);
155: }
157: PetscErrorCode BVScale_Mat(BV bv,PetscInt j,PetscScalar alpha)
158: {
160: BV_MAT *ctx = (BV_MAT*)bv->data;
161: PetscScalar *array;
164: MatDenseGetArray(ctx->A,&array);
165: if (j<0) {
166: BVScale_BLAS_Private(bv,(bv->k-bv->l)*bv->n,array+(bv->nc+bv->l)*bv->n,alpha);
167: } else {
168: BVScale_BLAS_Private(bv,bv->n,array+(bv->nc+j)*bv->n,alpha);
169: }
170: MatDenseRestoreArray(ctx->A,&array);
171: return(0);
172: }
174: PetscErrorCode BVNorm_Mat(BV bv,PetscInt j,NormType type,PetscReal *val)
175: {
177: BV_MAT *ctx = (BV_MAT*)bv->data;
178: PetscScalar *array;
181: MatDenseGetArray(ctx->A,&array);
182: if (j<0) {
183: BVNorm_LAPACK_Private(bv,bv->n,bv->k-bv->l,array+(bv->nc+bv->l)*bv->n,type,val,ctx->mpi);
184: } else {
185: BVNorm_LAPACK_Private(bv,bv->n,1,array+(bv->nc+j)*bv->n,type,val,ctx->mpi);
186: }
187: MatDenseRestoreArray(ctx->A,&array);
188: return(0);
189: }
191: PetscErrorCode BVNorm_Local_Mat(BV bv,PetscInt j,NormType type,PetscReal *val)
192: {
194: BV_MAT *ctx = (BV_MAT*)bv->data;
195: PetscScalar *array;
198: MatDenseGetArray(ctx->A,&array);
199: if (j<0) {
200: BVNorm_LAPACK_Private(bv,bv->n,bv->k-bv->l,array+(bv->nc+bv->l)*bv->n,type,val,PETSC_FALSE);
201: } else {
202: BVNorm_LAPACK_Private(bv,bv->n,1,array+(bv->nc+j)*bv->n,type,val,PETSC_FALSE);
203: }
204: MatDenseRestoreArray(ctx->A,&array);
205: return(0);
206: }
208: PetscErrorCode BVMatMult_Mat(BV V,Mat A,BV W)
209: {
211: PetscInt j;
212: PetscBool flg;
213: Mat Vmat,Wmat;
214: Vec vv,ww;
217: MatHasOperation(A,MATOP_MAT_MULT,&flg);
218: if (V->vmm && flg) {
219: BVGetMat(V,&Vmat);
220: BVGetMat(W,&Wmat);
221: MatProductCreateWithMat(A,Vmat,NULL,Wmat);
222: MatProductSetType(Wmat,MATPRODUCT_AB);
223: MatProductSetFromOptions(Wmat);
224: MatProductSymbolic(Wmat);
225: MatProductNumeric(Wmat);
226: BVRestoreMat(V,&Vmat);
227: BVRestoreMat(W,&Wmat);
228: } else {
229: for (j=0;j<V->k-V->l;j++) {
230: BVGetColumn(V,V->l+j,&vv);
231: BVGetColumn(W,W->l+j,&ww);
232: MatMult(A,vv,ww);
233: BVRestoreColumn(V,V->l+j,&vv);
234: BVRestoreColumn(W,W->l+j,&ww);
235: }
236: }
237: return(0);
238: }
240: PetscErrorCode BVCopy_Mat(BV V,BV W)
241: {
243: BV_MAT *v = (BV_MAT*)V->data,*w = (BV_MAT*)W->data;
244: PetscScalar *pv,*pw,*pvc,*pwc;
247: MatDenseGetArray(v->A,&pv);
248: MatDenseGetArray(w->A,&pw);
249: pvc = pv+(V->nc+V->l)*V->n;
250: pwc = pw+(W->nc+W->l)*W->n;
251: PetscArraycpy(pwc,pvc,(V->k-V->l)*V->n);
252: MatDenseRestoreArray(v->A,&pv);
253: MatDenseRestoreArray(w->A,&pw);
254: return(0);
255: }
257: PetscErrorCode BVCopyColumn_Mat(BV V,PetscInt j,PetscInt i)
258: {
260: BV_MAT *v = (BV_MAT*)V->data;
261: PetscScalar *pv;
264: MatDenseGetArray(v->A,&pv);
265: PetscArraycpy(pv+(V->nc+i)*V->n,pv+(V->nc+j)*V->n,V->n);
266: MatDenseRestoreArray(v->A,&pv);
267: return(0);
268: }
270: PetscErrorCode BVResize_Mat(BV bv,PetscInt m,PetscBool copy)
271: {
273: BV_MAT *ctx = (BV_MAT*)bv->data;
274: PetscScalar *pA,*pnew;
275: PetscInt lsplit;
276: Mat A;
277: char str[50];
278: PetscScalar *array;
279: BV parent;
282: if (bv->issplit==2) {
283: parent = bv->splitparent;
284: lsplit = parent->lsplit;
285: MatDenseGetArray(((BV_MAT*)parent->data)->A,&array);
286: MatDensePlaceArray(ctx->A,array+lsplit*bv->n);
287: MatDenseRestoreArray(((BV_MAT*)parent->data)->A,&array);
288: } else if (!bv->issplit) {
289: MatCreateDense(PetscObjectComm((PetscObject)bv->t),bv->n,PETSC_DECIDE,PETSC_DECIDE,m,NULL,&A);
290: MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);
291: MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);
292: PetscLogObjectParent((PetscObject)bv,(PetscObject)A);
293: if (((PetscObject)bv)->name) {
294: PetscSNPrintf(str,50,"%s_0",((PetscObject)bv)->name);
295: PetscObjectSetName((PetscObject)A,str);
296: }
297: if (copy) {
298: MatDenseGetArray(ctx->A,&pA);
299: MatDenseGetArray(A,&pnew);
300: PetscArraycpy(pnew,pA,PetscMin(m,bv->m)*bv->n);
301: MatDenseRestoreArray(ctx->A,&pA);
302: MatDenseRestoreArray(A,&pnew);
303: }
304: MatDestroy(&ctx->A);
305: ctx->A = A;
306: }
307: return(0);
308: }
310: PetscErrorCode BVGetColumn_Mat(BV bv,PetscInt j,Vec *v)
311: {
313: BV_MAT *ctx = (BV_MAT*)bv->data;
314: PetscScalar *pA;
315: PetscInt l;
318: l = BVAvailableVec;
319: MatDenseGetArray(ctx->A,&pA);
320: VecPlaceArray(bv->cv[l],pA+(bv->nc+j)*bv->n);
321: return(0);
322: }
324: PetscErrorCode BVRestoreColumn_Mat(BV bv,PetscInt j,Vec *v)
325: {
327: BV_MAT *ctx = (BV_MAT*)bv->data;
328: PetscScalar *pA;
329: PetscInt l;
332: l = (j==bv->ci[0])? 0: 1;
333: VecResetArray(bv->cv[l]);
334: MatDenseRestoreArray(ctx->A,&pA);
335: return(0);
336: }
338: PetscErrorCode BVGetArray_Mat(BV bv,PetscScalar **a)
339: {
341: BV_MAT *ctx = (BV_MAT*)bv->data;
344: MatDenseGetArray(ctx->A,a);
345: return(0);
346: }
348: PetscErrorCode BVRestoreArray_Mat(BV bv,PetscScalar **a)
349: {
351: BV_MAT *ctx = (BV_MAT*)bv->data;
354: if (a) { MatDenseRestoreArray(ctx->A,a); }
355: return(0);
356: }
358: PetscErrorCode BVGetArrayRead_Mat(BV bv,const PetscScalar **a)
359: {
361: BV_MAT *ctx = (BV_MAT*)bv->data;
364: MatDenseGetArray(ctx->A,(PetscScalar**)a);
365: return(0);
366: }
368: PetscErrorCode BVRestoreArrayRead_Mat(BV bv,const PetscScalar **a)
369: {
371: BV_MAT *ctx = (BV_MAT*)bv->data;
374: if (a) { MatDenseRestoreArray(ctx->A,(PetscScalar**)a); }
375: return(0);
376: }
378: PetscErrorCode BVView_Mat(BV bv,PetscViewer viewer)
379: {
380: PetscErrorCode ierr;
381: BV_MAT *ctx = (BV_MAT*)bv->data;
382: PetscViewerFormat format;
383: PetscBool isascii;
384: const char *bvname,*name;
387: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
388: if (isascii) {
389: PetscViewerGetFormat(viewer,&format);
390: if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) return(0);
391: MatView(ctx->A,viewer);
392: if (format == PETSC_VIEWER_ASCII_MATLAB) {
393: PetscObjectGetName((PetscObject)bv,&bvname);
394: PetscObjectGetName((PetscObject)ctx->A,&name);
395: PetscViewerASCIIPrintf(viewer,"%s=%s;clear %s\n",bvname,name,name);
396: if (bv->nc) {
397: PetscViewerASCIIPrintf(viewer,"%s=%s(:,%D:end);\n",bvname,bvname,bv->nc+1);
398: }
399: }
400: } else {
401: MatView(ctx->A,viewer);
402: }
403: return(0);
404: }
406: PetscErrorCode BVDestroy_Mat(BV bv)
407: {
409: BV_MAT *ctx = (BV_MAT*)bv->data;
412: MatDestroy(&ctx->A);
413: VecDestroy(&bv->cv[0]);
414: VecDestroy(&bv->cv[1]);
415: PetscFree(bv->data);
416: return(0);
417: }
419: SLEPC_EXTERN PetscErrorCode BVCreate_Mat(BV bv)
420: {
422: BV_MAT *ctx;
423: PetscInt nloc,bs,lsplit;
424: PetscBool seq;
425: char str[50];
426: PetscScalar *array,*ptr;
427: BV parent;
430: PetscNewLog(bv,&ctx);
431: bv->data = (void*)ctx;
433: PetscObjectTypeCompare((PetscObject)bv->t,VECMPI,&ctx->mpi);
434: if (!ctx->mpi) {
435: PetscObjectTypeCompare((PetscObject)bv->t,VECSEQ,&seq);
436: if (!seq) SETERRQ(PetscObjectComm((PetscObject)bv),PETSC_ERR_SUP,"Cannot create a BVMAT from a non-standard template vector");
437: }
439: VecGetLocalSize(bv->t,&nloc);
440: VecGetBlockSize(bv->t,&bs);
442: if (bv->issplit) {
443: /* split BV: share the memory of the parent BV */
444: parent = bv->splitparent;
445: lsplit = parent->lsplit;
446: MatDenseGetArray(((BV_MAT*)parent->data)->A,&array);
447: ptr = (bv->issplit==1)? array: array+lsplit*nloc;
448: MatDenseRestoreArray(((BV_MAT*)parent->data)->A,&array);
449: } else {
450: /* regular BV: allocate memory for the BV entries */
451: ptr = NULL;
452: }
453: MatCreateDense(PetscObjectComm((PetscObject)bv->t),nloc,PETSC_DECIDE,PETSC_DECIDE,bv->m,ptr,&ctx->A);
454: MatAssemblyBegin(ctx->A,MAT_FINAL_ASSEMBLY);
455: MatAssemblyEnd(ctx->A,MAT_FINAL_ASSEMBLY);
456: PetscLogObjectParent((PetscObject)bv,(PetscObject)ctx->A);
457: if (((PetscObject)bv)->name) {
458: PetscSNPrintf(str,50,"%s_0",((PetscObject)bv)->name);
459: PetscObjectSetName((PetscObject)ctx->A,str);
460: }
462: if (bv->Acreate) {
463: MatCopy(bv->Acreate,ctx->A,SAME_NONZERO_PATTERN);
464: MatDestroy(&bv->Acreate);
465: }
467: VecDuplicateEmpty(bv->t,&bv->cv[0]);
468: VecDuplicateEmpty(bv->t,&bv->cv[1]);
470: bv->ops->mult = BVMult_Mat;
471: bv->ops->multvec = BVMultVec_Mat;
472: bv->ops->multinplace = BVMultInPlace_Mat;
473: bv->ops->multinplacetrans = BVMultInPlaceTranspose_Mat;
474: bv->ops->dot = BVDot_Mat;
475: bv->ops->dotvec = BVDotVec_Mat;
476: bv->ops->dotvec_local = BVDotVec_Local_Mat;
477: bv->ops->scale = BVScale_Mat;
478: bv->ops->norm = BVNorm_Mat;
479: bv->ops->norm_local = BVNorm_Local_Mat;
480: bv->ops->matmult = BVMatMult_Mat;
481: bv->ops->copy = BVCopy_Mat;
482: bv->ops->copycolumn = BVCopyColumn_Mat;
483: bv->ops->resize = BVResize_Mat;
484: bv->ops->getcolumn = BVGetColumn_Mat;
485: bv->ops->restorecolumn = BVRestoreColumn_Mat;
486: bv->ops->getarray = BVGetArray_Mat;
487: bv->ops->restorearray = BVRestoreArray_Mat;
488: bv->ops->getarrayread = BVGetArrayRead_Mat;
489: bv->ops->restorearrayread = BVRestoreArrayRead_Mat;
490: bv->ops->destroy = BVDestroy_Mat;
491: if (!ctx->mpi) bv->ops->view = BVView_Mat;
492: return(0);
493: }