Actual source code: dense.c
petsc-3.11.0 2019-03-29
2: /*
3: Defines the basic matrix operations for sequential dense.
4: */
6: #include <../src/mat/impls/dense/seq/dense.h>
7: #include <petscblaslapack.h>
9: #include <../src/mat/impls/aij/seq/aij.h>
11: static PetscErrorCode MatSeqDenseSymmetrize_Private(Mat A, PetscBool hermitian)
12: {
13: Mat_SeqDense *mat = (Mat_SeqDense*)A->data;
14: PetscInt j, k, n = A->rmap->n;
17: if (A->rmap->n != A->cmap->n) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Cannot symmetrize a rectangular matrix");
18: if (!hermitian) {
19: for (k=0;k<n;k++) {
20: for (j=k;j<n;j++) {
21: mat->v[j*mat->lda + k] = mat->v[k*mat->lda + j];
22: }
23: }
24: } else {
25: for (k=0;k<n;k++) {
26: for (j=k;j<n;j++) {
27: mat->v[j*mat->lda + k] = PetscConj(mat->v[k*mat->lda + j]);
28: }
29: }
30: }
31: return(0);
32: }
34: PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat A)
35: {
36: #if defined(PETSC_MISSING_LAPACK_POTRF)
38: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"POTRF - Lapack routine is unavailable.");
39: #else
40: Mat_SeqDense *mat = (Mat_SeqDense*)A->data;
42: PetscBLASInt info,n;
45: if (!A->rmap->n || !A->cmap->n) return(0);
46: PetscBLASIntCast(A->cmap->n,&n);
47: if (A->factortype == MAT_FACTOR_LU) {
48: if (!mat->pivots) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Pivots not present");
49: if (!mat->fwork) {
50: mat->lfwork = n;
51: PetscMalloc1(mat->lfwork,&mat->fwork);
52: PetscLogObjectMemory((PetscObject)A,mat->lfwork*sizeof(PetscBLASInt));
53: }
54: PetscFPTrapPush(PETSC_FP_TRAP_OFF);
55: PetscStackCallBLAS("LAPACKgetri",LAPACKgetri_(&n,mat->v,&mat->lda,mat->pivots,mat->fwork,&mat->lfwork,&info));
56: PetscFPTrapPop();
57: PetscLogFlops((1.0*A->cmap->n*A->cmap->n*A->cmap->n)/3.0); /* TODO CHECK FLOPS */
58: } else if (A->factortype == MAT_FACTOR_CHOLESKY) {
59: if (A->spd) {
60: PetscFPTrapPush(PETSC_FP_TRAP_OFF);
61: PetscStackCallBLAS("LAPACKpotri",LAPACKpotri_("L",&n,mat->v,&mat->lda,&info));
62: PetscFPTrapPop();
63: MatSeqDenseSymmetrize_Private(A,PETSC_TRUE);
64: #if defined(PETSC_USE_COMPLEX)
65: } else if (A->hermitian) {
66: if (!mat->pivots) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Pivots not present");
67: if (!mat->fwork) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Fwork not present");
68: PetscFPTrapPush(PETSC_FP_TRAP_OFF);
69: PetscStackCallBLAS("LAPACKhetri",LAPACKhetri_("L",&n,mat->v,&mat->lda,mat->pivots,mat->fwork,&info));
70: PetscFPTrapPop();
71: MatSeqDenseSymmetrize_Private(A,PETSC_TRUE);
72: #endif
73: } else { /* symmetric case */
74: if (!mat->pivots) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Pivots not present");
75: if (!mat->fwork) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Fwork not present");
76: PetscFPTrapPush(PETSC_FP_TRAP_OFF);
77: PetscStackCallBLAS("LAPACKsytri",LAPACKsytri_("L",&n,mat->v,&mat->lda,mat->pivots,mat->fwork,&info));
78: PetscFPTrapPop();
79: MatSeqDenseSymmetrize_Private(A,PETSC_FALSE);
80: }
81: if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_MAT_CH_ZRPVT,"Bad Inversion: zero pivot in row %D",(PetscInt)info-1);
82: PetscLogFlops((1.0*A->cmap->n*A->cmap->n*A->cmap->n)/3.0); /* TODO CHECK FLOPS */
83: } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Matrix must be factored to solve");
84: #endif
86: A->ops->solve = NULL;
87: A->ops->matsolve = NULL;
88: A->ops->solvetranspose = NULL;
89: A->ops->matsolvetranspose = NULL;
90: A->ops->solveadd = NULL;
91: A->ops->solvetransposeadd = NULL;
92: A->factortype = MAT_FACTOR_NONE;
93: PetscFree(A->solvertype);
94: return(0);
95: }
97: PetscErrorCode MatZeroRowsColumns_SeqDense(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
98: {
99: PetscErrorCode ierr;
100: Mat_SeqDense *l = (Mat_SeqDense*)A->data;
101: PetscInt m = l->lda, n = A->cmap->n,r = A->rmap->n, i,j;
102: PetscScalar *slot,*bb;
103: const PetscScalar *xx;
106: #if defined(PETSC_USE_DEBUG)
107: for (i=0; i<N; i++) {
108: if (rows[i] < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative row requested to be zeroed");
109: if (rows[i] >= A->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row %D requested to be zeroed greater than or equal number of rows %D",rows[i],A->rmap->n);
110: if (rows[i] >= A->cmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Col %D requested to be zeroed greater than or equal number of cols %D",rows[i],A->cmap->n);
111: }
112: #endif
114: /* fix right hand side if needed */
115: if (x && b) {
116: VecGetArrayRead(x,&xx);
117: VecGetArray(b,&bb);
118: for (i=0; i<N; i++) bb[rows[i]] = diag*xx[rows[i]];
119: VecRestoreArrayRead(x,&xx);
120: VecRestoreArray(b,&bb);
121: }
123: for (i=0; i<N; i++) {
124: slot = l->v + rows[i]*m;
125: PetscMemzero(slot,r*sizeof(PetscScalar));
126: }
127: for (i=0; i<N; i++) {
128: slot = l->v + rows[i];
129: for (j=0; j<n; j++) { *slot = 0.0; slot += m;}
130: }
131: if (diag != 0.0) {
132: if (A->rmap->n != A->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only coded for square matrices");
133: for (i=0; i<N; i++) {
134: slot = l->v + (m+1)*rows[i];
135: *slot = diag;
136: }
137: }
138: return(0);
139: }
141: PetscErrorCode MatPtAPNumeric_SeqDense_SeqDense(Mat A,Mat P,Mat C)
142: {
143: Mat_SeqDense *c = (Mat_SeqDense*)(C->data);
147: MatMatMultNumeric_SeqDense_SeqDense(A,P,c->ptapwork);
148: MatTransposeMatMultNumeric_SeqDense_SeqDense(P,c->ptapwork,C);
149: return(0);
150: }
152: PetscErrorCode MatPtAPSymbolic_SeqDense_SeqDense(Mat A,Mat P,PetscReal fill,Mat *C)
153: {
154: Mat_SeqDense *c;
158: MatCreateSeqDense(PetscObjectComm((PetscObject)A),P->cmap->N,P->cmap->N,NULL,C);
159: c = (Mat_SeqDense*)((*C)->data);
160: MatCreateSeqDense(PetscObjectComm((PetscObject)A),A->rmap->N,P->cmap->N,NULL,&c->ptapwork);
161: return(0);
162: }
164: PETSC_INTERN PetscErrorCode MatPtAP_SeqDense_SeqDense(Mat A,Mat P,MatReuse reuse,PetscReal fill,Mat *C)
165: {
169: if (reuse == MAT_INITIAL_MATRIX) {
170: MatPtAPSymbolic_SeqDense_SeqDense(A,P,fill,C);
171: }
172: PetscLogEventBegin(MAT_PtAPNumeric,A,P,0,0);
173: (*(*C)->ops->ptapnumeric)(A,P,*C);
174: PetscLogEventEnd(MAT_PtAPNumeric,A,P,0,0);
175: return(0);
176: }
178: PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqDense(Mat A,MatType newtype,MatReuse reuse,Mat *newmat)
179: {
180: Mat B = NULL;
181: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
182: Mat_SeqDense *b;
184: PetscInt *ai=a->i,*aj=a->j,m=A->rmap->N,n=A->cmap->N,i;
185: MatScalar *av=a->a;
186: PetscBool isseqdense;
189: if (reuse == MAT_REUSE_MATRIX) {
190: PetscObjectTypeCompare((PetscObject)*newmat,MATSEQDENSE,&isseqdense);
191: if (!isseqdense) SETERRQ1(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_USER,"Cannot reuse matrix of type %s",((PetscObject)(*newmat))->type);
192: }
193: if (reuse != MAT_REUSE_MATRIX) {
194: MatCreate(PetscObjectComm((PetscObject)A),&B);
195: MatSetSizes(B,m,n,m,n);
196: MatSetType(B,MATSEQDENSE);
197: MatSeqDenseSetPreallocation(B,NULL);
198: b = (Mat_SeqDense*)(B->data);
199: } else {
200: b = (Mat_SeqDense*)((*newmat)->data);
201: PetscMemzero(b->v,m*n*sizeof(PetscScalar));
202: }
203: for (i=0; i<m; i++) {
204: PetscInt j;
205: for (j=0;j<ai[1]-ai[0];j++) {
206: b->v[*aj*m+i] = *av;
207: aj++;
208: av++;
209: }
210: ai++;
211: }
213: if (reuse == MAT_INPLACE_MATRIX) {
214: MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);
215: MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);
216: MatHeaderReplace(A,&B);
217: } else {
218: if (B) *newmat = B;
219: MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);
220: MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);
221: }
222: return(0);
223: }
225: PETSC_INTERN PetscErrorCode MatConvert_SeqDense_SeqAIJ(Mat A, MatType newtype,MatReuse reuse,Mat *newmat)
226: {
227: Mat B;
228: Mat_SeqDense *a = (Mat_SeqDense*)A->data;
230: PetscInt i, j;
231: PetscInt *rows, *nnz;
232: MatScalar *aa = a->v, *vals;
235: MatCreate(PetscObjectComm((PetscObject)A),&B);
236: MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);
237: MatSetType(B,MATSEQAIJ);
238: PetscCalloc3(A->rmap->n,&rows,A->rmap->n,&nnz,A->rmap->n,&vals);
239: for (j=0; j<A->cmap->n; j++) {
240: for (i=0; i<A->rmap->n; i++) if (aa[i] != 0.0 || i == j) ++nnz[i];
241: aa += a->lda;
242: }
243: MatSeqAIJSetPreallocation(B,PETSC_DETERMINE,nnz);
244: aa = a->v;
245: for (j=0; j<A->cmap->n; j++) {
246: PetscInt numRows = 0;
247: for (i=0; i<A->rmap->n; i++) if (aa[i] != 0.0 || i == j) {rows[numRows] = i; vals[numRows++] = aa[i];}
248: MatSetValues(B,numRows,rows,1,&j,vals,INSERT_VALUES);
249: aa += a->lda;
250: }
251: PetscFree3(rows,nnz,vals);
252: MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);
253: MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);
255: if (reuse == MAT_INPLACE_MATRIX) {
256: MatHeaderReplace(A,&B);
257: } else {
258: *newmat = B;
259: }
260: return(0);
261: }
263: static PetscErrorCode MatAXPY_SeqDense(Mat Y,PetscScalar alpha,Mat X,MatStructure str)
264: {
265: Mat_SeqDense *x = (Mat_SeqDense*)X->data,*y = (Mat_SeqDense*)Y->data;
266: PetscScalar oalpha = alpha;
267: PetscInt j;
268: PetscBLASInt N,m,ldax,lday,one = 1;
272: PetscBLASIntCast(X->rmap->n*X->cmap->n,&N);
273: PetscBLASIntCast(X->rmap->n,&m);
274: PetscBLASIntCast(x->lda,&ldax);
275: PetscBLASIntCast(y->lda,&lday);
276: if (ldax>m || lday>m) {
277: for (j=0; j<X->cmap->n; j++) {
278: PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&m,&oalpha,x->v+j*ldax,&one,y->v+j*lday,&one));
279: }
280: } else {
281: PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&N,&oalpha,x->v,&one,y->v,&one));
282: }
283: PetscObjectStateIncrease((PetscObject)Y);
284: PetscLogFlops(PetscMax(2*N-1,0));
285: return(0);
286: }
288: static PetscErrorCode MatGetInfo_SeqDense(Mat A,MatInfoType flag,MatInfo *info)
289: {
290: PetscInt N = A->rmap->n*A->cmap->n;
293: info->block_size = 1.0;
294: info->nz_allocated = (double)N;
295: info->nz_used = (double)N;
296: info->nz_unneeded = (double)0;
297: info->assemblies = (double)A->num_ass;
298: info->mallocs = 0;
299: info->memory = ((PetscObject)A)->mem;
300: info->fill_ratio_given = 0;
301: info->fill_ratio_needed = 0;
302: info->factor_mallocs = 0;
303: return(0);
304: }
306: static PetscErrorCode MatScale_SeqDense(Mat A,PetscScalar alpha)
307: {
308: Mat_SeqDense *a = (Mat_SeqDense*)A->data;
309: PetscScalar oalpha = alpha;
311: PetscBLASInt one = 1,j,nz,lda;
314: PetscBLASIntCast(a->lda,&lda);
315: if (lda>A->rmap->n) {
316: PetscBLASIntCast(A->rmap->n,&nz);
317: for (j=0; j<A->cmap->n; j++) {
318: PetscStackCallBLAS("BLASscal",BLASscal_(&nz,&oalpha,a->v+j*lda,&one));
319: }
320: } else {
321: PetscBLASIntCast(A->rmap->n*A->cmap->n,&nz);
322: PetscStackCallBLAS("BLASscal",BLASscal_(&nz,&oalpha,a->v,&one));
323: }
324: PetscLogFlops(nz);
325: return(0);
326: }
328: static PetscErrorCode MatIsHermitian_SeqDense(Mat A,PetscReal rtol,PetscBool *fl)
329: {
330: Mat_SeqDense *a = (Mat_SeqDense*)A->data;
331: PetscInt i,j,m = A->rmap->n,N;
332: PetscScalar *v = a->v;
335: *fl = PETSC_FALSE;
336: if (A->rmap->n != A->cmap->n) return(0);
337: N = a->lda;
339: for (i=0; i<m; i++) {
340: for (j=i+1; j<m; j++) {
341: if (PetscAbsScalar(v[i+j*N] - PetscConj(v[j+i*N])) > rtol) return(0);
342: }
343: }
344: *fl = PETSC_TRUE;
345: return(0);
346: }
348: static PetscErrorCode MatDuplicateNoCreate_SeqDense(Mat newi,Mat A,MatDuplicateOption cpvalues)
349: {
350: Mat_SeqDense *mat = (Mat_SeqDense*)A->data,*l;
352: PetscInt lda = (PetscInt)mat->lda,j,m;
355: PetscLayoutReference(A->rmap,&newi->rmap);
356: PetscLayoutReference(A->cmap,&newi->cmap);
357: MatSeqDenseSetPreallocation(newi,NULL);
358: if (cpvalues == MAT_COPY_VALUES) {
359: l = (Mat_SeqDense*)newi->data;
360: if (lda>A->rmap->n) {
361: m = A->rmap->n;
362: for (j=0; j<A->cmap->n; j++) {
363: PetscMemcpy(l->v+j*m,mat->v+j*lda,m*sizeof(PetscScalar));
364: }
365: } else {
366: PetscMemcpy(l->v,mat->v,A->rmap->n*A->cmap->n*sizeof(PetscScalar));
367: }
368: }
369: newi->assembled = PETSC_TRUE;
370: return(0);
371: }
373: static PetscErrorCode MatDuplicate_SeqDense(Mat A,MatDuplicateOption cpvalues,Mat *newmat)
374: {
378: MatCreate(PetscObjectComm((PetscObject)A),newmat);
379: MatSetSizes(*newmat,A->rmap->n,A->cmap->n,A->rmap->n,A->cmap->n);
380: MatSetType(*newmat,((PetscObject)A)->type_name);
381: MatDuplicateNoCreate_SeqDense(*newmat,A,cpvalues);
382: return(0);
383: }
386: static PetscErrorCode MatLUFactor_SeqDense(Mat,IS,IS,const MatFactorInfo*);
388: static PetscErrorCode MatLUFactorNumeric_SeqDense(Mat fact,Mat A,const MatFactorInfo *info_dummy)
389: {
390: MatFactorInfo info;
394: MatDuplicateNoCreate_SeqDense(fact,A,MAT_COPY_VALUES);
395: MatLUFactor_SeqDense(fact,0,0,&info);
396: return(0);
397: }
399: static PetscErrorCode MatSolve_SeqDense(Mat A,Vec xx,Vec yy)
400: {
401: Mat_SeqDense *mat = (Mat_SeqDense*)A->data;
402: PetscErrorCode ierr;
403: const PetscScalar *x;
404: PetscScalar *y;
405: PetscBLASInt one = 1,info,m;
408: PetscBLASIntCast(A->rmap->n,&m);
409: VecGetArrayRead(xx,&x);
410: VecGetArray(yy,&y);
411: PetscMemcpy(y,x,A->rmap->n*sizeof(PetscScalar));
412: if (A->factortype == MAT_FACTOR_LU) {
413: #if defined(PETSC_MISSING_LAPACK_GETRS)
414: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"GETRS - Lapack routine is unavailable.");
415: #else
416: PetscFPTrapPush(PETSC_FP_TRAP_OFF);
417: PetscStackCallBLAS("LAPACKgetrs",LAPACKgetrs_("N",&m,&one,mat->v,&mat->lda,mat->pivots,y,&m,&info));
418: PetscFPTrapPop();
419: if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"GETRS - Bad solve");
420: #endif
421: } else if (A->factortype == MAT_FACTOR_CHOLESKY) {
422: #if defined(PETSC_MISSING_LAPACK_POTRS)
423: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"POTRS - Lapack routine is unavailable.");
424: #else
425: if (A->spd) {
426: PetscFPTrapPush(PETSC_FP_TRAP_OFF);
427: PetscStackCallBLAS("LAPACKpotrs",LAPACKpotrs_("L",&m,&one,mat->v,&mat->lda,y,&m,&info));
428: PetscFPTrapPop();
429: if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"POTRS Bad solve");
430: #if defined(PETSC_USE_COMPLEX)
431: } else if (A->hermitian) {
432: PetscFPTrapPush(PETSC_FP_TRAP_OFF);
433: PetscStackCallBLAS("LAPACKhetrs",LAPACKhetrs_("L",&m,&one,mat->v,&mat->lda,mat->pivots,y,&m,&info));
434: PetscFPTrapPop();
435: if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"HETRS Bad solve");
436: #endif
437: } else { /* symmetric case */
438: PetscFPTrapPush(PETSC_FP_TRAP_OFF);
439: PetscStackCallBLAS("LAPACKsytrs",LAPACKsytrs_("L",&m,&one,mat->v,&mat->lda,mat->pivots,y,&m,&info));
440: PetscFPTrapPop();
441: if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"SYTRS Bad solve");
442: }
443: #endif
444: } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Matrix must be factored to solve");
445: VecRestoreArrayRead(xx,&x);
446: VecRestoreArray(yy,&y);
447: PetscLogFlops(2.0*A->cmap->n*A->cmap->n - A->cmap->n);
448: return(0);
449: }
451: static PetscErrorCode MatMatSolve_SeqDense(Mat A,Mat B,Mat X)
452: {
453: Mat_SeqDense *mat = (Mat_SeqDense*)A->data;
455: PetscScalar *b,*x;
456: PetscInt n;
457: PetscBLASInt nrhs,info,m;
458: PetscBool flg;
461: PetscBLASIntCast(A->rmap->n,&m);
462: PetscObjectTypeCompareAny((PetscObject)B,&flg,MATSEQDENSE,MATMPIDENSE,NULL);
463: if (!flg) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"Matrix B must be MATDENSE matrix");
464: PetscObjectTypeCompareAny((PetscObject)X,&flg,MATSEQDENSE,MATMPIDENSE,NULL);
465: if (!flg) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"Matrix X must be MATDENSE matrix");
467: MatGetSize(B,NULL,&n);
468: PetscBLASIntCast(n,&nrhs);
469: MatDenseGetArray(B,&b);
470: MatDenseGetArray(X,&x);
472: PetscMemcpy(x,b,m*nrhs*sizeof(PetscScalar));
474: if (A->factortype == MAT_FACTOR_LU) {
475: #if defined(PETSC_MISSING_LAPACK_GETRS)
476: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"GETRS - Lapack routine is unavailable.");
477: #else
478: PetscFPTrapPush(PETSC_FP_TRAP_OFF);
479: PetscStackCallBLAS("LAPACKgetrs",LAPACKgetrs_("N",&m,&nrhs,mat->v,&mat->lda,mat->pivots,x,&m,&info));
480: PetscFPTrapPop();
481: if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"GETRS - Bad solve");
482: #endif
483: } else if (A->factortype == MAT_FACTOR_CHOLESKY) {
484: #if defined(PETSC_MISSING_LAPACK_POTRS)
485: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"POTRS - Lapack routine is unavailable.");
486: #else
487: if (A->spd) {
488: PetscFPTrapPush(PETSC_FP_TRAP_OFF);
489: PetscStackCallBLAS("LAPACKpotrs",LAPACKpotrs_("L",&m,&nrhs,mat->v,&mat->lda,x,&m,&info));
490: PetscFPTrapPop();
491: if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"POTRS Bad solve");
492: #if defined(PETSC_USE_COMPLEX)
493: } else if (A->hermitian) {
494: PetscFPTrapPush(PETSC_FP_TRAP_OFF);
495: PetscStackCallBLAS("LAPACKhetrs",LAPACKhetrs_("L",&m,&nrhs,mat->v,&mat->lda,mat->pivots,x,&m,&info));
496: PetscFPTrapPop();
497: if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"HETRS Bad solve");
498: #endif
499: } else { /* symmetric case */
500: PetscFPTrapPush(PETSC_FP_TRAP_OFF);
501: PetscStackCallBLAS("LAPACKsytrs",LAPACKsytrs_("L",&m,&nrhs,mat->v,&mat->lda,mat->pivots,x,&m,&info));
502: PetscFPTrapPop();
503: if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"SYTRS Bad solve");
504: }
505: #endif
506: } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Matrix must be factored to solve");
508: MatDenseRestoreArray(B,&b);
509: MatDenseRestoreArray(X,&x);
510: PetscLogFlops(nrhs*(2.0*m*m - m));
511: return(0);
512: }
514: static PetscErrorCode MatConjugate_SeqDense(Mat);
516: static PetscErrorCode MatSolveTranspose_SeqDense(Mat A,Vec xx,Vec yy)
517: {
518: Mat_SeqDense *mat = (Mat_SeqDense*)A->data;
519: PetscErrorCode ierr;
520: const PetscScalar *x;
521: PetscScalar *y;
522: PetscBLASInt one = 1,info,m;
525: PetscBLASIntCast(A->rmap->n,&m);
526: VecGetArrayRead(xx,&x);
527: VecGetArray(yy,&y);
528: PetscMemcpy(y,x,A->rmap->n*sizeof(PetscScalar));
529: if (A->factortype == MAT_FACTOR_LU) {
530: #if defined(PETSC_MISSING_LAPACK_GETRS)
531: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"GETRS - Lapack routine is unavailable.");
532: #else
533: PetscFPTrapPush(PETSC_FP_TRAP_OFF);
534: PetscStackCallBLAS("LAPACKgetrs",LAPACKgetrs_("T",&m,&one,mat->v,&mat->lda,mat->pivots,y,&m,&info));
535: PetscFPTrapPop();
536: if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"POTRS - Bad solve");
537: #endif
538: } else if (A->factortype == MAT_FACTOR_CHOLESKY) {
539: #if defined(PETSC_MISSING_LAPACK_POTRS)
540: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"POTRS - Lapack routine is unavailable.");
541: #else
542: if (A->spd) {
543: #if defined(PETSC_USE_COMPLEX)
544: MatConjugate_SeqDense(A);
545: #endif
546: PetscFPTrapPush(PETSC_FP_TRAP_OFF);
547: PetscStackCallBLAS("LAPACKpotrs",LAPACKpotrs_("L",&m,&one,mat->v,&mat->lda,y,&m,&info));
548: PetscFPTrapPop();
549: #if defined(PETSC_USE_COMPLEX)
550: MatConjugate_SeqDense(A);
551: #endif
552: if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"POTRS Bad solve");
553: #if defined(PETSC_USE_COMPLEX)
554: } else if (A->hermitian) {
555: MatConjugate_SeqDense(A);
556: PetscFPTrapPush(PETSC_FP_TRAP_OFF);
557: PetscStackCallBLAS("LAPACKhetrs",LAPACKhetrs_("L",&m,&one,mat->v,&mat->lda,mat->pivots,y,&m,&info));
558: PetscFPTrapPop();
559: MatConjugate_SeqDense(A);
560: #endif
561: } else { /* symmetric case */
562: PetscFPTrapPush(PETSC_FP_TRAP_OFF);
563: PetscStackCallBLAS("LAPACKsytrs",LAPACKsytrs_("L",&m,&one,mat->v,&mat->lda,mat->pivots,y,&m,&info));
564: PetscFPTrapPop();
565: if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"SYTRS Bad solve");
566: }
567: #endif
568: } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Matrix must be factored to solve");
569: VecRestoreArrayRead(xx,&x);
570: VecRestoreArray(yy,&y);
571: PetscLogFlops(2.0*A->cmap->n*A->cmap->n - A->cmap->n);
572: return(0);
573: }
575: static PetscErrorCode MatSolveAdd_SeqDense(Mat A,Vec xx,Vec zz,Vec yy)
576: {
577: PetscErrorCode ierr;
578: const PetscScalar *x;
579: PetscScalar *y,sone = 1.0;
580: Vec tmp = 0;
583: VecGetArrayRead(xx,&x);
584: VecGetArray(yy,&y);
585: if (!A->rmap->n || !A->cmap->n) return(0);
586: if (yy == zz) {
587: VecDuplicate(yy,&tmp);
588: PetscLogObjectParent((PetscObject)A,(PetscObject)tmp);
589: VecCopy(yy,tmp);
590: }
591: MatSolve_SeqDense(A,xx,yy);
592: if (tmp) {
593: VecAXPY(yy,sone,tmp);
594: VecDestroy(&tmp);
595: } else {
596: VecAXPY(yy,sone,zz);
597: }
598: VecRestoreArrayRead(xx,&x);
599: VecRestoreArray(yy,&y);
600: PetscLogFlops(A->cmap->n);
601: return(0);
602: }
604: static PetscErrorCode MatSolveTransposeAdd_SeqDense(Mat A,Vec xx,Vec zz,Vec yy)
605: {
606: PetscErrorCode ierr;
607: const PetscScalar *x;
608: PetscScalar *y,sone = 1.0;
609: Vec tmp = NULL;
612: if (!A->rmap->n || !A->cmap->n) return(0);
613: VecGetArrayRead(xx,&x);
614: VecGetArray(yy,&y);
615: if (yy == zz) {
616: VecDuplicate(yy,&tmp);
617: PetscLogObjectParent((PetscObject)A,(PetscObject)tmp);
618: VecCopy(yy,tmp);
619: }
620: MatSolveTranspose_SeqDense(A,xx,yy);
621: if (tmp) {
622: VecAXPY(yy,sone,tmp);
623: VecDestroy(&tmp);
624: } else {
625: VecAXPY(yy,sone,zz);
626: }
627: VecRestoreArrayRead(xx,&x);
628: VecRestoreArray(yy,&y);
629: PetscLogFlops(A->cmap->n);
630: return(0);
631: }
633: /* ---------------------------------------------------------------*/
634: /* COMMENT: I have chosen to hide row permutation in the pivots,
635: rather than put it in the Mat->row slot.*/
636: static PetscErrorCode MatLUFactor_SeqDense(Mat A,IS row,IS col,const MatFactorInfo *minfo)
637: {
638: #if defined(PETSC_MISSING_LAPACK_GETRF)
640: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"GETRF - Lapack routine is unavailable.");
641: #else
642: Mat_SeqDense *mat = (Mat_SeqDense*)A->data;
644: PetscBLASInt n,m,info;
647: PetscBLASIntCast(A->cmap->n,&n);
648: PetscBLASIntCast(A->rmap->n,&m);
649: if (!mat->pivots) {
650: PetscMalloc1(A->rmap->n,&mat->pivots);
651: PetscLogObjectMemory((PetscObject)A,A->rmap->n*sizeof(PetscBLASInt));
652: }
653: if (!A->rmap->n || !A->cmap->n) return(0);
654: PetscFPTrapPush(PETSC_FP_TRAP_OFF);
655: PetscStackCallBLAS("LAPACKgetrf",LAPACKgetrf_(&m,&n,mat->v,&mat->lda,mat->pivots,&info));
656: PetscFPTrapPop();
658: if (info<0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Bad argument to LU factorization");
659: if (info>0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MAT_LU_ZRPVT,"Bad LU factorization");
661: A->ops->solve = MatSolve_SeqDense;
662: A->ops->matsolve = MatMatSolve_SeqDense;
663: A->ops->solvetranspose = MatSolveTranspose_SeqDense;
664: A->ops->solveadd = MatSolveAdd_SeqDense;
665: A->ops->solvetransposeadd = MatSolveTransposeAdd_SeqDense;
666: A->factortype = MAT_FACTOR_LU;
668: PetscFree(A->solvertype);
669: PetscStrallocpy(MATSOLVERPETSC,&A->solvertype);
671: PetscLogFlops((2.0*A->cmap->n*A->cmap->n*A->cmap->n)/3);
672: #endif
673: return(0);
674: }
676: /* Cholesky as L*L^T or L*D*L^T and the symmetric/hermitian complex variants */
677: static PetscErrorCode MatCholeskyFactor_SeqDense(Mat A,IS perm,const MatFactorInfo *factinfo)
678: {
679: #if defined(PETSC_MISSING_LAPACK_POTRF)
681: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"POTRF - Lapack routine is unavailable.");
682: #else
683: Mat_SeqDense *mat = (Mat_SeqDense*)A->data;
685: PetscBLASInt info,n;
688: PetscBLASIntCast(A->cmap->n,&n);
689: if (!A->rmap->n || !A->cmap->n) return(0);
690: if (A->spd) {
691: PetscFPTrapPush(PETSC_FP_TRAP_OFF);
692: PetscStackCallBLAS("LAPACKpotrf",LAPACKpotrf_("L",&n,mat->v,&mat->lda,&info));
693: PetscFPTrapPop();
694: #if defined(PETSC_USE_COMPLEX)
695: } else if (A->hermitian) {
696: if (!mat->pivots) {
697: PetscMalloc1(A->rmap->n,&mat->pivots);
698: PetscLogObjectMemory((PetscObject)A,A->rmap->n*sizeof(PetscBLASInt));
699: }
700: if (!mat->fwork) {
701: PetscScalar dummy;
703: mat->lfwork = -1;
704: PetscFPTrapPush(PETSC_FP_TRAP_OFF);
705: PetscStackCallBLAS("LAPACKhetrf",LAPACKhetrf_("L",&n,mat->v,&mat->lda,mat->pivots,&dummy,&mat->lfwork,&info));
706: PetscFPTrapPop();
707: mat->lfwork = (PetscInt)PetscRealPart(dummy);
708: PetscMalloc1(mat->lfwork,&mat->fwork);
709: PetscLogObjectMemory((PetscObject)A,mat->lfwork*sizeof(PetscBLASInt));
710: }
711: PetscFPTrapPush(PETSC_FP_TRAP_OFF);
712: PetscStackCallBLAS("LAPACKhetrf",LAPACKhetrf_("L",&n,mat->v,&mat->lda,mat->pivots,mat->fwork,&mat->lfwork,&info));
713: PetscFPTrapPop();
714: #endif
715: } else { /* symmetric case */
716: if (!mat->pivots) {
717: PetscMalloc1(A->rmap->n,&mat->pivots);
718: PetscLogObjectMemory((PetscObject)A,A->rmap->n*sizeof(PetscBLASInt));
719: }
720: if (!mat->fwork) {
721: PetscScalar dummy;
723: mat->lfwork = -1;
724: PetscFPTrapPush(PETSC_FP_TRAP_OFF);
725: PetscStackCallBLAS("LAPACKsytrf",LAPACKsytrf_("L",&n,mat->v,&mat->lda,mat->pivots,&dummy,&mat->lfwork,&info));
726: PetscFPTrapPop();
727: mat->lfwork = (PetscInt)PetscRealPart(dummy);
728: PetscMalloc1(mat->lfwork,&mat->fwork);
729: PetscLogObjectMemory((PetscObject)A,mat->lfwork*sizeof(PetscBLASInt));
730: }
731: PetscFPTrapPush(PETSC_FP_TRAP_OFF);
732: PetscStackCallBLAS("LAPACKsytrf",LAPACKsytrf_("L",&n,mat->v,&mat->lda,mat->pivots,mat->fwork,&mat->lfwork,&info));
733: PetscFPTrapPop();
734: }
735: if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_MAT_CH_ZRPVT,"Bad factorization: zero pivot in row %D",(PetscInt)info-1);
737: A->ops->solve = MatSolve_SeqDense;
738: A->ops->matsolve = MatMatSolve_SeqDense;
739: A->ops->solvetranspose = MatSolveTranspose_SeqDense;
740: A->ops->solveadd = MatSolveAdd_SeqDense;
741: A->ops->solvetransposeadd = MatSolveTransposeAdd_SeqDense;
742: A->factortype = MAT_FACTOR_CHOLESKY;
744: PetscFree(A->solvertype);
745: PetscStrallocpy(MATSOLVERPETSC,&A->solvertype);
747: PetscLogFlops((1.0*A->cmap->n*A->cmap->n*A->cmap->n)/3.0);
748: #endif
749: return(0);
750: }
753: PetscErrorCode MatCholeskyFactorNumeric_SeqDense(Mat fact,Mat A,const MatFactorInfo *info_dummy)
754: {
756: MatFactorInfo info;
759: info.fill = 1.0;
761: MatDuplicateNoCreate_SeqDense(fact,A,MAT_COPY_VALUES);
762: MatCholeskyFactor_SeqDense(fact,0,&info);
763: return(0);
764: }
766: static PetscErrorCode MatCholeskyFactorSymbolic_SeqDense(Mat fact,Mat A,IS row,const MatFactorInfo *info)
767: {
769: fact->assembled = PETSC_TRUE;
770: fact->preallocated = PETSC_TRUE;
771: fact->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqDense;
772: fact->ops->solve = MatSolve_SeqDense;
773: fact->ops->matsolve = MatMatSolve_SeqDense;
774: fact->ops->solvetranspose = MatSolveTranspose_SeqDense;
775: fact->ops->solveadd = MatSolveAdd_SeqDense;
776: fact->ops->solvetransposeadd = MatSolveTransposeAdd_SeqDense;
777: return(0);
778: }
780: static PetscErrorCode MatLUFactorSymbolic_SeqDense(Mat fact,Mat A,IS row,IS col,const MatFactorInfo *info)
781: {
783: fact->preallocated = PETSC_TRUE;
784: fact->assembled = PETSC_TRUE;
785: fact->ops->lufactornumeric = MatLUFactorNumeric_SeqDense;
786: fact->ops->solve = MatSolve_SeqDense;
787: fact->ops->matsolve = MatMatSolve_SeqDense;
788: fact->ops->solvetranspose = MatSolveTranspose_SeqDense;
789: fact->ops->solveadd = MatSolveAdd_SeqDense;
790: fact->ops->solvetransposeadd = MatSolveTransposeAdd_SeqDense;
791: return(0);
792: }
794: PETSC_INTERN PetscErrorCode MatGetFactor_seqdense_petsc(Mat A,MatFactorType ftype,Mat *fact)
795: {
799: MatCreate(PetscObjectComm((PetscObject)A),fact);
800: MatSetSizes(*fact,A->rmap->n,A->cmap->n,A->rmap->n,A->cmap->n);
801: MatSetType(*fact,((PetscObject)A)->type_name);
802: if (ftype == MAT_FACTOR_LU) {
803: (*fact)->ops->lufactorsymbolic = MatLUFactorSymbolic_SeqDense;
804: } else {
805: (*fact)->ops->choleskyfactorsymbolic = MatCholeskyFactorSymbolic_SeqDense;
806: }
807: (*fact)->factortype = ftype;
809: PetscFree((*fact)->solvertype);
810: PetscStrallocpy(MATSOLVERPETSC,&(*fact)->solvertype);
811: return(0);
812: }
814: /* ------------------------------------------------------------------*/
815: static PetscErrorCode MatSOR_SeqDense(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal shift,PetscInt its,PetscInt lits,Vec xx)
816: {
817: Mat_SeqDense *mat = (Mat_SeqDense*)A->data;
818: PetscScalar *x,*v = mat->v,zero = 0.0,xt;
819: const PetscScalar *b;
820: PetscErrorCode ierr;
821: PetscInt m = A->rmap->n,i;
822: PetscBLASInt o = 1,bm;
825: if (shift == -1) shift = 0.0; /* negative shift indicates do not error on zero diagonal; this code never zeros on zero diagonal */
826: PetscBLASIntCast(m,&bm);
827: if (flag & SOR_ZERO_INITIAL_GUESS) {
828: /* this is a hack fix, should have another version without the second BLASdotu */
829: VecSet(xx,zero);
830: }
831: VecGetArray(xx,&x);
832: VecGetArrayRead(bb,&b);
833: its = its*lits;
834: if (its <= 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Relaxation requires global its %D and local its %D both positive",its,lits);
835: while (its--) {
836: if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
837: for (i=0; i<m; i++) {
838: PetscStackCallBLAS("BLASdotu",xt = b[i] - BLASdotu_(&bm,v+i,&bm,x,&o));
839: x[i] = (1. - omega)*x[i] + omega*(xt+v[i + i*m]*x[i])/(v[i + i*m]+shift);
840: }
841: }
842: if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
843: for (i=m-1; i>=0; i--) {
844: PetscStackCallBLAS("BLASdotu",xt = b[i] - BLASdotu_(&bm,v+i,&bm,x,&o));
845: x[i] = (1. - omega)*x[i] + omega*(xt+v[i + i*m]*x[i])/(v[i + i*m]+shift);
846: }
847: }
848: }
849: VecRestoreArrayRead(bb,&b);
850: VecRestoreArray(xx,&x);
851: return(0);
852: }
854: /* -----------------------------------------------------------------*/
855: PETSC_INTERN PetscErrorCode MatMultTranspose_SeqDense(Mat A,Vec xx,Vec yy)
856: {
857: Mat_SeqDense *mat = (Mat_SeqDense*)A->data;
858: const PetscScalar *v = mat->v,*x;
859: PetscScalar *y;
860: PetscErrorCode ierr;
861: PetscBLASInt m, n,_One=1;
862: PetscScalar _DOne=1.0,_DZero=0.0;
865: PetscBLASIntCast(A->rmap->n,&m);
866: PetscBLASIntCast(A->cmap->n,&n);
867: VecGetArrayRead(xx,&x);
868: VecGetArray(yy,&y);
869: if (!A->rmap->n || !A->cmap->n) {
870: PetscBLASInt i;
871: for (i=0; i<n; i++) y[i] = 0.0;
872: } else {
873: PetscStackCallBLAS("BLASgemv",BLASgemv_("T",&m,&n,&_DOne,v,&mat->lda,x,&_One,&_DZero,y,&_One));
874: PetscLogFlops(2.0*A->rmap->n*A->cmap->n - A->cmap->n);
875: }
876: VecRestoreArrayRead(xx,&x);
877: VecRestoreArray(yy,&y);
878: return(0);
879: }
881: PETSC_INTERN PetscErrorCode MatMult_SeqDense(Mat A,Vec xx,Vec yy)
882: {
883: Mat_SeqDense *mat = (Mat_SeqDense*)A->data;
884: PetscScalar *y,_DOne=1.0,_DZero=0.0;
885: PetscErrorCode ierr;
886: PetscBLASInt m, n, _One=1;
887: const PetscScalar *v = mat->v,*x;
890: PetscBLASIntCast(A->rmap->n,&m);
891: PetscBLASIntCast(A->cmap->n,&n);
892: VecGetArrayRead(xx,&x);
893: VecGetArray(yy,&y);
894: if (!A->rmap->n || !A->cmap->n) {
895: PetscBLASInt i;
896: for (i=0; i<m; i++) y[i] = 0.0;
897: } else {
898: PetscStackCallBLAS("BLASgemv",BLASgemv_("N",&m,&n,&_DOne,v,&(mat->lda),x,&_One,&_DZero,y,&_One));
899: PetscLogFlops(2.0*A->rmap->n*A->cmap->n - A->rmap->n);
900: }
901: VecRestoreArrayRead(xx,&x);
902: VecRestoreArray(yy,&y);
903: return(0);
904: }
906: PETSC_INTERN PetscErrorCode MatMultAdd_SeqDense(Mat A,Vec xx,Vec zz,Vec yy)
907: {
908: Mat_SeqDense *mat = (Mat_SeqDense*)A->data;
909: const PetscScalar *v = mat->v,*x;
910: PetscScalar *y,_DOne=1.0;
911: PetscErrorCode ierr;
912: PetscBLASInt m, n, _One=1;
915: PetscBLASIntCast(A->rmap->n,&m);
916: PetscBLASIntCast(A->cmap->n,&n);
917: if (!A->rmap->n || !A->cmap->n) return(0);
918: if (zz != yy) {VecCopy(zz,yy);}
919: VecGetArrayRead(xx,&x);
920: VecGetArray(yy,&y);
921: PetscStackCallBLAS("BLASgemv",BLASgemv_("N",&m,&n,&_DOne,v,&(mat->lda),x,&_One,&_DOne,y,&_One));
922: VecRestoreArrayRead(xx,&x);
923: VecRestoreArray(yy,&y);
924: PetscLogFlops(2.0*A->rmap->n*A->cmap->n);
925: return(0);
926: }
928: static PetscErrorCode MatMultTransposeAdd_SeqDense(Mat A,Vec xx,Vec zz,Vec yy)
929: {
930: Mat_SeqDense *mat = (Mat_SeqDense*)A->data;
931: const PetscScalar *v = mat->v,*x;
932: PetscScalar *y;
933: PetscErrorCode ierr;
934: PetscBLASInt m, n, _One=1;
935: PetscScalar _DOne=1.0;
938: PetscBLASIntCast(A->rmap->n,&m);
939: PetscBLASIntCast(A->cmap->n,&n);
940: if (!A->rmap->n || !A->cmap->n) return(0);
941: if (zz != yy) {VecCopy(zz,yy);}
942: VecGetArrayRead(xx,&x);
943: VecGetArray(yy,&y);
944: PetscStackCallBLAS("BLASgemv",BLASgemv_("T",&m,&n,&_DOne,v,&(mat->lda),x,&_One,&_DOne,y,&_One));
945: VecRestoreArrayRead(xx,&x);
946: VecRestoreArray(yy,&y);
947: PetscLogFlops(2.0*A->rmap->n*A->cmap->n);
948: return(0);
949: }
951: /* -----------------------------------------------------------------*/
952: static PetscErrorCode MatGetRow_SeqDense(Mat A,PetscInt row,PetscInt *ncols,PetscInt **cols,PetscScalar **vals)
953: {
954: Mat_SeqDense *mat = (Mat_SeqDense*)A->data;
955: PetscScalar *v;
957: PetscInt i;
960: *ncols = A->cmap->n;
961: if (cols) {
962: PetscMalloc1(A->cmap->n+1,cols);
963: for (i=0; i<A->cmap->n; i++) (*cols)[i] = i;
964: }
965: if (vals) {
966: PetscMalloc1(A->cmap->n+1,vals);
967: v = mat->v + row;
968: for (i=0; i<A->cmap->n; i++) {(*vals)[i] = *v; v += mat->lda;}
969: }
970: return(0);
971: }
973: static PetscErrorCode MatRestoreRow_SeqDense(Mat A,PetscInt row,PetscInt *ncols,PetscInt **cols,PetscScalar **vals)
974: {
978: if (cols) {PetscFree(*cols);}
979: if (vals) {PetscFree(*vals); }
980: return(0);
981: }
982: /* ----------------------------------------------------------------*/
983: static PetscErrorCode MatSetValues_SeqDense(Mat A,PetscInt m,const PetscInt indexm[],PetscInt n,const PetscInt indexn[],const PetscScalar v[],InsertMode addv)
984: {
985: Mat_SeqDense *mat = (Mat_SeqDense*)A->data;
986: PetscInt i,j,idx=0;
989: if (!mat->roworiented) {
990: if (addv == INSERT_VALUES) {
991: for (j=0; j<n; j++) {
992: if (indexn[j] < 0) {idx += m; continue;}
993: #if defined(PETSC_USE_DEBUG)
994: if (indexn[j] >= A->cmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",indexn[j],A->cmap->n-1);
995: #endif
996: for (i=0; i<m; i++) {
997: if (indexm[i] < 0) {idx++; continue;}
998: #if defined(PETSC_USE_DEBUG)
999: if (indexm[i] >= A->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",indexm[i],A->rmap->n-1);
1000: #endif
1001: mat->v[indexn[j]*mat->lda + indexm[i]] = v[idx++];
1002: }
1003: }
1004: } else {
1005: for (j=0; j<n; j++) {
1006: if (indexn[j] < 0) {idx += m; continue;}
1007: #if defined(PETSC_USE_DEBUG)
1008: if (indexn[j] >= A->cmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",indexn[j],A->cmap->n-1);
1009: #endif
1010: for (i=0; i<m; i++) {
1011: if (indexm[i] < 0) {idx++; continue;}
1012: #if defined(PETSC_USE_DEBUG)
1013: if (indexm[i] >= A->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",indexm[i],A->rmap->n-1);
1014: #endif
1015: mat->v[indexn[j]*mat->lda + indexm[i]] += v[idx++];
1016: }
1017: }
1018: }
1019: } else {
1020: if (addv == INSERT_VALUES) {
1021: for (i=0; i<m; i++) {
1022: if (indexm[i] < 0) { idx += n; continue;}
1023: #if defined(PETSC_USE_DEBUG)
1024: if (indexm[i] >= A->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",indexm[i],A->rmap->n-1);
1025: #endif
1026: for (j=0; j<n; j++) {
1027: if (indexn[j] < 0) { idx++; continue;}
1028: #if defined(PETSC_USE_DEBUG)
1029: if (indexn[j] >= A->cmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",indexn[j],A->cmap->n-1);
1030: #endif
1031: mat->v[indexn[j]*mat->lda + indexm[i]] = v[idx++];
1032: }
1033: }
1034: } else {
1035: for (i=0; i<m; i++) {
1036: if (indexm[i] < 0) { idx += n; continue;}
1037: #if defined(PETSC_USE_DEBUG)
1038: if (indexm[i] >= A->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",indexm[i],A->rmap->n-1);
1039: #endif
1040: for (j=0; j<n; j++) {
1041: if (indexn[j] < 0) { idx++; continue;}
1042: #if defined(PETSC_USE_DEBUG)
1043: if (indexn[j] >= A->cmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",indexn[j],A->cmap->n-1);
1044: #endif
1045: mat->v[indexn[j]*mat->lda + indexm[i]] += v[idx++];
1046: }
1047: }
1048: }
1049: }
1050: return(0);
1051: }
1053: static PetscErrorCode MatGetValues_SeqDense(Mat A,PetscInt m,const PetscInt indexm[],PetscInt n,const PetscInt indexn[],PetscScalar v[])
1054: {
1055: Mat_SeqDense *mat = (Mat_SeqDense*)A->data;
1056: PetscInt i,j;
1059: /* row-oriented output */
1060: for (i=0; i<m; i++) {
1061: if (indexm[i] < 0) {v += n;continue;}
1062: if (indexm[i] >= A->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row %D requested larger than number rows %D",indexm[i],A->rmap->n);
1063: for (j=0; j<n; j++) {
1064: if (indexn[j] < 0) {v++; continue;}
1065: if (indexn[j] >= A->cmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column %D requested larger than number columns %D",indexn[j],A->cmap->n);
1066: *v++ = mat->v[indexn[j]*mat->lda + indexm[i]];
1067: }
1068: }
1069: return(0);
1070: }
1072: /* -----------------------------------------------------------------*/
1074: static PetscErrorCode MatLoad_SeqDense(Mat newmat,PetscViewer viewer)
1075: {
1076: Mat_SeqDense *a;
1078: PetscInt *scols,i,j,nz,header[4];
1079: int fd;
1080: PetscMPIInt size;
1081: PetscInt *rowlengths = 0,M,N,*cols,grows,gcols;
1082: PetscScalar *vals,*svals,*v,*w;
1083: MPI_Comm comm;
1084: PetscBool isbinary;
1087: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);
1088: if (!isbinary) SETERRQ2(PetscObjectComm((PetscObject)newmat),PETSC_ERR_SUP,"Viewer type %s not yet supported for reading %s matrices",((PetscObject)viewer)->type_name,((PetscObject)newmat)->type_name);
1090: /* force binary viewer to load .info file if it has not yet done so */
1091: PetscViewerSetUp(viewer);
1092: PetscObjectGetComm((PetscObject)viewer,&comm);
1093: MPI_Comm_size(comm,&size);
1094: if (size > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"view must have one processor");
1095: PetscViewerBinaryGetDescriptor(viewer,&fd);
1096: PetscBinaryRead(fd,header,4,PETSC_INT);
1097: if (header[0] != MAT_FILE_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Not matrix object");
1098: M = header[1]; N = header[2]; nz = header[3];
1100: /* set global size if not set already*/
1101: if (newmat->rmap->n < 0 && newmat->rmap->N < 0 && newmat->cmap->n < 0 && newmat->cmap->N < 0) {
1102: MatSetSizes(newmat,M,N,M,N);
1103: } else {
1104: /* if sizes and type are already set, check if the vector global sizes are correct */
1105: MatGetSize(newmat,&grows,&gcols);
1106: if (M != grows || N != gcols) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED, "Matrix in file of different length (%d, %d) than the input matrix (%d, %d)",M,N,grows,gcols);
1107: }
1108: a = (Mat_SeqDense*)newmat->data;
1109: if (!a->user_alloc) {
1110: MatSeqDenseSetPreallocation(newmat,NULL);
1111: }
1113: if (nz == MATRIX_BINARY_FORMAT_DENSE) { /* matrix in file is dense */
1114: a = (Mat_SeqDense*)newmat->data;
1115: v = a->v;
1116: /* Allocate some temp space to read in the values and then flip them
1117: from row major to column major */
1118: PetscMalloc1(M*N > 0 ? M*N : 1,&w);
1119: /* read in nonzero values */
1120: PetscBinaryRead(fd,w,M*N,PETSC_SCALAR);
1121: /* now flip the values and store them in the matrix*/
1122: for (j=0; j<N; j++) {
1123: for (i=0; i<M; i++) {
1124: *v++ =w[i*N+j];
1125: }
1126: }
1127: PetscFree(w);
1128: } else {
1129: /* read row lengths */
1130: PetscMalloc1(M+1,&rowlengths);
1131: PetscBinaryRead(fd,rowlengths,M,PETSC_INT);
1133: a = (Mat_SeqDense*)newmat->data;
1134: v = a->v;
1136: /* read column indices and nonzeros */
1137: PetscMalloc1(nz+1,&scols);
1138: cols = scols;
1139: PetscBinaryRead(fd,cols,nz,PETSC_INT);
1140: PetscMalloc1(nz+1,&svals);
1141: vals = svals;
1142: PetscBinaryRead(fd,vals,nz,PETSC_SCALAR);
1144: /* insert into matrix */
1145: for (i=0; i<M; i++) {
1146: for (j=0; j<rowlengths[i]; j++) v[i+M*scols[j]] = svals[j];
1147: svals += rowlengths[i]; scols += rowlengths[i];
1148: }
1149: PetscFree(vals);
1150: PetscFree(cols);
1151: PetscFree(rowlengths);
1152: }
1153: MatAssemblyBegin(newmat,MAT_FINAL_ASSEMBLY);
1154: MatAssemblyEnd(newmat,MAT_FINAL_ASSEMBLY);
1155: return(0);
1156: }
1158: static PetscErrorCode MatView_SeqDense_ASCII(Mat A,PetscViewer viewer)
1159: {
1160: Mat_SeqDense *a = (Mat_SeqDense*)A->data;
1161: PetscErrorCode ierr;
1162: PetscInt i,j;
1163: const char *name;
1164: PetscScalar *v;
1165: PetscViewerFormat format;
1166: #if defined(PETSC_USE_COMPLEX)
1167: PetscBool allreal = PETSC_TRUE;
1168: #endif
1171: PetscViewerGetFormat(viewer,&format);
1172: if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1173: return(0); /* do nothing for now */
1174: } else if (format == PETSC_VIEWER_ASCII_COMMON) {
1175: PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);
1176: for (i=0; i<A->rmap->n; i++) {
1177: v = a->v + i;
1178: PetscViewerASCIIPrintf(viewer,"row %D:",i);
1179: for (j=0; j<A->cmap->n; j++) {
1180: #if defined(PETSC_USE_COMPLEX)
1181: if (PetscRealPart(*v) != 0.0 && PetscImaginaryPart(*v) != 0.0) {
1182: PetscViewerASCIIPrintf(viewer," (%D, %g + %g i) ",j,(double)PetscRealPart(*v),(double)PetscImaginaryPart(*v));
1183: } else if (PetscRealPart(*v)) {
1184: PetscViewerASCIIPrintf(viewer," (%D, %g) ",j,(double)PetscRealPart(*v));
1185: }
1186: #else
1187: if (*v) {
1188: PetscViewerASCIIPrintf(viewer," (%D, %g) ",j,(double)*v);
1189: }
1190: #endif
1191: v += a->lda;
1192: }
1193: PetscViewerASCIIPrintf(viewer,"\n");
1194: }
1195: PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);
1196: } else {
1197: PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);
1198: #if defined(PETSC_USE_COMPLEX)
1199: /* determine if matrix has all real values */
1200: v = a->v;
1201: for (i=0; i<A->rmap->n*A->cmap->n; i++) {
1202: if (PetscImaginaryPart(v[i])) { allreal = PETSC_FALSE; break;}
1203: }
1204: #endif
1205: if (format == PETSC_VIEWER_ASCII_MATLAB) {
1206: PetscObjectGetName((PetscObject)A,&name);
1207: PetscViewerASCIIPrintf(viewer,"%% Size = %D %D \n",A->rmap->n,A->cmap->n);
1208: PetscViewerASCIIPrintf(viewer,"%s = zeros(%D,%D);\n",name,A->rmap->n,A->cmap->n);
1209: PetscViewerASCIIPrintf(viewer,"%s = [\n",name);
1210: }
1212: for (i=0; i<A->rmap->n; i++) {
1213: v = a->v + i;
1214: for (j=0; j<A->cmap->n; j++) {
1215: #if defined(PETSC_USE_COMPLEX)
1216: if (allreal) {
1217: PetscViewerASCIIPrintf(viewer,"%18.16e ",(double)PetscRealPart(*v));
1218: } else {
1219: PetscViewerASCIIPrintf(viewer,"%18.16e + %18.16ei ",(double)PetscRealPart(*v),(double)PetscImaginaryPart(*v));
1220: }
1221: #else
1222: PetscViewerASCIIPrintf(viewer,"%18.16e ",(double)*v);
1223: #endif
1224: v += a->lda;
1225: }
1226: PetscViewerASCIIPrintf(viewer,"\n");
1227: }
1228: if (format == PETSC_VIEWER_ASCII_MATLAB) {
1229: PetscViewerASCIIPrintf(viewer,"];\n");
1230: }
1231: PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);
1232: }
1233: PetscViewerFlush(viewer);
1234: return(0);
1235: }
1237: static PetscErrorCode MatView_SeqDense_Binary(Mat A,PetscViewer viewer)
1238: {
1239: Mat_SeqDense *a = (Mat_SeqDense*)A->data;
1240: PetscErrorCode ierr;
1241: int fd;
1242: PetscInt ict,j,n = A->cmap->n,m = A->rmap->n,i,*col_lens,nz = m*n;
1243: PetscScalar *v,*anonz,*vals;
1244: PetscViewerFormat format;
1247: PetscViewerBinaryGetDescriptor(viewer,&fd);
1249: PetscViewerGetFormat(viewer,&format);
1250: if (format == PETSC_VIEWER_NATIVE) {
1251: /* store the matrix as a dense matrix */
1252: PetscMalloc1(4,&col_lens);
1254: col_lens[0] = MAT_FILE_CLASSID;
1255: col_lens[1] = m;
1256: col_lens[2] = n;
1257: col_lens[3] = MATRIX_BINARY_FORMAT_DENSE;
1259: PetscBinaryWrite(fd,col_lens,4,PETSC_INT,PETSC_TRUE);
1260: PetscFree(col_lens);
1262: /* write out matrix, by rows */
1263: PetscMalloc1(m*n+1,&vals);
1264: v = a->v;
1265: for (j=0; j<n; j++) {
1266: for (i=0; i<m; i++) {
1267: vals[j + i*n] = *v++;
1268: }
1269: }
1270: PetscBinaryWrite(fd,vals,n*m,PETSC_SCALAR,PETSC_FALSE);
1271: PetscFree(vals);
1272: } else {
1273: PetscMalloc1(4+nz,&col_lens);
1275: col_lens[0] = MAT_FILE_CLASSID;
1276: col_lens[1] = m;
1277: col_lens[2] = n;
1278: col_lens[3] = nz;
1280: /* store lengths of each row and write (including header) to file */
1281: for (i=0; i<m; i++) col_lens[4+i] = n;
1282: PetscBinaryWrite(fd,col_lens,4+m,PETSC_INT,PETSC_TRUE);
1284: /* Possibly should write in smaller increments, not whole matrix at once? */
1285: /* store column indices (zero start index) */
1286: ict = 0;
1287: for (i=0; i<m; i++) {
1288: for (j=0; j<n; j++) col_lens[ict++] = j;
1289: }
1290: PetscBinaryWrite(fd,col_lens,nz,PETSC_INT,PETSC_FALSE);
1291: PetscFree(col_lens);
1293: /* store nonzero values */
1294: PetscMalloc1(nz+1,&anonz);
1295: ict = 0;
1296: for (i=0; i<m; i++) {
1297: v = a->v + i;
1298: for (j=0; j<n; j++) {
1299: anonz[ict++] = *v; v += a->lda;
1300: }
1301: }
1302: PetscBinaryWrite(fd,anonz,nz,PETSC_SCALAR,PETSC_FALSE);
1303: PetscFree(anonz);
1304: }
1305: return(0);
1306: }
1308: #include <petscdraw.h>
1309: static PetscErrorCode MatView_SeqDense_Draw_Zoom(PetscDraw draw,void *Aa)
1310: {
1311: Mat A = (Mat) Aa;
1312: Mat_SeqDense *a = (Mat_SeqDense*)A->data;
1313: PetscErrorCode ierr;
1314: PetscInt m = A->rmap->n,n = A->cmap->n,i,j;
1315: int color = PETSC_DRAW_WHITE;
1316: PetscScalar *v = a->v;
1317: PetscViewer viewer;
1318: PetscReal xl,yl,xr,yr,x_l,x_r,y_l,y_r;
1319: PetscViewerFormat format;
1322: PetscObjectQuery((PetscObject)A,"Zoomviewer",(PetscObject*)&viewer);
1323: PetscViewerGetFormat(viewer,&format);
1324: PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);
1326: /* Loop over matrix elements drawing boxes */
1328: if (format != PETSC_VIEWER_DRAW_CONTOUR) {
1329: PetscDrawCollectiveBegin(draw);
1330: /* Blue for negative and Red for positive */
1331: for (j = 0; j < n; j++) {
1332: x_l = j; x_r = x_l + 1.0;
1333: for (i = 0; i < m; i++) {
1334: y_l = m - i - 1.0;
1335: y_r = y_l + 1.0;
1336: if (PetscRealPart(v[j*m+i]) > 0.) {
1337: color = PETSC_DRAW_RED;
1338: } else if (PetscRealPart(v[j*m+i]) < 0.) {
1339: color = PETSC_DRAW_BLUE;
1340: } else {
1341: continue;
1342: }
1343: PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);
1344: }
1345: }
1346: PetscDrawCollectiveEnd(draw);
1347: } else {
1348: /* use contour shading to indicate magnitude of values */
1349: /* first determine max of all nonzero values */
1350: PetscReal minv = 0.0, maxv = 0.0;
1351: PetscDraw popup;
1353: for (i=0; i < m*n; i++) {
1354: if (PetscAbsScalar(v[i]) > maxv) maxv = PetscAbsScalar(v[i]);
1355: }
1356: if (minv >= maxv) maxv = minv + PETSC_SMALL;
1357: PetscDrawGetPopup(draw,&popup);
1358: PetscDrawScalePopup(popup,minv,maxv);
1360: PetscDrawCollectiveBegin(draw);
1361: for (j=0; j<n; j++) {
1362: x_l = j;
1363: x_r = x_l + 1.0;
1364: for (i=0; i<m; i++) {
1365: y_l = m - i - 1.0;
1366: y_r = y_l + 1.0;
1367: color = PetscDrawRealToColor(PetscAbsScalar(v[j*m+i]),minv,maxv);
1368: PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);
1369: }
1370: }
1371: PetscDrawCollectiveEnd(draw);
1372: }
1373: return(0);
1374: }
1376: static PetscErrorCode MatView_SeqDense_Draw(Mat A,PetscViewer viewer)
1377: {
1378: PetscDraw draw;
1379: PetscBool isnull;
1380: PetscReal xr,yr,xl,yl,h,w;
1384: PetscViewerDrawGetDraw(viewer,0,&draw);
1385: PetscDrawIsNull(draw,&isnull);
1386: if (isnull) return(0);
1388: xr = A->cmap->n; yr = A->rmap->n; h = yr/10.0; w = xr/10.0;
1389: xr += w; yr += h; xl = -w; yl = -h;
1390: PetscDrawSetCoordinates(draw,xl,yl,xr,yr);
1391: PetscObjectCompose((PetscObject)A,"Zoomviewer",(PetscObject)viewer);
1392: PetscDrawZoom(draw,MatView_SeqDense_Draw_Zoom,A);
1393: PetscObjectCompose((PetscObject)A,"Zoomviewer",NULL);
1394: PetscDrawSave(draw);
1395: return(0);
1396: }
1398: PetscErrorCode MatView_SeqDense(Mat A,PetscViewer viewer)
1399: {
1401: PetscBool iascii,isbinary,isdraw;
1404: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
1405: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);
1406: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);
1408: if (iascii) {
1409: MatView_SeqDense_ASCII(A,viewer);
1410: } else if (isbinary) {
1411: MatView_SeqDense_Binary(A,viewer);
1412: } else if (isdraw) {
1413: MatView_SeqDense_Draw(A,viewer);
1414: }
1415: return(0);
1416: }
1418: static PetscErrorCode MatDensePlaceArray_SeqDense(Mat A,const PetscScalar array[])
1419: {
1420: Mat_SeqDense *a = (Mat_SeqDense*)A->data;
1423: a->unplacedarray = a->v;
1424: a->unplaced_user_alloc = a->user_alloc;
1425: a->v = (PetscScalar*) array;
1426: return(0);
1427: }
1429: static PetscErrorCode MatDenseResetArray_SeqDense(Mat A)
1430: {
1431: Mat_SeqDense *a = (Mat_SeqDense*)A->data;
1434: a->v = a->unplacedarray;
1435: a->user_alloc = a->unplaced_user_alloc;
1436: a->unplacedarray = NULL;
1437: return(0);
1438: }
1440: static PetscErrorCode MatDestroy_SeqDense(Mat mat)
1441: {
1442: Mat_SeqDense *l = (Mat_SeqDense*)mat->data;
1446: #if defined(PETSC_USE_LOG)
1447: PetscLogObjectState((PetscObject)mat,"Rows %D Cols %D",mat->rmap->n,mat->cmap->n);
1448: #endif
1449: PetscFree(l->pivots);
1450: PetscFree(l->fwork);
1451: MatDestroy(&l->ptapwork);
1452: if (!l->user_alloc) {PetscFree(l->v);}
1453: PetscFree(mat->data);
1455: PetscObjectChangeTypeName((PetscObject)mat,0);
1456: PetscObjectComposeFunction((PetscObject)mat,"MatDenseGetArray_C",NULL);
1457: PetscObjectComposeFunction((PetscObject)mat,"MatDensePlaceArray_C",NULL);
1458: PetscObjectComposeFunction((PetscObject)mat,"MatDenseResetArray_C",NULL);
1459: PetscObjectComposeFunction((PetscObject)mat,"MatDenseRestoreArray_C",NULL);
1460: PetscObjectComposeFunction((PetscObject)mat,"MatConvert_seqdense_seqaij_C",NULL);
1461: #if defined(PETSC_HAVE_ELEMENTAL)
1462: PetscObjectComposeFunction((PetscObject)mat,"MatConvert_seqdense_elemental_C",NULL);
1463: #endif
1464: PetscObjectComposeFunction((PetscObject)mat,"MatSeqDenseSetPreallocation_C",NULL);
1465: PetscObjectComposeFunction((PetscObject)mat,"MatMatMult_seqaij_seqdense_C",NULL);
1466: PetscObjectComposeFunction((PetscObject)mat,"MatMatMultSymbolic_seqaij_seqdense_C",NULL);
1467: PetscObjectComposeFunction((PetscObject)mat,"MatMatMultNumeric_seqaij_seqdense_C",NULL);
1468: PetscObjectComposeFunction((PetscObject)mat,"MatPtAP_seqaij_seqdense_C",NULL);
1469: PetscObjectComposeFunction((PetscObject)mat,"MatTransposeMatMult_seqaij_seqdense_C",NULL);
1470: PetscObjectComposeFunction((PetscObject)mat,"MatTransposeMatMultSymbolic_seqaij_seqdense_C",NULL);
1471: PetscObjectComposeFunction((PetscObject)mat,"MatTransposeMatMultNumeric_seqaij_seqdense_C",NULL);
1472: PetscObjectComposeFunction((PetscObject)mat,"MatDenseGetColumn_C",NULL);
1473: PetscObjectComposeFunction((PetscObject)mat,"MatDenseRestoreColumn_C",NULL);
1474: return(0);
1475: }
1477: static PetscErrorCode MatTranspose_SeqDense(Mat A,MatReuse reuse,Mat *matout)
1478: {
1479: Mat_SeqDense *mat = (Mat_SeqDense*)A->data;
1481: PetscInt k,j,m,n,M;
1482: PetscScalar *v,tmp;
1485: v = mat->v; m = A->rmap->n; M = mat->lda; n = A->cmap->n;
1486: if (reuse == MAT_INPLACE_MATRIX && m == n) { /* in place transpose */
1487: for (j=0; j<m; j++) {
1488: for (k=0; k<j; k++) {
1489: tmp = v[j + k*M];
1490: v[j + k*M] = v[k + j*M];
1491: v[k + j*M] = tmp;
1492: }
1493: }
1494: } else { /* out-of-place transpose */
1495: Mat tmat;
1496: Mat_SeqDense *tmatd;
1497: PetscScalar *v2;
1498: PetscInt M2;
1500: if (reuse != MAT_REUSE_MATRIX) {
1501: MatCreate(PetscObjectComm((PetscObject)A),&tmat);
1502: MatSetSizes(tmat,A->cmap->n,A->rmap->n,A->cmap->n,A->rmap->n);
1503: MatSetType(tmat,((PetscObject)A)->type_name);
1504: MatSeqDenseSetPreallocation(tmat,NULL);
1505: } else {
1506: tmat = *matout;
1507: }
1508: tmatd = (Mat_SeqDense*)tmat->data;
1509: v = mat->v; v2 = tmatd->v; M2 = tmatd->lda;
1510: for (j=0; j<n; j++) {
1511: for (k=0; k<m; k++) v2[j + k*M2] = v[k + j*M];
1512: }
1513: MatAssemblyBegin(tmat,MAT_FINAL_ASSEMBLY);
1514: MatAssemblyEnd(tmat,MAT_FINAL_ASSEMBLY);
1515: if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX) *matout = tmat;
1516: else {
1517: MatHeaderMerge(A,&tmat);
1518: }
1519: }
1520: return(0);
1521: }
1523: static PetscErrorCode MatEqual_SeqDense(Mat A1,Mat A2,PetscBool *flg)
1524: {
1525: Mat_SeqDense *mat1 = (Mat_SeqDense*)A1->data;
1526: Mat_SeqDense *mat2 = (Mat_SeqDense*)A2->data;
1527: PetscInt i,j;
1528: PetscScalar *v1,*v2;
1531: if (A1->rmap->n != A2->rmap->n) {*flg = PETSC_FALSE; return(0);}
1532: if (A1->cmap->n != A2->cmap->n) {*flg = PETSC_FALSE; return(0);}
1533: for (i=0; i<A1->rmap->n; i++) {
1534: v1 = mat1->v+i; v2 = mat2->v+i;
1535: for (j=0; j<A1->cmap->n; j++) {
1536: if (*v1 != *v2) {*flg = PETSC_FALSE; return(0);}
1537: v1 += mat1->lda; v2 += mat2->lda;
1538: }
1539: }
1540: *flg = PETSC_TRUE;
1541: return(0);
1542: }
1544: static PetscErrorCode MatGetDiagonal_SeqDense(Mat A,Vec v)
1545: {
1546: Mat_SeqDense *mat = (Mat_SeqDense*)A->data;
1548: PetscInt i,n,len;
1549: PetscScalar *x,zero = 0.0;
1552: VecSet(v,zero);
1553: VecGetSize(v,&n);
1554: VecGetArray(v,&x);
1555: len = PetscMin(A->rmap->n,A->cmap->n);
1556: if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming mat and vec");
1557: for (i=0; i<len; i++) {
1558: x[i] = mat->v[i*mat->lda + i];
1559: }
1560: VecRestoreArray(v,&x);
1561: return(0);
1562: }
1564: static PetscErrorCode MatDiagonalScale_SeqDense(Mat A,Vec ll,Vec rr)
1565: {
1566: Mat_SeqDense *mat = (Mat_SeqDense*)A->data;
1567: const PetscScalar *l,*r;
1568: PetscScalar x,*v;
1569: PetscErrorCode ierr;
1570: PetscInt i,j,m = A->rmap->n,n = A->cmap->n;
1573: if (ll) {
1574: VecGetSize(ll,&m);
1575: VecGetArrayRead(ll,&l);
1576: if (m != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Left scaling vec wrong size");
1577: for (i=0; i<m; i++) {
1578: x = l[i];
1579: v = mat->v + i;
1580: for (j=0; j<n; j++) { (*v) *= x; v+= mat->lda;}
1581: }
1582: VecRestoreArrayRead(ll,&l);
1583: PetscLogFlops(1.0*n*m);
1584: }
1585: if (rr) {
1586: VecGetSize(rr,&n);
1587: VecGetArrayRead(rr,&r);
1588: if (n != A->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Right scaling vec wrong size");
1589: for (i=0; i<n; i++) {
1590: x = r[i];
1591: v = mat->v + i*mat->lda;
1592: for (j=0; j<m; j++) (*v++) *= x;
1593: }
1594: VecRestoreArrayRead(rr,&r);
1595: PetscLogFlops(1.0*n*m);
1596: }
1597: return(0);
1598: }
1600: static PetscErrorCode MatNorm_SeqDense(Mat A,NormType type,PetscReal *nrm)
1601: {
1602: Mat_SeqDense *mat = (Mat_SeqDense*)A->data;
1603: PetscScalar *v = mat->v;
1604: PetscReal sum = 0.0;
1605: PetscInt lda =mat->lda,m=A->rmap->n,i,j;
1609: if (type == NORM_FROBENIUS) {
1610: if (lda>m) {
1611: for (j=0; j<A->cmap->n; j++) {
1612: v = mat->v+j*lda;
1613: for (i=0; i<m; i++) {
1614: sum += PetscRealPart(PetscConj(*v)*(*v)); v++;
1615: }
1616: }
1617: } else {
1618: #if defined(PETSC_USE_REAL___FP16)
1619: PetscBLASInt one = 1,cnt = A->cmap->n*A->rmap->n;
1620: *nrm = BLASnrm2_(&cnt,v,&one);
1621: }
1622: #else
1623: for (i=0; i<A->cmap->n*A->rmap->n; i++) {
1624: sum += PetscRealPart(PetscConj(*v)*(*v)); v++;
1625: }
1626: }
1627: *nrm = PetscSqrtReal(sum);
1628: #endif
1629: PetscLogFlops(2.0*A->cmap->n*A->rmap->n);
1630: } else if (type == NORM_1) {
1631: *nrm = 0.0;
1632: for (j=0; j<A->cmap->n; j++) {
1633: v = mat->v + j*mat->lda;
1634: sum = 0.0;
1635: for (i=0; i<A->rmap->n; i++) {
1636: sum += PetscAbsScalar(*v); v++;
1637: }
1638: if (sum > *nrm) *nrm = sum;
1639: }
1640: PetscLogFlops(1.0*A->cmap->n*A->rmap->n);
1641: } else if (type == NORM_INFINITY) {
1642: *nrm = 0.0;
1643: for (j=0; j<A->rmap->n; j++) {
1644: v = mat->v + j;
1645: sum = 0.0;
1646: for (i=0; i<A->cmap->n; i++) {
1647: sum += PetscAbsScalar(*v); v += mat->lda;
1648: }
1649: if (sum > *nrm) *nrm = sum;
1650: }
1651: PetscLogFlops(1.0*A->cmap->n*A->rmap->n);
1652: } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No two norm");
1653: return(0);
1654: }
1656: static PetscErrorCode MatSetOption_SeqDense(Mat A,MatOption op,PetscBool flg)
1657: {
1658: Mat_SeqDense *aij = (Mat_SeqDense*)A->data;
1662: switch (op) {
1663: case MAT_ROW_ORIENTED:
1664: aij->roworiented = flg;
1665: break;
1666: case MAT_NEW_NONZERO_LOCATIONS:
1667: case MAT_NEW_NONZERO_LOCATION_ERR:
1668: case MAT_NEW_NONZERO_ALLOCATION_ERR:
1669: case MAT_NEW_DIAGONALS:
1670: case MAT_KEEP_NONZERO_PATTERN:
1671: case MAT_IGNORE_OFF_PROC_ENTRIES:
1672: case MAT_USE_HASH_TABLE:
1673: case MAT_IGNORE_ZERO_ENTRIES:
1674: case MAT_IGNORE_LOWER_TRIANGULAR:
1675: PetscInfo1(A,"Option %s ignored\n",MatOptions[op]);
1676: break;
1677: case MAT_SPD:
1678: case MAT_SYMMETRIC:
1679: case MAT_STRUCTURALLY_SYMMETRIC:
1680: case MAT_HERMITIAN:
1681: case MAT_SYMMETRY_ETERNAL:
1682: /* These options are handled directly by MatSetOption() */
1683: break;
1684: default:
1685: SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"unknown option %s",MatOptions[op]);
1686: }
1687: return(0);
1688: }
1690: static PetscErrorCode MatZeroEntries_SeqDense(Mat A)
1691: {
1692: Mat_SeqDense *l = (Mat_SeqDense*)A->data;
1694: PetscInt lda=l->lda,m=A->rmap->n,j;
1697: if (lda>m) {
1698: for (j=0; j<A->cmap->n; j++) {
1699: PetscMemzero(l->v+j*lda,m*sizeof(PetscScalar));
1700: }
1701: } else {
1702: PetscMemzero(l->v,A->rmap->n*A->cmap->n*sizeof(PetscScalar));
1703: }
1704: return(0);
1705: }
1707: static PetscErrorCode MatZeroRows_SeqDense(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
1708: {
1709: PetscErrorCode ierr;
1710: Mat_SeqDense *l = (Mat_SeqDense*)A->data;
1711: PetscInt m = l->lda, n = A->cmap->n, i,j;
1712: PetscScalar *slot,*bb;
1713: const PetscScalar *xx;
1716: #if defined(PETSC_USE_DEBUG)
1717: for (i=0; i<N; i++) {
1718: if (rows[i] < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative row requested to be zeroed");
1719: if (rows[i] >= A->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row %D requested to be zeroed greater than or equal number of rows %D",rows[i],A->rmap->n);
1720: }
1721: #endif
1723: /* fix right hand side if needed */
1724: if (x && b) {
1725: VecGetArrayRead(x,&xx);
1726: VecGetArray(b,&bb);
1727: for (i=0; i<N; i++) bb[rows[i]] = diag*xx[rows[i]];
1728: VecRestoreArrayRead(x,&xx);
1729: VecRestoreArray(b,&bb);
1730: }
1732: for (i=0; i<N; i++) {
1733: slot = l->v + rows[i];
1734: for (j=0; j<n; j++) { *slot = 0.0; slot += m;}
1735: }
1736: if (diag != 0.0) {
1737: if (A->rmap->n != A->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only coded for square matrices");
1738: for (i=0; i<N; i++) {
1739: slot = l->v + (m+1)*rows[i];
1740: *slot = diag;
1741: }
1742: }
1743: return(0);
1744: }
1746: static PetscErrorCode MatDenseGetArray_SeqDense(Mat A,PetscScalar *array[])
1747: {
1748: Mat_SeqDense *mat = (Mat_SeqDense*)A->data;
1751: if (mat->lda != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get array for Dense matrices with LDA different from number of rows");
1752: *array = mat->v;
1753: return(0);
1754: }
1756: static PetscErrorCode MatDenseRestoreArray_SeqDense(Mat A,PetscScalar *array[])
1757: {
1759: return(0);
1760: }
1762: /*@C
1763: MatDenseGetArray - gives access to the array where the data for a SeqDense matrix is stored
1765: Logically Collective on Mat
1767: Input Parameter:
1768: . mat - a MATSEQDENSE or MATMPIDENSE matrix
1770: Output Parameter:
1771: . array - pointer to the data
1773: Level: intermediate
1775: .seealso: MatDenseRestoreArray(), MatDenseGetArrayRead(), MatDenseRestoreArrayRead()
1776: @*/
1777: PetscErrorCode MatDenseGetArray(Mat A,PetscScalar **array)
1778: {
1782: PetscUseMethod(A,"MatDenseGetArray_C",(Mat,PetscScalar**),(A,array));
1783: return(0);
1784: }
1786: /*@C
1787: MatDenseRestoreArray - returns access to the array where the data for a dense matrix is stored obtained by MatDenseGetArray()
1789: Logically Collective on Mat
1791: Input Parameters:
1792: . mat - a MATSEQDENSE or MATMPIDENSE matrix
1793: . array - pointer to the data
1795: Level: intermediate
1797: .seealso: MatDenseGetArray(), MatDenseGetArrayRead(), MatDenseRestoreArrayRead()
1798: @*/
1799: PetscErrorCode MatDenseRestoreArray(Mat A,PetscScalar **array)
1800: {
1804: PetscUseMethod(A,"MatDenseRestoreArray_C",(Mat,PetscScalar**),(A,array));
1805: if (array) *array = NULL;
1806: PetscObjectStateIncrease((PetscObject)A);
1807: return(0);
1808: }
1810: /*@C
1811: MatDenseGetArrayRead - gives access to the array where the data for a SeqDense matrix is stored
1813: Not Collective
1815: Input Parameter:
1816: . mat - a MATSEQDENSE or MATMPIDENSE matrix
1818: Output Parameter:
1819: . array - pointer to the data
1821: Level: intermediate
1823: .seealso: MatDenseRestoreArray(), MatDenseGetArray(), MatDenseRestoreArrayRead()
1824: @*/
1825: PetscErrorCode MatDenseGetArrayRead(Mat A,const PetscScalar **array)
1826: {
1830: PetscUseMethod(A,"MatDenseGetArrayRead_C",(Mat,const PetscScalar**),(A,array));
1831: return(0);
1832: }
1834: /*@C
1835: MatDenseRestoreArrayRead - returns access to the array where the data for a dense matrix is stored obtained by MatDenseGetArray()
1837: Not Collective
1839: Input Parameters:
1840: . mat - a MATSEQDENSE or MATMPIDENSE matrix
1841: . array - pointer to the data
1843: Level: intermediate
1845: .seealso: MatDenseGetArray(), MatDenseGetArrayRead(), MatDenseRestoreArray()
1846: @*/
1847: PetscErrorCode MatDenseRestoreArrayRead(Mat A,const PetscScalar **array)
1848: {
1852: PetscUseMethod(A,"MatDenseRestoreArrayRead_C",(Mat,const PetscScalar**),(A,array));
1853: if (array) *array = NULL;
1854: return(0);
1855: }
1857: static PetscErrorCode MatCreateSubMatrix_SeqDense(Mat A,IS isrow,IS iscol,PetscInt cs,MatReuse scall,Mat *B)
1858: {
1859: Mat_SeqDense *mat = (Mat_SeqDense*)A->data;
1861: PetscInt i,j,nrows,ncols;
1862: const PetscInt *irow,*icol;
1863: PetscScalar *av,*bv,*v = mat->v;
1864: Mat newmat;
1867: ISGetIndices(isrow,&irow);
1868: ISGetIndices(iscol,&icol);
1869: ISGetLocalSize(isrow,&nrows);
1870: ISGetLocalSize(iscol,&ncols);
1872: /* Check submatrixcall */
1873: if (scall == MAT_REUSE_MATRIX) {
1874: PetscInt n_cols,n_rows;
1875: MatGetSize(*B,&n_rows,&n_cols);
1876: if (n_rows != nrows || n_cols != ncols) {
1877: /* resize the result matrix to match number of requested rows/columns */
1878: MatSetSizes(*B,nrows,ncols,nrows,ncols);
1879: }
1880: newmat = *B;
1881: } else {
1882: /* Create and fill new matrix */
1883: MatCreate(PetscObjectComm((PetscObject)A),&newmat);
1884: MatSetSizes(newmat,nrows,ncols,nrows,ncols);
1885: MatSetType(newmat,((PetscObject)A)->type_name);
1886: MatSeqDenseSetPreallocation(newmat,NULL);
1887: }
1889: /* Now extract the data pointers and do the copy,column at a time */
1890: bv = ((Mat_SeqDense*)newmat->data)->v;
1892: for (i=0; i<ncols; i++) {
1893: av = v + mat->lda*icol[i];
1894: for (j=0; j<nrows; j++) *bv++ = av[irow[j]];
1895: }
1897: /* Assemble the matrices so that the correct flags are set */
1898: MatAssemblyBegin(newmat,MAT_FINAL_ASSEMBLY);
1899: MatAssemblyEnd(newmat,MAT_FINAL_ASSEMBLY);
1901: /* Free work space */
1902: ISRestoreIndices(isrow,&irow);
1903: ISRestoreIndices(iscol,&icol);
1904: *B = newmat;
1905: return(0);
1906: }
1908: static PetscErrorCode MatCreateSubMatrices_SeqDense(Mat A,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *B[])
1909: {
1911: PetscInt i;
1914: if (scall == MAT_INITIAL_MATRIX) {
1915: PetscCalloc1(n+1,B);
1916: }
1918: for (i=0; i<n; i++) {
1919: MatCreateSubMatrix_SeqDense(A,irow[i],icol[i],PETSC_DECIDE,scall,&(*B)[i]);
1920: }
1921: return(0);
1922: }
1924: static PetscErrorCode MatAssemblyBegin_SeqDense(Mat mat,MatAssemblyType mode)
1925: {
1927: return(0);
1928: }
1930: static PetscErrorCode MatAssemblyEnd_SeqDense(Mat mat,MatAssemblyType mode)
1931: {
1933: return(0);
1934: }
1936: static PetscErrorCode MatCopy_SeqDense(Mat A,Mat B,MatStructure str)
1937: {
1938: Mat_SeqDense *a = (Mat_SeqDense*)A->data,*b = (Mat_SeqDense*)B->data;
1940: PetscInt lda1=a->lda,lda2=b->lda, m=A->rmap->n,n=A->cmap->n, j;
1943: /* If the two matrices don't have the same copy implementation, they aren't compatible for fast copy. */
1944: if (A->ops->copy != B->ops->copy) {
1945: MatCopy_Basic(A,B,str);
1946: return(0);
1947: }
1948: if (m != B->rmap->n || n != B->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"size(B) != size(A)");
1949: if (lda1>m || lda2>m) {
1950: for (j=0; j<n; j++) {
1951: PetscMemcpy(b->v+j*lda2,a->v+j*lda1,m*sizeof(PetscScalar));
1952: }
1953: } else {
1954: PetscMemcpy(b->v,a->v,A->rmap->n*A->cmap->n*sizeof(PetscScalar));
1955: }
1956: PetscObjectStateIncrease((PetscObject)B);
1957: return(0);
1958: }
1960: static PetscErrorCode MatSetUp_SeqDense(Mat A)
1961: {
1965: MatSeqDenseSetPreallocation(A,0);
1966: return(0);
1967: }
1969: static PetscErrorCode MatConjugate_SeqDense(Mat A)
1970: {
1971: Mat_SeqDense *a = (Mat_SeqDense*)A->data;
1972: PetscInt i,nz = A->rmap->n*A->cmap->n;
1973: PetscScalar *aa = a->v;
1976: for (i=0; i<nz; i++) aa[i] = PetscConj(aa[i]);
1977: return(0);
1978: }
1980: static PetscErrorCode MatRealPart_SeqDense(Mat A)
1981: {
1982: Mat_SeqDense *a = (Mat_SeqDense*)A->data;
1983: PetscInt i,nz = A->rmap->n*A->cmap->n;
1984: PetscScalar *aa = a->v;
1987: for (i=0; i<nz; i++) aa[i] = PetscRealPart(aa[i]);
1988: return(0);
1989: }
1991: static PetscErrorCode MatImaginaryPart_SeqDense(Mat A)
1992: {
1993: Mat_SeqDense *a = (Mat_SeqDense*)A->data;
1994: PetscInt i,nz = A->rmap->n*A->cmap->n;
1995: PetscScalar *aa = a->v;
1998: for (i=0; i<nz; i++) aa[i] = PetscImaginaryPart(aa[i]);
1999: return(0);
2000: }
2002: /* ----------------------------------------------------------------*/
2003: PETSC_INTERN PetscErrorCode MatMatMult_SeqDense_SeqDense(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
2004: {
2008: if (scall == MAT_INITIAL_MATRIX) {
2009: PetscLogEventBegin(MAT_MatMultSymbolic,A,B,0,0);
2010: MatMatMultSymbolic_SeqDense_SeqDense(A,B,fill,C);
2011: PetscLogEventEnd(MAT_MatMultSymbolic,A,B,0,0);
2012: }
2013: PetscLogEventBegin(MAT_MatMultNumeric,A,B,0,0);
2014: MatMatMultNumeric_SeqDense_SeqDense(A,B,*C);
2015: PetscLogEventEnd(MAT_MatMultNumeric,A,B,0,0);
2016: return(0);
2017: }
2019: PetscErrorCode MatMatMultSymbolic_SeqDense_SeqDense(Mat A,Mat B,PetscReal fill,Mat *C)
2020: {
2022: PetscInt m=A->rmap->n,n=B->cmap->n;
2023: Mat Cmat;
2026: if (A->cmap->n != B->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"A->cmap->n %d != B->rmap->n %d\n",A->cmap->n,B->rmap->n);
2027: MatCreate(PETSC_COMM_SELF,&Cmat);
2028: MatSetSizes(Cmat,m,n,m,n);
2029: MatSetType(Cmat,MATSEQDENSE);
2030: MatSeqDenseSetPreallocation(Cmat,NULL);
2032: *C = Cmat;
2033: return(0);
2034: }
2036: PetscErrorCode MatMatMultNumeric_SeqDense_SeqDense(Mat A,Mat B,Mat C)
2037: {
2038: Mat_SeqDense *a = (Mat_SeqDense*)A->data;
2039: Mat_SeqDense *b = (Mat_SeqDense*)B->data;
2040: Mat_SeqDense *c = (Mat_SeqDense*)C->data;
2041: PetscBLASInt m,n,k;
2042: PetscScalar _DOne=1.0,_DZero=0.0;
2044: PetscBool flg;
2047: PetscObjectTypeCompare((PetscObject)B,MATSEQDENSE,&flg);
2048: if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Second matrix must be dense");
2050: /* Handle case where where user provided the final C matrix rather than calling MatMatMult() with MAT_INITIAL_MATRIX*/
2051: PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&flg);
2052: if (flg) {
2053: C->ops->matmultnumeric = MatMatMultNumeric_SeqAIJ_SeqDense;
2054: (*C->ops->matmultnumeric)(A,B,C);
2055: return(0);
2056: }
2058: PetscObjectTypeCompare((PetscObject)A,MATSEQDENSE,&flg);
2059: if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"First matrix must be dense");
2060: PetscBLASIntCast(C->rmap->n,&m);
2061: PetscBLASIntCast(C->cmap->n,&n);
2062: PetscBLASIntCast(A->cmap->n,&k);
2063: if (!m || !n || !k) return(0);
2064: PetscStackCallBLAS("BLASgemm",BLASgemm_("N","N",&m,&n,&k,&_DOne,a->v,&a->lda,b->v,&b->lda,&_DZero,c->v,&c->lda));
2065: return(0);
2066: }
2068: PetscErrorCode MatMatTransposeMult_SeqDense_SeqDense(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
2069: {
2073: if (scall == MAT_INITIAL_MATRIX) {
2074: PetscLogEventBegin(MAT_MatTransposeMultSymbolic,A,B,0,0);
2075: MatMatTransposeMultSymbolic_SeqDense_SeqDense(A,B,fill,C);
2076: PetscLogEventEnd(MAT_MatTransposeMultSymbolic,A,B,0,0);
2077: }
2078: PetscLogEventBegin(MAT_MatTransposeMultNumeric,A,B,0,0);
2079: MatMatTransposeMultNumeric_SeqDense_SeqDense(A,B,*C);
2080: PetscLogEventEnd(MAT_MatTransposeMultNumeric,A,B,0,0);
2081: return(0);
2082: }
2084: PetscErrorCode MatMatTransposeMultSymbolic_SeqDense_SeqDense(Mat A,Mat B,PetscReal fill,Mat *C)
2085: {
2087: PetscInt m=A->rmap->n,n=B->rmap->n;
2088: Mat Cmat;
2091: if (A->cmap->n != B->cmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"A->cmap->n %d != B->cmap->n %d\n",A->cmap->n,B->cmap->n);
2092: MatCreate(PETSC_COMM_SELF,&Cmat);
2093: MatSetSizes(Cmat,m,n,m,n);
2094: MatSetType(Cmat,MATSEQDENSE);
2095: MatSeqDenseSetPreallocation(Cmat,NULL);
2097: Cmat->assembled = PETSC_TRUE;
2099: *C = Cmat;
2100: return(0);
2101: }
2103: PetscErrorCode MatMatTransposeMultNumeric_SeqDense_SeqDense(Mat A,Mat B,Mat C)
2104: {
2105: Mat_SeqDense *a = (Mat_SeqDense*)A->data;
2106: Mat_SeqDense *b = (Mat_SeqDense*)B->data;
2107: Mat_SeqDense *c = (Mat_SeqDense*)C->data;
2108: PetscBLASInt m,n,k;
2109: PetscScalar _DOne=1.0,_DZero=0.0;
2113: PetscBLASIntCast(C->rmap->n,&m);
2114: PetscBLASIntCast(C->cmap->n,&n);
2115: PetscBLASIntCast(A->cmap->n,&k);
2116: if (!m || !n || !k) return(0);
2117: PetscStackCallBLAS("BLASgemm",BLASgemm_("N","T",&m,&n,&k,&_DOne,a->v,&a->lda,b->v,&b->lda,&_DZero,c->v,&c->lda));
2118: return(0);
2119: }
2121: PetscErrorCode MatTransposeMatMult_SeqDense_SeqDense(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
2122: {
2126: if (scall == MAT_INITIAL_MATRIX) {
2127: PetscLogEventBegin(MAT_TransposeMatMultSymbolic,A,B,0,0);
2128: MatTransposeMatMultSymbolic_SeqDense_SeqDense(A,B,fill,C);
2129: PetscLogEventEnd(MAT_TransposeMatMultSymbolic,A,B,0,0);
2130: }
2131: PetscLogEventBegin(MAT_TransposeMatMultNumeric,A,B,0,0);
2132: MatTransposeMatMultNumeric_SeqDense_SeqDense(A,B,*C);
2133: PetscLogEventEnd(MAT_TransposeMatMultNumeric,A,B,0,0);
2134: return(0);
2135: }
2137: PetscErrorCode MatTransposeMatMultSymbolic_SeqDense_SeqDense(Mat A,Mat B,PetscReal fill,Mat *C)
2138: {
2140: PetscInt m=A->cmap->n,n=B->cmap->n;
2141: Mat Cmat;
2144: if (A->rmap->n != B->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"A->rmap->n %d != B->rmap->n %d\n",A->rmap->n,B->rmap->n);
2145: MatCreate(PETSC_COMM_SELF,&Cmat);
2146: MatSetSizes(Cmat,m,n,m,n);
2147: MatSetType(Cmat,MATSEQDENSE);
2148: MatSeqDenseSetPreallocation(Cmat,NULL);
2150: Cmat->assembled = PETSC_TRUE;
2152: *C = Cmat;
2153: return(0);
2154: }
2156: PetscErrorCode MatTransposeMatMultNumeric_SeqDense_SeqDense(Mat A,Mat B,Mat C)
2157: {
2158: Mat_SeqDense *a = (Mat_SeqDense*)A->data;
2159: Mat_SeqDense *b = (Mat_SeqDense*)B->data;
2160: Mat_SeqDense *c = (Mat_SeqDense*)C->data;
2161: PetscBLASInt m,n,k;
2162: PetscScalar _DOne=1.0,_DZero=0.0;
2166: PetscBLASIntCast(C->rmap->n,&m);
2167: PetscBLASIntCast(C->cmap->n,&n);
2168: PetscBLASIntCast(A->rmap->n,&k);
2169: if (!m || !n || !k) return(0);
2170: PetscStackCallBLAS("BLASgemm",BLASgemm_("T","N",&m,&n,&k,&_DOne,a->v,&a->lda,b->v,&b->lda,&_DZero,c->v,&c->lda));
2171: return(0);
2172: }
2174: static PetscErrorCode MatGetRowMax_SeqDense(Mat A,Vec v,PetscInt idx[])
2175: {
2176: Mat_SeqDense *a = (Mat_SeqDense*)A->data;
2178: PetscInt i,j,m = A->rmap->n,n = A->cmap->n,p;
2179: PetscScalar *x;
2180: MatScalar *aa = a->v;
2183: if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2185: VecSet(v,0.0);
2186: VecGetArray(v,&x);
2187: VecGetLocalSize(v,&p);
2188: if (p != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
2189: for (i=0; i<m; i++) {
2190: x[i] = aa[i]; if (idx) idx[i] = 0;
2191: for (j=1; j<n; j++) {
2192: if (PetscRealPart(x[i]) < PetscRealPart(aa[i+m*j])) {x[i] = aa[i + m*j]; if (idx) idx[i] = j;}
2193: }
2194: }
2195: VecRestoreArray(v,&x);
2196: return(0);
2197: }
2199: static PetscErrorCode MatGetRowMaxAbs_SeqDense(Mat A,Vec v,PetscInt idx[])
2200: {
2201: Mat_SeqDense *a = (Mat_SeqDense*)A->data;
2203: PetscInt i,j,m = A->rmap->n,n = A->cmap->n,p;
2204: PetscScalar *x;
2205: PetscReal atmp;
2206: MatScalar *aa = a->v;
2209: if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2211: VecSet(v,0.0);
2212: VecGetArray(v,&x);
2213: VecGetLocalSize(v,&p);
2214: if (p != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
2215: for (i=0; i<m; i++) {
2216: x[i] = PetscAbsScalar(aa[i]);
2217: for (j=1; j<n; j++) {
2218: atmp = PetscAbsScalar(aa[i+m*j]);
2219: if (PetscAbsScalar(x[i]) < atmp) {x[i] = atmp; if (idx) idx[i] = j;}
2220: }
2221: }
2222: VecRestoreArray(v,&x);
2223: return(0);
2224: }
2226: static PetscErrorCode MatGetRowMin_SeqDense(Mat A,Vec v,PetscInt idx[])
2227: {
2228: Mat_SeqDense *a = (Mat_SeqDense*)A->data;
2230: PetscInt i,j,m = A->rmap->n,n = A->cmap->n,p;
2231: PetscScalar *x;
2232: MatScalar *aa = a->v;
2235: if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2237: VecSet(v,0.0);
2238: VecGetArray(v,&x);
2239: VecGetLocalSize(v,&p);
2240: if (p != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
2241: for (i=0; i<m; i++) {
2242: x[i] = aa[i]; if (idx) idx[i] = 0;
2243: for (j=1; j<n; j++) {
2244: if (PetscRealPart(x[i]) > PetscRealPart(aa[i+m*j])) {x[i] = aa[i + m*j]; if (idx) idx[i] = j;}
2245: }
2246: }
2247: VecRestoreArray(v,&x);
2248: return(0);
2249: }
2251: static PetscErrorCode MatGetColumnVector_SeqDense(Mat A,Vec v,PetscInt col)
2252: {
2253: Mat_SeqDense *a = (Mat_SeqDense*)A->data;
2255: PetscScalar *x;
2258: if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2260: VecGetArray(v,&x);
2261: PetscMemcpy(x,a->v+col*a->lda,A->rmap->n*sizeof(PetscScalar));
2262: VecRestoreArray(v,&x);
2263: return(0);
2264: }
2266: PetscErrorCode MatGetColumnNorms_SeqDense(Mat A,NormType type,PetscReal *norms)
2267: {
2269: PetscInt i,j,m,n;
2270: PetscScalar *a;
2273: MatGetSize(A,&m,&n);
2274: PetscMemzero(norms,n*sizeof(PetscReal));
2275: MatDenseGetArray(A,&a);
2276: if (type == NORM_2) {
2277: for (i=0; i<n; i++) {
2278: for (j=0; j<m; j++) {
2279: norms[i] += PetscAbsScalar(a[j]*a[j]);
2280: }
2281: a += m;
2282: }
2283: } else if (type == NORM_1) {
2284: for (i=0; i<n; i++) {
2285: for (j=0; j<m; j++) {
2286: norms[i] += PetscAbsScalar(a[j]);
2287: }
2288: a += m;
2289: }
2290: } else if (type == NORM_INFINITY) {
2291: for (i=0; i<n; i++) {
2292: for (j=0; j<m; j++) {
2293: norms[i] = PetscMax(PetscAbsScalar(a[j]),norms[i]);
2294: }
2295: a += m;
2296: }
2297: } else SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"Unknown NormType");
2298: MatDenseRestoreArray(A,&a);
2299: if (type == NORM_2) {
2300: for (i=0; i<n; i++) norms[i] = PetscSqrtReal(norms[i]);
2301: }
2302: return(0);
2303: }
2305: static PetscErrorCode MatSetRandom_SeqDense(Mat x,PetscRandom rctx)
2306: {
2308: PetscScalar *a;
2309: PetscInt m,n,i;
2312: MatGetSize(x,&m,&n);
2313: MatDenseGetArray(x,&a);
2314: for (i=0; i<m*n; i++) {
2315: PetscRandomGetValue(rctx,a+i);
2316: }
2317: MatDenseRestoreArray(x,&a);
2318: return(0);
2319: }
2321: static PetscErrorCode MatMissingDiagonal_SeqDense(Mat A,PetscBool *missing,PetscInt *d)
2322: {
2324: *missing = PETSC_FALSE;
2325: return(0);
2326: }
2328: static PetscErrorCode MatDenseGetColumn_SeqDense(Mat A,PetscInt col,PetscScalar **vals)
2329: {
2330: Mat_SeqDense *a = (Mat_SeqDense*)A->data;
2333: if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2334: *vals = a->v+col*a->lda;
2335: return(0);
2336: }
2338: static PetscErrorCode MatDenseRestoreColumn_SeqDense(Mat A,PetscScalar **vals)
2339: {
2341: *vals = 0; /* user cannot accidently use the array later */
2342: return(0);
2343: }
2345: /* -------------------------------------------------------------------*/
2346: static struct _MatOps MatOps_Values = { MatSetValues_SeqDense,
2347: MatGetRow_SeqDense,
2348: MatRestoreRow_SeqDense,
2349: MatMult_SeqDense,
2350: /* 4*/ MatMultAdd_SeqDense,
2351: MatMultTranspose_SeqDense,
2352: MatMultTransposeAdd_SeqDense,
2353: 0,
2354: 0,
2355: 0,
2356: /* 10*/ 0,
2357: MatLUFactor_SeqDense,
2358: MatCholeskyFactor_SeqDense,
2359: MatSOR_SeqDense,
2360: MatTranspose_SeqDense,
2361: /* 15*/ MatGetInfo_SeqDense,
2362: MatEqual_SeqDense,
2363: MatGetDiagonal_SeqDense,
2364: MatDiagonalScale_SeqDense,
2365: MatNorm_SeqDense,
2366: /* 20*/ MatAssemblyBegin_SeqDense,
2367: MatAssemblyEnd_SeqDense,
2368: MatSetOption_SeqDense,
2369: MatZeroEntries_SeqDense,
2370: /* 24*/ MatZeroRows_SeqDense,
2371: 0,
2372: 0,
2373: 0,
2374: 0,
2375: /* 29*/ MatSetUp_SeqDense,
2376: 0,
2377: 0,
2378: 0,
2379: 0,
2380: /* 34*/ MatDuplicate_SeqDense,
2381: 0,
2382: 0,
2383: 0,
2384: 0,
2385: /* 39*/ MatAXPY_SeqDense,
2386: MatCreateSubMatrices_SeqDense,
2387: 0,
2388: MatGetValues_SeqDense,
2389: MatCopy_SeqDense,
2390: /* 44*/ MatGetRowMax_SeqDense,
2391: MatScale_SeqDense,
2392: MatShift_Basic,
2393: 0,
2394: MatZeroRowsColumns_SeqDense,
2395: /* 49*/ MatSetRandom_SeqDense,
2396: 0,
2397: 0,
2398: 0,
2399: 0,
2400: /* 54*/ 0,
2401: 0,
2402: 0,
2403: 0,
2404: 0,
2405: /* 59*/ 0,
2406: MatDestroy_SeqDense,
2407: MatView_SeqDense,
2408: 0,
2409: 0,
2410: /* 64*/ 0,
2411: 0,
2412: 0,
2413: 0,
2414: 0,
2415: /* 69*/ MatGetRowMaxAbs_SeqDense,
2416: 0,
2417: 0,
2418: 0,
2419: 0,
2420: /* 74*/ 0,
2421: 0,
2422: 0,
2423: 0,
2424: 0,
2425: /* 79*/ 0,
2426: 0,
2427: 0,
2428: 0,
2429: /* 83*/ MatLoad_SeqDense,
2430: 0,
2431: MatIsHermitian_SeqDense,
2432: 0,
2433: 0,
2434: 0,
2435: /* 89*/ MatMatMult_SeqDense_SeqDense,
2436: MatMatMultSymbolic_SeqDense_SeqDense,
2437: MatMatMultNumeric_SeqDense_SeqDense,
2438: MatPtAP_SeqDense_SeqDense,
2439: MatPtAPSymbolic_SeqDense_SeqDense,
2440: /* 94*/ MatPtAPNumeric_SeqDense_SeqDense,
2441: MatMatTransposeMult_SeqDense_SeqDense,
2442: MatMatTransposeMultSymbolic_SeqDense_SeqDense,
2443: MatMatTransposeMultNumeric_SeqDense_SeqDense,
2444: 0,
2445: /* 99*/ 0,
2446: 0,
2447: 0,
2448: MatConjugate_SeqDense,
2449: 0,
2450: /*104*/ 0,
2451: MatRealPart_SeqDense,
2452: MatImaginaryPart_SeqDense,
2453: 0,
2454: 0,
2455: /*109*/ 0,
2456: 0,
2457: MatGetRowMin_SeqDense,
2458: MatGetColumnVector_SeqDense,
2459: MatMissingDiagonal_SeqDense,
2460: /*114*/ 0,
2461: 0,
2462: 0,
2463: 0,
2464: 0,
2465: /*119*/ 0,
2466: 0,
2467: 0,
2468: 0,
2469: 0,
2470: /*124*/ 0,
2471: MatGetColumnNorms_SeqDense,
2472: 0,
2473: 0,
2474: 0,
2475: /*129*/ 0,
2476: MatTransposeMatMult_SeqDense_SeqDense,
2477: MatTransposeMatMultSymbolic_SeqDense_SeqDense,
2478: MatTransposeMatMultNumeric_SeqDense_SeqDense,
2479: 0,
2480: /*134*/ 0,
2481: 0,
2482: 0,
2483: 0,
2484: 0,
2485: /*139*/ 0,
2486: 0,
2487: 0,
2488: 0,
2489: 0,
2490: /*144*/ MatCreateMPIMatConcatenateSeqMat_SeqDense
2491: };
2493: /*@C
2494: MatCreateSeqDense - Creates a sequential dense matrix that
2495: is stored in column major order (the usual Fortran 77 manner). Many
2496: of the matrix operations use the BLAS and LAPACK routines.
2498: Collective on MPI_Comm
2500: Input Parameters:
2501: + comm - MPI communicator, set to PETSC_COMM_SELF
2502: . m - number of rows
2503: . n - number of columns
2504: - data - optional location of matrix data in column major order. Set data=NULL for PETSc
2505: to control all matrix memory allocation.
2507: Output Parameter:
2508: . A - the matrix
2510: Notes:
2511: The data input variable is intended primarily for Fortran programmers
2512: who wish to allocate their own matrix memory space. Most users should
2513: set data=NULL.
2515: Level: intermediate
2517: .keywords: dense, matrix, LAPACK, BLAS
2519: .seealso: MatCreate(), MatCreateDense(), MatSetValues()
2520: @*/
2521: PetscErrorCode MatCreateSeqDense(MPI_Comm comm,PetscInt m,PetscInt n,PetscScalar *data,Mat *A)
2522: {
2526: MatCreate(comm,A);
2527: MatSetSizes(*A,m,n,m,n);
2528: MatSetType(*A,MATSEQDENSE);
2529: MatSeqDenseSetPreallocation(*A,data);
2530: return(0);
2531: }
2533: /*@C
2534: MatSeqDenseSetPreallocation - Sets the array used for storing the matrix elements
2536: Collective on MPI_Comm
2538: Input Parameters:
2539: + B - the matrix
2540: - data - the array (or NULL)
2542: Notes:
2543: The data input variable is intended primarily for Fortran programmers
2544: who wish to allocate their own matrix memory space. Most users should
2545: need not call this routine.
2547: Level: intermediate
2549: .keywords: dense, matrix, LAPACK, BLAS
2551: .seealso: MatCreate(), MatCreateDense(), MatSetValues(), MatSeqDenseSetLDA()
2553: @*/
2554: PetscErrorCode MatSeqDenseSetPreallocation(Mat B,PetscScalar data[])
2555: {
2559: PetscTryMethod(B,"MatSeqDenseSetPreallocation_C",(Mat,PetscScalar[]),(B,data));
2560: return(0);
2561: }
2563: PetscErrorCode MatSeqDenseSetPreallocation_SeqDense(Mat B,PetscScalar *data)
2564: {
2565: Mat_SeqDense *b;
2569: B->preallocated = PETSC_TRUE;
2571: PetscLayoutSetUp(B->rmap);
2572: PetscLayoutSetUp(B->cmap);
2574: b = (Mat_SeqDense*)B->data;
2575: b->Mmax = B->rmap->n;
2576: b->Nmax = B->cmap->n;
2577: if (b->lda <= 0 || b->changelda) b->lda = B->rmap->n;
2579: PetscIntMultError(b->lda,b->Nmax,NULL);
2580: if (!data) { /* petsc-allocated storage */
2581: if (!b->user_alloc) { PetscFree(b->v); }
2582: PetscCalloc1((size_t)b->lda*b->Nmax,&b->v);
2583: PetscLogObjectMemory((PetscObject)B,b->lda*b->Nmax*sizeof(PetscScalar));
2585: b->user_alloc = PETSC_FALSE;
2586: } else { /* user-allocated storage */
2587: if (!b->user_alloc) { PetscFree(b->v); }
2588: b->v = data;
2589: b->user_alloc = PETSC_TRUE;
2590: }
2591: B->assembled = PETSC_TRUE;
2592: return(0);
2593: }
2595: #if defined(PETSC_HAVE_ELEMENTAL)
2596: PETSC_INTERN PetscErrorCode MatConvert_SeqDense_Elemental(Mat A, MatType newtype,MatReuse reuse,Mat *newmat)
2597: {
2598: Mat mat_elemental;
2600: PetscScalar *array,*v_colwise;
2601: PetscInt M=A->rmap->N,N=A->cmap->N,i,j,k,*rows,*cols;
2604: PetscMalloc3(M*N,&v_colwise,M,&rows,N,&cols);
2605: MatDenseGetArray(A,&array);
2606: /* convert column-wise array into row-wise v_colwise, see MatSetValues_Elemental() */
2607: k = 0;
2608: for (j=0; j<N; j++) {
2609: cols[j] = j;
2610: for (i=0; i<M; i++) {
2611: v_colwise[j*M+i] = array[k++];
2612: }
2613: }
2614: for (i=0; i<M; i++) {
2615: rows[i] = i;
2616: }
2617: MatDenseRestoreArray(A,&array);
2619: MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental);
2620: MatSetSizes(mat_elemental,PETSC_DECIDE,PETSC_DECIDE,M,N);
2621: MatSetType(mat_elemental,MATELEMENTAL);
2622: MatSetUp(mat_elemental);
2624: /* PETSc-Elemental interaface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */
2625: MatSetValues(mat_elemental,M,rows,N,cols,v_colwise,ADD_VALUES);
2626: MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY);
2627: MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY);
2628: PetscFree3(v_colwise,rows,cols);
2630: if (reuse == MAT_INPLACE_MATRIX) {
2631: MatHeaderReplace(A,&mat_elemental);
2632: } else {
2633: *newmat = mat_elemental;
2634: }
2635: return(0);
2636: }
2637: #endif
2639: /*@C
2640: MatSeqDenseSetLDA - Declare the leading dimension of the user-provided array
2642: Input parameter:
2643: + A - the matrix
2644: - lda - the leading dimension
2646: Notes:
2647: This routine is to be used in conjunction with MatSeqDenseSetPreallocation();
2648: it asserts that the preallocation has a leading dimension (the LDA parameter
2649: of Blas and Lapack fame) larger than M, the first dimension of the matrix.
2651: Level: intermediate
2653: .keywords: dense, matrix, LAPACK, BLAS
2655: .seealso: MatCreate(), MatCreateSeqDense(), MatSeqDenseSetPreallocation(), MatSetMaximumSize()
2657: @*/
2658: PetscErrorCode MatSeqDenseSetLDA(Mat B,PetscInt lda)
2659: {
2660: Mat_SeqDense *b = (Mat_SeqDense*)B->data;
2663: if (lda < B->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"LDA %D must be at least matrix dimension %D",lda,B->rmap->n);
2664: b->lda = lda;
2665: b->changelda = PETSC_FALSE;
2666: b->Mmax = PetscMax(b->Mmax,lda);
2667: return(0);
2668: }
2670: PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqDense(MPI_Comm comm,Mat inmat,PetscInt n,MatReuse scall,Mat *outmat)
2671: {
2673: PetscMPIInt size;
2676: MPI_Comm_size(comm,&size);
2677: if (size == 1) {
2678: if (scall == MAT_INITIAL_MATRIX) {
2679: MatDuplicate(inmat,MAT_COPY_VALUES,outmat);
2680: } else {
2681: MatCopy(inmat,*outmat,SAME_NONZERO_PATTERN);
2682: }
2683: } else {
2684: MatCreateMPIMatConcatenateSeqMat_MPIDense(comm,inmat,n,scall,outmat);
2685: }
2686: return(0);
2687: }
2689: /*MC
2690: MATSEQDENSE - MATSEQDENSE = "seqdense" - A matrix type to be used for sequential dense matrices.
2692: Options Database Keys:
2693: . -mat_type seqdense - sets the matrix type to "seqdense" during a call to MatSetFromOptions()
2695: Level: beginner
2697: .seealso: MatCreateSeqDense()
2699: M*/
2701: PETSC_EXTERN PetscErrorCode MatCreate_SeqDense(Mat B)
2702: {
2703: Mat_SeqDense *b;
2705: PetscMPIInt size;
2708: MPI_Comm_size(PetscObjectComm((PetscObject)B),&size);
2709: if (size > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Comm must be of size 1");
2711: PetscNewLog(B,&b);
2712: PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));
2713: B->data = (void*)b;
2715: b->roworiented = PETSC_TRUE;
2717: PetscObjectComposeFunction((PetscObject)B,"MatDenseGetArray_C",MatDenseGetArray_SeqDense);
2718: PetscObjectComposeFunction((PetscObject)B,"MatDenseRestoreArray_C",MatDenseRestoreArray_SeqDense);
2719: PetscObjectComposeFunction((PetscObject)B,"MatDensePlaceArray_C",MatDensePlaceArray_SeqDense);
2720: PetscObjectComposeFunction((PetscObject)B,"MatDenseResetArray_C",MatDenseResetArray_SeqDense);
2721: PetscObjectComposeFunction((PetscObject)B,"MatDenseGetArrayRead_C",MatDenseGetArray_SeqDense);
2722: PetscObjectComposeFunction((PetscObject)B,"MatDenseRestoreArrayRead_C",MatDenseRestoreArray_SeqDense);
2723: PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqdense_seqaij_C",MatConvert_SeqDense_SeqAIJ);
2724: #if defined(PETSC_HAVE_ELEMENTAL)
2725: PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqdense_elemental_C",MatConvert_SeqDense_Elemental);
2726: #endif
2727: PetscObjectComposeFunction((PetscObject)B,"MatSeqDenseSetPreallocation_C",MatSeqDenseSetPreallocation_SeqDense);
2728: PetscObjectComposeFunction((PetscObject)B,"MatMatMult_seqaij_seqdense_C",MatMatMult_SeqAIJ_SeqDense);
2729: PetscObjectComposeFunction((PetscObject)B,"MatMatMultSymbolic_seqaij_seqdense_C",MatMatMultSymbolic_SeqAIJ_SeqDense);
2730: PetscObjectComposeFunction((PetscObject)B,"MatMatMultNumeric_seqaij_seqdense_C",MatMatMultNumeric_SeqAIJ_SeqDense);
2731: PetscObjectComposeFunction((PetscObject)B,"MatPtAP_seqaij_seqdense_C",MatPtAP_SeqDense_SeqDense);
2732: PetscObjectComposeFunction((PetscObject)B,"MatMatMult_seqaijperm_seqdense_C",MatMatMult_SeqAIJ_SeqDense);
2733: PetscObjectComposeFunction((PetscObject)B,"MatMatMultSymbolic_seqaijperm_seqdense_C",MatMatMultSymbolic_SeqAIJ_SeqDense);
2734: PetscObjectComposeFunction((PetscObject)B,"MatMatMultNumeric_seqaijperm_seqdense_C",MatMatMultNumeric_SeqAIJ_SeqDense);
2735: PetscObjectComposeFunction((PetscObject)B,"MatPtAP_seqaijperm_seqdense_C",MatPtAP_SeqDense_SeqDense);
2736: PetscObjectComposeFunction((PetscObject)B,"MatMatMult_seqaijsell_seqdense_C",MatMatMult_SeqAIJ_SeqDense);
2737: PetscObjectComposeFunction((PetscObject)B,"MatMatMultSymbolic_seqaijsell_seqdense_C",MatMatMultSymbolic_SeqAIJ_SeqDense);
2738: PetscObjectComposeFunction((PetscObject)B,"MatMatMultNumeric_seqaijsell_seqdense_C",MatMatMultNumeric_SeqAIJ_SeqDense);
2739: PetscObjectComposeFunction((PetscObject)B,"MatPtAP_seqaijsell_seqdense_C",MatPtAP_SeqDense_SeqDense);
2740: PetscObjectComposeFunction((PetscObject)B,"MatMatMult_seqaijmkl_seqdense_C",MatMatMult_SeqAIJ_SeqDense);
2741: PetscObjectComposeFunction((PetscObject)B,"MatMatMultSymbolic_seqaijmkl_seqdense_C",MatMatMultSymbolic_SeqAIJ_SeqDense);
2742: PetscObjectComposeFunction((PetscObject)B,"MatMatMultNumeric_seqaijmkl_seqdense_C",MatMatMultNumeric_SeqAIJ_SeqDense);
2743: PetscObjectComposeFunction((PetscObject)B,"MatPtAP_seqaijmkl_seqdense_C",MatPtAP_SeqDense_SeqDense);
2745: PetscObjectComposeFunction((PetscObject)B,"MatTransposeMatMult_seqaij_seqdense_C",MatTransposeMatMult_SeqAIJ_SeqDense);
2746: PetscObjectComposeFunction((PetscObject)B,"MatTransposeMatMultSymbolic_seqaij_seqdense_C",MatTransposeMatMultSymbolic_SeqAIJ_SeqDense);
2747: PetscObjectComposeFunction((PetscObject)B,"MatTransposeMatMultNumeric_seqaij_seqdense_C",MatTransposeMatMultNumeric_SeqAIJ_SeqDense);
2748: PetscObjectComposeFunction((PetscObject)B,"MatTransposeMatMult_seqaijperm_seqdense_C",MatTransposeMatMult_SeqAIJ_SeqDense);
2749: PetscObjectComposeFunction((PetscObject)B,"MatTransposeMatMultSymbolic_seqaijperm_seqdense_C",MatTransposeMatMultSymbolic_SeqAIJ_SeqDense);
2750: PetscObjectComposeFunction((PetscObject)B,"MatTransposeMatMultNumeric_seqaijperm_seqdense_C",MatTransposeMatMultNumeric_SeqAIJ_SeqDense);
2751: PetscObjectComposeFunction((PetscObject)B,"MatTransposeMatMult_seqaijsell_seqdense_C",MatTransposeMatMult_SeqAIJ_SeqDense);
2752: PetscObjectComposeFunction((PetscObject)B,"MatTransposeMatMultSymbolic_seqaijsell_seqdense_C",MatTransposeMatMultSymbolic_SeqAIJ_SeqDense);
2753: PetscObjectComposeFunction((PetscObject)B,"MatTransposeMatMultNumeric_seqaijsell_seqdense_C",MatTransposeMatMultNumeric_SeqAIJ_SeqDense);
2755: PetscObjectComposeFunction((PetscObject)B,"MatTransposeMatMult_seqaijmkl_seqdense_C",MatTransposeMatMult_SeqAIJ_SeqDense);
2756: PetscObjectComposeFunction((PetscObject)B,"MatTransposeMatMultSymbolic_seqaijmkl_seqdense_C",MatTransposeMatMultSymbolic_SeqAIJ_SeqDense);
2757: PetscObjectComposeFunction((PetscObject)B,"MatTransposeMatMultNumeric_seqaijmkl_seqdense_C",MatTransposeMatMultNumeric_SeqAIJ_SeqDense);
2758: PetscObjectComposeFunction((PetscObject)B,"MatDenseGetColumn_C",MatDenseGetColumn_SeqDense);
2759: PetscObjectComposeFunction((PetscObject)B,"MatDenseRestoreColumn_C",MatDenseRestoreColumn_SeqDense);
2760: PetscObjectChangeTypeName((PetscObject)B,MATSEQDENSE);
2761: return(0);
2762: }
2764: /*@C
2765: MatDenseGetColumn - gives access to a column of a dense matrix. This is only the local part of the column. You MUST call MatDenseRestoreColumn() to avoid memory bleeding.
2767: Not Collective
2769: Input Parameter:
2770: + mat - a MATSEQDENSE or MATMPIDENSE matrix
2771: - col - column index
2773: Output Parameter:
2774: . vals - pointer to the data
2776: Level: intermediate
2778: .seealso: MatDenseRestoreColumn()
2779: @*/
2780: PetscErrorCode MatDenseGetColumn(Mat A,PetscInt col,PetscScalar **vals)
2781: {
2785: PetscUseMethod(A,"MatDenseGetColumn_C",(Mat,PetscInt,PetscScalar**),(A,col,vals));
2786: return(0);
2787: }
2789: /*@C
2790: MatDenseRestoreColumn - returns access to a column of a dense matrix which is returned by MatDenseGetColumn().
2792: Not Collective
2794: Input Parameter:
2795: . mat - a MATSEQDENSE or MATMPIDENSE matrix
2797: Output Parameter:
2798: . vals - pointer to the data
2800: Level: intermediate
2802: .seealso: MatDenseGetColumn()
2803: @*/
2804: PetscErrorCode MatDenseRestoreColumn(Mat A,PetscScalar **vals)
2805: {
2809: PetscUseMethod(A,"MatDenseRestoreColumn_C",(Mat,PetscScalar**),(A,vals));
2810: return(0);
2811: }