Actual source code: aij.c
petsc-3.3-p0 2012-06-05
2: /*
3: Defines the basic matrix operations for the AIJ (compressed row)
4: matrix storage format.
5: */
8: #include <../src/mat/impls/aij/seq/aij.h> /*I "petscmat.h" I*/
9: #include <petscblaslapack.h>
10: #include <petscbt.h>
11: #include <../src/mat/blocktranspose.h>
15: PetscErrorCode MatGetColumnNorms_SeqAIJ(Mat A,NormType type,PetscReal *norms)
16: {
18: PetscInt i,m,n;
19: Mat_SeqAIJ *aij = (Mat_SeqAIJ*)A->data;
22: MatGetSize(A,&m,&n);
23: PetscMemzero(norms,n*sizeof(PetscReal));
24: if (type == NORM_2) {
25: for (i=0; i<aij->i[m]; i++) {
26: norms[aij->j[i]] += PetscAbsScalar(aij->a[i]*aij->a[i]);
27: }
28: } else if (type == NORM_1) {
29: for (i=0; i<aij->i[m]; i++) {
30: norms[aij->j[i]] += PetscAbsScalar(aij->a[i]);
31: }
32: } else if (type == NORM_INFINITY) {
33: for (i=0; i<aij->i[m]; i++) {
34: norms[aij->j[i]] = PetscMax(PetscAbsScalar(aij->a[i]),norms[aij->j[i]]);
35: }
36: } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Unknown NormType");
38: if (type == NORM_2) {
39: for (i=0; i<n; i++) norms[i] = PetscSqrtReal(norms[i]);
40: }
41: return(0);
42: }
46: PetscErrorCode MatFindZeroDiagonals_SeqAIJ(Mat A,IS *zrows)
47: {
48: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
49: const MatScalar *aa = a->a;
50: PetscInt i,m=A->rmap->n,cnt = 0;
51: const PetscInt *jj = a->j,*diag;
52: PetscInt *rows;
53: PetscErrorCode ierr;
56: MatMarkDiagonal_SeqAIJ(A);
57: diag = a->diag;
58: for (i=0; i<m; i++) {
59: if ((jj[diag[i]] != i) || (aa[diag[i]] == 0.0)) {
60: cnt++;
61: }
62: }
63: PetscMalloc(cnt*sizeof(PetscInt),&rows);
64: cnt = 0;
65: for (i=0; i<m; i++) {
66: if ((jj[diag[i]] != i) || (aa[diag[i]] == 0.0)) {
67: rows[cnt++] = i;
68: }
69: }
70: ISCreateGeneral(((PetscObject)A)->comm,cnt,rows,PETSC_OWN_POINTER,zrows);
71: return(0);
72: }
76: PetscErrorCode MatFindNonzeroRows_SeqAIJ(Mat A,IS *keptrows)
77: {
78: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
79: const MatScalar *aa;
80: PetscInt m=A->rmap->n,cnt = 0;
81: const PetscInt *ii;
82: PetscInt n,i,j,*rows;
83: PetscErrorCode ierr;
86: *keptrows = 0;
87: ii = a->i;
88: for (i=0; i<m; i++) {
89: n = ii[i+1] - ii[i];
90: if (!n) {
91: cnt++;
92: goto ok1;
93: }
94: aa = a->a + ii[i];
95: for (j=0; j<n; j++) {
96: if (aa[j] != 0.0) goto ok1;
97: }
98: cnt++;
99: ok1:;
100: }
101: if (!cnt) return(0);
102: PetscMalloc((A->rmap->n-cnt)*sizeof(PetscInt),&rows);
103: cnt = 0;
104: for (i=0; i<m; i++) {
105: n = ii[i+1] - ii[i];
106: if (!n) continue;
107: aa = a->a + ii[i];
108: for (j=0; j<n; j++) {
109: if (aa[j] != 0.0) {
110: rows[cnt++] = i;
111: break;
112: }
113: }
114: }
115: ISCreateGeneral(PETSC_COMM_SELF,cnt,rows,PETSC_OWN_POINTER,keptrows);
116: return(0);
117: }
121: PetscErrorCode MatDiagonalSet_SeqAIJ(Mat Y,Vec D,InsertMode is)
122: {
124: Mat_SeqAIJ *aij = (Mat_SeqAIJ*) Y->data;
125: PetscInt i,*diag, m = Y->rmap->n;
126: MatScalar *aa = aij->a;
127: PetscScalar *v;
128: PetscBool missing;
131: if (Y->assembled) {
132: MatMissingDiagonal_SeqAIJ(Y,&missing,PETSC_NULL);
133: if (!missing) {
134: diag = aij->diag;
135: VecGetArray(D,&v);
136: if (is == INSERT_VALUES) {
137: for (i=0; i<m; i++) {
138: aa[diag[i]] = v[i];
139: }
140: } else {
141: for (i=0; i<m; i++) {
142: aa[diag[i]] += v[i];
143: }
144: }
145: VecRestoreArray(D,&v);
146: return(0);
147: }
148: aij->idiagvalid = PETSC_FALSE;
149: aij->ibdiagvalid = PETSC_FALSE;
150: }
151: MatDiagonalSet_Default(Y,D,is);
152: return(0);
153: }
157: PetscErrorCode MatGetRowIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *m,PetscInt *ia[],PetscInt *ja[],PetscBool *done)
158: {
159: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
161: PetscInt i,ishift;
162:
164: *m = A->rmap->n;
165: if (!ia) return(0);
166: ishift = 0;
167: if (symmetric && !A->structurally_symmetric) {
168: MatToSymmetricIJ_SeqAIJ(A->rmap->n,a->i,a->j,ishift,oshift,ia,ja);
169: } else if (oshift == 1) {
170: PetscInt nz = a->i[A->rmap->n];
171: /* malloc space and add 1 to i and j indices */
172: PetscMalloc((A->rmap->n+1)*sizeof(PetscInt),ia);
173: for (i=0; i<A->rmap->n+1; i++) (*ia)[i] = a->i[i] + 1;
174: if (ja) {
175: PetscMalloc((nz+1)*sizeof(PetscInt),ja);
176: for (i=0; i<nz; i++) (*ja)[i] = a->j[i] + 1;
177: }
178: } else {
179: *ia = a->i;
180: if (ja) *ja = a->j;
181: }
182: return(0);
183: }
187: PetscErrorCode MatRestoreRowIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,PetscInt *ia[],PetscInt *ja[],PetscBool *done)
188: {
190:
192: if (!ia) return(0);
193: if ((symmetric && !A->structurally_symmetric) || oshift == 1) {
194: PetscFree(*ia);
195: if (ja) {PetscFree(*ja);}
196: }
197: return(0);
198: }
202: PetscErrorCode MatGetColumnIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *nn,PetscInt *ia[],PetscInt *ja[],PetscBool *done)
203: {
204: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
206: PetscInt i,*collengths,*cia,*cja,n = A->cmap->n,m = A->rmap->n;
207: PetscInt nz = a->i[m],row,*jj,mr,col;
210: *nn = n;
211: if (!ia) return(0);
212: if (symmetric) {
213: MatToSymmetricIJ_SeqAIJ(A->rmap->n,a->i,a->j,0,oshift,ia,ja);
214: } else {
215: PetscMalloc((n+1)*sizeof(PetscInt),&collengths);
216: PetscMemzero(collengths,n*sizeof(PetscInt));
217: PetscMalloc((n+1)*sizeof(PetscInt),&cia);
218: PetscMalloc((nz+1)*sizeof(PetscInt),&cja);
219: jj = a->j;
220: for (i=0; i<nz; i++) {
221: collengths[jj[i]]++;
222: }
223: cia[0] = oshift;
224: for (i=0; i<n; i++) {
225: cia[i+1] = cia[i] + collengths[i];
226: }
227: PetscMemzero(collengths,n*sizeof(PetscInt));
228: jj = a->j;
229: for (row=0; row<m; row++) {
230: mr = a->i[row+1] - a->i[row];
231: for (i=0; i<mr; i++) {
232: col = *jj++;
233: cja[cia[col] + collengths[col]++ - oshift] = row + oshift;
234: }
235: }
236: PetscFree(collengths);
237: *ia = cia; *ja = cja;
238: }
239: return(0);
240: }
244: PetscErrorCode MatRestoreColumnIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,PetscInt *ia[],PetscInt *ja[],PetscBool *done)
245: {
249: if (!ia) return(0);
251: PetscFree(*ia);
252: PetscFree(*ja);
253:
254: return(0);
255: }
259: PetscErrorCode MatSetValuesRow_SeqAIJ(Mat A,PetscInt row,const PetscScalar v[])
260: {
261: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
262: PetscInt *ai = a->i;
266: PetscMemcpy(a->a+ai[row],v,(ai[row+1]-ai[row])*sizeof(PetscScalar));
267: return(0);
268: }
272: PetscErrorCode MatSetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
273: {
274: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
275: PetscInt *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N;
276: PetscInt *imax = a->imax,*ai = a->i,*ailen = a->ilen;
278: PetscInt *aj = a->j,nonew = a->nonew,lastcol = -1;
279: MatScalar *ap,value,*aa = a->a;
280: PetscBool ignorezeroentries = a->ignorezeroentries;
281: PetscBool roworiented = a->roworiented;
285: for (k=0; k<m; k++) { /* loop over added rows */
286: row = im[k];
287: if (row < 0) continue;
288: #if defined(PETSC_USE_DEBUG)
289: if (row >= A->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",row,A->rmap->n-1);
290: #endif
291: rp = aj + ai[row]; ap = aa + ai[row];
292: rmax = imax[row]; nrow = ailen[row];
293: low = 0;
294: high = nrow;
295: for (l=0; l<n; l++) { /* loop over added columns */
296: if (in[l] < 0) continue;
297: #if defined(PETSC_USE_DEBUG)
298: if (in[l] >= A->cmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",in[l],A->cmap->n-1);
299: #endif
300: col = in[l];
301: if (v) {
302: if (roworiented) {
303: value = v[l + k*n];
304: } else {
305: value = v[k + l*m];
306: }
307: } else {
308: value = 0.;
309: }
310: if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue;
312: if (col <= lastcol) low = 0; else high = nrow;
313: lastcol = col;
314: while (high-low > 5) {
315: t = (low+high)/2;
316: if (rp[t] > col) high = t;
317: else low = t;
318: }
319: for (i=low; i<high; i++) {
320: if (rp[i] > col) break;
321: if (rp[i] == col) {
322: if (is == ADD_VALUES) ap[i] += value;
323: else ap[i] = value;
324: low = i + 1;
325: goto noinsert;
326: }
327: }
328: if (value == 0.0 && ignorezeroentries) goto noinsert;
329: if (nonew == 1) goto noinsert;
330: if (nonew == -1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero at (%D,%D) in the matrix",row,col);
331: MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
332: N = nrow++ - 1; a->nz++; high++;
333: /* shift up all the later entries in this row */
334: for (ii=N; ii>=i; ii--) {
335: rp[ii+1] = rp[ii];
336: ap[ii+1] = ap[ii];
337: }
338: rp[i] = col;
339: ap[i] = value;
340: low = i + 1;
341: noinsert:;
342: }
343: ailen[row] = nrow;
344: }
345: A->same_nonzero = PETSC_FALSE;
346: return(0);
347: }
352: PetscErrorCode MatGetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],PetscScalar v[])
353: {
354: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
355: PetscInt *rp,k,low,high,t,row,nrow,i,col,l,*aj = a->j;
356: PetscInt *ai = a->i,*ailen = a->ilen;
357: MatScalar *ap,*aa = a->a;
360: for (k=0; k<m; k++) { /* loop over rows */
361: row = im[k];
362: if (row < 0) {v += n; continue;} /* SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative row: %D",row); */
363: if (row >= A->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",row,A->rmap->n-1);
364: rp = aj + ai[row]; ap = aa + ai[row];
365: nrow = ailen[row];
366: for (l=0; l<n; l++) { /* loop over columns */
367: if (in[l] < 0) {v++; continue;} /* SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column: %D",in[l]); */
368: if (in[l] >= A->cmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",in[l],A->cmap->n-1);
369: col = in[l] ;
370: high = nrow; low = 0; /* assume unsorted */
371: while (high-low > 5) {
372: t = (low+high)/2;
373: if (rp[t] > col) high = t;
374: else low = t;
375: }
376: for (i=low; i<high; i++) {
377: if (rp[i] > col) break;
378: if (rp[i] == col) {
379: *v++ = ap[i];
380: goto finished;
381: }
382: }
383: *v++ = 0.0;
384: finished:;
385: }
386: }
387: return(0);
388: }
393: PetscErrorCode MatView_SeqAIJ_Binary(Mat A,PetscViewer viewer)
394: {
395: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
397: PetscInt i,*col_lens;
398: int fd;
401: PetscViewerBinaryGetDescriptor(viewer,&fd);
402: PetscMalloc((4+A->rmap->n)*sizeof(PetscInt),&col_lens);
403: col_lens[0] = MAT_FILE_CLASSID;
404: col_lens[1] = A->rmap->n;
405: col_lens[2] = A->cmap->n;
406: col_lens[3] = a->nz;
408: /* store lengths of each row and write (including header) to file */
409: for (i=0; i<A->rmap->n; i++) {
410: col_lens[4+i] = a->i[i+1] - a->i[i];
411: }
412: PetscBinaryWrite(fd,col_lens,4+A->rmap->n,PETSC_INT,PETSC_TRUE);
413: PetscFree(col_lens);
415: /* store column indices (zero start index) */
416: PetscBinaryWrite(fd,a->j,a->nz,PETSC_INT,PETSC_FALSE);
418: /* store nonzero values */
419: PetscBinaryWrite(fd,a->a,a->nz,PETSC_SCALAR,PETSC_FALSE);
420: return(0);
421: }
423: extern PetscErrorCode MatSeqAIJFactorInfo_Matlab(Mat,PetscViewer);
427: PetscErrorCode MatView_SeqAIJ_ASCII(Mat A,PetscViewer viewer)
428: {
429: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
430: PetscErrorCode ierr;
431: PetscInt i,j,m = A->rmap->n,shift=0;
432: const char *name;
433: PetscViewerFormat format;
436: PetscViewerGetFormat(viewer,&format);
437: if (format == PETSC_VIEWER_ASCII_MATLAB) {
438: PetscInt nofinalvalue = 0;
439: if ((a->i[m] == a->i[m-1]) || (a->j[a->nz-1] != A->cmap->n-!shift)) {
440: nofinalvalue = 1;
441: }
442: PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);
443: PetscViewerASCIIPrintf(viewer,"%% Size = %D %D \n",m,A->cmap->n);
444: PetscViewerASCIIPrintf(viewer,"%% Nonzeros = %D \n",a->nz);
445: PetscViewerASCIIPrintf(viewer,"zzz = zeros(%D,3);\n",a->nz+nofinalvalue);
446: PetscViewerASCIIPrintf(viewer,"zzz = [\n");
448: for (i=0; i<m; i++) {
449: for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
450: #if defined(PETSC_USE_COMPLEX)
451: PetscViewerASCIIPrintf(viewer,"%D %D %18.16e + %18.16ei \n",i+1,a->j[j]+!shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));
452: #else
453: PetscViewerASCIIPrintf(viewer,"%D %D %18.16e\n",i+1,a->j[j]+!shift,a->a[j]);
454: #endif
455: }
456: }
457: if (nofinalvalue) {
458: PetscViewerASCIIPrintf(viewer,"%D %D %18.16e\n",m,A->cmap->n,0.0);
459: }
460: PetscObjectGetName((PetscObject)A,&name);
461: PetscViewerASCIIPrintf(viewer,"];\n %s = spconvert(zzz);\n",name);
462: PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);
463: } else if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO) {
464: return(0);
465: } else if (format == PETSC_VIEWER_ASCII_COMMON) {
466: PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);
467: PetscObjectPrintClassNamePrefixType((PetscObject)A,viewer,"Matrix Object");
468: for (i=0; i<m; i++) {
469: PetscViewerASCIIPrintf(viewer,"row %D:",i);
470: for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
471: #if defined(PETSC_USE_COMPLEX)
472: if (PetscImaginaryPart(a->a[j]) > 0.0 && PetscRealPart(a->a[j]) != 0.0) {
473: PetscViewerASCIIPrintf(viewer," (%D, %G + %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));
474: } else if (PetscImaginaryPart(a->a[j]) < 0.0 && PetscRealPart(a->a[j]) != 0.0) {
475: PetscViewerASCIIPrintf(viewer," (%D, %G - %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),-PetscImaginaryPart(a->a[j]));
476: } else if (PetscRealPart(a->a[j]) != 0.0) {
477: PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,PetscRealPart(a->a[j]));
478: }
479: #else
480: if (a->a[j] != 0.0) {PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,a->a[j]);}
481: #endif
482: }
483: PetscViewerASCIIPrintf(viewer,"\n");
484: }
485: PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);
486: } else if (format == PETSC_VIEWER_ASCII_SYMMODU) {
487: PetscInt nzd=0,fshift=1,*sptr;
488: PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);
489: PetscObjectPrintClassNamePrefixType((PetscObject)A,viewer,"Matrix Object");
490: PetscMalloc((m+1)*sizeof(PetscInt),&sptr);
491: for (i=0; i<m; i++) {
492: sptr[i] = nzd+1;
493: for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
494: if (a->j[j] >= i) {
495: #if defined(PETSC_USE_COMPLEX)
496: if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) nzd++;
497: #else
498: if (a->a[j] != 0.0) nzd++;
499: #endif
500: }
501: }
502: }
503: sptr[m] = nzd+1;
504: PetscViewerASCIIPrintf(viewer," %D %D\n\n",m,nzd);
505: for (i=0; i<m+1; i+=6) {
506: if (i+4<m) {PetscViewerASCIIPrintf(viewer," %D %D %D %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2],sptr[i+3],sptr[i+4],sptr[i+5]);}
507: else if (i+3<m) {PetscViewerASCIIPrintf(viewer," %D %D %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2],sptr[i+3],sptr[i+4]);}
508: else if (i+2<m) {PetscViewerASCIIPrintf(viewer," %D %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2],sptr[i+3]);}
509: else if (i+1<m) {PetscViewerASCIIPrintf(viewer," %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2]);}
510: else if (i<m) {PetscViewerASCIIPrintf(viewer," %D %D\n",sptr[i],sptr[i+1]);}
511: else {PetscViewerASCIIPrintf(viewer," %D\n",sptr[i]);}
512: }
513: PetscViewerASCIIPrintf(viewer,"\n");
514: PetscFree(sptr);
515: for (i=0; i<m; i++) {
516: for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
517: if (a->j[j] >= i) {PetscViewerASCIIPrintf(viewer," %D ",a->j[j]+fshift);}
518: }
519: PetscViewerASCIIPrintf(viewer,"\n");
520: }
521: PetscViewerASCIIPrintf(viewer,"\n");
522: for (i=0; i<m; i++) {
523: for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
524: if (a->j[j] >= i) {
525: #if defined(PETSC_USE_COMPLEX)
526: if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) {
527: PetscViewerASCIIPrintf(viewer," %18.16e %18.16e ",PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));
528: }
529: #else
530: if (a->a[j] != 0.0) {PetscViewerASCIIPrintf(viewer," %18.16e ",a->a[j]);}
531: #endif
532: }
533: }
534: PetscViewerASCIIPrintf(viewer,"\n");
535: }
536: PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);
537: } else if (format == PETSC_VIEWER_ASCII_DENSE) {
538: PetscInt cnt = 0,jcnt;
539: PetscScalar value;
541: PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);
542: PetscObjectPrintClassNamePrefixType((PetscObject)A,viewer,"Matrix Object");
543: for (i=0; i<m; i++) {
544: jcnt = 0;
545: for (j=0; j<A->cmap->n; j++) {
546: if (jcnt < a->i[i+1]-a->i[i] && j == a->j[cnt]) {
547: value = a->a[cnt++];
548: jcnt++;
549: } else {
550: value = 0.0;
551: }
552: #if defined(PETSC_USE_COMPLEX)
553: PetscViewerASCIIPrintf(viewer," %7.5e+%7.5e i ",PetscRealPart(value),PetscImaginaryPart(value));
554: #else
555: PetscViewerASCIIPrintf(viewer," %7.5e ",value);
556: #endif
557: }
558: PetscViewerASCIIPrintf(viewer,"\n");
559: }
560: PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);
561: } else if (format == PETSC_VIEWER_ASCII_MATRIXMARKET) {
562: PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);
563: PetscObjectPrintClassNamePrefixType((PetscObject)A,viewer,"Matrix Object");
564: #if defined(PETSC_USE_COMPLEX)
565: PetscViewerASCIIPrintf(viewer,"%%matrix complex general\n");
566: #else
567: PetscViewerASCIIPrintf(viewer,"%%matrix real general\n");
568: #endif
569: PetscViewerASCIIPrintf(viewer,"%D %D %D\n", m, A->cmap->n, a->nz);
570: for (i=0; i<m; i++) {
571: for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
572: #if defined(PETSC_USE_COMPLEX)
573: if (PetscImaginaryPart(a->a[j]) > 0.0) {
574: PetscViewerASCIIPrintf(viewer,"%D %D, %G %G\n", i+shift,a->j[j]+shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));
575: } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
576: PetscViewerASCIIPrintf(viewer,"%D %D, %G -%G\n", i+shift,a->j[j]+shift,PetscRealPart(a->a[j]),-PetscImaginaryPart(a->a[j]));
577: } else {
578: PetscViewerASCIIPrintf(viewer,"%D %D, %G\n", i+shift,a->j[j]+shift,PetscRealPart(a->a[j]));
579: }
580: #else
581: PetscViewerASCIIPrintf(viewer,"%D %D %G\n", i+shift, a->j[j]+shift, a->a[j]);
582: #endif
583: }
584: }
585: PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);
586: } else {
587: PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);
588: PetscObjectPrintClassNamePrefixType((PetscObject)A,viewer,"Matrix Object");
589: if (A->factortype){
590: for (i=0; i<m; i++) {
591: PetscViewerASCIIPrintf(viewer,"row %D:",i);
592: /* L part */
593: for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
594: #if defined(PETSC_USE_COMPLEX)
595: if (PetscImaginaryPart(a->a[j]) > 0.0) {
596: PetscViewerASCIIPrintf(viewer," (%D, %G + %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));
597: } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
598: PetscViewerASCIIPrintf(viewer," (%D, %G - %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),-PetscImaginaryPart(a->a[j]));
599: } else {
600: PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,PetscRealPart(a->a[j]));
601: }
602: #else
603: PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,a->a[j]);
604: #endif
605: }
606: /* diagonal */
607: j = a->diag[i];
608: #if defined(PETSC_USE_COMPLEX)
609: if (PetscImaginaryPart(a->a[j]) > 0.0) {
610: PetscViewerASCIIPrintf(viewer," (%D, %G + %G i)",a->j[j]+shift,PetscRealPart(1.0/a->a[j]),PetscImaginaryPart(1.0/a->a[j]));
611: } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
612: PetscViewerASCIIPrintf(viewer," (%D, %G - %G i)",a->j[j]+shift,PetscRealPart(1.0/a->a[j]),-PetscImaginaryPart(1.0/a->a[j]));
613: } else {
614: PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,PetscRealPart(1.0/a->a[j]));
615: }
616: #else
617: PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,1.0/a->a[j]);
618: #endif
620: /* U part */
621: for (j=a->diag[i+1]+1+shift; j<a->diag[i]+shift; j++) {
622: #if defined(PETSC_USE_COMPLEX)
623: if (PetscImaginaryPart(a->a[j]) > 0.0) {
624: PetscViewerASCIIPrintf(viewer," (%D, %G + %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));
625: } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
626: PetscViewerASCIIPrintf(viewer," (%D, %G - %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),-PetscImaginaryPart(a->a[j]));
627: } else {
628: PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,PetscRealPart(a->a[j]));
629: }
630: #else
631: PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,a->a[j]);
632: #endif
633: }
634: PetscViewerASCIIPrintf(viewer,"\n");
635: }
636: } else {
637: for (i=0; i<m; i++) {
638: PetscViewerASCIIPrintf(viewer,"row %D:",i);
639: for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
640: #if defined(PETSC_USE_COMPLEX)
641: if (PetscImaginaryPart(a->a[j]) > 0.0) {
642: PetscViewerASCIIPrintf(viewer," (%D, %G + %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));
643: } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
644: PetscViewerASCIIPrintf(viewer," (%D, %G - %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),-PetscImaginaryPart(a->a[j]));
645: } else {
646: PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,PetscRealPart(a->a[j]));
647: }
648: #else
649: PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,a->a[j]);
650: #endif
651: }
652: PetscViewerASCIIPrintf(viewer,"\n");
653: }
654: }
655: PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);
656: }
657: PetscViewerFlush(viewer);
658: return(0);
659: }
663: PetscErrorCode MatView_SeqAIJ_Draw_Zoom(PetscDraw draw,void *Aa)
664: {
665: Mat A = (Mat) Aa;
666: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
667: PetscErrorCode ierr;
668: PetscInt i,j,m = A->rmap->n,color;
669: PetscReal xl,yl,xr,yr,x_l,x_r,y_l,y_r,maxv = 0.0;
670: PetscViewer viewer;
671: PetscViewerFormat format;
674: PetscObjectQuery((PetscObject)A,"Zoomviewer",(PetscObject*)&viewer);
675: PetscViewerGetFormat(viewer,&format);
677: PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);
678: /* loop over matrix elements drawing boxes */
680: if (format != PETSC_VIEWER_DRAW_CONTOUR) {
681: /* Blue for negative, Cyan for zero and Red for positive */
682: color = PETSC_DRAW_BLUE;
683: for (i=0; i<m; i++) {
684: y_l = m - i - 1.0; y_r = y_l + 1.0;
685: for (j=a->i[i]; j<a->i[i+1]; j++) {
686: x_l = a->j[j] ; x_r = x_l + 1.0;
687: #if defined(PETSC_USE_COMPLEX)
688: if (PetscRealPart(a->a[j]) >= 0.) continue;
689: #else
690: if (a->a[j] >= 0.) continue;
691: #endif
692: PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);
693: }
694: }
695: color = PETSC_DRAW_CYAN;
696: for (i=0; i<m; i++) {
697: y_l = m - i - 1.0; y_r = y_l + 1.0;
698: for (j=a->i[i]; j<a->i[i+1]; j++) {
699: x_l = a->j[j]; x_r = x_l + 1.0;
700: if (a->a[j] != 0.) continue;
701: PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);
702: }
703: }
704: color = PETSC_DRAW_RED;
705: for (i=0; i<m; i++) {
706: y_l = m - i - 1.0; y_r = y_l + 1.0;
707: for (j=a->i[i]; j<a->i[i+1]; j++) {
708: x_l = a->j[j]; x_r = x_l + 1.0;
709: #if defined(PETSC_USE_COMPLEX)
710: if (PetscRealPart(a->a[j]) <= 0.) continue;
711: #else
712: if (a->a[j] <= 0.) continue;
713: #endif
714: PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);
715: }
716: }
717: } else {
718: /* use contour shading to indicate magnitude of values */
719: /* first determine max of all nonzero values */
720: PetscInt nz = a->nz,count;
721: PetscDraw popup;
722: PetscReal scale;
724: for (i=0; i<nz; i++) {
725: if (PetscAbsScalar(a->a[i]) > maxv) maxv = PetscAbsScalar(a->a[i]);
726: }
727: scale = (245.0 - PETSC_DRAW_BASIC_COLORS)/maxv;
728: PetscDrawGetPopup(draw,&popup);
729: if (popup) {PetscDrawScalePopup(popup,0.0,maxv);}
730: count = 0;
731: for (i=0; i<m; i++) {
732: y_l = m - i - 1.0; y_r = y_l + 1.0;
733: for (j=a->i[i]; j<a->i[i+1]; j++) {
734: x_l = a->j[j]; x_r = x_l + 1.0;
735: color = PETSC_DRAW_BASIC_COLORS + (PetscInt)(scale*PetscAbsScalar(a->a[count]));
736: PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);
737: count++;
738: }
739: }
740: }
741: return(0);
742: }
746: PetscErrorCode MatView_SeqAIJ_Draw(Mat A,PetscViewer viewer)
747: {
749: PetscDraw draw;
750: PetscReal xr,yr,xl,yl,h,w;
751: PetscBool isnull;
754: PetscViewerDrawGetDraw(viewer,0,&draw);
755: PetscDrawIsNull(draw,&isnull);
756: if (isnull) return(0);
758: PetscObjectCompose((PetscObject)A,"Zoomviewer",(PetscObject)viewer);
759: xr = A->cmap->n; yr = A->rmap->n; h = yr/10.0; w = xr/10.0;
760: xr += w; yr += h; xl = -w; yl = -h;
761: PetscDrawSetCoordinates(draw,xl,yl,xr,yr);
762: PetscDrawZoom(draw,MatView_SeqAIJ_Draw_Zoom,A);
763: PetscObjectCompose((PetscObject)A,"Zoomviewer",PETSC_NULL);
764: return(0);
765: }
769: PetscErrorCode MatView_SeqAIJ(Mat A,PetscViewer viewer)
770: {
772: PetscBool iascii,isbinary,isdraw;
775: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
776: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);
777: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);
778: if (iascii) {
779: MatView_SeqAIJ_ASCII(A,viewer);
780: } else if (isbinary) {
781: MatView_SeqAIJ_Binary(A,viewer);
782: } else if (isdraw) {
783: MatView_SeqAIJ_Draw(A,viewer);
784: } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported by SeqAIJ matrices",((PetscObject)viewer)->type_name);
785: MatView_SeqAIJ_Inode(A,viewer);
786: return(0);
787: }
791: PetscErrorCode MatAssemblyEnd_SeqAIJ(Mat A,MatAssemblyType mode)
792: {
793: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
795: PetscInt fshift = 0,i,j,*ai = a->i,*aj = a->j,*imax = a->imax;
796: PetscInt m = A->rmap->n,*ip,N,*ailen = a->ilen,rmax = 0;
797: MatScalar *aa = a->a,*ap;
798: PetscReal ratio=0.6;
801: if (mode == MAT_FLUSH_ASSEMBLY) return(0);
803: if (m) rmax = ailen[0]; /* determine row with most nonzeros */
804: for (i=1; i<m; i++) {
805: /* move each row back by the amount of empty slots (fshift) before it*/
806: fshift += imax[i-1] - ailen[i-1];
807: rmax = PetscMax(rmax,ailen[i]);
808: if (fshift) {
809: ip = aj + ai[i] ;
810: ap = aa + ai[i] ;
811: N = ailen[i];
812: for (j=0; j<N; j++) {
813: ip[j-fshift] = ip[j];
814: ap[j-fshift] = ap[j];
815: }
816: }
817: ai[i] = ai[i-1] + ailen[i-1];
818: }
819: if (m) {
820: fshift += imax[m-1] - ailen[m-1];
821: ai[m] = ai[m-1] + ailen[m-1];
822: }
823: /* reset ilen and imax for each row */
824: for (i=0; i<m; i++) {
825: ailen[i] = imax[i] = ai[i+1] - ai[i];
826: }
827: a->nz = ai[m];
828: if (fshift && a->nounused == -1) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_PLIB, "Unused space detected in matrix: %D X %D, %D unneeded", m, A->cmap->n, fshift);
830: MatMarkDiagonal_SeqAIJ(A);
831: PetscInfo4(A,"Matrix size: %D X %D; storage space: %D unneeded,%D used\n",m,A->cmap->n,fshift,a->nz);
832: PetscInfo1(A,"Number of mallocs during MatSetValues() is %D\n",a->reallocs);
833: PetscInfo1(A,"Maximum nonzeros in any row is %D\n",rmax);
834: A->info.mallocs += a->reallocs;
835: a->reallocs = 0;
836: A->info.nz_unneeded = (double)fshift;
837: a->rmax = rmax;
839: MatCheckCompressedRow(A,&a->compressedrow,a->i,m,ratio);
840: A->same_nonzero = PETSC_TRUE;
842: MatAssemblyEnd_SeqAIJ_Inode(A,mode);
844: a->idiagvalid = PETSC_FALSE;
845: a->ibdiagvalid = PETSC_FALSE;
846: return(0);
847: }
851: PetscErrorCode MatRealPart_SeqAIJ(Mat A)
852: {
853: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
854: PetscInt i,nz = a->nz;
855: MatScalar *aa = a->a;
858: for (i=0; i<nz; i++) aa[i] = PetscRealPart(aa[i]);
859: a->idiagvalid = PETSC_FALSE;
860: a->ibdiagvalid = PETSC_FALSE;
861: return(0);
862: }
866: PetscErrorCode MatImaginaryPart_SeqAIJ(Mat A)
867: {
868: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
869: PetscInt i,nz = a->nz;
870: MatScalar *aa = a->a;
873: for (i=0; i<nz; i++) aa[i] = PetscImaginaryPart(aa[i]);
874: a->idiagvalid = PETSC_FALSE;
875: a->ibdiagvalid = PETSC_FALSE;
876: return(0);
877: }
881: PetscErrorCode MatZeroEntries_SeqAIJ(Mat A)
882: {
883: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
887: PetscMemzero(a->a,(a->i[A->rmap->n])*sizeof(PetscScalar));
888: a->idiagvalid = PETSC_FALSE;
889: a->ibdiagvalid = PETSC_FALSE;
890: return(0);
891: }
895: PetscErrorCode MatDestroy_SeqAIJ(Mat A)
896: {
897: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
901: #if defined(PETSC_USE_LOG)
902: PetscLogObjectState((PetscObject)A,"Rows=%D, Cols=%D, NZ=%D",A->rmap->n,A->cmap->n,a->nz);
903: #endif
904: MatSeqXAIJFreeAIJ(A,&a->a,&a->j,&a->i);
905: ISDestroy(&a->row);
906: ISDestroy(&a->col);
907: PetscFree(a->diag);
908: PetscFree(a->ibdiag);
909: PetscFree2(a->imax,a->ilen);
910: PetscFree3(a->idiag,a->mdiag,a->ssor_work);
911: PetscFree(a->solve_work);
912: ISDestroy(&a->icol);
913: PetscFree(a->saved_values);
914: ISColoringDestroy(&a->coloring);
915: PetscFree(a->xtoy);
916: MatDestroy(&a->XtoY);
917: PetscFree2(a->compressedrow.i,a->compressedrow.rindex);
918: PetscFree(a->matmult_abdense);
920: MatDestroy_SeqAIJ_Inode(A);
921: PetscFree(A->data);
923: PetscObjectChangeTypeName((PetscObject)A,0);
924: PetscObjectComposeFunctionDynamic((PetscObject)A,"MatSeqAIJSetColumnIndices_C","",PETSC_NULL);
925: PetscObjectComposeFunctionDynamic((PetscObject)A,"MatStoreValues_C","",PETSC_NULL);
926: PetscObjectComposeFunctionDynamic((PetscObject)A,"MatRetrieveValues_C","",PETSC_NULL);
927: PetscObjectComposeFunctionDynamic((PetscObject)A,"MatConvert_seqaij_seqsbaij_C","",PETSC_NULL);
928: PetscObjectComposeFunctionDynamic((PetscObject)A,"MatConvert_seqaij_seqbaij_C","",PETSC_NULL);
929: PetscObjectComposeFunctionDynamic((PetscObject)A,"MatConvert_seqaij_seqaijperm_C","",PETSC_NULL);
930: PetscObjectComposeFunctionDynamic((PetscObject)A,"MatIsTranspose_C","",PETSC_NULL);
931: PetscObjectComposeFunctionDynamic((PetscObject)A,"MatSeqAIJSetPreallocation_C","",PETSC_NULL);
932: PetscObjectComposeFunctionDynamic((PetscObject)A,"MatSeqAIJSetPreallocationCSR_C","",PETSC_NULL);
933: PetscObjectComposeFunctionDynamic((PetscObject)A,"MatReorderForNonzeroDiagonal_C","",PETSC_NULL);
934: return(0);
935: }
939: PetscErrorCode MatSetOption_SeqAIJ(Mat A,MatOption op,PetscBool flg)
940: {
941: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
945: switch (op) {
946: case MAT_ROW_ORIENTED:
947: a->roworiented = flg;
948: break;
949: case MAT_KEEP_NONZERO_PATTERN:
950: a->keepnonzeropattern = flg;
951: break;
952: case MAT_NEW_NONZERO_LOCATIONS:
953: a->nonew = (flg ? 0 : 1);
954: break;
955: case MAT_NEW_NONZERO_LOCATION_ERR:
956: a->nonew = (flg ? -1 : 0);
957: break;
958: case MAT_NEW_NONZERO_ALLOCATION_ERR:
959: a->nonew = (flg ? -2 : 0);
960: break;
961: case MAT_UNUSED_NONZERO_LOCATION_ERR:
962: a->nounused = (flg ? -1 : 0);
963: break;
964: case MAT_IGNORE_ZERO_ENTRIES:
965: a->ignorezeroentries = flg;
966: break;
967: case MAT_CHECK_COMPRESSED_ROW:
968: a->compressedrow.check = flg;
969: break;
970: case MAT_SPD:
971: A->spd_set = PETSC_TRUE;
972: A->spd = flg;
973: if (flg) {
974: A->symmetric = PETSC_TRUE;
975: A->structurally_symmetric = PETSC_TRUE;
976: A->symmetric_set = PETSC_TRUE;
977: A->structurally_symmetric_set = PETSC_TRUE;
978: }
979: break;
980: case MAT_SYMMETRIC:
981: case MAT_STRUCTURALLY_SYMMETRIC:
982: case MAT_HERMITIAN:
983: case MAT_SYMMETRY_ETERNAL:
984: case MAT_NEW_DIAGONALS:
985: case MAT_IGNORE_OFF_PROC_ENTRIES:
986: case MAT_USE_HASH_TABLE:
987: PetscInfo1(A,"Option %s ignored\n",MatOptions[op]);
988: break;
989: case MAT_USE_INODES:
990: /* Not an error because MatSetOption_SeqAIJ_Inode handles this one */
991: break;
992: default:
993: SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"unknown option %d",op);
994: }
995: MatSetOption_SeqAIJ_Inode(A,op,flg);
996: return(0);
997: }
1001: PetscErrorCode MatGetDiagonal_SeqAIJ(Mat A,Vec v)
1002: {
1003: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1005: PetscInt i,j,n,*ai=a->i,*aj=a->j,nz;
1006: PetscScalar *aa=a->a,*x,zero=0.0;
1009: VecGetLocalSize(v,&n);
1010: if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
1012: if (A->factortype == MAT_FACTOR_ILU || A->factortype == MAT_FACTOR_LU){
1013: PetscInt *diag=a->diag;
1014: VecGetArray(v,&x);
1015: for (i=0; i<n; i++) x[i] = 1.0/aa[diag[i]];
1016: VecRestoreArray(v,&x);
1017: return(0);
1018: }
1020: VecSet(v,zero);
1021: VecGetArray(v,&x);
1022: for (i=0; i<n; i++) {
1023: nz = ai[i+1] - ai[i];
1024: if (!nz) x[i] = 0.0;
1025: for (j=ai[i]; j<ai[i+1]; j++){
1026: if (aj[j] == i) {
1027: x[i] = aa[j];
1028: break;
1029: }
1030: }
1031: }
1032: VecRestoreArray(v,&x);
1033: return(0);
1034: }
1036: #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h>
1039: PetscErrorCode MatMultTransposeAdd_SeqAIJ(Mat A,Vec xx,Vec zz,Vec yy)
1040: {
1041: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1042: PetscScalar *x,*y;
1043: PetscErrorCode ierr;
1044: PetscInt m = A->rmap->n;
1045: #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
1046: MatScalar *v;
1047: PetscScalar alpha;
1048: PetscInt n,i,j,*idx,*ii,*ridx=PETSC_NULL;
1049: Mat_CompressedRow cprow = a->compressedrow;
1050: PetscBool usecprow = cprow.use;
1051: #endif
1054: if (zz != yy) {VecCopy(zz,yy);}
1055: VecGetArray(xx,&x);
1056: VecGetArray(yy,&y);
1058: #if defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
1059: fortranmulttransposeaddaij_(&m,x,a->i,a->j,a->a,y);
1060: #else
1061: if (usecprow){
1062: m = cprow.nrows;
1063: ii = cprow.i;
1064: ridx = cprow.rindex;
1065: } else {
1066: ii = a->i;
1067: }
1068: for (i=0; i<m; i++) {
1069: idx = a->j + ii[i] ;
1070: v = a->a + ii[i] ;
1071: n = ii[i+1] - ii[i];
1072: if (usecprow){
1073: alpha = x[ridx[i]];
1074: } else {
1075: alpha = x[i];
1076: }
1077: for (j=0; j<n; j++) y[idx[j]] += alpha*v[j];
1078: }
1079: #endif
1080: PetscLogFlops(2.0*a->nz);
1081: VecRestoreArray(xx,&x);
1082: VecRestoreArray(yy,&y);
1083: return(0);
1084: }
1088: PetscErrorCode MatMultTranspose_SeqAIJ(Mat A,Vec xx,Vec yy)
1089: {
1093: VecSet(yy,0.0);
1094: MatMultTransposeAdd_SeqAIJ(A,xx,yy,yy);
1095: return(0);
1096: }
1098: #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h>
1101: PetscErrorCode MatMult_SeqAIJ(Mat A,Vec xx,Vec yy)
1102: {
1103: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1104: PetscScalar *y;
1105: const PetscScalar *x;
1106: const MatScalar *aa;
1107: PetscErrorCode ierr;
1108: PetscInt m=A->rmap->n;
1109: const PetscInt *aj,*ii,*ridx=PETSC_NULL;
1110: PetscInt n,i,nonzerorow=0;
1111: PetscScalar sum;
1112: PetscBool usecprow=a->compressedrow.use;
1114: #if defined(PETSC_HAVE_PRAGMA_DISJOINT)
1115: #pragma disjoint(*x,*y,*aa)
1116: #endif
1119: VecGetArrayRead(xx,&x);
1120: VecGetArray(yy,&y);
1121: aj = a->j;
1122: aa = a->a;
1123: ii = a->i;
1124: if (usecprow){ /* use compressed row format */
1125: m = a->compressedrow.nrows;
1126: ii = a->compressedrow.i;
1127: ridx = a->compressedrow.rindex;
1128: for (i=0; i<m; i++){
1129: n = ii[i+1] - ii[i];
1130: aj = a->j + ii[i];
1131: aa = a->a + ii[i];
1132: sum = 0.0;
1133: nonzerorow += (n>0);
1134: PetscSparseDensePlusDot(sum,x,aa,aj,n);
1135: /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */
1136: y[*ridx++] = sum;
1137: }
1138: } else { /* do not use compressed row format */
1139: #if defined(PETSC_USE_FORTRAN_KERNEL_MULTAIJ)
1140: fortranmultaij_(&m,x,ii,aj,aa,y);
1141: #else
1142: for (i=0; i<m; i++) {
1143: n = ii[i+1] - ii[i];
1144: aj = a->j + ii[i];
1145: aa = a->a + ii[i];
1146: sum = 0.0;
1147: nonzerorow += (n>0);
1148: PetscSparseDensePlusDot(sum,x,aa,aj,n);
1149: y[i] = sum;
1150: }
1151: #endif
1152: }
1153: PetscLogFlops(2.0*a->nz - nonzerorow);
1154: VecRestoreArrayRead(xx,&x);
1155: VecRestoreArray(yy,&y);
1156: return(0);
1157: }
1159: #include <../src/mat/impls/aij/seq/ftn-kernels/fmultadd.h>
1162: PetscErrorCode MatMultAdd_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz)
1163: {
1164: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1165: PetscScalar *y,*z;
1166: const PetscScalar *x;
1167: const MatScalar *aa;
1168: PetscErrorCode ierr;
1169: PetscInt m = A->rmap->n,*aj,*ii;
1170: PetscInt n,i,*ridx=PETSC_NULL;
1171: PetscScalar sum;
1172: PetscBool usecprow=a->compressedrow.use;
1175: VecGetArrayRead(xx,&x);
1176: VecGetArray(yy,&y);
1177: if (zz != yy) {
1178: VecGetArray(zz,&z);
1179: } else {
1180: z = y;
1181: }
1183: aj = a->j;
1184: aa = a->a;
1185: ii = a->i;
1186: if (usecprow){ /* use compressed row format */
1187: if (zz != yy){
1188: PetscMemcpy(z,y,m*sizeof(PetscScalar));
1189: }
1190: m = a->compressedrow.nrows;
1191: ii = a->compressedrow.i;
1192: ridx = a->compressedrow.rindex;
1193: for (i=0; i<m; i++){
1194: n = ii[i+1] - ii[i];
1195: aj = a->j + ii[i];
1196: aa = a->a + ii[i];
1197: sum = y[*ridx];
1198: PetscSparseDensePlusDot(sum,x,aa,aj,n);
1199: z[*ridx++] = sum;
1200: }
1201: } else { /* do not use compressed row format */
1202: #if defined(PETSC_USE_FORTRAN_KERNEL_MULTADDAIJ)
1203: fortranmultaddaij_(&m,x,ii,aj,aa,y,z);
1204: #else
1205: for (i=0; i<m; i++) {
1206: n = ii[i+1] - ii[i];
1207: aj = a->j + ii[i];
1208: aa = a->a + ii[i];
1209: sum = y[i];
1210: PetscSparseDensePlusDot(sum,x,aa,aj,n);
1211: z[i] = sum;
1212: }
1213: #endif
1214: }
1215: PetscLogFlops(2.0*a->nz);
1216: VecRestoreArrayRead(xx,&x);
1217: VecRestoreArray(yy,&y);
1218: if (zz != yy) {
1219: VecRestoreArray(zz,&z);
1220: }
1221: #if defined(PETSC_HAVE_CUSP)
1222: /*
1223: VecView(xx,0);
1224: VecView(zz,0);
1225: MatView(A,0);
1226: */
1227: #endif
1228: return(0);
1229: }
1231: /*
1232: Adds diagonal pointers to sparse matrix structure.
1233: */
1236: PetscErrorCode MatMarkDiagonal_SeqAIJ(Mat A)
1237: {
1238: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1240: PetscInt i,j,m = A->rmap->n;
1243: if (!a->diag) {
1244: PetscMalloc(m*sizeof(PetscInt),&a->diag);
1245: PetscLogObjectMemory(A, m*sizeof(PetscInt));
1246: }
1247: for (i=0; i<A->rmap->n; i++) {
1248: a->diag[i] = a->i[i+1];
1249: for (j=a->i[i]; j<a->i[i+1]; j++) {
1250: if (a->j[j] == i) {
1251: a->diag[i] = j;
1252: break;
1253: }
1254: }
1255: }
1256: return(0);
1257: }
1259: /*
1260: Checks for missing diagonals
1261: */
1264: PetscErrorCode MatMissingDiagonal_SeqAIJ(Mat A,PetscBool *missing,PetscInt *d)
1265: {
1266: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1267: PetscInt *diag,*jj = a->j,i;
1270: *missing = PETSC_FALSE;
1271: if (A->rmap->n > 0 && !jj) {
1272: *missing = PETSC_TRUE;
1273: if (d) *d = 0;
1274: PetscInfo(A,"Matrix has no entries therefore is missing diagonal");
1275: } else {
1276: diag = a->diag;
1277: for (i=0; i<A->rmap->n; i++) {
1278: if (jj[diag[i]] != i) {
1279: *missing = PETSC_TRUE;
1280: if (d) *d = i;
1281: PetscInfo1(A,"Matrix is missing diagonal number %D",i);
1282: break;
1283: }
1284: }
1285: }
1286: return(0);
1287: }
1289: EXTERN_C_BEGIN
1292: PetscErrorCode MatInvertDiagonal_SeqAIJ(Mat A,PetscScalar omega,PetscScalar fshift)
1293: {
1294: Mat_SeqAIJ *a = (Mat_SeqAIJ*) A->data;
1296: PetscInt i,*diag,m = A->rmap->n;
1297: MatScalar *v = a->a;
1298: PetscScalar *idiag,*mdiag;
1301: if (a->idiagvalid) return(0);
1302: MatMarkDiagonal_SeqAIJ(A);
1303: diag = a->diag;
1304: if (!a->idiag) {
1305: PetscMalloc3(m,PetscScalar,&a->idiag,m,PetscScalar,&a->mdiag,m,PetscScalar,&a->ssor_work);
1306: PetscLogObjectMemory(A, 3*m*sizeof(PetscScalar));
1307: v = a->a;
1308: }
1309: mdiag = a->mdiag;
1310: idiag = a->idiag;
1311:
1312: if (omega == 1.0 && !PetscAbsScalar(fshift)) {
1313: for (i=0; i<m; i++) {
1314: mdiag[i] = v[diag[i]];
1315: if (!PetscAbsScalar(mdiag[i])) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Zero diagonal on row %D",i);
1316: idiag[i] = 1.0/v[diag[i]];
1317: }
1318: PetscLogFlops(m);
1319: } else {
1320: for (i=0; i<m; i++) {
1321: mdiag[i] = v[diag[i]];
1322: idiag[i] = omega/(fshift + v[diag[i]]);
1323: }
1324: PetscLogFlops(2.0*m);
1325: }
1326: a->idiagvalid = PETSC_TRUE;
1327: return(0);
1328: }
1329: EXTERN_C_END
1331: #include <../src/mat/impls/aij/seq/ftn-kernels/frelax.h>
1334: PetscErrorCode MatSOR_SeqAIJ(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx)
1335: {
1336: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1337: PetscScalar *x,d,sum,*t,scale;
1338: const MatScalar *v = a->a,*idiag=0,*mdiag;
1339: const PetscScalar *b, *bs,*xb, *ts;
1340: PetscErrorCode ierr;
1341: PetscInt n = A->cmap->n,m = A->rmap->n,i;
1342: const PetscInt *idx,*diag;
1345: its = its*lits;
1347: if (fshift != a->fshift || omega != a->omega) a->idiagvalid = PETSC_FALSE; /* must recompute idiag[] */
1348: if (!a->idiagvalid) {MatInvertDiagonal_SeqAIJ(A,omega,fshift);}
1349: a->fshift = fshift;
1350: a->omega = omega;
1352: diag = a->diag;
1353: t = a->ssor_work;
1354: idiag = a->idiag;
1355: mdiag = a->mdiag;
1357: VecGetArray(xx,&x);
1358: VecGetArrayRead(bb,&b);
1359: CHKMEMQ;
1360: /* We count flops by assuming the upper triangular and lower triangular parts have the same number of nonzeros */
1361: if (flag == SOR_APPLY_UPPER) {
1362: /* apply (U + D/omega) to the vector */
1363: bs = b;
1364: for (i=0; i<m; i++) {
1365: d = fshift + mdiag[i];
1366: n = a->i[i+1] - diag[i] - 1;
1367: idx = a->j + diag[i] + 1;
1368: v = a->a + diag[i] + 1;
1369: sum = b[i]*d/omega;
1370: PetscSparseDensePlusDot(sum,bs,v,idx,n);
1371: x[i] = sum;
1372: }
1373: VecRestoreArray(xx,&x);
1374: VecRestoreArrayRead(bb,&b);
1375: PetscLogFlops(a->nz);
1376: return(0);
1377: }
1379: if (flag == SOR_APPLY_LOWER) {
1380: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"SOR_APPLY_LOWER is not implemented");
1381: } else if (flag & SOR_EISENSTAT) {
1382: /* Let A = L + U + D; where L is lower trianglar,
1383: U is upper triangular, E = D/omega; This routine applies
1385: (L + E)^{-1} A (U + E)^{-1}
1387: to a vector efficiently using Eisenstat's trick.
1388: */
1389: scale = (2.0/omega) - 1.0;
1391: /* x = (E + U)^{-1} b */
1392: for (i=m-1; i>=0; i--) {
1393: n = a->i[i+1] - diag[i] - 1;
1394: idx = a->j + diag[i] + 1;
1395: v = a->a + diag[i] + 1;
1396: sum = b[i];
1397: PetscSparseDenseMinusDot(sum,x,v,idx,n);
1398: x[i] = sum*idiag[i];
1399: }
1401: /* t = b - (2*E - D)x */
1402: v = a->a;
1403: for (i=0; i<m; i++) { t[i] = b[i] - scale*(v[*diag++])*x[i]; }
1405: /* t = (E + L)^{-1}t */
1406: ts = t;
1407: diag = a->diag;
1408: for (i=0; i<m; i++) {
1409: n = diag[i] - a->i[i];
1410: idx = a->j + a->i[i];
1411: v = a->a + a->i[i];
1412: sum = t[i];
1413: PetscSparseDenseMinusDot(sum,ts,v,idx,n);
1414: t[i] = sum*idiag[i];
1415: /* x = x + t */
1416: x[i] += t[i];
1417: }
1419: PetscLogFlops(6.0*m-1 + 2.0*a->nz);
1420: VecRestoreArray(xx,&x);
1421: VecRestoreArrayRead(bb,&b);
1422: return(0);
1423: }
1424: if (flag & SOR_ZERO_INITIAL_GUESS) {
1425: if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){
1426: for (i=0; i<m; i++) {
1427: n = diag[i] - a->i[i];
1428: idx = a->j + a->i[i];
1429: v = a->a + a->i[i];
1430: sum = b[i];
1431: PetscSparseDenseMinusDot(sum,x,v,idx,n);
1432: t[i] = sum;
1433: x[i] = sum*idiag[i];
1434: }
1435: xb = t;
1436: PetscLogFlops(a->nz);
1437: } else xb = b;
1438: if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){
1439: for (i=m-1; i>=0; i--) {
1440: n = a->i[i+1] - diag[i] - 1;
1441: idx = a->j + diag[i] + 1;
1442: v = a->a + diag[i] + 1;
1443: sum = xb[i];
1444: PetscSparseDenseMinusDot(sum,x,v,idx,n);
1445: if (xb == b) {
1446: x[i] = sum*idiag[i];
1447: } else {
1448: x[i] = (1-omega)*x[i] + sum*idiag[i];
1449: }
1450: }
1451: PetscLogFlops(a->nz);
1452: }
1453: its--;
1454: }
1455: while (its--) {
1456: if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){
1457: for (i=0; i<m; i++) {
1458: n = a->i[i+1] - a->i[i];
1459: idx = a->j + a->i[i];
1460: v = a->a + a->i[i];
1461: sum = b[i];
1462: PetscSparseDenseMinusDot(sum,x,v,idx,n);
1463: x[i] = (1. - omega)*x[i] + (sum + mdiag[i]*x[i])*idiag[i];
1464: }
1465: PetscLogFlops(2.0*a->nz);
1466: }
1467: if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){
1468: for (i=m-1; i>=0; i--) {
1469: n = a->i[i+1] - a->i[i];
1470: idx = a->j + a->i[i];
1471: v = a->a + a->i[i];
1472: sum = b[i];
1473: PetscSparseDenseMinusDot(sum,x,v,idx,n);
1474: x[i] = (1. - omega)*x[i] + (sum + mdiag[i]*x[i])*idiag[i];
1475: }
1476: PetscLogFlops(2.0*a->nz);
1477: }
1478: }
1479: VecRestoreArray(xx,&x);
1480: VecRestoreArrayRead(bb,&b);
1481: CHKMEMQ; return(0);
1482: }
1487: PetscErrorCode MatGetInfo_SeqAIJ(Mat A,MatInfoType flag,MatInfo *info)
1488: {
1489: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1492: info->block_size = 1.0;
1493: info->nz_allocated = (double)a->maxnz;
1494: info->nz_used = (double)a->nz;
1495: info->nz_unneeded = (double)(a->maxnz - a->nz);
1496: info->assemblies = (double)A->num_ass;
1497: info->mallocs = (double)A->info.mallocs;
1498: info->memory = ((PetscObject)A)->mem;
1499: if (A->factortype) {
1500: info->fill_ratio_given = A->info.fill_ratio_given;
1501: info->fill_ratio_needed = A->info.fill_ratio_needed;
1502: info->factor_mallocs = A->info.factor_mallocs;
1503: } else {
1504: info->fill_ratio_given = 0;
1505: info->fill_ratio_needed = 0;
1506: info->factor_mallocs = 0;
1507: }
1508: return(0);
1509: }
1513: PetscErrorCode MatZeroRows_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
1514: {
1515: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1516: PetscInt i,m = A->rmap->n - 1,d = 0;
1517: PetscErrorCode ierr;
1518: const PetscScalar *xx;
1519: PetscScalar *bb;
1520: PetscBool missing;
1523: if (x && b) {
1524: VecGetArrayRead(x,&xx);
1525: VecGetArray(b,&bb);
1526: for (i=0; i<N; i++) {
1527: if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
1528: bb[rows[i]] = diag*xx[rows[i]];
1529: }
1530: VecRestoreArrayRead(x,&xx);
1531: VecRestoreArray(b,&bb);
1532: }
1534: if (a->keepnonzeropattern) {
1535: for (i=0; i<N; i++) {
1536: if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
1537: PetscMemzero(&a->a[a->i[rows[i]]],a->ilen[rows[i]]*sizeof(PetscScalar));
1538: }
1539: if (diag != 0.0) {
1540: MatMissingDiagonal_SeqAIJ(A,&missing,&d);
1541: if (missing) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Matrix is missing diagonal entry in row %D",d);
1542: for (i=0; i<N; i++) {
1543: a->a[a->diag[rows[i]]] = diag;
1544: }
1545: }
1546: A->same_nonzero = PETSC_TRUE;
1547: } else {
1548: if (diag != 0.0) {
1549: for (i=0; i<N; i++) {
1550: if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
1551: if (a->ilen[rows[i]] > 0) {
1552: a->ilen[rows[i]] = 1;
1553: a->a[a->i[rows[i]]] = diag;
1554: a->j[a->i[rows[i]]] = rows[i];
1555: } else { /* in case row was completely empty */
1556: MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES);
1557: }
1558: }
1559: } else {
1560: for (i=0; i<N; i++) {
1561: if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
1562: a->ilen[rows[i]] = 0;
1563: }
1564: }
1565: A->same_nonzero = PETSC_FALSE;
1566: }
1567: MatAssemblyEnd_SeqAIJ(A,MAT_FINAL_ASSEMBLY);
1568: return(0);
1569: }
1573: PetscErrorCode MatZeroRowsColumns_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
1574: {
1575: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1576: PetscInt i,j,m = A->rmap->n - 1,d = 0;
1577: PetscErrorCode ierr;
1578: PetscBool missing,*zeroed,vecs = PETSC_FALSE;
1579: const PetscScalar *xx;
1580: PetscScalar *bb;
1583: if (x && b) {
1584: VecGetArrayRead(x,&xx);
1585: VecGetArray(b,&bb);
1586: vecs = PETSC_TRUE;
1587: }
1588: PetscMalloc(A->rmap->n*sizeof(PetscBool),&zeroed);
1589: PetscMemzero(zeroed,A->rmap->n*sizeof(PetscBool));
1590: for (i=0; i<N; i++) {
1591: if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
1592: PetscMemzero(&a->a[a->i[rows[i]]],a->ilen[rows[i]]*sizeof(PetscScalar));
1593: zeroed[rows[i]] = PETSC_TRUE;
1594: }
1595: for (i=0; i<A->rmap->n; i++) {
1596: if (!zeroed[i]) {
1597: for (j=a->i[i]; j<a->i[i+1]; j++) {
1598: if (zeroed[a->j[j]]) {
1599: if (vecs) bb[i] -= a->a[j]*xx[a->j[j]];
1600: a->a[j] = 0.0;
1601: }
1602: }
1603: } else if (vecs) bb[i] = diag*xx[i];
1604: }
1605: if (x && b) {
1606: VecRestoreArrayRead(x,&xx);
1607: VecRestoreArray(b,&bb);
1608: }
1609: PetscFree(zeroed);
1610: if (diag != 0.0) {
1611: MatMissingDiagonal_SeqAIJ(A,&missing,&d);
1612: if (missing) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Matrix is missing diagonal entry in row %D",d);
1613: for (i=0; i<N; i++) {
1614: a->a[a->diag[rows[i]]] = diag;
1615: }
1616: }
1617: A->same_nonzero = PETSC_TRUE;
1618: MatAssemblyEnd_SeqAIJ(A,MAT_FINAL_ASSEMBLY);
1619: return(0);
1620: }
1624: PetscErrorCode MatGetRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
1625: {
1626: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1627: PetscInt *itmp;
1630: if (row < 0 || row >= A->rmap->n) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row %D out of range",row);
1632: *nz = a->i[row+1] - a->i[row];
1633: if (v) *v = a->a + a->i[row];
1634: if (idx) {
1635: itmp = a->j + a->i[row];
1636: if (*nz) {
1637: *idx = itmp;
1638: }
1639: else *idx = 0;
1640: }
1641: return(0);
1642: }
1644: /* remove this function? */
1647: PetscErrorCode MatRestoreRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
1648: {
1650: return(0);
1651: }
1655: PetscErrorCode MatNorm_SeqAIJ(Mat A,NormType type,PetscReal *nrm)
1656: {
1657: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1658: MatScalar *v = a->a;
1659: PetscReal sum = 0.0;
1661: PetscInt i,j;
1664: if (type == NORM_FROBENIUS) {
1665: for (i=0; i<a->nz; i++) {
1666: #if defined(PETSC_USE_COMPLEX)
1667: sum += PetscRealPart(PetscConj(*v)*(*v)); v++;
1668: #else
1669: sum += (*v)*(*v); v++;
1670: #endif
1671: }
1672: *nrm = PetscSqrtReal(sum);
1673: } else if (type == NORM_1) {
1674: PetscReal *tmp;
1675: PetscInt *jj = a->j;
1676: PetscMalloc((A->cmap->n+1)*sizeof(PetscReal),&tmp);
1677: PetscMemzero(tmp,A->cmap->n*sizeof(PetscReal));
1678: *nrm = 0.0;
1679: for (j=0; j<a->nz; j++) {
1680: tmp[*jj++] += PetscAbsScalar(*v); v++;
1681: }
1682: for (j=0; j<A->cmap->n; j++) {
1683: if (tmp[j] > *nrm) *nrm = tmp[j];
1684: }
1685: PetscFree(tmp);
1686: } else if (type == NORM_INFINITY) {
1687: *nrm = 0.0;
1688: for (j=0; j<A->rmap->n; j++) {
1689: v = a->a + a->i[j];
1690: sum = 0.0;
1691: for (i=0; i<a->i[j+1]-a->i[j]; i++) {
1692: sum += PetscAbsScalar(*v); v++;
1693: }
1694: if (sum > *nrm) *nrm = sum;
1695: }
1696: } else {
1697: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for two norm");
1698: }
1699: return(0);
1700: }
1702: /* Merged from MatGetSymbolicTranspose_SeqAIJ() - replace MatGetSymbolicTranspose_SeqAIJ()? */
1705: PetscErrorCode MatTransposeSymbolic_SeqAIJ(Mat A,Mat *B)
1706: {
1708: PetscInt i,j,anzj;
1709: Mat_SeqAIJ *a=(Mat_SeqAIJ *)A->data,*b;
1710: PetscInt an=A->cmap->N,am=A->rmap->N;
1711: PetscInt *ati,*atj,*atfill,*ai=a->i,*aj=a->j;
1714: /* Allocate space for symbolic transpose info and work array */
1715: PetscMalloc((an+1)*sizeof(PetscInt),&ati);
1716: PetscMalloc(ai[am]*sizeof(PetscInt),&atj);
1717: PetscMalloc(an*sizeof(PetscInt),&atfill);
1718: PetscMemzero(ati,(an+1)*sizeof(PetscInt));
1720: /* Walk through aj and count ## of non-zeros in each row of A^T. */
1721: /* Note: offset by 1 for fast conversion into csr format. */
1722: for (i=0;i<ai[am];i++) {
1723: ati[aj[i]+1] += 1;
1724: }
1725: /* Form ati for csr format of A^T. */
1726: for (i=0;i<an;i++) {
1727: ati[i+1] += ati[i];
1728: }
1730: /* Copy ati into atfill so we have locations of the next free space in atj */
1731: PetscMemcpy(atfill,ati,an*sizeof(PetscInt));
1733: /* Walk through A row-wise and mark nonzero entries of A^T. */
1734: for (i=0;i<am;i++) {
1735: anzj = ai[i+1] - ai[i];
1736: for (j=0;j<anzj;j++) {
1737: atj[atfill[*aj]] = i;
1738: atfill[*aj++] += 1;
1739: }
1740: }
1742: /* Clean up temporary space and complete requests. */
1743: PetscFree(atfill);
1744: MatCreateSeqAIJWithArrays(((PetscObject)A)->comm,an,am,ati,atj,PETSC_NULL,B);
1745: (*B)->rmap->bs = A->cmap->bs;
1746: (*B)->cmap->bs = A->rmap->bs;
1748: b = (Mat_SeqAIJ *)((*B)->data);
1749: b->free_a = PETSC_FALSE;
1750: b->free_ij = PETSC_TRUE;
1751: b->nonew = 0;
1752: return(0);
1753: }
1757: PetscErrorCode MatTranspose_SeqAIJ(Mat A,MatReuse reuse,Mat *B)
1758: {
1759: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1760: Mat C;
1762: PetscInt i,*aj = a->j,*ai = a->i,m = A->rmap->n,len,*col;
1763: MatScalar *array = a->a;
1766: if (reuse == MAT_REUSE_MATRIX && A == *B && m != A->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Square matrix only for in-place");
1768: if (reuse == MAT_INITIAL_MATRIX || *B == A) {
1769: PetscMalloc((1+A->cmap->n)*sizeof(PetscInt),&col);
1770: PetscMemzero(col,(1+A->cmap->n)*sizeof(PetscInt));
1771:
1772: for (i=0; i<ai[m]; i++) col[aj[i]] += 1;
1773: MatCreate(((PetscObject)A)->comm,&C);
1774: MatSetSizes(C,A->cmap->n,m,A->cmap->n,m);
1775: MatSetBlockSizes(C,A->cmap->bs,A->rmap->bs);
1776: MatSetType(C,((PetscObject)A)->type_name);
1777: MatSeqAIJSetPreallocation_SeqAIJ(C,0,col);
1778: PetscFree(col);
1779: } else {
1780: C = *B;
1781: }
1783: for (i=0; i<m; i++) {
1784: len = ai[i+1]-ai[i];
1785: MatSetValues_SeqAIJ(C,len,aj,1,&i,array,INSERT_VALUES);
1786: array += len;
1787: aj += len;
1788: }
1789: MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);
1790: MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);
1792: if (reuse == MAT_INITIAL_MATRIX || *B != A) {
1793: *B = C;
1794: } else {
1795: MatHeaderMerge(A,C);
1796: }
1797: return(0);
1798: }
1800: EXTERN_C_BEGIN
1803: PetscErrorCode MatIsTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool *f)
1804: {
1805: Mat_SeqAIJ *aij = (Mat_SeqAIJ *) A->data,*bij = (Mat_SeqAIJ*) A->data;
1806: PetscInt *adx,*bdx,*aii,*bii,*aptr,*bptr;
1807: MatScalar *va,*vb;
1809: PetscInt ma,na,mb,nb, i;
1812: bij = (Mat_SeqAIJ *) B->data;
1814: MatGetSize(A,&ma,&na);
1815: MatGetSize(B,&mb,&nb);
1816: if (ma!=nb || na!=mb){
1817: *f = PETSC_FALSE;
1818: return(0);
1819: }
1820: aii = aij->i; bii = bij->i;
1821: adx = aij->j; bdx = bij->j;
1822: va = aij->a; vb = bij->a;
1823: PetscMalloc(ma*sizeof(PetscInt),&aptr);
1824: PetscMalloc(mb*sizeof(PetscInt),&bptr);
1825: for (i=0; i<ma; i++) aptr[i] = aii[i];
1826: for (i=0; i<mb; i++) bptr[i] = bii[i];
1828: *f = PETSC_TRUE;
1829: for (i=0; i<ma; i++) {
1830: while (aptr[i]<aii[i+1]) {
1831: PetscInt idc,idr;
1832: PetscScalar vc,vr;
1833: /* column/row index/value */
1834: idc = adx[aptr[i]];
1835: idr = bdx[bptr[idc]];
1836: vc = va[aptr[i]];
1837: vr = vb[bptr[idc]];
1838: if (i!=idr || PetscAbsScalar(vc-vr) > tol) {
1839: *f = PETSC_FALSE;
1840: goto done;
1841: } else {
1842: aptr[i]++;
1843: if (B || i!=idc) bptr[idc]++;
1844: }
1845: }
1846: }
1847: done:
1848: PetscFree(aptr);
1849: PetscFree(bptr);
1850: return(0);
1851: }
1852: EXTERN_C_END
1854: EXTERN_C_BEGIN
1857: PetscErrorCode MatIsHermitianTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool *f)
1858: {
1859: Mat_SeqAIJ *aij = (Mat_SeqAIJ *) A->data,*bij = (Mat_SeqAIJ*) A->data;
1860: PetscInt *adx,*bdx,*aii,*bii,*aptr,*bptr;
1861: MatScalar *va,*vb;
1863: PetscInt ma,na,mb,nb, i;
1866: bij = (Mat_SeqAIJ *) B->data;
1868: MatGetSize(A,&ma,&na);
1869: MatGetSize(B,&mb,&nb);
1870: if (ma!=nb || na!=mb){
1871: *f = PETSC_FALSE;
1872: return(0);
1873: }
1874: aii = aij->i; bii = bij->i;
1875: adx = aij->j; bdx = bij->j;
1876: va = aij->a; vb = bij->a;
1877: PetscMalloc(ma*sizeof(PetscInt),&aptr);
1878: PetscMalloc(mb*sizeof(PetscInt),&bptr);
1879: for (i=0; i<ma; i++) aptr[i] = aii[i];
1880: for (i=0; i<mb; i++) bptr[i] = bii[i];
1882: *f = PETSC_TRUE;
1883: for (i=0; i<ma; i++) {
1884: while (aptr[i]<aii[i+1]) {
1885: PetscInt idc,idr;
1886: PetscScalar vc,vr;
1887: /* column/row index/value */
1888: idc = adx[aptr[i]];
1889: idr = bdx[bptr[idc]];
1890: vc = va[aptr[i]];
1891: vr = vb[bptr[idc]];
1892: if (i!=idr || PetscAbsScalar(vc-PetscConj(vr)) > tol) {
1893: *f = PETSC_FALSE;
1894: goto done;
1895: } else {
1896: aptr[i]++;
1897: if (B || i!=idc) bptr[idc]++;
1898: }
1899: }
1900: }
1901: done:
1902: PetscFree(aptr);
1903: PetscFree(bptr);
1904: return(0);
1905: }
1906: EXTERN_C_END
1910: PetscErrorCode MatIsSymmetric_SeqAIJ(Mat A,PetscReal tol,PetscBool *f)
1911: {
1914: MatIsTranspose_SeqAIJ(A,A,tol,f);
1915: return(0);
1916: }
1920: PetscErrorCode MatIsHermitian_SeqAIJ(Mat A,PetscReal tol,PetscBool *f)
1921: {
1924: MatIsHermitianTranspose_SeqAIJ(A,A,tol,f);
1925: return(0);
1926: }
1930: PetscErrorCode MatDiagonalScale_SeqAIJ(Mat A,Vec ll,Vec rr)
1931: {
1932: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1933: PetscScalar *l,*r,x;
1934: MatScalar *v;
1936: PetscInt i,j,m = A->rmap->n,n = A->cmap->n,M,nz = a->nz,*jj;
1939: if (ll) {
1940: /* The local size is used so that VecMPI can be passed to this routine
1941: by MatDiagonalScale_MPIAIJ */
1942: VecGetLocalSize(ll,&m);
1943: if (m != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Left scaling vector wrong length");
1944: VecGetArray(ll,&l);
1945: v = a->a;
1946: for (i=0; i<m; i++) {
1947: x = l[i];
1948: M = a->i[i+1] - a->i[i];
1949: for (j=0; j<M; j++) { (*v++) *= x;}
1950: }
1951: VecRestoreArray(ll,&l);
1952: PetscLogFlops(nz);
1953: }
1954: if (rr) {
1955: VecGetLocalSize(rr,&n);
1956: if (n != A->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Right scaling vector wrong length");
1957: VecGetArray(rr,&r);
1958: v = a->a; jj = a->j;
1959: for (i=0; i<nz; i++) {
1960: (*v++) *= r[*jj++];
1961: }
1962: VecRestoreArray(rr,&r);
1963: PetscLogFlops(nz);
1964: }
1965: a->idiagvalid = PETSC_FALSE;
1966: a->ibdiagvalid = PETSC_FALSE;
1967: return(0);
1968: }
1972: PetscErrorCode MatGetSubMatrix_SeqAIJ(Mat A,IS isrow,IS iscol,PetscInt csize,MatReuse scall,Mat *B)
1973: {
1974: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data,*c;
1976: PetscInt *smap,i,k,kstart,kend,oldcols = A->cmap->n,*lens;
1977: PetscInt row,mat_i,*mat_j,tcol,first,step,*mat_ilen,sum,lensi;
1978: const PetscInt *irow,*icol;
1979: PetscInt nrows,ncols;
1980: PetscInt *starts,*j_new,*i_new,*aj = a->j,*ai = a->i,ii,*ailen = a->ilen;
1981: MatScalar *a_new,*mat_a;
1982: Mat C;
1983: PetscBool stride,sorted;
1986: ISSorted(isrow,&sorted);
1987: if (!sorted) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"ISrow is not sorted");
1988: ISSorted(iscol,&sorted);
1989: if (!sorted) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"IScol is not sorted");
1991: ISGetIndices(isrow,&irow);
1992: ISGetLocalSize(isrow,&nrows);
1993: ISGetLocalSize(iscol,&ncols);
1995: ISStrideGetInfo(iscol,&first,&step);
1996: PetscObjectTypeCompare((PetscObject)iscol,ISSTRIDE,&stride);
1997: if (stride && step == 1) {
1998: /* special case of contiguous rows */
1999: PetscMalloc2(nrows,PetscInt,&lens,nrows,PetscInt,&starts);
2000: /* loop over new rows determining lens and starting points */
2001: for (i=0; i<nrows; i++) {
2002: kstart = ai[irow[i]];
2003: kend = kstart + ailen[irow[i]];
2004: for (k=kstart; k<kend; k++) {
2005: if (aj[k] >= first) {
2006: starts[i] = k;
2007: break;
2008: }
2009: }
2010: sum = 0;
2011: while (k < kend) {
2012: if (aj[k++] >= first+ncols) break;
2013: sum++;
2014: }
2015: lens[i] = sum;
2016: }
2017: /* create submatrix */
2018: if (scall == MAT_REUSE_MATRIX) {
2019: PetscInt n_cols,n_rows;
2020: MatGetSize(*B,&n_rows,&n_cols);
2021: if (n_rows != nrows || n_cols != ncols) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Reused submatrix wrong size");
2022: MatZeroEntries(*B);
2023: C = *B;
2024: } else {
2025: PetscInt rbs,cbs;
2026: MatCreate(((PetscObject)A)->comm,&C);
2027: MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);
2028: ISGetBlockSize(isrow,&rbs);
2029: ISGetBlockSize(iscol,&cbs);
2030: MatSetBlockSizes(C,rbs,cbs);
2031: MatSetType(C,((PetscObject)A)->type_name);
2032: MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);
2033: }
2034: c = (Mat_SeqAIJ*)C->data;
2036: /* loop over rows inserting into submatrix */
2037: a_new = c->a;
2038: j_new = c->j;
2039: i_new = c->i;
2041: for (i=0; i<nrows; i++) {
2042: ii = starts[i];
2043: lensi = lens[i];
2044: for (k=0; k<lensi; k++) {
2045: *j_new++ = aj[ii+k] - first;
2046: }
2047: PetscMemcpy(a_new,a->a + starts[i],lensi*sizeof(PetscScalar));
2048: a_new += lensi;
2049: i_new[i+1] = i_new[i] + lensi;
2050: c->ilen[i] = lensi;
2051: }
2052: PetscFree2(lens,starts);
2053: } else {
2054: ISGetIndices(iscol,&icol);
2055: PetscMalloc(oldcols*sizeof(PetscInt),&smap);
2056: PetscMemzero(smap,oldcols*sizeof(PetscInt));
2057: PetscMalloc((1+nrows)*sizeof(PetscInt),&lens);
2058: for (i=0; i<ncols; i++) {
2059: #if defined(PETSC_USE_DEBUG)
2060: if (icol[i] >= oldcols) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Requesting column beyond largest column icol[%D] %D <= A->cmap->n %D",i,icol[i],oldcols);
2061: #endif
2062: smap[icol[i]] = i+1;
2063: }
2065: /* determine lens of each row */
2066: for (i=0; i<nrows; i++) {
2067: kstart = ai[irow[i]];
2068: kend = kstart + a->ilen[irow[i]];
2069: lens[i] = 0;
2070: for (k=kstart; k<kend; k++) {
2071: if (smap[aj[k]]) {
2072: lens[i]++;
2073: }
2074: }
2075: }
2076: /* Create and fill new matrix */
2077: if (scall == MAT_REUSE_MATRIX) {
2078: PetscBool equal;
2080: c = (Mat_SeqAIJ *)((*B)->data);
2081: if ((*B)->rmap->n != nrows || (*B)->cmap->n != ncols) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong size");
2082: PetscMemcmp(c->ilen,lens,(*B)->rmap->n*sizeof(PetscInt),&equal);
2083: if (!equal) {
2084: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong no of nonzeros");
2085: }
2086: PetscMemzero(c->ilen,(*B)->rmap->n*sizeof(PetscInt));
2087: C = *B;
2088: } else {
2089: PetscInt rbs,cbs;
2090: MatCreate(((PetscObject)A)->comm,&C);
2091: MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);
2092: ISGetBlockSize(isrow,&rbs);
2093: ISGetBlockSize(iscol,&cbs);
2094: MatSetBlockSizes(C,rbs,cbs);
2095: MatSetType(C,((PetscObject)A)->type_name);
2096: MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);
2097: }
2098: c = (Mat_SeqAIJ *)(C->data);
2099: for (i=0; i<nrows; i++) {
2100: row = irow[i];
2101: kstart = ai[row];
2102: kend = kstart + a->ilen[row];
2103: mat_i = c->i[i];
2104: mat_j = c->j + mat_i;
2105: mat_a = c->a + mat_i;
2106: mat_ilen = c->ilen + i;
2107: for (k=kstart; k<kend; k++) {
2108: if ((tcol=smap[a->j[k]])) {
2109: *mat_j++ = tcol - 1;
2110: *mat_a++ = a->a[k];
2111: (*mat_ilen)++;
2113: }
2114: }
2115: }
2116: /* Free work space */
2117: ISRestoreIndices(iscol,&icol);
2118: PetscFree(smap);
2119: PetscFree(lens);
2120: }
2121: MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);
2122: MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);
2124: ISRestoreIndices(isrow,&irow);
2125: *B = C;
2126: return(0);
2127: }
2131: PetscErrorCode MatGetMultiProcBlock_SeqAIJ(Mat mat,MPI_Comm subComm,MatReuse scall,Mat* subMat)
2132: {
2134: Mat B;
2137: MatCreate(subComm,&B);
2138: MatSetSizes(B,mat->rmap->n,mat->cmap->n,mat->rmap->n,mat->cmap->n);
2139: MatSetBlockSizes(B,mat->rmap->bs,mat->cmap->bs);
2140: MatSetType(B,MATSEQAIJ);
2141: MatDuplicateNoCreate_SeqAIJ(B,mat,MAT_COPY_VALUES,PETSC_TRUE);
2142: *subMat = B;
2143: return(0);
2144: }
2148: PetscErrorCode MatILUFactor_SeqAIJ(Mat inA,IS row,IS col,const MatFactorInfo *info)
2149: {
2150: Mat_SeqAIJ *a = (Mat_SeqAIJ*)inA->data;
2152: Mat outA;
2153: PetscBool row_identity,col_identity;
2156: if (info->levels != 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only levels=0 supported for in-place ilu");
2158: ISIdentity(row,&row_identity);
2159: ISIdentity(col,&col_identity);
2161: outA = inA;
2162: outA->factortype = MAT_FACTOR_LU;
2163: PetscObjectReference((PetscObject)row);
2164: ISDestroy(&a->row);
2165: a->row = row;
2166: PetscObjectReference((PetscObject)col);
2167: ISDestroy(&a->col);
2168: a->col = col;
2170: /* Create the inverse permutation so that it can be used in MatLUFactorNumeric() */
2171: ISDestroy(&a->icol);
2172: ISInvertPermutation(col,PETSC_DECIDE,&a->icol);
2173: PetscLogObjectParent(inA,a->icol);
2175: if (!a->solve_work) { /* this matrix may have been factored before */
2176: PetscMalloc((inA->rmap->n+1)*sizeof(PetscScalar),&a->solve_work);
2177: PetscLogObjectMemory(inA, (inA->rmap->n+1)*sizeof(PetscScalar));
2178: }
2180: MatMarkDiagonal_SeqAIJ(inA);
2181: if (row_identity && col_identity) {
2182: MatLUFactorNumeric_SeqAIJ_inplace(outA,inA,info);
2183: } else {
2184: MatLUFactorNumeric_SeqAIJ_InplaceWithPerm(outA,inA,info);
2185: }
2186: return(0);
2187: }
2191: PetscErrorCode MatScale_SeqAIJ(Mat inA,PetscScalar alpha)
2192: {
2193: Mat_SeqAIJ *a = (Mat_SeqAIJ*)inA->data;
2194: PetscScalar oalpha = alpha;
2196: PetscBLASInt one = 1,bnz = PetscBLASIntCast(a->nz);
2199: BLASscal_(&bnz,&oalpha,a->a,&one);
2200: PetscLogFlops(a->nz);
2201: a->idiagvalid = PETSC_FALSE;
2202: a->ibdiagvalid = PETSC_FALSE;
2203: return(0);
2204: }
2208: PetscErrorCode MatGetSubMatrices_SeqAIJ(Mat A,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *B[])
2209: {
2211: PetscInt i;
2214: if (scall == MAT_INITIAL_MATRIX) {
2215: PetscMalloc((n+1)*sizeof(Mat),B);
2216: }
2218: for (i=0; i<n; i++) {
2219: MatGetSubMatrix_SeqAIJ(A,irow[i],icol[i],PETSC_DECIDE,scall,&(*B)[i]);
2220: }
2221: return(0);
2222: }
2226: PetscErrorCode MatIncreaseOverlap_SeqAIJ(Mat A,PetscInt is_max,IS is[],PetscInt ov)
2227: {
2228: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
2230: PetscInt row,i,j,k,l,m,n,*nidx,isz,val;
2231: const PetscInt *idx;
2232: PetscInt start,end,*ai,*aj;
2233: PetscBT table;
2236: m = A->rmap->n;
2237: ai = a->i;
2238: aj = a->j;
2240: if (ov < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"illegal negative overlap value used");
2242: PetscMalloc((m+1)*sizeof(PetscInt),&nidx);
2243: PetscBTCreate(m,&table);
2245: for (i=0; i<is_max; i++) {
2246: /* Initialize the two local arrays */
2247: isz = 0;
2248: PetscBTMemzero(m,table);
2249:
2250: /* Extract the indices, assume there can be duplicate entries */
2251: ISGetIndices(is[i],&idx);
2252: ISGetLocalSize(is[i],&n);
2253:
2254: /* Enter these into the temp arrays. I.e., mark table[row], enter row into new index */
2255: for (j=0; j<n ; ++j){
2256: if(!PetscBTLookupSet(table,idx[j])) { nidx[isz++] = idx[j];}
2257: }
2258: ISRestoreIndices(is[i],&idx);
2259: ISDestroy(&is[i]);
2260:
2261: k = 0;
2262: for (j=0; j<ov; j++){ /* for each overlap */
2263: n = isz;
2264: for (; k<n ; k++){ /* do only those rows in nidx[k], which are not done yet */
2265: row = nidx[k];
2266: start = ai[row];
2267: end = ai[row+1];
2268: for (l = start; l<end ; l++){
2269: val = aj[l] ;
2270: if (!PetscBTLookupSet(table,val)) {nidx[isz++] = val;}
2271: }
2272: }
2273: }
2274: ISCreateGeneral(PETSC_COMM_SELF,isz,nidx,PETSC_COPY_VALUES,(is+i));
2275: }
2276: PetscBTDestroy(&table);
2277: PetscFree(nidx);
2278: return(0);
2279: }
2281: /* -------------------------------------------------------------- */
2284: PetscErrorCode MatPermute_SeqAIJ(Mat A,IS rowp,IS colp,Mat *B)
2285: {
2286: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
2288: PetscInt i,nz = 0,m = A->rmap->n,n = A->cmap->n;
2289: const PetscInt *row,*col;
2290: PetscInt *cnew,j,*lens;
2291: IS icolp,irowp;
2292: PetscInt *cwork = PETSC_NULL;
2293: PetscScalar *vwork = PETSC_NULL;
2296: ISInvertPermutation(rowp,PETSC_DECIDE,&irowp);
2297: ISGetIndices(irowp,&row);
2298: ISInvertPermutation(colp,PETSC_DECIDE,&icolp);
2299: ISGetIndices(icolp,&col);
2300:
2301: /* determine lengths of permuted rows */
2302: PetscMalloc((m+1)*sizeof(PetscInt),&lens);
2303: for (i=0; i<m; i++) {
2304: lens[row[i]] = a->i[i+1] - a->i[i];
2305: }
2306: MatCreate(((PetscObject)A)->comm,B);
2307: MatSetSizes(*B,m,n,m,n);
2308: MatSetBlockSizes(*B,A->rmap->bs,A->cmap->bs);
2309: MatSetType(*B,((PetscObject)A)->type_name);
2310: MatSeqAIJSetPreallocation_SeqAIJ(*B,0,lens);
2311: PetscFree(lens);
2313: PetscMalloc(n*sizeof(PetscInt),&cnew);
2314: for (i=0; i<m; i++) {
2315: MatGetRow_SeqAIJ(A,i,&nz,&cwork,&vwork);
2316: for (j=0; j<nz; j++) { cnew[j] = col[cwork[j]];}
2317: MatSetValues_SeqAIJ(*B,1,&row[i],nz,cnew,vwork,INSERT_VALUES);
2318: MatRestoreRow_SeqAIJ(A,i,&nz,&cwork,&vwork);
2319: }
2320: PetscFree(cnew);
2321: (*B)->assembled = PETSC_FALSE;
2322: MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);
2323: MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);
2324: ISRestoreIndices(irowp,&row);
2325: ISRestoreIndices(icolp,&col);
2326: ISDestroy(&irowp);
2327: ISDestroy(&icolp);
2328: return(0);
2329: }
2333: PetscErrorCode MatCopy_SeqAIJ(Mat A,Mat B,MatStructure str)
2334: {
2338: /* If the two matrices have the same copy implementation, use fast copy. */
2339: if (str == SAME_NONZERO_PATTERN && (A->ops->copy == B->ops->copy)) {
2340: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
2341: Mat_SeqAIJ *b = (Mat_SeqAIJ*)B->data;
2343: if (a->i[A->rmap->n] != b->i[B->rmap->n]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of nonzeros in two matrices are different");
2344: PetscMemcpy(b->a,a->a,(a->i[A->rmap->n])*sizeof(PetscScalar));
2345: } else {
2346: MatCopy_Basic(A,B,str);
2347: }
2348: return(0);
2349: }
2353: PetscErrorCode MatSetUp_SeqAIJ(Mat A)
2354: {
2358: MatSeqAIJSetPreallocation_SeqAIJ(A,PETSC_DEFAULT,0);
2359: return(0);
2360: }
2364: PetscErrorCode MatGetArray_SeqAIJ(Mat A,PetscScalar *array[])
2365: {
2366: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
2368: *array = a->a;
2369: return(0);
2370: }
2374: PetscErrorCode MatRestoreArray_SeqAIJ(Mat A,PetscScalar *array[])
2375: {
2377: return(0);
2378: }
2382: PetscErrorCode MatFDColoringApply_SeqAIJ(Mat J,MatFDColoring coloring,Vec x1,MatStructure *flag,void *sctx)
2383: {
2384: PetscErrorCode (*f)(void*,Vec,Vec,void*) = (PetscErrorCode (*)(void*,Vec,Vec,void *))coloring->f;
2386: PetscInt k,N,start,end,l,row,col,srow,**vscaleforrow,m1,m2;
2387: PetscScalar dx,*y,*xx,*w3_array;
2388: PetscScalar *vscale_array;
2389: PetscReal epsilon = coloring->error_rel,umin = coloring->umin;
2390: Vec w1,w2,w3;
2391: void *fctx = coloring->fctx;
2392: PetscBool flg = PETSC_FALSE;
2395: if (!coloring->w1) {
2396: VecDuplicate(x1,&coloring->w1);
2397: PetscLogObjectParent(coloring,coloring->w1);
2398: VecDuplicate(x1,&coloring->w2);
2399: PetscLogObjectParent(coloring,coloring->w2);
2400: VecDuplicate(x1,&coloring->w3);
2401: PetscLogObjectParent(coloring,coloring->w3);
2402: }
2403: w1 = coloring->w1; w2 = coloring->w2; w3 = coloring->w3;
2405: MatSetUnfactored(J);
2406: PetscOptionsGetBool(((PetscObject)coloring)->prefix,"-mat_fd_coloring_dont_rezero",&flg,PETSC_NULL);
2407: if (flg) {
2408: PetscInfo(coloring,"Not calling MatZeroEntries()\n");
2409: } else {
2410: PetscBool assembled;
2411: MatAssembled(J,&assembled);
2412: if (assembled) {
2413: MatZeroEntries(J);
2414: }
2415: }
2417: VecGetOwnershipRange(x1,&start,&end);
2418: VecGetSize(x1,&N);
2420: /*
2421: This is a horrible, horrible, hack.
2422: */
2423: if (coloring->F) {
2424: VecGetLocalSize(coloring->F,&m1);
2425: VecGetLocalSize(w1,&m2);
2426: if (m1 != m2) {
2427: coloring->F = 0;
2428: }
2429: }
2431: if (coloring->F) {
2432: w1 = coloring->F;
2433: coloring->F = 0;
2434: } else {
2435: PetscLogEventBegin(MAT_FDColoringFunction,0,0,0,0);
2436: (*f)(sctx,x1,w1,fctx);
2437: PetscLogEventEnd(MAT_FDColoringFunction,0,0,0,0);
2438: }
2440: /*
2441: Compute all the scale factors and share with other processors
2442: */
2443: VecGetArray(x1,&xx);xx = xx - start;
2444: VecGetArray(coloring->vscale,&vscale_array);vscale_array = vscale_array - start;
2445: for (k=0; k<coloring->ncolors; k++) {
2446: /*
2447: Loop over each column associated with color adding the
2448: perturbation to the vector w3.
2449: */
2450: for (l=0; l<coloring->ncolumns[k]; l++) {
2451: col = coloring->columns[k][l]; /* column of the matrix we are probing for */
2452: dx = xx[col];
2453: if (dx == 0.0) dx = 1.0;
2454: #if !defined(PETSC_USE_COMPLEX)
2455: if (dx < umin && dx >= 0.0) dx = umin;
2456: else if (dx < 0.0 && dx > -umin) dx = -umin;
2457: #else
2458: if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0) dx = umin;
2459: else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
2460: #endif
2461: dx *= epsilon;
2462: vscale_array[col] = 1.0/dx;
2463: }
2464: }
2465: vscale_array = vscale_array + start;VecRestoreArray(coloring->vscale,&vscale_array);
2466: VecGhostUpdateBegin(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);
2467: VecGhostUpdateEnd(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);
2469: /* VecView(coloring->vscale,PETSC_VIEWER_STDOUT_WORLD);
2470: VecView(x1,PETSC_VIEWER_STDOUT_WORLD);*/
2472: if (coloring->vscaleforrow) vscaleforrow = coloring->vscaleforrow;
2473: else vscaleforrow = coloring->columnsforrow;
2475: VecGetArray(coloring->vscale,&vscale_array);
2476: /*
2477: Loop over each color
2478: */
2479: for (k=0; k<coloring->ncolors; k++) {
2480: coloring->currentcolor = k;
2481: VecCopy(x1,w3);
2482: VecGetArray(w3,&w3_array);w3_array = w3_array - start;
2483: /*
2484: Loop over each column associated with color adding the
2485: perturbation to the vector w3.
2486: */
2487: for (l=0; l<coloring->ncolumns[k]; l++) {
2488: col = coloring->columns[k][l]; /* column of the matrix we are probing for */
2489: dx = xx[col];
2490: if (dx == 0.0) dx = 1.0;
2491: #if !defined(PETSC_USE_COMPLEX)
2492: if (dx < umin && dx >= 0.0) dx = umin;
2493: else if (dx < 0.0 && dx > -umin) dx = -umin;
2494: #else
2495: if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0) dx = umin;
2496: else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
2497: #endif
2498: dx *= epsilon;
2499: if (!PetscAbsScalar(dx)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Computed 0 differencing parameter");
2500: w3_array[col] += dx;
2501: }
2502: w3_array = w3_array + start; VecRestoreArray(w3,&w3_array);
2504: /*
2505: Evaluate function at x1 + dx (here dx is a vector of perturbations)
2506: */
2508: PetscLogEventBegin(MAT_FDColoringFunction,0,0,0,0);
2509: (*f)(sctx,w3,w2,fctx);
2510: PetscLogEventEnd(MAT_FDColoringFunction,0,0,0,0);
2511: VecAXPY(w2,-1.0,w1);
2513: /*
2514: Loop over rows of vector, putting results into Jacobian matrix
2515: */
2516: VecGetArray(w2,&y);
2517: for (l=0; l<coloring->nrows[k]; l++) {
2518: row = coloring->rows[k][l];
2519: col = coloring->columnsforrow[k][l];
2520: y[row] *= vscale_array[vscaleforrow[k][l]];
2521: srow = row + start;
2522: MatSetValues_SeqAIJ(J,1,&srow,1,&col,y+row,INSERT_VALUES);
2523: }
2524: VecRestoreArray(w2,&y);
2525: }
2526: coloring->currentcolor = k;
2527: VecRestoreArray(coloring->vscale,&vscale_array);
2528: xx = xx + start; VecRestoreArray(x1,&xx);
2529: MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);
2530: MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);
2531: return(0);
2532: }
2534: /*
2535: Computes the number of nonzeros per row needed for preallocation when X and Y
2536: have different nonzero structure.
2537: */
2540: PetscErrorCode MatAXPYGetPreallocation_SeqAIJ(Mat Y,Mat X,PetscInt* nnz)
2541: {
2542: PetscInt i,m=Y->rmap->N;
2543: Mat_SeqAIJ *x = (Mat_SeqAIJ*)X->data;
2544: Mat_SeqAIJ *y = (Mat_SeqAIJ*)Y->data;
2545: const PetscInt *xi = x->i,*yi = y->i;
2548: /* Set the number of nonzeros in the new matrix */
2549: for(i=0; i<m; i++) {
2550: PetscInt j,k,nzx = xi[i+1] - xi[i],nzy = yi[i+1] - yi[i];
2551: const PetscInt *xj = x->j+xi[i],*yj = y->j+yi[i];
2552: nnz[i] = 0;
2553: for (j=0,k=0; j<nzx; j++) { /* Point in X */
2554: for (; k<nzy && yj[k]<xj[j]; k++) nnz[i]++; /* Catch up to X */
2555: if (k<nzy && yj[k]==xj[j]) k++; /* Skip duplicate */
2556: nnz[i]++;
2557: }
2558: for (; k<nzy; k++) nnz[i]++;
2559: }
2560: return(0);
2561: }
2565: PetscErrorCode MatAXPY_SeqAIJ(Mat Y,PetscScalar a,Mat X,MatStructure str)
2566: {
2568: PetscInt i;
2569: Mat_SeqAIJ *x = (Mat_SeqAIJ *)X->data,*y = (Mat_SeqAIJ *)Y->data;
2570: PetscBLASInt one=1,bnz = PetscBLASIntCast(x->nz);
2573: if (str == SAME_NONZERO_PATTERN) {
2574: PetscScalar alpha = a;
2575: BLASaxpy_(&bnz,&alpha,x->a,&one,y->a,&one);
2576: y->idiagvalid = PETSC_FALSE;
2577: y->ibdiagvalid = PETSC_FALSE;
2578: } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */
2579: if (y->xtoy && y->XtoY != X) {
2580: PetscFree(y->xtoy);
2581: MatDestroy(&y->XtoY);
2582: }
2583: if (!y->xtoy) { /* get xtoy */
2584: MatAXPYGetxtoy_Private(X->rmap->n,x->i,x->j,PETSC_NULL, y->i,y->j,PETSC_NULL, &y->xtoy);
2585: y->XtoY = X;
2586: PetscObjectReference((PetscObject)X);
2587: }
2588: for (i=0; i<x->nz; i++) y->a[y->xtoy[i]] += a*(x->a[i]);
2589: PetscInfo3(Y,"ratio of nnz(X)/nnz(Y): %d/%d = %G\n",x->nz,y->nz,(PetscReal)(x->nz)/(y->nz+1));
2590: } else {
2591: Mat B;
2592: PetscInt *nnz;
2593: PetscMalloc(Y->rmap->N*sizeof(PetscInt),&nnz);
2594: MatCreate(((PetscObject)Y)->comm,&B);
2595: PetscObjectSetName((PetscObject)B,((PetscObject)Y)->name);
2596: MatSetSizes(B,Y->rmap->n,Y->cmap->n,Y->rmap->N,Y->cmap->N);
2597: MatSetBlockSizes(B,Y->rmap->bs,Y->cmap->bs);
2598: MatSetType(B,(MatType) ((PetscObject)Y)->type_name);
2599: MatAXPYGetPreallocation_SeqAIJ(Y,X,nnz);
2600: MatSeqAIJSetPreallocation(B,0,nnz);
2601: MatAXPY_BasicWithPreallocation(B,Y,a,X,str);
2602: MatHeaderReplace(Y,B);
2603: PetscFree(nnz);
2604: }
2605: return(0);
2606: }
2610: PetscErrorCode MatConjugate_SeqAIJ(Mat mat)
2611: {
2612: #if defined(PETSC_USE_COMPLEX)
2613: Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data;
2614: PetscInt i,nz;
2615: PetscScalar *a;
2618: nz = aij->nz;
2619: a = aij->a;
2620: for (i=0; i<nz; i++) {
2621: a[i] = PetscConj(a[i]);
2622: }
2623: #else
2625: #endif
2626: return(0);
2627: }
2631: PetscErrorCode MatGetRowMaxAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[])
2632: {
2633: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
2635: PetscInt i,j,m = A->rmap->n,*ai,*aj,ncols,n;
2636: PetscReal atmp;
2637: PetscScalar *x;
2638: MatScalar *aa;
2641: if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2642: aa = a->a;
2643: ai = a->i;
2644: aj = a->j;
2646: VecSet(v,0.0);
2647: VecGetArray(v,&x);
2648: VecGetLocalSize(v,&n);
2649: if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
2650: for (i=0; i<m; i++) {
2651: ncols = ai[1] - ai[0]; ai++;
2652: x[i] = 0.0;
2653: for (j=0; j<ncols; j++){
2654: atmp = PetscAbsScalar(*aa);
2655: if (PetscAbsScalar(x[i]) < atmp) {x[i] = atmp; if (idx) idx[i] = *aj;}
2656: aa++; aj++;
2657: }
2658: }
2659: VecRestoreArray(v,&x);
2660: return(0);
2661: }
2665: PetscErrorCode MatGetRowMax_SeqAIJ(Mat A,Vec v,PetscInt idx[])
2666: {
2667: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
2669: PetscInt i,j,m = A->rmap->n,*ai,*aj,ncols,n;
2670: PetscScalar *x;
2671: MatScalar *aa;
2674: if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2675: aa = a->a;
2676: ai = a->i;
2677: aj = a->j;
2679: VecSet(v,0.0);
2680: VecGetArray(v,&x);
2681: VecGetLocalSize(v,&n);
2682: if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
2683: for (i=0; i<m; i++) {
2684: ncols = ai[1] - ai[0]; ai++;
2685: if (ncols == A->cmap->n) { /* row is dense */
2686: x[i] = *aa; if (idx) idx[i] = 0;
2687: } else { /* row is sparse so already KNOW maximum is 0.0 or higher */
2688: x[i] = 0.0;
2689: if (idx) {
2690: idx[i] = 0; /* in case ncols is zero */
2691: for (j=0;j<ncols;j++) { /* find first implicit 0.0 in the row */
2692: if (aj[j] > j) {
2693: idx[i] = j;
2694: break;
2695: }
2696: }
2697: }
2698: }
2699: for (j=0; j<ncols; j++){
2700: if (PetscRealPart(x[i]) < PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
2701: aa++; aj++;
2702: }
2703: }
2704: VecRestoreArray(v,&x);
2705: return(0);
2706: }
2710: PetscErrorCode MatGetRowMinAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[])
2711: {
2712: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
2714: PetscInt i,j,m = A->rmap->n,*ai,*aj,ncols,n;
2715: PetscReal atmp;
2716: PetscScalar *x;
2717: MatScalar *aa;
2720: if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2721: aa = a->a;
2722: ai = a->i;
2723: aj = a->j;
2725: VecSet(v,0.0);
2726: VecGetArray(v,&x);
2727: VecGetLocalSize(v,&n);
2728: if (n != A->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector, %d vs. %d rows", A->rmap->n, n);
2729: for (i=0; i<m; i++) {
2730: ncols = ai[1] - ai[0]; ai++;
2731: if (ncols) {
2732: /* Get first nonzero */
2733: for(j = 0; j < ncols; j++) {
2734: atmp = PetscAbsScalar(aa[j]);
2735: if (atmp > 1.0e-12) {x[i] = atmp; if (idx) idx[i] = aj[j]; break;}
2736: }
2737: if (j == ncols) {x[i] = PetscAbsScalar(*aa); if (idx) idx[i] = *aj;}
2738: } else {
2739: x[i] = 0.0; if (idx) idx[i] = 0;
2740: }
2741: for(j = 0; j < ncols; j++) {
2742: atmp = PetscAbsScalar(*aa);
2743: if (atmp > 1.0e-12 && PetscAbsScalar(x[i]) > atmp) {x[i] = atmp; if (idx) idx[i] = *aj;}
2744: aa++; aj++;
2745: }
2746: }
2747: VecRestoreArray(v,&x);
2748: return(0);
2749: }
2753: PetscErrorCode MatGetRowMin_SeqAIJ(Mat A,Vec v,PetscInt idx[])
2754: {
2755: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
2757: PetscInt i,j,m = A->rmap->n,*ai,*aj,ncols,n;
2758: PetscScalar *x;
2759: MatScalar *aa;
2762: if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2763: aa = a->a;
2764: ai = a->i;
2765: aj = a->j;
2767: VecSet(v,0.0);
2768: VecGetArray(v,&x);
2769: VecGetLocalSize(v,&n);
2770: if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
2771: for (i=0; i<m; i++) {
2772: ncols = ai[1] - ai[0]; ai++;
2773: if (ncols == A->cmap->n) { /* row is dense */
2774: x[i] = *aa; if (idx) idx[i] = 0;
2775: } else { /* row is sparse so already KNOW minimum is 0.0 or lower */
2776: x[i] = 0.0;
2777: if (idx) { /* find first implicit 0.0 in the row */
2778: idx[i] = 0; /* in case ncols is zero */
2779: for (j=0;j<ncols;j++) {
2780: if (aj[j] > j) {
2781: idx[i] = j;
2782: break;
2783: }
2784: }
2785: }
2786: }
2787: for (j=0; j<ncols; j++){
2788: if (PetscRealPart(x[i]) > PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
2789: aa++; aj++;
2790: }
2791: }
2792: VecRestoreArray(v,&x);
2793: return(0);
2794: }
2796: #include <petscblaslapack.h>
2797: #include <../src/mat/blockinvert.h>
2801: PetscErrorCode MatInvertBlockDiagonal_SeqAIJ(Mat A,const PetscScalar **values)
2802: {
2803: Mat_SeqAIJ *a = (Mat_SeqAIJ*) A->data;
2805: PetscInt i,bs = A->rmap->bs,mbs = A->rmap->n/A->rmap->bs,ipvt[5],bs2 = bs*bs,*v_pivots,ij[7],*IJ,j;
2806: MatScalar *diag,work[25],*v_work;
2807: PetscReal shift = 0.0;
2810: if (a->ibdiagvalid) {
2811: if (values) *values = a->ibdiag;
2812: return(0);
2813: }
2814: MatMarkDiagonal_SeqAIJ(A);
2815: if (!a->ibdiag) {
2816: PetscMalloc(bs2*mbs*sizeof(PetscScalar),&a->ibdiag);
2817: PetscLogObjectMemory(A,bs2*mbs*sizeof(PetscScalar));
2818: }
2819: diag = a->ibdiag;
2820: if (values) *values = a->ibdiag;
2821: /* factor and invert each block */
2822: switch (bs){
2823: case 1:
2824: for (i=0; i<mbs; i++) {
2825: MatGetValues(A,1,&i,1,&i,diag+i);
2826: diag[i] = (PetscScalar)1.0 / (diag[i] + shift);
2827: }
2828: break;
2829: case 2:
2830: for (i=0; i<mbs; i++) {
2831: ij[0] = 2*i; ij[1] = 2*i + 1;
2832: MatGetValues(A,2,ij,2,ij,diag);
2833: PetscKernel_A_gets_inverse_A_2(diag,shift);
2834: PetscKernel_A_gets_transpose_A_2(diag);
2835: diag += 4;
2836: }
2837: break;
2838: case 3:
2839: for (i=0; i<mbs; i++) {
2840: ij[0] = 3*i; ij[1] = 3*i + 1; ij[2] = 3*i + 2;
2841: MatGetValues(A,3,ij,3,ij,diag);
2842: PetscKernel_A_gets_inverse_A_3(diag,shift);
2843: PetscKernel_A_gets_transpose_A_3(diag);
2844: diag += 9;
2845: }
2846: break;
2847: case 4:
2848: for (i=0; i<mbs; i++) {
2849: ij[0] = 4*i; ij[1] = 4*i + 1; ij[2] = 4*i + 2; ij[3] = 4*i + 3;
2850: MatGetValues(A,4,ij,4,ij,diag);
2851: PetscKernel_A_gets_inverse_A_4(diag,shift);
2852: PetscKernel_A_gets_transpose_A_4(diag);
2853: diag += 16;
2854: }
2855: break;
2856: case 5:
2857: for (i=0; i<mbs; i++) {
2858: ij[0] = 5*i; ij[1] = 5*i + 1; ij[2] = 5*i + 2; ij[3] = 5*i + 3; ij[4] = 5*i + 4;
2859: MatGetValues(A,5,ij,5,ij,diag);
2860: PetscKernel_A_gets_inverse_A_5(diag,ipvt,work,shift);
2861: PetscKernel_A_gets_transpose_A_5(diag);
2862: diag += 25;
2863: }
2864: break;
2865: case 6:
2866: for (i=0; i<mbs; i++) {
2867: ij[0] = 6*i; ij[1] = 6*i + 1; ij[2] = 6*i + 2; ij[3] = 6*i + 3; ij[4] = 6*i + 4; ij[5] = 6*i + 5;
2868: MatGetValues(A,6,ij,6,ij,diag);
2869: PetscKernel_A_gets_inverse_A_6(diag,shift);
2870: PetscKernel_A_gets_transpose_A_6(diag);
2871: diag += 36;
2872: }
2873: break;
2874: case 7:
2875: for (i=0; i<mbs; i++) {
2876: ij[0] = 7*i; ij[1] = 7*i + 1; ij[2] = 7*i + 2; ij[3] = 7*i + 3; ij[4] = 7*i + 4; ij[5] = 7*i + 5; ij[5] = 7*i + 6;
2877: MatGetValues(A,7,ij,7,ij,diag);
2878: PetscKernel_A_gets_inverse_A_7(diag,shift);
2879: PetscKernel_A_gets_transpose_A_7(diag);
2880: diag += 49;
2881: }
2882: break;
2883: default:
2884: PetscMalloc3(bs,MatScalar,&v_work,bs,PetscInt,&v_pivots,bs,PetscInt,&IJ);
2885: for (i=0; i<mbs; i++) {
2886: for (j=0; j<bs; j++) {
2887: IJ[j] = bs*i + j;
2888: }
2889: MatGetValues(A,bs,IJ,bs,IJ,diag);
2890: PetscKernel_A_gets_inverse_A(bs,diag,v_pivots,v_work);
2891: PetscKernel_A_gets_transpose_A_N(diag,bs);
2892: diag += bs2;
2893: }
2894: PetscFree3(v_work,v_pivots,IJ);
2895: }
2896: a->ibdiagvalid = PETSC_TRUE;
2897: return(0);
2898: }
2900: extern PetscErrorCode MatFDColoringApply_AIJ(Mat,MatFDColoring,Vec,MatStructure*,void*);
2901: /* -------------------------------------------------------------------*/
2902: static struct _MatOps MatOps_Values = {MatSetValues_SeqAIJ,
2903: MatGetRow_SeqAIJ,
2904: MatRestoreRow_SeqAIJ,
2905: MatMult_SeqAIJ,
2906: /* 4*/ MatMultAdd_SeqAIJ,
2907: MatMultTranspose_SeqAIJ,
2908: MatMultTransposeAdd_SeqAIJ,
2909: 0,
2910: 0,
2911: 0,
2912: /*10*/ 0,
2913: MatLUFactor_SeqAIJ,
2914: 0,
2915: MatSOR_SeqAIJ,
2916: MatTranspose_SeqAIJ,
2917: /*15*/ MatGetInfo_SeqAIJ,
2918: MatEqual_SeqAIJ,
2919: MatGetDiagonal_SeqAIJ,
2920: MatDiagonalScale_SeqAIJ,
2921: MatNorm_SeqAIJ,
2922: /*20*/ 0,
2923: MatAssemblyEnd_SeqAIJ,
2924: MatSetOption_SeqAIJ,
2925: MatZeroEntries_SeqAIJ,
2926: /*24*/ MatZeroRows_SeqAIJ,
2927: 0,
2928: 0,
2929: 0,
2930: 0,
2931: /*29*/ MatSetUp_SeqAIJ,
2932: 0,
2933: 0,
2934: MatGetArray_SeqAIJ,
2935: MatRestoreArray_SeqAIJ,
2936: /*34*/ MatDuplicate_SeqAIJ,
2937: 0,
2938: 0,
2939: MatILUFactor_SeqAIJ,
2940: 0,
2941: /*39*/ MatAXPY_SeqAIJ,
2942: MatGetSubMatrices_SeqAIJ,
2943: MatIncreaseOverlap_SeqAIJ,
2944: MatGetValues_SeqAIJ,
2945: MatCopy_SeqAIJ,
2946: /*44*/ MatGetRowMax_SeqAIJ,
2947: MatScale_SeqAIJ,
2948: 0,
2949: MatDiagonalSet_SeqAIJ,
2950: MatZeroRowsColumns_SeqAIJ,
2951: /*49*/ 0,
2952: MatGetRowIJ_SeqAIJ,
2953: MatRestoreRowIJ_SeqAIJ,
2954: MatGetColumnIJ_SeqAIJ,
2955: MatRestoreColumnIJ_SeqAIJ,
2956: /*54*/ MatFDColoringCreate_SeqAIJ,
2957: 0,
2958: 0,
2959: MatPermute_SeqAIJ,
2960: 0,
2961: /*59*/ 0,
2962: MatDestroy_SeqAIJ,
2963: MatView_SeqAIJ,
2964: 0,
2965: 0,
2966: /*64*/ 0,
2967: 0,
2968: 0,
2969: 0,
2970: 0,
2971: /*69*/ MatGetRowMaxAbs_SeqAIJ,
2972: MatGetRowMinAbs_SeqAIJ,
2973: 0,
2974: MatSetColoring_SeqAIJ,
2975: #if defined(PETSC_HAVE_ADIC)
2976: MatSetValuesAdic_SeqAIJ,
2977: #else
2978: 0,
2979: #endif
2980: /*74*/ MatSetValuesAdifor_SeqAIJ,
2981: MatFDColoringApply_AIJ,
2982: 0,
2983: 0,
2984: 0,
2985: /*79*/ MatFindZeroDiagonals_SeqAIJ,
2986: 0,
2987: 0,
2988: 0,
2989: MatLoad_SeqAIJ,
2990: /*84*/ MatIsSymmetric_SeqAIJ,
2991: MatIsHermitian_SeqAIJ,
2992: 0,
2993: 0,
2994: 0,
2995: /*89*/ MatMatMult_SeqAIJ_SeqAIJ,
2996: MatMatMultSymbolic_SeqAIJ_SeqAIJ,
2997: MatMatMultNumeric_SeqAIJ_SeqAIJ,
2998: MatPtAP_Basic,
2999: MatPtAPSymbolic_SeqAIJ,
3000: /*94*/ MatPtAPNumeric_SeqAIJ,
3001: MatMatTransposeMult_SeqAIJ_SeqAIJ,
3002: MatMatTransposeMultSymbolic_SeqAIJ_SeqAIJ,
3003: MatMatTransposeMultNumeric_SeqAIJ_SeqAIJ,
3004: MatPtAPSymbolic_SeqAIJ_SeqAIJ,
3005: /*99*/ MatPtAPNumeric_SeqAIJ_SeqAIJ,
3006: 0,
3007: 0,
3008: MatConjugate_SeqAIJ,
3009: 0,
3010: /*104*/MatSetValuesRow_SeqAIJ,
3011: MatRealPart_SeqAIJ,
3012: MatImaginaryPart_SeqAIJ,
3013: 0,
3014: 0,
3015: /*109*/MatMatSolve_SeqAIJ,
3016: 0,
3017: MatGetRowMin_SeqAIJ,
3018: 0,
3019: MatMissingDiagonal_SeqAIJ,
3020: /*114*/0,
3021: 0,
3022: 0,
3023: 0,
3024: 0,
3025: /*119*/0,
3026: 0,
3027: 0,
3028: 0,
3029: MatGetMultiProcBlock_SeqAIJ,
3030: /*124*/MatFindNonzeroRows_SeqAIJ,
3031: MatGetColumnNorms_SeqAIJ,
3032: MatInvertBlockDiagonal_SeqAIJ,
3033: 0,
3034: 0,
3035: /*129*/0,
3036: MatTransposeMatMult_SeqAIJ_SeqAIJ,
3037: MatTransposeMatMultSymbolic_SeqAIJ_SeqAIJ,
3038: MatTransposeMatMultNumeric_SeqAIJ_SeqAIJ,
3039: MatTransposeColoringCreate_SeqAIJ,
3040: /*134*/MatTransColoringApplySpToDen_SeqAIJ,
3041: MatTransColoringApplyDenToSp_SeqAIJ,
3042: MatRARt_SeqAIJ_SeqAIJ,
3043: MatRARtSymbolic_SeqAIJ_SeqAIJ,
3044: MatRARtNumeric_SeqAIJ_SeqAIJ
3045: };
3047: EXTERN_C_BEGIN
3050: PetscErrorCode MatSeqAIJSetColumnIndices_SeqAIJ(Mat mat,PetscInt *indices)
3051: {
3052: Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data;
3053: PetscInt i,nz,n;
3057: nz = aij->maxnz;
3058: n = mat->rmap->n;
3059: for (i=0; i<nz; i++) {
3060: aij->j[i] = indices[i];
3061: }
3062: aij->nz = nz;
3063: for (i=0; i<n; i++) {
3064: aij->ilen[i] = aij->imax[i];
3065: }
3067: return(0);
3068: }
3069: EXTERN_C_END
3073: /*@
3074: MatSeqAIJSetColumnIndices - Set the column indices for all the rows
3075: in the matrix.
3077: Input Parameters:
3078: + mat - the SeqAIJ matrix
3079: - indices - the column indices
3081: Level: advanced
3083: Notes:
3084: This can be called if you have precomputed the nonzero structure of the
3085: matrix and want to provide it to the matrix object to improve the performance
3086: of the MatSetValues() operation.
3088: You MUST have set the correct numbers of nonzeros per row in the call to
3089: MatCreateSeqAIJ(), and the columns indices MUST be sorted.
3091: MUST be called before any calls to MatSetValues();
3093: The indices should start with zero, not one.
3095: @*/
3096: PetscErrorCode MatSeqAIJSetColumnIndices(Mat mat,PetscInt *indices)
3097: {
3103: PetscUseMethod(mat,"MatSeqAIJSetColumnIndices_C",(Mat,PetscInt *),(mat,indices));
3104: return(0);
3105: }
3107: /* ----------------------------------------------------------------------------------------*/
3109: EXTERN_C_BEGIN
3112: PetscErrorCode MatStoreValues_SeqAIJ(Mat mat)
3113: {
3114: Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data;
3116: size_t nz = aij->i[mat->rmap->n];
3119: if (aij->nonew != 1) {
3120: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
3121: }
3123: /* allocate space for values if not already there */
3124: if (!aij->saved_values) {
3125: PetscMalloc((nz+1)*sizeof(PetscScalar),&aij->saved_values);
3126: PetscLogObjectMemory(mat,(nz+1)*sizeof(PetscScalar));
3127: }
3129: /* copy values over */
3130: PetscMemcpy(aij->saved_values,aij->a,nz*sizeof(PetscScalar));
3131: return(0);
3132: }
3133: EXTERN_C_END
3137: /*@
3138: MatStoreValues - Stashes a copy of the matrix values; this allows, for
3139: example, reuse of the linear part of a Jacobian, while recomputing the
3140: nonlinear portion.
3142: Collect on Mat
3144: Input Parameters:
3145: . mat - the matrix (currently only AIJ matrices support this option)
3147: Level: advanced
3149: Common Usage, with SNESSolve():
3150: $ Create Jacobian matrix
3151: $ Set linear terms into matrix
3152: $ Apply boundary conditions to matrix, at this time matrix must have
3153: $ final nonzero structure (i.e. setting the nonlinear terms and applying
3154: $ boundary conditions again will not change the nonzero structure
3155: $ MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
3156: $ MatStoreValues(mat);
3157: $ Call SNESSetJacobian() with matrix
3158: $ In your Jacobian routine
3159: $ MatRetrieveValues(mat);
3160: $ Set nonlinear terms in matrix
3161:
3162: Common Usage without SNESSolve(), i.e. when you handle nonlinear solve yourself:
3163: $ // build linear portion of Jacobian
3164: $ MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
3165: $ MatStoreValues(mat);
3166: $ loop over nonlinear iterations
3167: $ MatRetrieveValues(mat);
3168: $ // call MatSetValues(mat,...) to set nonliner portion of Jacobian
3169: $ // call MatAssemblyBegin/End() on matrix
3170: $ Solve linear system with Jacobian
3171: $ endloop
3173: Notes:
3174: Matrix must already be assemblied before calling this routine
3175: Must set the matrix option MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); before
3176: calling this routine.
3178: When this is called multiple times it overwrites the previous set of stored values
3179: and does not allocated additional space.
3181: .seealso: MatRetrieveValues()
3183: @*/
3184: PetscErrorCode MatStoreValues(Mat mat)
3185: {
3190: if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3191: if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3192: PetscUseMethod(mat,"MatStoreValues_C",(Mat),(mat));
3193: return(0);
3194: }
3196: EXTERN_C_BEGIN
3199: PetscErrorCode MatRetrieveValues_SeqAIJ(Mat mat)
3200: {
3201: Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data;
3203: PetscInt nz = aij->i[mat->rmap->n];
3206: if (aij->nonew != 1) {
3207: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
3208: }
3209: if (!aij->saved_values) {
3210: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatStoreValues(A);first");
3211: }
3212: /* copy values over */
3213: PetscMemcpy(aij->a,aij->saved_values,nz*sizeof(PetscScalar));
3214: return(0);
3215: }
3216: EXTERN_C_END
3220: /*@
3221: MatRetrieveValues - Retrieves the copy of the matrix values; this allows, for
3222: example, reuse of the linear part of a Jacobian, while recomputing the
3223: nonlinear portion.
3225: Collect on Mat
3227: Input Parameters:
3228: . mat - the matrix (currently on AIJ matrices support this option)
3230: Level: advanced
3232: .seealso: MatStoreValues()
3234: @*/
3235: PetscErrorCode MatRetrieveValues(Mat mat)
3236: {
3241: if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3242: if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3243: PetscUseMethod(mat,"MatRetrieveValues_C",(Mat),(mat));
3244: return(0);
3245: }
3248: /* --------------------------------------------------------------------------------*/
3251: /*@C
3252: MatCreateSeqAIJ - Creates a sparse matrix in AIJ (compressed row) format
3253: (the default parallel PETSc format). For good matrix assembly performance
3254: the user should preallocate the matrix storage by setting the parameter nz
3255: (or the array nnz). By setting these parameters accurately, performance
3256: during matrix assembly can be increased by more than a factor of 50.
3258: Collective on MPI_Comm
3260: Input Parameters:
3261: + comm - MPI communicator, set to PETSC_COMM_SELF
3262: . m - number of rows
3263: . n - number of columns
3264: . nz - number of nonzeros per row (same for all rows)
3265: - nnz - array containing the number of nonzeros in the various rows
3266: (possibly different for each row) or PETSC_NULL
3268: Output Parameter:
3269: . A - the matrix
3271: It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(),
3272: MatXXXXSetPreallocation() paradgm instead of this routine directly.
3273: [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation]
3275: Notes:
3276: If nnz is given then nz is ignored
3278: The AIJ format (also called the Yale sparse matrix format or
3279: compressed row storage), is fully compatible with standard Fortran 77
3280: storage. That is, the stored row and column indices can begin at
3281: either one (as in Fortran) or zero. See the users' manual for details.
3283: Specify the preallocated storage with either nz or nnz (not both).
3284: Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory
3285: allocation. For large problems you MUST preallocate memory or you
3286: will get TERRIBLE performance, see the users' manual chapter on matrices.
3288: By default, this format uses inodes (identical nodes) when possible, to
3289: improve numerical efficiency of matrix-vector products and solves. We
3290: search for consecutive rows with the same nonzero structure, thereby
3291: reusing matrix information to achieve increased efficiency.
3293: Options Database Keys:
3294: + -mat_no_inode - Do not use inodes
3295: - -mat_inode_limit <limit> - Sets inode limit (max limit=5)
3297: Level: intermediate
3299: .seealso: MatCreate(), MatCreateAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays()
3301: @*/
3302: PetscErrorCode MatCreateSeqAIJ(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],Mat *A)
3303: {
3307: MatCreate(comm,A);
3308: MatSetSizes(*A,m,n,m,n);
3309: MatSetType(*A,MATSEQAIJ);
3310: MatSeqAIJSetPreallocation_SeqAIJ(*A,nz,nnz);
3311: return(0);
3312: }
3316: /*@C
3317: MatSeqAIJSetPreallocation - For good matrix assembly performance
3318: the user should preallocate the matrix storage by setting the parameter nz
3319: (or the array nnz). By setting these parameters accurately, performance
3320: during matrix assembly can be increased by more than a factor of 50.
3322: Collective on MPI_Comm
3324: Input Parameters:
3325: + B - The matrix-free
3326: . nz - number of nonzeros per row (same for all rows)
3327: - nnz - array containing the number of nonzeros in the various rows
3328: (possibly different for each row) or PETSC_NULL
3330: Notes:
3331: If nnz is given then nz is ignored
3333: The AIJ format (also called the Yale sparse matrix format or
3334: compressed row storage), is fully compatible with standard Fortran 77
3335: storage. That is, the stored row and column indices can begin at
3336: either one (as in Fortran) or zero. See the users' manual for details.
3338: Specify the preallocated storage with either nz or nnz (not both).
3339: Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory
3340: allocation. For large problems you MUST preallocate memory or you
3341: will get TERRIBLE performance, see the users' manual chapter on matrices.
3343: You can call MatGetInfo() to get information on how effective the preallocation was;
3344: for example the fields mallocs,nz_allocated,nz_used,nz_unneeded;
3345: You can also run with the option -info and look for messages with the string
3346: malloc in them to see if additional memory allocation was needed.
3348: Developers: Use nz of MAT_SKIP_ALLOCATION to not allocate any space for the matrix
3349: entries or columns indices
3351: By default, this format uses inodes (identical nodes) when possible, to
3352: improve numerical efficiency of matrix-vector products and solves. We
3353: search for consecutive rows with the same nonzero structure, thereby
3354: reusing matrix information to achieve increased efficiency.
3356: Options Database Keys:
3357: + -mat_no_inode - Do not use inodes
3358: . -mat_inode_limit <limit> - Sets inode limit (max limit=5)
3359: - -mat_aij_oneindex - Internally use indexing starting at 1
3360: rather than 0. Note that when calling MatSetValues(),
3361: the user still MUST index entries starting at 0!
3363: Level: intermediate
3365: .seealso: MatCreate(), MatCreateAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays(), MatGetInfo()
3367: @*/
3368: PetscErrorCode MatSeqAIJSetPreallocation(Mat B,PetscInt nz,const PetscInt nnz[])
3369: {
3375: PetscTryMethod(B,"MatSeqAIJSetPreallocation_C",(Mat,PetscInt,const PetscInt[]),(B,nz,nnz));
3376: return(0);
3377: }
3379: EXTERN_C_BEGIN
3382: PetscErrorCode MatSeqAIJSetPreallocation_SeqAIJ(Mat B,PetscInt nz,const PetscInt *nnz)
3383: {
3384: Mat_SeqAIJ *b;
3385: PetscBool skipallocation = PETSC_FALSE,realalloc = PETSC_FALSE;
3387: PetscInt i;
3390: if (nz >= 0 || nnz) realalloc = PETSC_TRUE;
3391: if (nz == MAT_SKIP_ALLOCATION) {
3392: skipallocation = PETSC_TRUE;
3393: nz = 0;
3394: }
3396: PetscLayoutSetUp(B->rmap);
3397: PetscLayoutSetUp(B->cmap);
3399: if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
3400: if (nz < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %d",nz);
3401: if (nnz) {
3402: for (i=0; i<B->rmap->n; i++) {
3403: if (nnz[i] < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be less than 0: local row %d value %d",i,nnz[i]);
3404: if (nnz[i] > B->cmap->n) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be greater than row length: local row %d value %d rowlength %d",i,nnz[i],B->cmap->n);
3405: }
3406: }
3408: B->preallocated = PETSC_TRUE;
3409: b = (Mat_SeqAIJ*)B->data;
3411: if (!skipallocation) {
3412: if (!b->imax) {
3413: PetscMalloc2(B->rmap->n,PetscInt,&b->imax,B->rmap->n,PetscInt,&b->ilen);
3414: PetscLogObjectMemory(B,2*B->rmap->n*sizeof(PetscInt));
3415: }
3416: if (!nnz) {
3417: if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 10;
3418: else if (nz < 0) nz = 1;
3419: for (i=0; i<B->rmap->n; i++) b->imax[i] = nz;
3420: nz = nz*B->rmap->n;
3421: } else {
3422: nz = 0;
3423: for (i=0; i<B->rmap->n; i++) {b->imax[i] = nnz[i]; nz += nnz[i];}
3424: }
3425: /* b->ilen will count nonzeros in each row so far. */
3426: for (i=0; i<B->rmap->n; i++) { b->ilen[i] = 0; }
3428: /* allocate the matrix space */
3429: MatSeqXAIJFreeAIJ(B,&b->a,&b->j,&b->i);
3430: PetscMalloc3(nz,PetscScalar,&b->a,nz,PetscInt,&b->j,B->rmap->n+1,PetscInt,&b->i);
3431: PetscLogObjectMemory(B,(B->rmap->n+1)*sizeof(PetscInt)+nz*(sizeof(PetscScalar)+sizeof(PetscInt)));
3432: b->i[0] = 0;
3433: for (i=1; i<B->rmap->n+1; i++) {
3434: b->i[i] = b->i[i-1] + b->imax[i-1];
3435: }
3436: b->singlemalloc = PETSC_TRUE;
3437: b->free_a = PETSC_TRUE;
3438: b->free_ij = PETSC_TRUE;
3439: } else {
3440: b->free_a = PETSC_FALSE;
3441: b->free_ij = PETSC_FALSE;
3442: }
3444: b->nz = 0;
3445: b->maxnz = nz;
3446: B->info.nz_unneeded = (double)b->maxnz;
3447: if (realalloc) {MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);}
3448: return(0);
3449: }
3450: EXTERN_C_END
3452: #undef __FUNCT__
3454: /*@
3455: MatSeqAIJSetPreallocationCSR - Allocates memory for a sparse sequential matrix in AIJ format.
3457: Input Parameters:
3458: + B - the matrix
3459: . i - the indices into j for the start of each row (starts with zero)
3460: . j - the column indices for each row (starts with zero) these must be sorted for each row
3461: - v - optional values in the matrix
3463: Level: developer
3465: The i,j,v values are COPIED with this routine; to avoid the copy use MatCreateSeqAIJWithArrays()
3467: .keywords: matrix, aij, compressed row, sparse, sequential
3469: .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatSeqAIJSetPreallocation(), MatCreateSeqAIJ(), SeqAIJ
3470: @*/
3471: PetscErrorCode MatSeqAIJSetPreallocationCSR(Mat B,const PetscInt i[],const PetscInt j[],const PetscScalar v[])
3472: {
3478: PetscTryMethod(B,"MatSeqAIJSetPreallocationCSR_C",(Mat,const PetscInt[],const PetscInt[],const PetscScalar[]),(B,i,j,v));
3479: return(0);
3480: }
3482: EXTERN_C_BEGIN
3483: #undef __FUNCT__
3485: PetscErrorCode MatSeqAIJSetPreallocationCSR_SeqAIJ(Mat B,const PetscInt Ii[],const PetscInt J[],const PetscScalar v[])
3486: {
3487: PetscInt i;
3488: PetscInt m,n;
3489: PetscInt nz;
3490: PetscInt *nnz, nz_max = 0;
3491: PetscScalar *values;
3495: if (Ii[0]) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Ii[0] must be 0 it is %D", Ii[0]);
3497: PetscLayoutSetUp(B->rmap);
3498: PetscLayoutSetUp(B->cmap);
3500: MatGetSize(B, &m, &n);
3501: PetscMalloc((m+1) * sizeof(PetscInt), &nnz);
3502: for(i = 0; i < m; i++) {
3503: nz = Ii[i+1]- Ii[i];
3504: nz_max = PetscMax(nz_max, nz);
3505: if (nz < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Local row %D has a negative number of columns %D", i, nnz);
3506: nnz[i] = nz;
3507: }
3508: MatSeqAIJSetPreallocation(B, 0, nnz);
3509: PetscFree(nnz);
3511: if (v) {
3512: values = (PetscScalar*) v;
3513: } else {
3514: PetscMalloc(nz_max*sizeof(PetscScalar), &values);
3515: PetscMemzero(values, nz_max*sizeof(PetscScalar));
3516: }
3518: for(i = 0; i < m; i++) {
3519: nz = Ii[i+1] - Ii[i];
3520: MatSetValues_SeqAIJ(B, 1, &i, nz, J+Ii[i], values + (v ? Ii[i] : 0), INSERT_VALUES);
3521: }
3523: MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);
3524: MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);
3526: if (!v) {
3527: PetscFree(values);
3528: }
3529: MatSetOption(B,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);
3530: return(0);
3531: }
3532: EXTERN_C_END
3534: #include <../src/mat/impls/dense/seq/dense.h>
3535: #include <petsc-private/petscaxpy.h>
3539: /*
3540: Computes (B'*A')' since computing B*A directly is untenable
3542: n p p
3543: ( ) ( ) ( )
3544: m ( A ) * n ( B ) = m ( C )
3545: ( ) ( ) ( )
3547: */
3548: PetscErrorCode MatMatMultNumeric_SeqDense_SeqAIJ(Mat A,Mat B,Mat C)
3549: {
3550: PetscErrorCode ierr;
3551: Mat_SeqDense *sub_a = (Mat_SeqDense*)A->data;
3552: Mat_SeqAIJ *sub_b = (Mat_SeqAIJ*)B->data;
3553: Mat_SeqDense *sub_c = (Mat_SeqDense*)C->data;
3554: PetscInt i,n,m,q,p;
3555: const PetscInt *ii,*idx;
3556: const PetscScalar *b,*a,*a_q;
3557: PetscScalar *c,*c_q;
3560: m = A->rmap->n;
3561: n = A->cmap->n;
3562: p = B->cmap->n;
3563: a = sub_a->v;
3564: b = sub_b->a;
3565: c = sub_c->v;
3566: PetscMemzero(c,m*p*sizeof(PetscScalar));
3568: ii = sub_b->i;
3569: idx = sub_b->j;
3570: for (i=0; i<n; i++) {
3571: q = ii[i+1] - ii[i];
3572: while (q-->0) {
3573: c_q = c + m*(*idx);
3574: a_q = a + m*i;
3575: PetscAXPY(c_q,*b,a_q,m);
3576: idx++;
3577: b++;
3578: }
3579: }
3580: return(0);
3581: }
3585: PetscErrorCode MatMatMultSymbolic_SeqDense_SeqAIJ(Mat A,Mat B,PetscReal fill,Mat *C)
3586: {
3588: PetscInt m=A->rmap->n,n=B->cmap->n;
3589: Mat Cmat;
3592: 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);
3593: MatCreate(((PetscObject)A)->comm,&Cmat);
3594: MatSetSizes(Cmat,m,n,m,n);
3595: MatSetBlockSizes(Cmat,A->rmap->bs,B->cmap->bs);
3596: MatSetType(Cmat,MATSEQDENSE);
3597: MatSeqDenseSetPreallocation(Cmat,PETSC_NULL);
3598: Cmat->assembled = PETSC_TRUE;
3599: Cmat->ops->matmult = MatMatMult_SeqDense_SeqAIJ;
3600: *C = Cmat;
3601: return(0);
3602: }
3604: /* ----------------------------------------------------------------*/
3607: PetscErrorCode MatMatMult_SeqDense_SeqAIJ(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
3608: {
3612: if (scall == MAT_INITIAL_MATRIX){
3613: MatMatMultSymbolic_SeqDense_SeqAIJ(A,B,fill,C);
3614: }
3615: MatMatMultNumeric_SeqDense_SeqAIJ(A,B,*C);
3616: return(0);
3617: }
3620: /*MC
3621: MATSEQAIJ - MATSEQAIJ = "seqaij" - A matrix type to be used for sequential sparse matrices,
3622: based on compressed sparse row format.
3624: Options Database Keys:
3625: . -mat_type seqaij - sets the matrix type to "seqaij" during a call to MatSetFromOptions()
3627: Level: beginner
3629: .seealso: MatCreateSeqAIJ(), MatSetFromOptions(), MatSetType(), MatCreate(), MatType
3630: M*/
3632: EXTERN_C_BEGIN
3633: #if defined(PETSC_HAVE_PASTIX)
3634: extern PetscErrorCode MatGetFactor_seqaij_pastix(Mat,MatFactorType,Mat*);
3635: #endif
3636: #if defined(PETSC_HAVE_ESSL) && !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_REAL_SINGLE) && !defined(PETSC_USE_REAL___FLOAT128)
3637: extern PetscErrorCode MatGetFactor_seqaij_essl(Mat,MatFactorType,Mat *);
3638: #endif
3639: extern PetscErrorCode MatConvert_SeqAIJ_SeqAIJCRL(Mat,MatType,MatReuse,Mat*);
3640: extern PetscErrorCode MatGetFactor_seqaij_petsc(Mat,MatFactorType,Mat*);
3641: extern PetscErrorCode MatGetFactor_seqaij_bas(Mat,MatFactorType,Mat*);
3642: extern PetscErrorCode MatGetFactorAvailable_seqaij_petsc(Mat,MatFactorType,PetscBool *);
3643: #if defined(PETSC_HAVE_MUMPS)
3644: extern PetscErrorCode MatGetFactor_aij_mumps(Mat,MatFactorType,Mat*);
3645: #endif
3646: #if defined(PETSC_HAVE_SUPERLU)
3647: extern PetscErrorCode MatGetFactor_seqaij_superlu(Mat,MatFactorType,Mat*);
3648: #endif
3649: #if defined(PETSC_HAVE_SUPERLU_DIST)
3650: extern PetscErrorCode MatGetFactor_seqaij_superlu_dist(Mat,MatFactorType,Mat*);
3651: #endif
3652: #if defined(PETSC_HAVE_SPOOLES)
3653: extern PetscErrorCode MatGetFactor_seqaij_spooles(Mat,MatFactorType,Mat*);
3654: #endif
3655: #if defined(PETSC_HAVE_UMFPACK)
3656: extern PetscErrorCode MatGetFactor_seqaij_umfpack(Mat,MatFactorType,Mat*);
3657: #endif
3658: #if defined(PETSC_HAVE_CHOLMOD)
3659: extern PetscErrorCode MatGetFactor_seqaij_cholmod(Mat,MatFactorType,Mat*);
3660: #endif
3661: #if defined(PETSC_HAVE_LUSOL)
3662: extern PetscErrorCode MatGetFactor_seqaij_lusol(Mat,MatFactorType,Mat*);
3663: #endif
3664: #if defined(PETSC_HAVE_MATLAB_ENGINE)
3665: extern PetscErrorCode MatGetFactor_seqaij_matlab(Mat,MatFactorType,Mat*);
3666: extern PetscErrorCode MatlabEnginePut_SeqAIJ(PetscObject,void*);
3667: extern PetscErrorCode MatlabEngineGet_SeqAIJ(PetscObject,void*);
3668: #endif
3669: EXTERN_C_END
3672: EXTERN_C_BEGIN
3675: PetscErrorCode MatCreate_SeqAIJ(Mat B)
3676: {
3677: Mat_SeqAIJ *b;
3679: PetscMPIInt size;
3682: MPI_Comm_size(((PetscObject)B)->comm,&size);
3683: if (size > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Comm must be of size 1");
3685: PetscNewLog(B,Mat_SeqAIJ,&b);
3686: B->data = (void*)b;
3687: PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));
3688: b->row = 0;
3689: b->col = 0;
3690: b->icol = 0;
3691: b->reallocs = 0;
3692: b->ignorezeroentries = PETSC_FALSE;
3693: b->roworiented = PETSC_TRUE;
3694: b->nonew = 0;
3695: b->diag = 0;
3696: b->solve_work = 0;
3697: B->spptr = 0;
3698: b->saved_values = 0;
3699: b->idiag = 0;
3700: b->mdiag = 0;
3701: b->ssor_work = 0;
3702: b->omega = 1.0;
3703: b->fshift = 0.0;
3704: b->idiagvalid = PETSC_FALSE;
3705: b->ibdiagvalid = PETSC_FALSE;
3706: b->keepnonzeropattern = PETSC_FALSE;
3707: b->xtoy = 0;
3708: b->XtoY = 0;
3709: B->same_nonzero = PETSC_FALSE;
3711: PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);
3712: #if defined(PETSC_HAVE_MATLAB_ENGINE)
3713: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_matlab_C","MatGetFactor_seqaij_matlab",MatGetFactor_seqaij_matlab);
3714: PetscObjectComposeFunctionDynamic((PetscObject)B,"PetscMatlabEnginePut_C","MatlabEnginePut_SeqAIJ",MatlabEnginePut_SeqAIJ);
3715: PetscObjectComposeFunctionDynamic((PetscObject)B,"PetscMatlabEngineGet_C","MatlabEngineGet_SeqAIJ",MatlabEngineGet_SeqAIJ);
3716: #endif
3717: #if defined(PETSC_HAVE_PASTIX)
3718: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_pastix_C","MatGetFactor_seqaij_pastix",MatGetFactor_seqaij_pastix);
3719: #endif
3720: #if defined(PETSC_HAVE_ESSL) && !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_REAL_SINGLE) && !defined(PETSC_USE_REAL___FLOAT128)
3721: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_essl_C","MatGetFactor_seqaij_essl",MatGetFactor_seqaij_essl);
3722: #endif
3723: #if defined(PETSC_HAVE_SUPERLU)
3724: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_superlu_C","MatGetFactor_seqaij_superlu",MatGetFactor_seqaij_superlu);
3725: #endif
3726: #if defined(PETSC_HAVE_SUPERLU_DIST)
3727: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_superlu_dist_C","MatGetFactor_seqaij_superlu_dist",MatGetFactor_seqaij_superlu_dist);
3728: #endif
3729: #if defined(PETSC_HAVE_SPOOLES)
3730: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_spooles_C","MatGetFactor_seqaij_spooles",MatGetFactor_seqaij_spooles);
3731: #endif
3732: #if defined(PETSC_HAVE_MUMPS)
3733: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_mumps_C","MatGetFactor_aij_mumps",MatGetFactor_aij_mumps);
3734: #endif
3735: #if defined(PETSC_HAVE_UMFPACK)
3736: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_umfpack_C","MatGetFactor_seqaij_umfpack",MatGetFactor_seqaij_umfpack);
3737: #endif
3738: #if defined(PETSC_HAVE_CHOLMOD)
3739: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_cholmod_C","MatGetFactor_seqaij_cholmod",MatGetFactor_seqaij_cholmod);
3740: #endif
3741: #if defined(PETSC_HAVE_LUSOL)
3742: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_lusol_C","MatGetFactor_seqaij_lusol",MatGetFactor_seqaij_lusol);
3743: #endif
3744: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_petsc_C","MatGetFactor_seqaij_petsc",MatGetFactor_seqaij_petsc);
3745: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactorAvailable_petsc_C","MatGetFactorAvailable_seqaij_petsc",MatGetFactorAvailable_seqaij_petsc);
3746: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_bas_C","MatGetFactor_seqaij_bas",MatGetFactor_seqaij_bas);
3747: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqAIJSetColumnIndices_C","MatSeqAIJSetColumnIndices_SeqAIJ",MatSeqAIJSetColumnIndices_SeqAIJ);
3748: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatStoreValues_C","MatStoreValues_SeqAIJ",MatStoreValues_SeqAIJ);
3749: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatRetrieveValues_C","MatRetrieveValues_SeqAIJ",MatRetrieveValues_SeqAIJ);
3750: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_seqsbaij_C","MatConvert_SeqAIJ_SeqSBAIJ",MatConvert_SeqAIJ_SeqSBAIJ);
3751: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_seqbaij_C","MatConvert_SeqAIJ_SeqBAIJ",MatConvert_SeqAIJ_SeqBAIJ);
3752: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_seqaijperm_C","MatConvert_SeqAIJ_SeqAIJPERM",MatConvert_SeqAIJ_SeqAIJPERM);
3753: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_seqaijcrl_C","MatConvert_SeqAIJ_SeqAIJCRL",MatConvert_SeqAIJ_SeqAIJCRL);
3754: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatIsTranspose_C","MatIsTranspose_SeqAIJ",MatIsTranspose_SeqAIJ);
3755: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatIsHermitianTranspose_C","MatIsHermitianTranspose_SeqAIJ",MatIsTranspose_SeqAIJ);
3756: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqAIJSetPreallocation_C","MatSeqAIJSetPreallocation_SeqAIJ",MatSeqAIJSetPreallocation_SeqAIJ);
3757: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqAIJSetPreallocationCSR_C","MatSeqAIJSetPreallocationCSR_SeqAIJ",MatSeqAIJSetPreallocationCSR_SeqAIJ);
3758: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatReorderForNonzeroDiagonal_C","MatReorderForNonzeroDiagonal_SeqAIJ",MatReorderForNonzeroDiagonal_SeqAIJ);
3759: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatMatMult_seqdense_seqaij_C","MatMatMult_SeqDense_SeqAIJ",MatMatMult_SeqDense_SeqAIJ);
3760: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatMatMultSymbolic_seqdense_seqaij_C","MatMatMultSymbolic_SeqDense_SeqAIJ",MatMatMultSymbolic_SeqDense_SeqAIJ);
3761: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatMatMultNumeric_seqdense_seqaij_C","MatMatMultNumeric_SeqDense_SeqAIJ",MatMatMultNumeric_SeqDense_SeqAIJ);
3762: MatCreate_SeqAIJ_Inode(B);
3763: PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);
3764: return(0);
3765: }
3766: EXTERN_C_END
3770: /*
3771: Given a matrix generated with MatGetFactor() duplicates all the information in A into B
3772: */
3773: PetscErrorCode MatDuplicateNoCreate_SeqAIJ(Mat C,Mat A,MatDuplicateOption cpvalues,PetscBool mallocmatspace)
3774: {
3775: Mat_SeqAIJ *c,*a = (Mat_SeqAIJ*)A->data;
3777: PetscInt i,m = A->rmap->n;
3780: c = (Mat_SeqAIJ*)C->data;
3782: C->factortype = A->factortype;
3783: c->row = 0;
3784: c->col = 0;
3785: c->icol = 0;
3786: c->reallocs = 0;
3788: C->assembled = PETSC_TRUE;
3789:
3790: PetscLayoutReference(A->rmap,&C->rmap);
3791: PetscLayoutReference(A->cmap,&C->cmap);
3793: PetscMalloc2(m,PetscInt,&c->imax,m,PetscInt,&c->ilen);
3794: PetscLogObjectMemory(C, 2*m*sizeof(PetscInt));
3795: for (i=0; i<m; i++) {
3796: c->imax[i] = a->imax[i];
3797: c->ilen[i] = a->ilen[i];
3798: }
3800: /* allocate the matrix space */
3801: if (mallocmatspace){
3802: PetscMalloc3(a->i[m],PetscScalar,&c->a,a->i[m],PetscInt,&c->j,m+1,PetscInt,&c->i);
3803: PetscLogObjectMemory(C, a->i[m]*(sizeof(PetscScalar)+sizeof(PetscInt))+(m+1)*sizeof(PetscInt));
3804: c->singlemalloc = PETSC_TRUE;
3805: PetscMemcpy(c->i,a->i,(m+1)*sizeof(PetscInt));
3806: if (m > 0) {
3807: PetscMemcpy(c->j,a->j,(a->i[m])*sizeof(PetscInt));
3808: if (cpvalues == MAT_COPY_VALUES) {
3809: PetscMemcpy(c->a,a->a,(a->i[m])*sizeof(PetscScalar));
3810: } else {
3811: PetscMemzero(c->a,(a->i[m])*sizeof(PetscScalar));
3812: }
3813: }
3814: }
3816: c->ignorezeroentries = a->ignorezeroentries;
3817: c->roworiented = a->roworiented;
3818: c->nonew = a->nonew;
3819: if (a->diag) {
3820: PetscMalloc((m+1)*sizeof(PetscInt),&c->diag);
3821: PetscLogObjectMemory(C,(m+1)*sizeof(PetscInt));
3822: for (i=0; i<m; i++) {
3823: c->diag[i] = a->diag[i];
3824: }
3825: } else c->diag = 0;
3826: c->solve_work = 0;
3827: c->saved_values = 0;
3828: c->idiag = 0;
3829: c->ssor_work = 0;
3830: c->keepnonzeropattern = a->keepnonzeropattern;
3831: c->free_a = PETSC_TRUE;
3832: c->free_ij = PETSC_TRUE;
3833: c->xtoy = 0;
3834: c->XtoY = 0;
3836: c->rmax = a->rmax;
3837: c->nz = a->nz;
3838: c->maxnz = a->nz; /* Since we allocate exactly the right amount */
3839: C->preallocated = PETSC_TRUE;
3841: c->compressedrow.use = a->compressedrow.use;
3842: c->compressedrow.nrows = a->compressedrow.nrows;
3843: c->compressedrow.check = a->compressedrow.check;
3844: if (a->compressedrow.use){
3845: i = a->compressedrow.nrows;
3846: PetscMalloc2(i+1,PetscInt,&c->compressedrow.i,i,PetscInt,&c->compressedrow.rindex);
3847: PetscMemcpy(c->compressedrow.i,a->compressedrow.i,(i+1)*sizeof(PetscInt));
3848: PetscMemcpy(c->compressedrow.rindex,a->compressedrow.rindex,i*sizeof(PetscInt));
3849: } else {
3850: c->compressedrow.use = PETSC_FALSE;
3851: c->compressedrow.i = PETSC_NULL;
3852: c->compressedrow.rindex = PETSC_NULL;
3853: }
3854: C->same_nonzero = A->same_nonzero;
3855: MatDuplicate_SeqAIJ_Inode(A,cpvalues,&C);
3857: PetscFListDuplicate(((PetscObject)A)->qlist,&((PetscObject)C)->qlist);
3858: return(0);
3859: }
3863: PetscErrorCode MatDuplicate_SeqAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B)
3864: {
3868: MatCreate(((PetscObject)A)->comm,B);
3869: MatSetSizes(*B,A->rmap->n,A->cmap->n,A->rmap->n,A->cmap->n);
3870: MatSetBlockSizes(*B,A->rmap->bs,A->cmap->bs);
3871: MatSetType(*B,((PetscObject)A)->type_name);
3872: MatDuplicateNoCreate_SeqAIJ(*B,A,cpvalues,PETSC_TRUE);
3873: return(0);
3874: }
3878: PetscErrorCode MatLoad_SeqAIJ(Mat newMat, PetscViewer viewer)
3879: {
3880: Mat_SeqAIJ *a;
3882: PetscInt i,sum,nz,header[4],*rowlengths = 0,M,N,rows,cols;
3883: int fd;
3884: PetscMPIInt size;
3885: MPI_Comm comm;
3886: PetscInt bs = 1;
3887:
3889: PetscObjectGetComm((PetscObject)viewer,&comm);
3890: MPI_Comm_size(comm,&size);
3891: if (size > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"view must have one processor");
3893: PetscOptionsBegin(comm,PETSC_NULL,"Options for loading SEQAIJ matrix","Mat");
3894: PetscOptionsInt("-matload_block_size","Set the blocksize used to store the matrix","MatLoad",bs,&bs,PETSC_NULL);
3895: PetscOptionsEnd();
3897: PetscViewerBinaryGetDescriptor(viewer,&fd);
3898: PetscBinaryRead(fd,header,4,PETSC_INT);
3899: if (header[0] != MAT_FILE_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"not matrix object in file");
3900: M = header[1]; N = header[2]; nz = header[3];
3902: if (nz < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format on disk,cannot load as SeqAIJ");
3904: /* read in row lengths */
3905: PetscMalloc(M*sizeof(PetscInt),&rowlengths);
3906: PetscBinaryRead(fd,rowlengths,M,PETSC_INT);
3908: /* check if sum of rowlengths is same as nz */
3909: for (i=0,sum=0; i< M; i++) sum +=rowlengths[i];
3910: if (sum != nz) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Inconsistant matrix data in file. no-nonzeros = %d, sum-row-lengths = %d\n",nz,sum);
3912: /* set global size if not set already*/
3913: if (newMat->rmap->n < 0 && newMat->rmap->N < 0 && newMat->cmap->n < 0 && newMat->cmap->N < 0) {
3914: MatSetSizes(newMat,PETSC_DECIDE,PETSC_DECIDE,M,N);
3915: } else {
3916: /* if sizes and type are already set, check if the vector global sizes are correct */
3917: MatGetSize(newMat,&rows,&cols);
3918: if (rows < 0 && cols < 0){ /* user might provide local size instead of global size */
3919: MatGetLocalSize(newMat,&rows,&cols);
3920: }
3921: if (M != rows || N != cols) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED, "Matrix in file of different length (%d, %d) than the input matrix (%d, %d)",M,N,rows,cols);
3922: }
3923: MatSeqAIJSetPreallocation_SeqAIJ(newMat,0,rowlengths);
3924: a = (Mat_SeqAIJ*)newMat->data;
3926: PetscBinaryRead(fd,a->j,nz,PETSC_INT);
3928: /* read in nonzero values */
3929: PetscBinaryRead(fd,a->a,nz,PETSC_SCALAR);
3931: /* set matrix "i" values */
3932: a->i[0] = 0;
3933: for (i=1; i<= M; i++) {
3934: a->i[i] = a->i[i-1] + rowlengths[i-1];
3935: a->ilen[i-1] = rowlengths[i-1];
3936: }
3937: PetscFree(rowlengths);
3939: MatAssemblyBegin(newMat,MAT_FINAL_ASSEMBLY);
3940: MatAssemblyEnd(newMat,MAT_FINAL_ASSEMBLY);
3941: if (bs > 1) {MatSetBlockSize(newMat,bs);}
3942: return(0);
3943: }
3947: PetscErrorCode MatEqual_SeqAIJ(Mat A,Mat B,PetscBool * flg)
3948: {
3949: Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data,*b = (Mat_SeqAIJ *)B->data;
3951: #if defined(PETSC_USE_COMPLEX)
3952: PetscInt k;
3953: #endif
3956: /* If the matrix dimensions are not equal,or no of nonzeros */
3957: if ((A->rmap->n != B->rmap->n) || (A->cmap->n != B->cmap->n) ||(a->nz != b->nz)) {
3958: *flg = PETSC_FALSE;
3959: return(0);
3960: }
3961:
3962: /* if the a->i are the same */
3963: PetscMemcmp(a->i,b->i,(A->rmap->n+1)*sizeof(PetscInt),flg);
3964: if (!*flg) return(0);
3965:
3966: /* if a->j are the same */
3967: PetscMemcmp(a->j,b->j,(a->nz)*sizeof(PetscInt),flg);
3968: if (!*flg) return(0);
3969:
3970: /* if a->a are the same */
3971: #if defined(PETSC_USE_COMPLEX)
3972: for (k=0; k<a->nz; k++){
3973: if (PetscRealPart(a->a[k]) != PetscRealPart(b->a[k]) || PetscImaginaryPart(a->a[k]) != PetscImaginaryPart(b->a[k])){
3974: *flg = PETSC_FALSE;
3975: return(0);
3976: }
3977: }
3978: #else
3979: PetscMemcmp(a->a,b->a,(a->nz)*sizeof(PetscScalar),flg);
3980: #endif
3981: return(0);
3982: }
3986: /*@
3987: MatCreateSeqAIJWithArrays - Creates an sequential AIJ matrix using matrix elements (in CSR format)
3988: provided by the user.
3990: Collective on MPI_Comm
3992: Input Parameters:
3993: + comm - must be an MPI communicator of size 1
3994: . m - number of rows
3995: . n - number of columns
3996: . i - row indices
3997: . j - column indices
3998: - a - matrix values
4000: Output Parameter:
4001: . mat - the matrix
4003: Level: intermediate
4005: Notes:
4006: The i, j, and a arrays are not copied by this routine, the user must free these arrays
4007: once the matrix is destroyed and not before
4009: You cannot set new nonzero locations into this matrix, that will generate an error.
4011: The i and j indices are 0 based
4013: The format which is used for the sparse matrix input, is equivalent to a
4014: row-major ordering.. i.e for the following matrix, the input data expected is
4015: as shown:
4017: 1 0 0
4018: 2 0 3
4019: 4 5 6
4021: i = {0,1,3,6} [size = nrow+1 = 3+1]
4022: j = {0,0,2,0,1,2} [size = nz = 6]; values must be sorted for each row
4023: v = {1,2,3,4,5,6} [size = nz = 6]
4025:
4026: .seealso: MatCreate(), MatCreateAIJ(), MatCreateSeqAIJ(), MatCreateMPIAIJWithArrays(), MatMPIAIJSetPreallocationCSR()
4028: @*/
4029: PetscErrorCode MatCreateSeqAIJWithArrays(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt* i,PetscInt*j,PetscScalar *a,Mat *mat)
4030: {
4032: PetscInt ii;
4033: Mat_SeqAIJ *aij;
4034: #if defined(PETSC_USE_DEBUG)
4035: PetscInt jj;
4036: #endif
4039: if (i[0]) {
4040: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0");
4041: }
4042: MatCreate(comm,mat);
4043: MatSetSizes(*mat,m,n,m,n);
4044: /* MatSetBlockSizes(*mat,,); */
4045: MatSetType(*mat,MATSEQAIJ);
4046: MatSeqAIJSetPreallocation_SeqAIJ(*mat,MAT_SKIP_ALLOCATION,0);
4047: aij = (Mat_SeqAIJ*)(*mat)->data;
4048: PetscMalloc2(m,PetscInt,&aij->imax,m,PetscInt,&aij->ilen);
4050: aij->i = i;
4051: aij->j = j;
4052: aij->a = a;
4053: aij->singlemalloc = PETSC_FALSE;
4054: aij->nonew = -1; /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/
4055: aij->free_a = PETSC_FALSE;
4056: aij->free_ij = PETSC_FALSE;
4058: for (ii=0; ii<m; ii++) {
4059: aij->ilen[ii] = aij->imax[ii] = i[ii+1] - i[ii];
4060: #if defined(PETSC_USE_DEBUG)
4061: if (i[ii+1] - i[ii] < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative row length in i (row indices) row = %d length = %d",ii,i[ii+1] - i[ii]);
4062: for (jj=i[ii]+1; jj<i[ii+1]; jj++) {
4063: if (j[jj] < j[jj-1]) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column entry number %D (actual colum %D) in row %D is not sorted",jj-i[ii],j[jj],ii);
4064: if (j[jj] == j[jj]-1) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column entry number %D (actual colum %D) in row %D is identical to previous entry",jj-i[ii],j[jj],ii);
4065: }
4066: #endif
4067: }
4068: #if defined(PETSC_USE_DEBUG)
4069: for (ii=0; ii<aij->i[m]; ii++) {
4070: if (j[ii] < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column index at location = %d index = %d",ii,j[ii]);
4071: if (j[ii] > n - 1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column index to large at location = %d index = %d",ii,j[ii]);
4072: }
4073: #endif
4075: MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);
4076: MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);
4077: return(0);
4078: }
4081: /*@C
4082: MatCreateSeqAIJFromTriple - Creates an sequential AIJ matrix using matrix elements (in COO format)
4083: provided by the user.
4085: Collective on MPI_Comm
4087: Input Parameters:
4088: + comm - must be an MPI communicator of size 1
4089: . m - number of rows
4090: . n - number of columns
4091: . i - row indices
4092: . j - column indices
4093: . a - matrix values
4094: . nz - number of nonzeros
4095: - idx - 0 or 1 based
4097: Output Parameter:
4098: . mat - the matrix
4100: Level: intermediate
4102: Notes:
4103: The i and j indices are 0 based
4105: The format which is used for the sparse matrix input, is equivalent to a
4106: row-major ordering.. i.e for the following matrix, the input data expected is
4107: as shown:
4109: 1 0 0
4110: 2 0 3
4111: 4 5 6
4113: i = {0,1,1,2,2,2}
4114: j = {0,0,2,0,1,2}
4115: v = {1,2,3,4,5,6}
4117:
4118: .seealso: MatCreate(), MatCreateAIJ(), MatCreateSeqAIJ(), MatCreateSeqAIJWithArrays(), MatMPIAIJSetPreallocationCSR()
4120: @*/
4121: PetscErrorCode MatCreateSeqAIJFromTriple(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt* i,PetscInt*j,PetscScalar *a,Mat *mat,PetscInt nz,PetscBool idx)
4122: {
4124: PetscInt ii, *nnz, one = 1,row,col;
4128: PetscMalloc(m*sizeof(PetscInt),&nnz);
4129: PetscMemzero(nnz,m*sizeof(PetscInt));
4130: for (ii = 0; ii < nz; ii++){
4131: nnz[i[ii]] += 1;
4132: }
4133: MatCreate(comm,mat);
4134: MatSetSizes(*mat,m,n,m,n);
4135: /* MatSetBlockSizes(*mat,,); */
4136: MatSetType(*mat,MATSEQAIJ);
4137: MatSeqAIJSetPreallocation_SeqAIJ(*mat,0,nnz);
4138: for (ii = 0; ii < nz; ii++){
4139: if (idx){
4140: row = i[ii] - 1;
4141: col = j[ii] - 1;
4142: } else {
4143: row = i[ii];
4144: col = j[ii];
4145: }
4146: MatSetValues(*mat,one,&row,one,&col,&a[ii],ADD_VALUES);
4147: }
4148: MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);
4149: MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);
4150: PetscFree(nnz);
4151: return(0);
4152: }
4156: PetscErrorCode MatSetColoring_SeqAIJ(Mat A,ISColoring coloring)
4157: {
4159: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
4162: if (coloring->ctype == IS_COLORING_GLOBAL) {
4163: ISColoringReference(coloring);
4164: a->coloring = coloring;
4165: } else if (coloring->ctype == IS_COLORING_GHOSTED) {
4166: PetscInt i,*larray;
4167: ISColoring ocoloring;
4168: ISColoringValue *colors;
4170: /* set coloring for diagonal portion */
4171: PetscMalloc(A->cmap->n*sizeof(PetscInt),&larray);
4172: for (i=0; i<A->cmap->n; i++) {
4173: larray[i] = i;
4174: }
4175: ISGlobalToLocalMappingApply(A->cmap->mapping,IS_GTOLM_MASK,A->cmap->n,larray,PETSC_NULL,larray);
4176: PetscMalloc(A->cmap->n*sizeof(ISColoringValue),&colors);
4177: for (i=0; i<A->cmap->n; i++) {
4178: colors[i] = coloring->colors[larray[i]];
4179: }
4180: PetscFree(larray);
4181: ISColoringCreate(PETSC_COMM_SELF,coloring->n,A->cmap->n,colors,&ocoloring);
4182: a->coloring = ocoloring;
4183: }
4184: return(0);
4185: }
4187: #if defined(PETSC_HAVE_ADIC)
4188: EXTERN_C_BEGIN
4189: #include <adic/ad_utils.h>
4190: EXTERN_C_END
4194: PetscErrorCode MatSetValuesAdic_SeqAIJ(Mat A,void *advalues)
4195: {
4196: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
4197: PetscInt m = A->rmap->n,*ii = a->i,*jj = a->j,nz,i,j,nlen;
4198: PetscScalar *v = a->a,*values = ((PetscScalar*)advalues)+1;
4199: ISColoringValue *color;
4202: if (!a->coloring) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Coloring not set for matrix");
4203: nlen = PetscADGetDerivTypeSize()/sizeof(PetscScalar);
4204: color = a->coloring->colors;
4205: /* loop over rows */
4206: for (i=0; i<m; i++) {
4207: nz = ii[i+1] - ii[i];
4208: /* loop over columns putting computed value into matrix */
4209: for (j=0; j<nz; j++) {
4210: *v++ = values[color[*jj++]];
4211: }
4212: values += nlen; /* jump to next row of derivatives */
4213: }
4214: return(0);
4215: }
4216: #endif
4220: PetscErrorCode MatSetValuesAdifor_SeqAIJ(Mat A,PetscInt nl,void *advalues)
4221: {
4222: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
4223: PetscInt m = A->rmap->n,*ii = a->i,*jj = a->j,nz,i,j;
4224: MatScalar *v = a->a;
4225: PetscScalar *values = (PetscScalar *)advalues;
4226: ISColoringValue *color;
4229: if (!a->coloring) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Coloring not set for matrix");
4230: color = a->coloring->colors;
4231: /* loop over rows */
4232: for (i=0; i<m; i++) {
4233: nz = ii[i+1] - ii[i];
4234: /* loop over columns putting computed value into matrix */
4235: for (j=0; j<nz; j++) {
4236: *v++ = values[color[*jj++]];
4237: }
4238: values += nl; /* jump to next row of derivatives */
4239: }
4240: return(0);
4241: }
4243: /*
4244: Special version for direct calls from Fortran
4245: */
4246: #include <petsc-private/fortranimpl.h>
4247: #if defined(PETSC_HAVE_FORTRAN_CAPS)
4248: #define matsetvaluesseqaij_ MATSETVALUESSEQAIJ
4249: #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
4250: #define matsetvaluesseqaij_ matsetvaluesseqaij
4251: #endif
4253: /* Change these macros so can be used in void function */
4254: #undef CHKERRQ
4255: #define CHKERRQ(ierr) CHKERRABORT(((PetscObject)A)->comm,ierr)
4256: #undef SETERRQ2
4257: #define SETERRQ2(comm,ierr,b,c,d) CHKERRABORT(comm,ierr)
4258: #undef SETERRQ3
4259: #define SETERRQ3(comm,ierr,b,c,d,e) CHKERRABORT(comm,ierr)
4261: EXTERN_C_BEGIN
4264: void PETSC_STDCALL matsetvaluesseqaij_(Mat *AA,PetscInt *mm,const PetscInt im[],PetscInt *nn,const PetscInt in[],const PetscScalar v[],InsertMode *isis, PetscErrorCode *_ierr)
4265: {
4266: Mat A = *AA;
4267: PetscInt m = *mm, n = *nn;
4268: InsertMode is = *isis;
4269: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
4270: PetscInt *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N;
4271: PetscInt *imax,*ai,*ailen;
4273: PetscInt *aj,nonew = a->nonew,lastcol = -1;
4274: MatScalar *ap,value,*aa;
4275: PetscBool ignorezeroentries = a->ignorezeroentries;
4276: PetscBool roworiented = a->roworiented;
4279: MatCheckPreallocated(A,1);
4280: imax = a->imax;
4281: ai = a->i;
4282: ailen = a->ilen;
4283: aj = a->j;
4284: aa = a->a;
4286: for (k=0; k<m; k++) { /* loop over added rows */
4287: row = im[k];
4288: if (row < 0) continue;
4289: #if defined(PETSC_USE_DEBUG)
4290: if (row >= A->rmap->n) SETERRABORT(((PetscObject)A)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Row too large");
4291: #endif
4292: rp = aj + ai[row]; ap = aa + ai[row];
4293: rmax = imax[row]; nrow = ailen[row];
4294: low = 0;
4295: high = nrow;
4296: for (l=0; l<n; l++) { /* loop over added columns */
4297: if (in[l] < 0) continue;
4298: #if defined(PETSC_USE_DEBUG)
4299: if (in[l] >= A->cmap->n) SETERRABORT(((PetscObject)A)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Column too large");
4300: #endif
4301: col = in[l];
4302: if (roworiented) {
4303: value = v[l + k*n];
4304: } else {
4305: value = v[k + l*m];
4306: }
4307: if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue;
4309: if (col <= lastcol) low = 0; else high = nrow;
4310: lastcol = col;
4311: while (high-low > 5) {
4312: t = (low+high)/2;
4313: if (rp[t] > col) high = t;
4314: else low = t;
4315: }
4316: for (i=low; i<high; i++) {
4317: if (rp[i] > col) break;
4318: if (rp[i] == col) {
4319: if (is == ADD_VALUES) ap[i] += value;
4320: else ap[i] = value;
4321: goto noinsert;
4322: }
4323: }
4324: if (value == 0.0 && ignorezeroentries) goto noinsert;
4325: if (nonew == 1) goto noinsert;
4326: if (nonew == -1) SETERRABORT(((PetscObject)A)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero in the matrix");
4327: MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
4328: N = nrow++ - 1; a->nz++; high++;
4329: /* shift up all the later entries in this row */
4330: for (ii=N; ii>=i; ii--) {
4331: rp[ii+1] = rp[ii];
4332: ap[ii+1] = ap[ii];
4333: }
4334: rp[i] = col;
4335: ap[i] = value;
4336: noinsert:;
4337: low = i + 1;
4338: }
4339: ailen[row] = nrow;
4340: }
4341: A->same_nonzero = PETSC_FALSE;
4342: PetscFunctionReturnVoid();
4343: }
4344: EXTERN_C_END