Actual source code: dense.c
petsc-3.10.5 2019-03-28
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;
1086: /* force binary viewer to load .info file if it has not yet done so */
1087: PetscViewerSetUp(viewer);
1088: PetscObjectGetComm((PetscObject)viewer,&comm);
1089: MPI_Comm_size(comm,&size);
1090: if (size > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"view must have one processor");
1091: PetscViewerBinaryGetDescriptor(viewer,&fd);
1092: PetscBinaryRead(fd,header,4,PETSC_INT);
1093: if (header[0] != MAT_FILE_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Not matrix object");
1094: M = header[1]; N = header[2]; nz = header[3];
1096: /* set global size if not set already*/
1097: if (newmat->rmap->n < 0 && newmat->rmap->N < 0 && newmat->cmap->n < 0 && newmat->cmap->N < 0) {
1098: MatSetSizes(newmat,M,N,M,N);
1099: } else {
1100: /* if sizes and type are already set, check if the vector global sizes are correct */
1101: MatGetSize(newmat,&grows,&gcols);
1102: 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);
1103: }
1104: a = (Mat_SeqDense*)newmat->data;
1105: if (!a->user_alloc) {
1106: MatSeqDenseSetPreallocation(newmat,NULL);
1107: }
1109: if (nz == MATRIX_BINARY_FORMAT_DENSE) { /* matrix in file is dense */
1110: a = (Mat_SeqDense*)newmat->data;
1111: v = a->v;
1112: /* Allocate some temp space to read in the values and then flip them
1113: from row major to column major */
1114: PetscMalloc1(M*N > 0 ? M*N : 1,&w);
1115: /* read in nonzero values */
1116: PetscBinaryRead(fd,w,M*N,PETSC_SCALAR);
1117: /* now flip the values and store them in the matrix*/
1118: for (j=0; j<N; j++) {
1119: for (i=0; i<M; i++) {
1120: *v++ =w[i*N+j];
1121: }
1122: }
1123: PetscFree(w);
1124: } else {
1125: /* read row lengths */
1126: PetscMalloc1(M+1,&rowlengths);
1127: PetscBinaryRead(fd,rowlengths,M,PETSC_INT);
1129: a = (Mat_SeqDense*)newmat->data;
1130: v = a->v;
1132: /* read column indices and nonzeros */
1133: PetscMalloc1(nz+1,&scols);
1134: cols = scols;
1135: PetscBinaryRead(fd,cols,nz,PETSC_INT);
1136: PetscMalloc1(nz+1,&svals);
1137: vals = svals;
1138: PetscBinaryRead(fd,vals,nz,PETSC_SCALAR);
1140: /* insert into matrix */
1141: for (i=0; i<M; i++) {
1142: for (j=0; j<rowlengths[i]; j++) v[i+M*scols[j]] = svals[j];
1143: svals += rowlengths[i]; scols += rowlengths[i];
1144: }
1145: PetscFree(vals);
1146: PetscFree(cols);
1147: PetscFree(rowlengths);
1148: }
1149: MatAssemblyBegin(newmat,MAT_FINAL_ASSEMBLY);
1150: MatAssemblyEnd(newmat,MAT_FINAL_ASSEMBLY);
1151: return(0);
1152: }
1154: static PetscErrorCode MatView_SeqDense_ASCII(Mat A,PetscViewer viewer)
1155: {
1156: Mat_SeqDense *a = (Mat_SeqDense*)A->data;
1157: PetscErrorCode ierr;
1158: PetscInt i,j;
1159: const char *name;
1160: PetscScalar *v;
1161: PetscViewerFormat format;
1162: #if defined(PETSC_USE_COMPLEX)
1163: PetscBool allreal = PETSC_TRUE;
1164: #endif
1167: PetscViewerGetFormat(viewer,&format);
1168: if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1169: return(0); /* do nothing for now */
1170: } else if (format == PETSC_VIEWER_ASCII_COMMON) {
1171: PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);
1172: for (i=0; i<A->rmap->n; i++) {
1173: v = a->v + i;
1174: PetscViewerASCIIPrintf(viewer,"row %D:",i);
1175: for (j=0; j<A->cmap->n; j++) {
1176: #if defined(PETSC_USE_COMPLEX)
1177: if (PetscRealPart(*v) != 0.0 && PetscImaginaryPart(*v) != 0.0) {
1178: PetscViewerASCIIPrintf(viewer," (%D, %g + %g i) ",j,(double)PetscRealPart(*v),(double)PetscImaginaryPart(*v));
1179: } else if (PetscRealPart(*v)) {
1180: PetscViewerASCIIPrintf(viewer," (%D, %g) ",j,(double)PetscRealPart(*v));
1181: }
1182: #else
1183: if (*v) {
1184: PetscViewerASCIIPrintf(viewer," (%D, %g) ",j,(double)*v);
1185: }
1186: #endif
1187: v += a->lda;
1188: }
1189: PetscViewerASCIIPrintf(viewer,"\n");
1190: }
1191: PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);
1192: } else {
1193: PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);
1194: #if defined(PETSC_USE_COMPLEX)
1195: /* determine if matrix has all real values */
1196: v = a->v;
1197: for (i=0; i<A->rmap->n*A->cmap->n; i++) {
1198: if (PetscImaginaryPart(v[i])) { allreal = PETSC_FALSE; break;}
1199: }
1200: #endif
1201: if (format == PETSC_VIEWER_ASCII_MATLAB) {
1202: PetscObjectGetName((PetscObject)A,&name);
1203: PetscViewerASCIIPrintf(viewer,"%% Size = %D %D \n",A->rmap->n,A->cmap->n);
1204: PetscViewerASCIIPrintf(viewer,"%s = zeros(%D,%D);\n",name,A->rmap->n,A->cmap->n);
1205: PetscViewerASCIIPrintf(viewer,"%s = [\n",name);
1206: }
1208: for (i=0; i<A->rmap->n; i++) {
1209: v = a->v + i;
1210: for (j=0; j<A->cmap->n; j++) {
1211: #if defined(PETSC_USE_COMPLEX)
1212: if (allreal) {
1213: PetscViewerASCIIPrintf(viewer,"%18.16e ",(double)PetscRealPart(*v));
1214: } else {
1215: PetscViewerASCIIPrintf(viewer,"%18.16e + %18.16ei ",(double)PetscRealPart(*v),(double)PetscImaginaryPart(*v));
1216: }
1217: #else
1218: PetscViewerASCIIPrintf(viewer,"%18.16e ",(double)*v);
1219: #endif
1220: v += a->lda;
1221: }
1222: PetscViewerASCIIPrintf(viewer,"\n");
1223: }
1224: if (format == PETSC_VIEWER_ASCII_MATLAB) {
1225: PetscViewerASCIIPrintf(viewer,"];\n");
1226: }
1227: PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);
1228: }
1229: PetscViewerFlush(viewer);
1230: return(0);
1231: }
1233: static PetscErrorCode MatView_SeqDense_Binary(Mat A,PetscViewer viewer)
1234: {
1235: Mat_SeqDense *a = (Mat_SeqDense*)A->data;
1236: PetscErrorCode ierr;
1237: int fd;
1238: PetscInt ict,j,n = A->cmap->n,m = A->rmap->n,i,*col_lens,nz = m*n;
1239: PetscScalar *v,*anonz,*vals;
1240: PetscViewerFormat format;
1243: PetscViewerBinaryGetDescriptor(viewer,&fd);
1245: PetscViewerGetFormat(viewer,&format);
1246: if (format == PETSC_VIEWER_NATIVE) {
1247: /* store the matrix as a dense matrix */
1248: PetscMalloc1(4,&col_lens);
1250: col_lens[0] = MAT_FILE_CLASSID;
1251: col_lens[1] = m;
1252: col_lens[2] = n;
1253: col_lens[3] = MATRIX_BINARY_FORMAT_DENSE;
1255: PetscBinaryWrite(fd,col_lens,4,PETSC_INT,PETSC_TRUE);
1256: PetscFree(col_lens);
1258: /* write out matrix, by rows */
1259: PetscMalloc1(m*n+1,&vals);
1260: v = a->v;
1261: for (j=0; j<n; j++) {
1262: for (i=0; i<m; i++) {
1263: vals[j + i*n] = *v++;
1264: }
1265: }
1266: PetscBinaryWrite(fd,vals,n*m,PETSC_SCALAR,PETSC_FALSE);
1267: PetscFree(vals);
1268: } else {
1269: PetscMalloc1(4+nz,&col_lens);
1271: col_lens[0] = MAT_FILE_CLASSID;
1272: col_lens[1] = m;
1273: col_lens[2] = n;
1274: col_lens[3] = nz;
1276: /* store lengths of each row and write (including header) to file */
1277: for (i=0; i<m; i++) col_lens[4+i] = n;
1278: PetscBinaryWrite(fd,col_lens,4+m,PETSC_INT,PETSC_TRUE);
1280: /* Possibly should write in smaller increments, not whole matrix at once? */
1281: /* store column indices (zero start index) */
1282: ict = 0;
1283: for (i=0; i<m; i++) {
1284: for (j=0; j<n; j++) col_lens[ict++] = j;
1285: }
1286: PetscBinaryWrite(fd,col_lens,nz,PETSC_INT,PETSC_FALSE);
1287: PetscFree(col_lens);
1289: /* store nonzero values */
1290: PetscMalloc1(nz+1,&anonz);
1291: ict = 0;
1292: for (i=0; i<m; i++) {
1293: v = a->v + i;
1294: for (j=0; j<n; j++) {
1295: anonz[ict++] = *v; v += a->lda;
1296: }
1297: }
1298: PetscBinaryWrite(fd,anonz,nz,PETSC_SCALAR,PETSC_FALSE);
1299: PetscFree(anonz);
1300: }
1301: return(0);
1302: }
1304: #include <petscdraw.h>
1305: static PetscErrorCode MatView_SeqDense_Draw_Zoom(PetscDraw draw,void *Aa)
1306: {
1307: Mat A = (Mat) Aa;
1308: Mat_SeqDense *a = (Mat_SeqDense*)A->data;
1309: PetscErrorCode ierr;
1310: PetscInt m = A->rmap->n,n = A->cmap->n,i,j;
1311: int color = PETSC_DRAW_WHITE;
1312: PetscScalar *v = a->v;
1313: PetscViewer viewer;
1314: PetscReal xl,yl,xr,yr,x_l,x_r,y_l,y_r;
1315: PetscViewerFormat format;
1318: PetscObjectQuery((PetscObject)A,"Zoomviewer",(PetscObject*)&viewer);
1319: PetscViewerGetFormat(viewer,&format);
1320: PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);
1322: /* Loop over matrix elements drawing boxes */
1324: if (format != PETSC_VIEWER_DRAW_CONTOUR) {
1325: PetscDrawCollectiveBegin(draw);
1326: /* Blue for negative and Red for positive */
1327: for (j = 0; j < n; j++) {
1328: x_l = j; x_r = x_l + 1.0;
1329: for (i = 0; i < m; i++) {
1330: y_l = m - i - 1.0;
1331: y_r = y_l + 1.0;
1332: if (PetscRealPart(v[j*m+i]) > 0.) {
1333: color = PETSC_DRAW_RED;
1334: } else if (PetscRealPart(v[j*m+i]) < 0.) {
1335: color = PETSC_DRAW_BLUE;
1336: } else {
1337: continue;
1338: }
1339: PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);
1340: }
1341: }
1342: PetscDrawCollectiveEnd(draw);
1343: } else {
1344: /* use contour shading to indicate magnitude of values */
1345: /* first determine max of all nonzero values */
1346: PetscReal minv = 0.0, maxv = 0.0;
1347: PetscDraw popup;
1349: for (i=0; i < m*n; i++) {
1350: if (PetscAbsScalar(v[i]) > maxv) maxv = PetscAbsScalar(v[i]);
1351: }
1352: if (minv >= maxv) maxv = minv + PETSC_SMALL;
1353: PetscDrawGetPopup(draw,&popup);
1354: PetscDrawScalePopup(popup,minv,maxv);
1356: PetscDrawCollectiveBegin(draw);
1357: for (j=0; j<n; j++) {
1358: x_l = j;
1359: x_r = x_l + 1.0;
1360: for (i=0; i<m; i++) {
1361: y_l = m - i - 1.0;
1362: y_r = y_l + 1.0;
1363: color = PetscDrawRealToColor(PetscAbsScalar(v[j*m+i]),minv,maxv);
1364: PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);
1365: }
1366: }
1367: PetscDrawCollectiveEnd(draw);
1368: }
1369: return(0);
1370: }
1372: static PetscErrorCode MatView_SeqDense_Draw(Mat A,PetscViewer viewer)
1373: {
1374: PetscDraw draw;
1375: PetscBool isnull;
1376: PetscReal xr,yr,xl,yl,h,w;
1380: PetscViewerDrawGetDraw(viewer,0,&draw);
1381: PetscDrawIsNull(draw,&isnull);
1382: if (isnull) return(0);
1384: xr = A->cmap->n; yr = A->rmap->n; h = yr/10.0; w = xr/10.0;
1385: xr += w; yr += h; xl = -w; yl = -h;
1386: PetscDrawSetCoordinates(draw,xl,yl,xr,yr);
1387: PetscObjectCompose((PetscObject)A,"Zoomviewer",(PetscObject)viewer);
1388: PetscDrawZoom(draw,MatView_SeqDense_Draw_Zoom,A);
1389: PetscObjectCompose((PetscObject)A,"Zoomviewer",NULL);
1390: PetscDrawSave(draw);
1391: return(0);
1392: }
1394: PetscErrorCode MatView_SeqDense(Mat A,PetscViewer viewer)
1395: {
1397: PetscBool iascii,isbinary,isdraw;
1400: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
1401: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);
1402: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);
1404: if (iascii) {
1405: MatView_SeqDense_ASCII(A,viewer);
1406: } else if (isbinary) {
1407: MatView_SeqDense_Binary(A,viewer);
1408: } else if (isdraw) {
1409: MatView_SeqDense_Draw(A,viewer);
1410: }
1411: return(0);
1412: }
1414: static PetscErrorCode MatDensePlaceArray_SeqDense(Mat A,const PetscScalar array[])
1415: {
1416: Mat_SeqDense *a = (Mat_SeqDense*)A->data;
1419: a->unplacedarray = a->v;
1420: a->unplaced_user_alloc = a->user_alloc;
1421: a->v = (PetscScalar*) array;
1422: return(0);
1423: }
1425: static PetscErrorCode MatDenseResetArray_SeqDense(Mat A)
1426: {
1427: Mat_SeqDense *a = (Mat_SeqDense*)A->data;
1430: a->v = a->unplacedarray;
1431: a->user_alloc = a->unplaced_user_alloc;
1432: a->unplacedarray = NULL;
1433: return(0);
1434: }
1436: static PetscErrorCode MatDestroy_SeqDense(Mat mat)
1437: {
1438: Mat_SeqDense *l = (Mat_SeqDense*)mat->data;
1442: #if defined(PETSC_USE_LOG)
1443: PetscLogObjectState((PetscObject)mat,"Rows %D Cols %D",mat->rmap->n,mat->cmap->n);
1444: #endif
1445: PetscFree(l->pivots);
1446: PetscFree(l->fwork);
1447: MatDestroy(&l->ptapwork);
1448: if (!l->user_alloc) {PetscFree(l->v);}
1449: PetscFree(mat->data);
1451: PetscObjectChangeTypeName((PetscObject)mat,0);
1452: PetscObjectComposeFunction((PetscObject)mat,"MatDenseGetArray_C",NULL);
1453: PetscObjectComposeFunction((PetscObject)mat,"MatDensePlaceArray_C",NULL);
1454: PetscObjectComposeFunction((PetscObject)mat,"MatDenseResetArray_C",NULL);
1455: PetscObjectComposeFunction((PetscObject)mat,"MatDenseRestoreArray_C",NULL);
1456: PetscObjectComposeFunction((PetscObject)mat,"MatConvert_seqdense_seqaij_C",NULL);
1457: #if defined(PETSC_HAVE_ELEMENTAL)
1458: PetscObjectComposeFunction((PetscObject)mat,"MatConvert_seqdense_elemental_C",NULL);
1459: #endif
1460: PetscObjectComposeFunction((PetscObject)mat,"MatSeqDenseSetPreallocation_C",NULL);
1461: PetscObjectComposeFunction((PetscObject)mat,"MatMatMult_seqaij_seqdense_C",NULL);
1462: PetscObjectComposeFunction((PetscObject)mat,"MatMatMultSymbolic_seqaij_seqdense_C",NULL);
1463: PetscObjectComposeFunction((PetscObject)mat,"MatMatMultNumeric_seqaij_seqdense_C",NULL);
1464: PetscObjectComposeFunction((PetscObject)mat,"MatPtAP_seqaij_seqdense_C",NULL);
1465: PetscObjectComposeFunction((PetscObject)mat,"MatTransposeMatMult_seqaij_seqdense_C",NULL);
1466: PetscObjectComposeFunction((PetscObject)mat,"MatTransposeMatMultSymbolic_seqaij_seqdense_C",NULL);
1467: PetscObjectComposeFunction((PetscObject)mat,"MatTransposeMatMultNumeric_seqaij_seqdense_C",NULL);
1468: PetscObjectComposeFunction((PetscObject)mat,"MatDenseGetColumn_C",NULL);
1469: PetscObjectComposeFunction((PetscObject)mat,"MatDenseRestoreColumn_C",NULL);
1470: return(0);
1471: }
1473: static PetscErrorCode MatTranspose_SeqDense(Mat A,MatReuse reuse,Mat *matout)
1474: {
1475: Mat_SeqDense *mat = (Mat_SeqDense*)A->data;
1477: PetscInt k,j,m,n,M;
1478: PetscScalar *v,tmp;
1481: v = mat->v; m = A->rmap->n; M = mat->lda; n = A->cmap->n;
1482: if (reuse == MAT_INPLACE_MATRIX && m == n) { /* in place transpose */
1483: for (j=0; j<m; j++) {
1484: for (k=0; k<j; k++) {
1485: tmp = v[j + k*M];
1486: v[j + k*M] = v[k + j*M];
1487: v[k + j*M] = tmp;
1488: }
1489: }
1490: } else { /* out-of-place transpose */
1491: Mat tmat;
1492: Mat_SeqDense *tmatd;
1493: PetscScalar *v2;
1494: PetscInt M2;
1496: if (reuse != MAT_REUSE_MATRIX) {
1497: MatCreate(PetscObjectComm((PetscObject)A),&tmat);
1498: MatSetSizes(tmat,A->cmap->n,A->rmap->n,A->cmap->n,A->rmap->n);
1499: MatSetType(tmat,((PetscObject)A)->type_name);
1500: MatSeqDenseSetPreallocation(tmat,NULL);
1501: } else {
1502: tmat = *matout;
1503: }
1504: tmatd = (Mat_SeqDense*)tmat->data;
1505: v = mat->v; v2 = tmatd->v; M2 = tmatd->lda;
1506: for (j=0; j<n; j++) {
1507: for (k=0; k<m; k++) v2[j + k*M2] = v[k + j*M];
1508: }
1509: MatAssemblyBegin(tmat,MAT_FINAL_ASSEMBLY);
1510: MatAssemblyEnd(tmat,MAT_FINAL_ASSEMBLY);
1511: if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX) *matout = tmat;
1512: else {
1513: MatHeaderMerge(A,&tmat);
1514: }
1515: }
1516: return(0);
1517: }
1519: static PetscErrorCode MatEqual_SeqDense(Mat A1,Mat A2,PetscBool *flg)
1520: {
1521: Mat_SeqDense *mat1 = (Mat_SeqDense*)A1->data;
1522: Mat_SeqDense *mat2 = (Mat_SeqDense*)A2->data;
1523: PetscInt i,j;
1524: PetscScalar *v1,*v2;
1527: if (A1->rmap->n != A2->rmap->n) {*flg = PETSC_FALSE; return(0);}
1528: if (A1->cmap->n != A2->cmap->n) {*flg = PETSC_FALSE; return(0);}
1529: for (i=0; i<A1->rmap->n; i++) {
1530: v1 = mat1->v+i; v2 = mat2->v+i;
1531: for (j=0; j<A1->cmap->n; j++) {
1532: if (*v1 != *v2) {*flg = PETSC_FALSE; return(0);}
1533: v1 += mat1->lda; v2 += mat2->lda;
1534: }
1535: }
1536: *flg = PETSC_TRUE;
1537: return(0);
1538: }
1540: static PetscErrorCode MatGetDiagonal_SeqDense(Mat A,Vec v)
1541: {
1542: Mat_SeqDense *mat = (Mat_SeqDense*)A->data;
1544: PetscInt i,n,len;
1545: PetscScalar *x,zero = 0.0;
1548: VecSet(v,zero);
1549: VecGetSize(v,&n);
1550: VecGetArray(v,&x);
1551: len = PetscMin(A->rmap->n,A->cmap->n);
1552: if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming mat and vec");
1553: for (i=0; i<len; i++) {
1554: x[i] = mat->v[i*mat->lda + i];
1555: }
1556: VecRestoreArray(v,&x);
1557: return(0);
1558: }
1560: static PetscErrorCode MatDiagonalScale_SeqDense(Mat A,Vec ll,Vec rr)
1561: {
1562: Mat_SeqDense *mat = (Mat_SeqDense*)A->data;
1563: const PetscScalar *l,*r;
1564: PetscScalar x,*v;
1565: PetscErrorCode ierr;
1566: PetscInt i,j,m = A->rmap->n,n = A->cmap->n;
1569: if (ll) {
1570: VecGetSize(ll,&m);
1571: VecGetArrayRead(ll,&l);
1572: if (m != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Left scaling vec wrong size");
1573: for (i=0; i<m; i++) {
1574: x = l[i];
1575: v = mat->v + i;
1576: for (j=0; j<n; j++) { (*v) *= x; v+= mat->lda;}
1577: }
1578: VecRestoreArrayRead(ll,&l);
1579: PetscLogFlops(1.0*n*m);
1580: }
1581: if (rr) {
1582: VecGetSize(rr,&n);
1583: VecGetArrayRead(rr,&r);
1584: if (n != A->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Right scaling vec wrong size");
1585: for (i=0; i<n; i++) {
1586: x = r[i];
1587: v = mat->v + i*mat->lda;
1588: for (j=0; j<m; j++) (*v++) *= x;
1589: }
1590: VecRestoreArrayRead(rr,&r);
1591: PetscLogFlops(1.0*n*m);
1592: }
1593: return(0);
1594: }
1596: static PetscErrorCode MatNorm_SeqDense(Mat A,NormType type,PetscReal *nrm)
1597: {
1598: Mat_SeqDense *mat = (Mat_SeqDense*)A->data;
1599: PetscScalar *v = mat->v;
1600: PetscReal sum = 0.0;
1601: PetscInt lda =mat->lda,m=A->rmap->n,i,j;
1605: if (type == NORM_FROBENIUS) {
1606: if (lda>m) {
1607: for (j=0; j<A->cmap->n; j++) {
1608: v = mat->v+j*lda;
1609: for (i=0; i<m; i++) {
1610: sum += PetscRealPart(PetscConj(*v)*(*v)); v++;
1611: }
1612: }
1613: } else {
1614: #if defined(PETSC_USE_REAL___FP16)
1615: PetscBLASInt one = 1,cnt = A->cmap->n*A->rmap->n;
1616: *nrm = BLASnrm2_(&cnt,v,&one);
1617: }
1618: #else
1619: for (i=0; i<A->cmap->n*A->rmap->n; i++) {
1620: sum += PetscRealPart(PetscConj(*v)*(*v)); v++;
1621: }
1622: }
1623: *nrm = PetscSqrtReal(sum);
1624: #endif
1625: PetscLogFlops(2.0*A->cmap->n*A->rmap->n);
1626: } else if (type == NORM_1) {
1627: *nrm = 0.0;
1628: for (j=0; j<A->cmap->n; j++) {
1629: v = mat->v + j*mat->lda;
1630: sum = 0.0;
1631: for (i=0; i<A->rmap->n; i++) {
1632: sum += PetscAbsScalar(*v); v++;
1633: }
1634: if (sum > *nrm) *nrm = sum;
1635: }
1636: PetscLogFlops(1.0*A->cmap->n*A->rmap->n);
1637: } else if (type == NORM_INFINITY) {
1638: *nrm = 0.0;
1639: for (j=0; j<A->rmap->n; j++) {
1640: v = mat->v + j;
1641: sum = 0.0;
1642: for (i=0; i<A->cmap->n; i++) {
1643: sum += PetscAbsScalar(*v); v += mat->lda;
1644: }
1645: if (sum > *nrm) *nrm = sum;
1646: }
1647: PetscLogFlops(1.0*A->cmap->n*A->rmap->n);
1648: } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No two norm");
1649: return(0);
1650: }
1652: static PetscErrorCode MatSetOption_SeqDense(Mat A,MatOption op,PetscBool flg)
1653: {
1654: Mat_SeqDense *aij = (Mat_SeqDense*)A->data;
1658: switch (op) {
1659: case MAT_ROW_ORIENTED:
1660: aij->roworiented = flg;
1661: break;
1662: case MAT_NEW_NONZERO_LOCATIONS:
1663: case MAT_NEW_NONZERO_LOCATION_ERR:
1664: case MAT_NEW_NONZERO_ALLOCATION_ERR:
1665: case MAT_NEW_DIAGONALS:
1666: case MAT_KEEP_NONZERO_PATTERN:
1667: case MAT_IGNORE_OFF_PROC_ENTRIES:
1668: case MAT_USE_HASH_TABLE:
1669: case MAT_IGNORE_ZERO_ENTRIES:
1670: case MAT_IGNORE_LOWER_TRIANGULAR:
1671: PetscInfo1(A,"Option %s ignored\n",MatOptions[op]);
1672: break;
1673: case MAT_SPD:
1674: case MAT_SYMMETRIC:
1675: case MAT_STRUCTURALLY_SYMMETRIC:
1676: case MAT_HERMITIAN:
1677: case MAT_SYMMETRY_ETERNAL:
1678: /* These options are handled directly by MatSetOption() */
1679: break;
1680: default:
1681: SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"unknown option %s",MatOptions[op]);
1682: }
1683: return(0);
1684: }
1686: static PetscErrorCode MatZeroEntries_SeqDense(Mat A)
1687: {
1688: Mat_SeqDense *l = (Mat_SeqDense*)A->data;
1690: PetscInt lda=l->lda,m=A->rmap->n,j;
1693: if (lda>m) {
1694: for (j=0; j<A->cmap->n; j++) {
1695: PetscMemzero(l->v+j*lda,m*sizeof(PetscScalar));
1696: }
1697: } else {
1698: PetscMemzero(l->v,A->rmap->n*A->cmap->n*sizeof(PetscScalar));
1699: }
1700: return(0);
1701: }
1703: static PetscErrorCode MatZeroRows_SeqDense(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
1704: {
1705: PetscErrorCode ierr;
1706: Mat_SeqDense *l = (Mat_SeqDense*)A->data;
1707: PetscInt m = l->lda, n = A->cmap->n, i,j;
1708: PetscScalar *slot,*bb;
1709: const PetscScalar *xx;
1712: #if defined(PETSC_USE_DEBUG)
1713: for (i=0; i<N; i++) {
1714: if (rows[i] < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative row requested to be zeroed");
1715: 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);
1716: }
1717: #endif
1719: /* fix right hand side if needed */
1720: if (x && b) {
1721: VecGetArrayRead(x,&xx);
1722: VecGetArray(b,&bb);
1723: for (i=0; i<N; i++) bb[rows[i]] = diag*xx[rows[i]];
1724: VecRestoreArrayRead(x,&xx);
1725: VecRestoreArray(b,&bb);
1726: }
1728: for (i=0; i<N; i++) {
1729: slot = l->v + rows[i];
1730: for (j=0; j<n; j++) { *slot = 0.0; slot += m;}
1731: }
1732: if (diag != 0.0) {
1733: if (A->rmap->n != A->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only coded for square matrices");
1734: for (i=0; i<N; i++) {
1735: slot = l->v + (m+1)*rows[i];
1736: *slot = diag;
1737: }
1738: }
1739: return(0);
1740: }
1742: static PetscErrorCode MatDenseGetArray_SeqDense(Mat A,PetscScalar *array[])
1743: {
1744: Mat_SeqDense *mat = (Mat_SeqDense*)A->data;
1747: 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");
1748: *array = mat->v;
1749: return(0);
1750: }
1752: static PetscErrorCode MatDenseRestoreArray_SeqDense(Mat A,PetscScalar *array[])
1753: {
1755: return(0);
1756: }
1758: /*@C
1759: MatDenseGetArray - gives access to the array where the data for a SeqDense matrix is stored
1761: Logically Collective on Mat
1763: Input Parameter:
1764: . mat - a MATSEQDENSE or MATMPIDENSE matrix
1766: Output Parameter:
1767: . array - pointer to the data
1769: Level: intermediate
1771: .seealso: MatDenseRestoreArray(), MatDenseGetArrayRead(), MatDenseRestoreArrayRead()
1772: @*/
1773: PetscErrorCode MatDenseGetArray(Mat A,PetscScalar **array)
1774: {
1778: PetscUseMethod(A,"MatDenseGetArray_C",(Mat,PetscScalar**),(A,array));
1779: return(0);
1780: }
1782: /*@C
1783: MatDenseRestoreArray - returns access to the array where the data for a dense matrix is stored obtained by MatDenseGetArray()
1785: Logically Collective on Mat
1787: Input Parameters:
1788: . mat - a MATSEQDENSE or MATMPIDENSE matrix
1789: . array - pointer to the data
1791: Level: intermediate
1793: .seealso: MatDenseGetArray(), MatDenseGetArrayRead(), MatDenseRestoreArrayRead()
1794: @*/
1795: PetscErrorCode MatDenseRestoreArray(Mat A,PetscScalar **array)
1796: {
1800: PetscUseMethod(A,"MatDenseRestoreArray_C",(Mat,PetscScalar**),(A,array));
1801: if (array) *array = NULL;
1802: PetscObjectStateIncrease((PetscObject)A);
1803: return(0);
1804: }
1806: /*@C
1807: MatDenseGetArrayRead - gives access to the array where the data for a SeqDense matrix is stored
1809: Not Collective
1811: Input Parameter:
1812: . mat - a MATSEQDENSE or MATMPIDENSE matrix
1814: Output Parameter:
1815: . array - pointer to the data
1817: Level: intermediate
1819: .seealso: MatDenseRestoreArray(), MatDenseGetArray(), MatDenseRestoreArrayRead()
1820: @*/
1821: PetscErrorCode MatDenseGetArrayRead(Mat A,const PetscScalar **array)
1822: {
1826: PetscUseMethod(A,"MatDenseGetArrayRead_C",(Mat,const PetscScalar**),(A,array));
1827: return(0);
1828: }
1830: /*@C
1831: MatDenseRestoreArrayRead - returns access to the array where the data for a dense matrix is stored obtained by MatDenseGetArray()
1833: Not Collective
1835: Input Parameters:
1836: . mat - a MATSEQDENSE or MATMPIDENSE matrix
1837: . array - pointer to the data
1839: Level: intermediate
1841: .seealso: MatDenseGetArray(), MatDenseGetArrayRead(), MatDenseRestoreArray()
1842: @*/
1843: PetscErrorCode MatDenseRestoreArrayRead(Mat A,const PetscScalar **array)
1844: {
1848: PetscUseMethod(A,"MatDenseRestoreArrayRead_C",(Mat,const PetscScalar**),(A,array));
1849: if (array) *array = NULL;
1850: return(0);
1851: }
1853: static PetscErrorCode MatCreateSubMatrix_SeqDense(Mat A,IS isrow,IS iscol,PetscInt cs,MatReuse scall,Mat *B)
1854: {
1855: Mat_SeqDense *mat = (Mat_SeqDense*)A->data;
1857: PetscInt i,j,nrows,ncols;
1858: const PetscInt *irow,*icol;
1859: PetscScalar *av,*bv,*v = mat->v;
1860: Mat newmat;
1863: ISGetIndices(isrow,&irow);
1864: ISGetIndices(iscol,&icol);
1865: ISGetLocalSize(isrow,&nrows);
1866: ISGetLocalSize(iscol,&ncols);
1868: /* Check submatrixcall */
1869: if (scall == MAT_REUSE_MATRIX) {
1870: PetscInt n_cols,n_rows;
1871: MatGetSize(*B,&n_rows,&n_cols);
1872: if (n_rows != nrows || n_cols != ncols) {
1873: /* resize the result matrix to match number of requested rows/columns */
1874: MatSetSizes(*B,nrows,ncols,nrows,ncols);
1875: }
1876: newmat = *B;
1877: } else {
1878: /* Create and fill new matrix */
1879: MatCreate(PetscObjectComm((PetscObject)A),&newmat);
1880: MatSetSizes(newmat,nrows,ncols,nrows,ncols);
1881: MatSetType(newmat,((PetscObject)A)->type_name);
1882: MatSeqDenseSetPreallocation(newmat,NULL);
1883: }
1885: /* Now extract the data pointers and do the copy,column at a time */
1886: bv = ((Mat_SeqDense*)newmat->data)->v;
1888: for (i=0; i<ncols; i++) {
1889: av = v + mat->lda*icol[i];
1890: for (j=0; j<nrows; j++) *bv++ = av[irow[j]];
1891: }
1893: /* Assemble the matrices so that the correct flags are set */
1894: MatAssemblyBegin(newmat,MAT_FINAL_ASSEMBLY);
1895: MatAssemblyEnd(newmat,MAT_FINAL_ASSEMBLY);
1897: /* Free work space */
1898: ISRestoreIndices(isrow,&irow);
1899: ISRestoreIndices(iscol,&icol);
1900: *B = newmat;
1901: return(0);
1902: }
1904: static PetscErrorCode MatCreateSubMatrices_SeqDense(Mat A,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *B[])
1905: {
1907: PetscInt i;
1910: if (scall == MAT_INITIAL_MATRIX) {
1911: PetscCalloc1(n+1,B);
1912: }
1914: for (i=0; i<n; i++) {
1915: MatCreateSubMatrix_SeqDense(A,irow[i],icol[i],PETSC_DECIDE,scall,&(*B)[i]);
1916: }
1917: return(0);
1918: }
1920: static PetscErrorCode MatAssemblyBegin_SeqDense(Mat mat,MatAssemblyType mode)
1921: {
1923: return(0);
1924: }
1926: static PetscErrorCode MatAssemblyEnd_SeqDense(Mat mat,MatAssemblyType mode)
1927: {
1929: return(0);
1930: }
1932: static PetscErrorCode MatCopy_SeqDense(Mat A,Mat B,MatStructure str)
1933: {
1934: Mat_SeqDense *a = (Mat_SeqDense*)A->data,*b = (Mat_SeqDense*)B->data;
1936: PetscInt lda1=a->lda,lda2=b->lda, m=A->rmap->n,n=A->cmap->n, j;
1939: /* If the two matrices don't have the same copy implementation, they aren't compatible for fast copy. */
1940: if (A->ops->copy != B->ops->copy) {
1941: MatCopy_Basic(A,B,str);
1942: return(0);
1943: }
1944: if (m != B->rmap->n || n != B->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"size(B) != size(A)");
1945: if (lda1>m || lda2>m) {
1946: for (j=0; j<n; j++) {
1947: PetscMemcpy(b->v+j*lda2,a->v+j*lda1,m*sizeof(PetscScalar));
1948: }
1949: } else {
1950: PetscMemcpy(b->v,a->v,A->rmap->n*A->cmap->n*sizeof(PetscScalar));
1951: }
1952: PetscObjectStateIncrease((PetscObject)B);
1953: return(0);
1954: }
1956: static PetscErrorCode MatSetUp_SeqDense(Mat A)
1957: {
1961: MatSeqDenseSetPreallocation(A,0);
1962: return(0);
1963: }
1965: static PetscErrorCode MatConjugate_SeqDense(Mat A)
1966: {
1967: Mat_SeqDense *a = (Mat_SeqDense*)A->data;
1968: PetscInt i,nz = A->rmap->n*A->cmap->n;
1969: PetscScalar *aa = a->v;
1972: for (i=0; i<nz; i++) aa[i] = PetscConj(aa[i]);
1973: return(0);
1974: }
1976: static PetscErrorCode MatRealPart_SeqDense(Mat A)
1977: {
1978: Mat_SeqDense *a = (Mat_SeqDense*)A->data;
1979: PetscInt i,nz = A->rmap->n*A->cmap->n;
1980: PetscScalar *aa = a->v;
1983: for (i=0; i<nz; i++) aa[i] = PetscRealPart(aa[i]);
1984: return(0);
1985: }
1987: static PetscErrorCode MatImaginaryPart_SeqDense(Mat A)
1988: {
1989: Mat_SeqDense *a = (Mat_SeqDense*)A->data;
1990: PetscInt i,nz = A->rmap->n*A->cmap->n;
1991: PetscScalar *aa = a->v;
1994: for (i=0; i<nz; i++) aa[i] = PetscImaginaryPart(aa[i]);
1995: return(0);
1996: }
1998: /* ----------------------------------------------------------------*/
1999: PETSC_INTERN PetscErrorCode MatMatMult_SeqDense_SeqDense(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
2000: {
2004: if (scall == MAT_INITIAL_MATRIX) {
2005: PetscLogEventBegin(MAT_MatMultSymbolic,A,B,0,0);
2006: MatMatMultSymbolic_SeqDense_SeqDense(A,B,fill,C);
2007: PetscLogEventEnd(MAT_MatMultSymbolic,A,B,0,0);
2008: }
2009: PetscLogEventBegin(MAT_MatMultNumeric,A,B,0,0);
2010: MatMatMultNumeric_SeqDense_SeqDense(A,B,*C);
2011: PetscLogEventEnd(MAT_MatMultNumeric,A,B,0,0);
2012: return(0);
2013: }
2015: PetscErrorCode MatMatMultSymbolic_SeqDense_SeqDense(Mat A,Mat B,PetscReal fill,Mat *C)
2016: {
2018: PetscInt m=A->rmap->n,n=B->cmap->n;
2019: Mat Cmat;
2022: 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);
2023: MatCreate(PETSC_COMM_SELF,&Cmat);
2024: MatSetSizes(Cmat,m,n,m,n);
2025: MatSetType(Cmat,MATSEQDENSE);
2026: MatSeqDenseSetPreallocation(Cmat,NULL);
2028: *C = Cmat;
2029: return(0);
2030: }
2032: PetscErrorCode MatMatMultNumeric_SeqDense_SeqDense(Mat A,Mat B,Mat C)
2033: {
2034: Mat_SeqDense *a = (Mat_SeqDense*)A->data;
2035: Mat_SeqDense *b = (Mat_SeqDense*)B->data;
2036: Mat_SeqDense *c = (Mat_SeqDense*)C->data;
2037: PetscBLASInt m,n,k;
2038: PetscScalar _DOne=1.0,_DZero=0.0;
2040: PetscBool flg;
2043: PetscObjectTypeCompare((PetscObject)B,MATSEQDENSE,&flg);
2044: if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Second matrix must be dense");
2046: /* Handle case where where user provided the final C matrix rather than calling MatMatMult() with MAT_INITIAL_MATRIX*/
2047: PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&flg);
2048: if (flg) {
2049: C->ops->matmultnumeric = MatMatMultNumeric_SeqAIJ_SeqDense;
2050: (*C->ops->matmultnumeric)(A,B,C);
2051: return(0);
2052: }
2054: PetscObjectTypeCompare((PetscObject)A,MATSEQDENSE,&flg);
2055: if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"First matrix must be dense");
2056: PetscBLASIntCast(C->rmap->n,&m);
2057: PetscBLASIntCast(C->cmap->n,&n);
2058: PetscBLASIntCast(A->cmap->n,&k);
2059: PetscStackCallBLAS("BLASgemm",BLASgemm_("N","N",&m,&n,&k,&_DOne,a->v,&a->lda,b->v,&b->lda,&_DZero,c->v,&c->lda));
2060: return(0);
2061: }
2063: PetscErrorCode MatMatTransposeMult_SeqDense_SeqDense(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
2064: {
2068: if (scall == MAT_INITIAL_MATRIX) {
2069: PetscLogEventBegin(MAT_MatTransposeMultSymbolic,A,B,0,0);
2070: MatMatTransposeMultSymbolic_SeqDense_SeqDense(A,B,fill,C);
2071: PetscLogEventEnd(MAT_MatTransposeMultSymbolic,A,B,0,0);
2072: }
2073: PetscLogEventBegin(MAT_MatTransposeMultNumeric,A,B,0,0);
2074: MatMatTransposeMultNumeric_SeqDense_SeqDense(A,B,*C);
2075: PetscLogEventEnd(MAT_MatTransposeMultNumeric,A,B,0,0);
2076: return(0);
2077: }
2079: PetscErrorCode MatMatTransposeMultSymbolic_SeqDense_SeqDense(Mat A,Mat B,PetscReal fill,Mat *C)
2080: {
2082: PetscInt m=A->rmap->n,n=B->rmap->n;
2083: Mat Cmat;
2086: 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);
2087: MatCreate(PETSC_COMM_SELF,&Cmat);
2088: MatSetSizes(Cmat,m,n,m,n);
2089: MatSetType(Cmat,MATSEQDENSE);
2090: MatSeqDenseSetPreallocation(Cmat,NULL);
2092: Cmat->assembled = PETSC_TRUE;
2094: *C = Cmat;
2095: return(0);
2096: }
2098: PetscErrorCode MatMatTransposeMultNumeric_SeqDense_SeqDense(Mat A,Mat B,Mat C)
2099: {
2100: Mat_SeqDense *a = (Mat_SeqDense*)A->data;
2101: Mat_SeqDense *b = (Mat_SeqDense*)B->data;
2102: Mat_SeqDense *c = (Mat_SeqDense*)C->data;
2103: PetscBLASInt m,n,k;
2104: PetscScalar _DOne=1.0,_DZero=0.0;
2108: PetscBLASIntCast(A->rmap->n,&m);
2109: PetscBLASIntCast(B->rmap->n,&n);
2110: PetscBLASIntCast(A->cmap->n,&k);
2111: PetscStackCallBLAS("BLASgemm",BLASgemm_("N","T",&m,&n,&k,&_DOne,a->v,&a->lda,b->v,&b->lda,&_DZero,c->v,&c->lda));
2112: return(0);
2113: }
2115: PetscErrorCode MatTransposeMatMult_SeqDense_SeqDense(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
2116: {
2120: if (scall == MAT_INITIAL_MATRIX) {
2121: PetscLogEventBegin(MAT_TransposeMatMultSymbolic,A,B,0,0);
2122: MatTransposeMatMultSymbolic_SeqDense_SeqDense(A,B,fill,C);
2123: PetscLogEventEnd(MAT_TransposeMatMultSymbolic,A,B,0,0);
2124: }
2125: PetscLogEventBegin(MAT_TransposeMatMultNumeric,A,B,0,0);
2126: MatTransposeMatMultNumeric_SeqDense_SeqDense(A,B,*C);
2127: PetscLogEventEnd(MAT_TransposeMatMultNumeric,A,B,0,0);
2128: return(0);
2129: }
2131: PetscErrorCode MatTransposeMatMultSymbolic_SeqDense_SeqDense(Mat A,Mat B,PetscReal fill,Mat *C)
2132: {
2134: PetscInt m=A->cmap->n,n=B->cmap->n;
2135: Mat Cmat;
2138: 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);
2139: MatCreate(PETSC_COMM_SELF,&Cmat);
2140: MatSetSizes(Cmat,m,n,m,n);
2141: MatSetType(Cmat,MATSEQDENSE);
2142: MatSeqDenseSetPreallocation(Cmat,NULL);
2144: Cmat->assembled = PETSC_TRUE;
2146: *C = Cmat;
2147: return(0);
2148: }
2150: PetscErrorCode MatTransposeMatMultNumeric_SeqDense_SeqDense(Mat A,Mat B,Mat C)
2151: {
2152: Mat_SeqDense *a = (Mat_SeqDense*)A->data;
2153: Mat_SeqDense *b = (Mat_SeqDense*)B->data;
2154: Mat_SeqDense *c = (Mat_SeqDense*)C->data;
2155: PetscBLASInt m,n,k;
2156: PetscScalar _DOne=1.0,_DZero=0.0;
2160: PetscBLASIntCast(C->rmap->n,&m);
2161: PetscBLASIntCast(C->cmap->n,&n);
2162: PetscBLASIntCast(A->rmap->n,&k);
2163: PetscStackCallBLAS("BLASgemm",BLASgemm_("T","N",&m,&n,&k,&_DOne,a->v,&a->lda,b->v,&b->lda,&_DZero,c->v,&c->lda));
2164: return(0);
2165: }
2167: static PetscErrorCode MatGetRowMax_SeqDense(Mat A,Vec v,PetscInt idx[])
2168: {
2169: Mat_SeqDense *a = (Mat_SeqDense*)A->data;
2171: PetscInt i,j,m = A->rmap->n,n = A->cmap->n,p;
2172: PetscScalar *x;
2173: MatScalar *aa = a->v;
2176: if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2178: VecSet(v,0.0);
2179: VecGetArray(v,&x);
2180: VecGetLocalSize(v,&p);
2181: if (p != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
2182: for (i=0; i<m; i++) {
2183: x[i] = aa[i]; if (idx) idx[i] = 0;
2184: for (j=1; j<n; j++) {
2185: if (PetscRealPart(x[i]) < PetscRealPart(aa[i+m*j])) {x[i] = aa[i + m*j]; if (idx) idx[i] = j;}
2186: }
2187: }
2188: VecRestoreArray(v,&x);
2189: return(0);
2190: }
2192: static PetscErrorCode MatGetRowMaxAbs_SeqDense(Mat A,Vec v,PetscInt idx[])
2193: {
2194: Mat_SeqDense *a = (Mat_SeqDense*)A->data;
2196: PetscInt i,j,m = A->rmap->n,n = A->cmap->n,p;
2197: PetscScalar *x;
2198: PetscReal atmp;
2199: MatScalar *aa = a->v;
2202: if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2204: VecSet(v,0.0);
2205: VecGetArray(v,&x);
2206: VecGetLocalSize(v,&p);
2207: if (p != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
2208: for (i=0; i<m; i++) {
2209: x[i] = PetscAbsScalar(aa[i]);
2210: for (j=1; j<n; j++) {
2211: atmp = PetscAbsScalar(aa[i+m*j]);
2212: if (PetscAbsScalar(x[i]) < atmp) {x[i] = atmp; if (idx) idx[i] = j;}
2213: }
2214: }
2215: VecRestoreArray(v,&x);
2216: return(0);
2217: }
2219: static PetscErrorCode MatGetRowMin_SeqDense(Mat A,Vec v,PetscInt idx[])
2220: {
2221: Mat_SeqDense *a = (Mat_SeqDense*)A->data;
2223: PetscInt i,j,m = A->rmap->n,n = A->cmap->n,p;
2224: PetscScalar *x;
2225: MatScalar *aa = a->v;
2228: if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2230: VecSet(v,0.0);
2231: VecGetArray(v,&x);
2232: VecGetLocalSize(v,&p);
2233: if (p != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
2234: for (i=0; i<m; i++) {
2235: x[i] = aa[i]; if (idx) idx[i] = 0;
2236: for (j=1; j<n; j++) {
2237: if (PetscRealPart(x[i]) > PetscRealPart(aa[i+m*j])) {x[i] = aa[i + m*j]; if (idx) idx[i] = j;}
2238: }
2239: }
2240: VecRestoreArray(v,&x);
2241: return(0);
2242: }
2244: static PetscErrorCode MatGetColumnVector_SeqDense(Mat A,Vec v,PetscInt col)
2245: {
2246: Mat_SeqDense *a = (Mat_SeqDense*)A->data;
2248: PetscScalar *x;
2251: if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2253: VecGetArray(v,&x);
2254: PetscMemcpy(x,a->v+col*a->lda,A->rmap->n*sizeof(PetscScalar));
2255: VecRestoreArray(v,&x);
2256: return(0);
2257: }
2259: PetscErrorCode MatGetColumnNorms_SeqDense(Mat A,NormType type,PetscReal *norms)
2260: {
2262: PetscInt i,j,m,n;
2263: PetscScalar *a;
2266: MatGetSize(A,&m,&n);
2267: PetscMemzero(norms,n*sizeof(PetscReal));
2268: MatDenseGetArray(A,&a);
2269: if (type == NORM_2) {
2270: for (i=0; i<n; i++) {
2271: for (j=0; j<m; j++) {
2272: norms[i] += PetscAbsScalar(a[j]*a[j]);
2273: }
2274: a += m;
2275: }
2276: } else if (type == NORM_1) {
2277: for (i=0; i<n; i++) {
2278: for (j=0; j<m; j++) {
2279: norms[i] += PetscAbsScalar(a[j]);
2280: }
2281: a += m;
2282: }
2283: } else if (type == NORM_INFINITY) {
2284: for (i=0; i<n; i++) {
2285: for (j=0; j<m; j++) {
2286: norms[i] = PetscMax(PetscAbsScalar(a[j]),norms[i]);
2287: }
2288: a += m;
2289: }
2290: } else SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"Unknown NormType");
2291: MatDenseRestoreArray(A,&a);
2292: if (type == NORM_2) {
2293: for (i=0; i<n; i++) norms[i] = PetscSqrtReal(norms[i]);
2294: }
2295: return(0);
2296: }
2298: static PetscErrorCode MatSetRandom_SeqDense(Mat x,PetscRandom rctx)
2299: {
2301: PetscScalar *a;
2302: PetscInt m,n,i;
2305: MatGetSize(x,&m,&n);
2306: MatDenseGetArray(x,&a);
2307: for (i=0; i<m*n; i++) {
2308: PetscRandomGetValue(rctx,a+i);
2309: }
2310: MatDenseRestoreArray(x,&a);
2311: return(0);
2312: }
2314: static PetscErrorCode MatMissingDiagonal_SeqDense(Mat A,PetscBool *missing,PetscInt *d)
2315: {
2317: *missing = PETSC_FALSE;
2318: return(0);
2319: }
2321: static PetscErrorCode MatDenseGetColumn_SeqDense(Mat A,PetscInt col,PetscScalar **vals)
2322: {
2323: Mat_SeqDense *a = (Mat_SeqDense*)A->data;
2326: if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2327: *vals = a->v+col*a->lda;
2328: return(0);
2329: }
2331: static PetscErrorCode MatDenseRestoreColumn_SeqDense(Mat A,PetscScalar **vals)
2332: {
2334: *vals = 0; /* user cannot accidently use the array later */
2335: return(0);
2336: }
2338: /* -------------------------------------------------------------------*/
2339: static struct _MatOps MatOps_Values = { MatSetValues_SeqDense,
2340: MatGetRow_SeqDense,
2341: MatRestoreRow_SeqDense,
2342: MatMult_SeqDense,
2343: /* 4*/ MatMultAdd_SeqDense,
2344: MatMultTranspose_SeqDense,
2345: MatMultTransposeAdd_SeqDense,
2346: 0,
2347: 0,
2348: 0,
2349: /* 10*/ 0,
2350: MatLUFactor_SeqDense,
2351: MatCholeskyFactor_SeqDense,
2352: MatSOR_SeqDense,
2353: MatTranspose_SeqDense,
2354: /* 15*/ MatGetInfo_SeqDense,
2355: MatEqual_SeqDense,
2356: MatGetDiagonal_SeqDense,
2357: MatDiagonalScale_SeqDense,
2358: MatNorm_SeqDense,
2359: /* 20*/ MatAssemblyBegin_SeqDense,
2360: MatAssemblyEnd_SeqDense,
2361: MatSetOption_SeqDense,
2362: MatZeroEntries_SeqDense,
2363: /* 24*/ MatZeroRows_SeqDense,
2364: 0,
2365: 0,
2366: 0,
2367: 0,
2368: /* 29*/ MatSetUp_SeqDense,
2369: 0,
2370: 0,
2371: 0,
2372: 0,
2373: /* 34*/ MatDuplicate_SeqDense,
2374: 0,
2375: 0,
2376: 0,
2377: 0,
2378: /* 39*/ MatAXPY_SeqDense,
2379: MatCreateSubMatrices_SeqDense,
2380: 0,
2381: MatGetValues_SeqDense,
2382: MatCopy_SeqDense,
2383: /* 44*/ MatGetRowMax_SeqDense,
2384: MatScale_SeqDense,
2385: MatShift_Basic,
2386: 0,
2387: MatZeroRowsColumns_SeqDense,
2388: /* 49*/ MatSetRandom_SeqDense,
2389: 0,
2390: 0,
2391: 0,
2392: 0,
2393: /* 54*/ 0,
2394: 0,
2395: 0,
2396: 0,
2397: 0,
2398: /* 59*/ 0,
2399: MatDestroy_SeqDense,
2400: MatView_SeqDense,
2401: 0,
2402: 0,
2403: /* 64*/ 0,
2404: 0,
2405: 0,
2406: 0,
2407: 0,
2408: /* 69*/ MatGetRowMaxAbs_SeqDense,
2409: 0,
2410: 0,
2411: 0,
2412: 0,
2413: /* 74*/ 0,
2414: 0,
2415: 0,
2416: 0,
2417: 0,
2418: /* 79*/ 0,
2419: 0,
2420: 0,
2421: 0,
2422: /* 83*/ MatLoad_SeqDense,
2423: 0,
2424: MatIsHermitian_SeqDense,
2425: 0,
2426: 0,
2427: 0,
2428: /* 89*/ MatMatMult_SeqDense_SeqDense,
2429: MatMatMultSymbolic_SeqDense_SeqDense,
2430: MatMatMultNumeric_SeqDense_SeqDense,
2431: MatPtAP_SeqDense_SeqDense,
2432: MatPtAPSymbolic_SeqDense_SeqDense,
2433: /* 94*/ MatPtAPNumeric_SeqDense_SeqDense,
2434: MatMatTransposeMult_SeqDense_SeqDense,
2435: MatMatTransposeMultSymbolic_SeqDense_SeqDense,
2436: MatMatTransposeMultNumeric_SeqDense_SeqDense,
2437: 0,
2438: /* 99*/ 0,
2439: 0,
2440: 0,
2441: MatConjugate_SeqDense,
2442: 0,
2443: /*104*/ 0,
2444: MatRealPart_SeqDense,
2445: MatImaginaryPart_SeqDense,
2446: 0,
2447: 0,
2448: /*109*/ 0,
2449: 0,
2450: MatGetRowMin_SeqDense,
2451: MatGetColumnVector_SeqDense,
2452: MatMissingDiagonal_SeqDense,
2453: /*114*/ 0,
2454: 0,
2455: 0,
2456: 0,
2457: 0,
2458: /*119*/ 0,
2459: 0,
2460: 0,
2461: 0,
2462: 0,
2463: /*124*/ 0,
2464: MatGetColumnNorms_SeqDense,
2465: 0,
2466: 0,
2467: 0,
2468: /*129*/ 0,
2469: MatTransposeMatMult_SeqDense_SeqDense,
2470: MatTransposeMatMultSymbolic_SeqDense_SeqDense,
2471: MatTransposeMatMultNumeric_SeqDense_SeqDense,
2472: 0,
2473: /*134*/ 0,
2474: 0,
2475: 0,
2476: 0,
2477: 0,
2478: /*139*/ 0,
2479: 0,
2480: 0,
2481: 0,
2482: 0,
2483: /*144*/ MatCreateMPIMatConcatenateSeqMat_SeqDense
2484: };
2486: /*@C
2487: MatCreateSeqDense - Creates a sequential dense matrix that
2488: is stored in column major order (the usual Fortran 77 manner). Many
2489: of the matrix operations use the BLAS and LAPACK routines.
2491: Collective on MPI_Comm
2493: Input Parameters:
2494: + comm - MPI communicator, set to PETSC_COMM_SELF
2495: . m - number of rows
2496: . n - number of columns
2497: - data - optional location of matrix data in column major order. Set data=NULL for PETSc
2498: to control all matrix memory allocation.
2500: Output Parameter:
2501: . A - the matrix
2503: Notes:
2504: The data input variable is intended primarily for Fortran programmers
2505: who wish to allocate their own matrix memory space. Most users should
2506: set data=NULL.
2508: Level: intermediate
2510: .keywords: dense, matrix, LAPACK, BLAS
2512: .seealso: MatCreate(), MatCreateDense(), MatSetValues()
2513: @*/
2514: PetscErrorCode MatCreateSeqDense(MPI_Comm comm,PetscInt m,PetscInt n,PetscScalar *data,Mat *A)
2515: {
2519: MatCreate(comm,A);
2520: MatSetSizes(*A,m,n,m,n);
2521: MatSetType(*A,MATSEQDENSE);
2522: MatSeqDenseSetPreallocation(*A,data);
2523: return(0);
2524: }
2526: /*@C
2527: MatSeqDenseSetPreallocation - Sets the array used for storing the matrix elements
2529: Collective on MPI_Comm
2531: Input Parameters:
2532: + B - the matrix
2533: - data - the array (or NULL)
2535: Notes:
2536: The data input variable is intended primarily for Fortran programmers
2537: who wish to allocate their own matrix memory space. Most users should
2538: need not call this routine.
2540: Level: intermediate
2542: .keywords: dense, matrix, LAPACK, BLAS
2544: .seealso: MatCreate(), MatCreateDense(), MatSetValues(), MatSeqDenseSetLDA()
2546: @*/
2547: PetscErrorCode MatSeqDenseSetPreallocation(Mat B,PetscScalar data[])
2548: {
2552: PetscTryMethod(B,"MatSeqDenseSetPreallocation_C",(Mat,PetscScalar[]),(B,data));
2553: return(0);
2554: }
2556: PetscErrorCode MatSeqDenseSetPreallocation_SeqDense(Mat B,PetscScalar *data)
2557: {
2558: Mat_SeqDense *b;
2562: B->preallocated = PETSC_TRUE;
2564: PetscLayoutSetUp(B->rmap);
2565: PetscLayoutSetUp(B->cmap);
2567: b = (Mat_SeqDense*)B->data;
2568: b->Mmax = B->rmap->n;
2569: b->Nmax = B->cmap->n;
2570: if (b->lda <= 0 || b->changelda) b->lda = B->rmap->n;
2572: PetscIntMultError(b->lda,b->Nmax,NULL);
2573: if (!data) { /* petsc-allocated storage */
2574: if (!b->user_alloc) { PetscFree(b->v); }
2575: PetscCalloc1((size_t)b->lda*b->Nmax,&b->v);
2576: PetscLogObjectMemory((PetscObject)B,b->lda*b->Nmax*sizeof(PetscScalar));
2578: b->user_alloc = PETSC_FALSE;
2579: } else { /* user-allocated storage */
2580: if (!b->user_alloc) { PetscFree(b->v); }
2581: b->v = data;
2582: b->user_alloc = PETSC_TRUE;
2583: }
2584: B->assembled = PETSC_TRUE;
2585: return(0);
2586: }
2588: #if defined(PETSC_HAVE_ELEMENTAL)
2589: PETSC_INTERN PetscErrorCode MatConvert_SeqDense_Elemental(Mat A, MatType newtype,MatReuse reuse,Mat *newmat)
2590: {
2591: Mat mat_elemental;
2593: PetscScalar *array,*v_colwise;
2594: PetscInt M=A->rmap->N,N=A->cmap->N,i,j,k,*rows,*cols;
2597: PetscMalloc3(M*N,&v_colwise,M,&rows,N,&cols);
2598: MatDenseGetArray(A,&array);
2599: /* convert column-wise array into row-wise v_colwise, see MatSetValues_Elemental() */
2600: k = 0;
2601: for (j=0; j<N; j++) {
2602: cols[j] = j;
2603: for (i=0; i<M; i++) {
2604: v_colwise[j*M+i] = array[k++];
2605: }
2606: }
2607: for (i=0; i<M; i++) {
2608: rows[i] = i;
2609: }
2610: MatDenseRestoreArray(A,&array);
2612: MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental);
2613: MatSetSizes(mat_elemental,PETSC_DECIDE,PETSC_DECIDE,M,N);
2614: MatSetType(mat_elemental,MATELEMENTAL);
2615: MatSetUp(mat_elemental);
2617: /* PETSc-Elemental interaface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */
2618: MatSetValues(mat_elemental,M,rows,N,cols,v_colwise,ADD_VALUES);
2619: MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY);
2620: MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY);
2621: PetscFree3(v_colwise,rows,cols);
2623: if (reuse == MAT_INPLACE_MATRIX) {
2624: MatHeaderReplace(A,&mat_elemental);
2625: } else {
2626: *newmat = mat_elemental;
2627: }
2628: return(0);
2629: }
2630: #endif
2632: /*@C
2633: MatSeqDenseSetLDA - Declare the leading dimension of the user-provided array
2635: Input parameter:
2636: + A - the matrix
2637: - lda - the leading dimension
2639: Notes:
2640: This routine is to be used in conjunction with MatSeqDenseSetPreallocation();
2641: it asserts that the preallocation has a leading dimension (the LDA parameter
2642: of Blas and Lapack fame) larger than M, the first dimension of the matrix.
2644: Level: intermediate
2646: .keywords: dense, matrix, LAPACK, BLAS
2648: .seealso: MatCreate(), MatCreateSeqDense(), MatSeqDenseSetPreallocation(), MatSetMaximumSize()
2650: @*/
2651: PetscErrorCode MatSeqDenseSetLDA(Mat B,PetscInt lda)
2652: {
2653: Mat_SeqDense *b = (Mat_SeqDense*)B->data;
2656: 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);
2657: b->lda = lda;
2658: b->changelda = PETSC_FALSE;
2659: b->Mmax = PetscMax(b->Mmax,lda);
2660: return(0);
2661: }
2663: PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqDense(MPI_Comm comm,Mat inmat,PetscInt n,MatReuse scall,Mat *outmat)
2664: {
2666: PetscMPIInt size;
2669: MPI_Comm_size(comm,&size);
2670: if (size == 1) {
2671: if (scall == MAT_INITIAL_MATRIX) {
2672: MatDuplicate(inmat,MAT_COPY_VALUES,outmat);
2673: } else {
2674: MatCopy(inmat,*outmat,SAME_NONZERO_PATTERN);
2675: }
2676: } else {
2677: MatCreateMPIMatConcatenateSeqMat_MPIDense(comm,inmat,n,scall,outmat);
2678: }
2679: return(0);
2680: }
2682: /*MC
2683: MATSEQDENSE - MATSEQDENSE = "seqdense" - A matrix type to be used for sequential dense matrices.
2685: Options Database Keys:
2686: . -mat_type seqdense - sets the matrix type to "seqdense" during a call to MatSetFromOptions()
2688: Level: beginner
2690: .seealso: MatCreateSeqDense()
2692: M*/
2694: PETSC_EXTERN PetscErrorCode MatCreate_SeqDense(Mat B)
2695: {
2696: Mat_SeqDense *b;
2698: PetscMPIInt size;
2701: MPI_Comm_size(PetscObjectComm((PetscObject)B),&size);
2702: if (size > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Comm must be of size 1");
2704: PetscNewLog(B,&b);
2705: PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));
2706: B->data = (void*)b;
2708: b->roworiented = PETSC_TRUE;
2710: PetscObjectComposeFunction((PetscObject)B,"MatDenseGetArray_C",MatDenseGetArray_SeqDense);
2711: PetscObjectComposeFunction((PetscObject)B,"MatDenseRestoreArray_C",MatDenseRestoreArray_SeqDense);
2712: PetscObjectComposeFunction((PetscObject)B,"MatDensePlaceArray_C",MatDensePlaceArray_SeqDense);
2713: PetscObjectComposeFunction((PetscObject)B,"MatDenseResetArray_C",MatDenseResetArray_SeqDense);
2714: PetscObjectComposeFunction((PetscObject)B,"MatDenseGetArrayRead_C",MatDenseGetArray_SeqDense);
2715: PetscObjectComposeFunction((PetscObject)B,"MatDenseRestoreArrayRead_C",MatDenseRestoreArray_SeqDense);
2716: PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqdense_seqaij_C",MatConvert_SeqDense_SeqAIJ);
2717: #if defined(PETSC_HAVE_ELEMENTAL)
2718: PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqdense_elemental_C",MatConvert_SeqDense_Elemental);
2719: #endif
2720: PetscObjectComposeFunction((PetscObject)B,"MatSeqDenseSetPreallocation_C",MatSeqDenseSetPreallocation_SeqDense);
2721: PetscObjectComposeFunction((PetscObject)B,"MatMatMult_seqaij_seqdense_C",MatMatMult_SeqAIJ_SeqDense);
2722: PetscObjectComposeFunction((PetscObject)B,"MatMatMultSymbolic_seqaij_seqdense_C",MatMatMultSymbolic_SeqAIJ_SeqDense);
2723: PetscObjectComposeFunction((PetscObject)B,"MatMatMultNumeric_seqaij_seqdense_C",MatMatMultNumeric_SeqAIJ_SeqDense);
2724: PetscObjectComposeFunction((PetscObject)B,"MatPtAP_seqaij_seqdense_C",MatPtAP_SeqDense_SeqDense);
2725: PetscObjectComposeFunction((PetscObject)B,"MatMatMult_seqaijperm_seqdense_C",MatMatMult_SeqAIJ_SeqDense);
2726: PetscObjectComposeFunction((PetscObject)B,"MatMatMultSymbolic_seqaijperm_seqdense_C",MatMatMultSymbolic_SeqAIJ_SeqDense);
2727: PetscObjectComposeFunction((PetscObject)B,"MatMatMultNumeric_seqaijperm_seqdense_C",MatMatMultNumeric_SeqAIJ_SeqDense);
2728: PetscObjectComposeFunction((PetscObject)B,"MatPtAP_seqaijperm_seqdense_C",MatPtAP_SeqDense_SeqDense);
2729: PetscObjectComposeFunction((PetscObject)B,"MatMatMult_seqaijsell_seqdense_C",MatMatMult_SeqAIJ_SeqDense);
2730: PetscObjectComposeFunction((PetscObject)B,"MatMatMultSymbolic_seqaijsell_seqdense_C",MatMatMultSymbolic_SeqAIJ_SeqDense);
2731: PetscObjectComposeFunction((PetscObject)B,"MatMatMultNumeric_seqaijsell_seqdense_C",MatMatMultNumeric_SeqAIJ_SeqDense);
2732: PetscObjectComposeFunction((PetscObject)B,"MatPtAP_seqaijsell_seqdense_C",MatPtAP_SeqDense_SeqDense);
2733: PetscObjectComposeFunction((PetscObject)B,"MatMatMult_seqaijmkl_seqdense_C",MatMatMult_SeqAIJ_SeqDense);
2734: PetscObjectComposeFunction((PetscObject)B,"MatMatMultSymbolic_seqaijmkl_seqdense_C",MatMatMultSymbolic_SeqAIJ_SeqDense);
2735: PetscObjectComposeFunction((PetscObject)B,"MatMatMultNumeric_seqaijmkl_seqdense_C",MatMatMultNumeric_SeqAIJ_SeqDense);
2736: PetscObjectComposeFunction((PetscObject)B,"MatPtAP_seqaijmkl_seqdense_C",MatPtAP_SeqDense_SeqDense);
2738: PetscObjectComposeFunction((PetscObject)B,"MatTransposeMatMult_seqaij_seqdense_C",MatTransposeMatMult_SeqAIJ_SeqDense);
2739: PetscObjectComposeFunction((PetscObject)B,"MatTransposeMatMultSymbolic_seqaij_seqdense_C",MatTransposeMatMultSymbolic_SeqAIJ_SeqDense);
2740: PetscObjectComposeFunction((PetscObject)B,"MatTransposeMatMultNumeric_seqaij_seqdense_C",MatTransposeMatMultNumeric_SeqAIJ_SeqDense);
2741: PetscObjectComposeFunction((PetscObject)B,"MatTransposeMatMult_seqaijperm_seqdense_C",MatTransposeMatMult_SeqAIJ_SeqDense);
2742: PetscObjectComposeFunction((PetscObject)B,"MatTransposeMatMultSymbolic_seqaijperm_seqdense_C",MatTransposeMatMultSymbolic_SeqAIJ_SeqDense);
2743: PetscObjectComposeFunction((PetscObject)B,"MatTransposeMatMultNumeric_seqaijperm_seqdense_C",MatTransposeMatMultNumeric_SeqAIJ_SeqDense);
2744: PetscObjectComposeFunction((PetscObject)B,"MatTransposeMatMult_seqaijsell_seqdense_C",MatTransposeMatMult_SeqAIJ_SeqDense);
2745: PetscObjectComposeFunction((PetscObject)B,"MatTransposeMatMultSymbolic_seqaijsell_seqdense_C",MatTransposeMatMultSymbolic_SeqAIJ_SeqDense);
2746: PetscObjectComposeFunction((PetscObject)B,"MatTransposeMatMultNumeric_seqaijsell_seqdense_C",MatTransposeMatMultNumeric_SeqAIJ_SeqDense);
2748: PetscObjectComposeFunction((PetscObject)B,"MatTransposeMatMult_seqaijmkl_seqdense_C",MatTransposeMatMult_SeqAIJ_SeqDense);
2749: PetscObjectComposeFunction((PetscObject)B,"MatTransposeMatMultSymbolic_seqaijmkl_seqdense_C",MatTransposeMatMultSymbolic_SeqAIJ_SeqDense);
2750: PetscObjectComposeFunction((PetscObject)B,"MatTransposeMatMultNumeric_seqaijmkl_seqdense_C",MatTransposeMatMultNumeric_SeqAIJ_SeqDense);
2751: PetscObjectComposeFunction((PetscObject)B,"MatDenseGetColumn_C",MatDenseGetColumn_SeqDense);
2752: PetscObjectComposeFunction((PetscObject)B,"MatDenseRestoreColumn_C",MatDenseRestoreColumn_SeqDense);
2753: PetscObjectChangeTypeName((PetscObject)B,MATSEQDENSE);
2754: return(0);
2755: }
2757: /*@C
2758: 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.
2760: Not Collective
2762: Input Parameter:
2763: + mat - a MATSEQDENSE or MATMPIDENSE matrix
2764: - col - column index
2766: Output Parameter:
2767: . vals - pointer to the data
2769: Level: intermediate
2771: .seealso: MatDenseRestoreColumn()
2772: @*/
2773: PetscErrorCode MatDenseGetColumn(Mat A,PetscInt col,PetscScalar **vals)
2774: {
2778: PetscUseMethod(A,"MatDenseGetColumn_C",(Mat,PetscInt,PetscScalar**),(A,col,vals));
2779: return(0);
2780: }
2782: /*@C
2783: MatDenseRestoreColumn - returns access to a column of a dense matrix which is returned by MatDenseGetColumn().
2785: Not Collective
2787: Input Parameter:
2788: . mat - a MATSEQDENSE or MATMPIDENSE matrix
2790: Output Parameter:
2791: . vals - pointer to the data
2793: Level: intermediate
2795: .seealso: MatDenseGetColumn()
2796: @*/
2797: PetscErrorCode MatDenseRestoreColumn(Mat A,PetscScalar **vals)
2798: {
2802: PetscUseMethod(A,"MatDenseRestoreColumn_C",(Mat,PetscScalar**),(A,vals));
2803: return(0);
2804: }