Actual source code: aij.c
petsc-3.3-p5 2012-12-01
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_Private(Mat A,PetscInt *nrows,PetscInt **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: *nrows = cnt;
71: *zrows = rows;
72: return(0);
73: }
77: PetscErrorCode MatFindZeroDiagonals_SeqAIJ(Mat A,IS *zrows)
78: {
79: PetscInt nrows,*rows;
83: *zrows = PETSC_NULL;
84: MatFindZeroDiagonals_SeqAIJ_Private(A,&nrows,&rows);
85: ISCreateGeneral(((PetscObject)A)->comm,nrows,rows,PETSC_OWN_POINTER,zrows);
86: return(0);
87: }
91: PetscErrorCode MatFindNonzeroRows_SeqAIJ(Mat A,IS *keptrows)
92: {
93: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
94: const MatScalar *aa;
95: PetscInt m=A->rmap->n,cnt = 0;
96: const PetscInt *ii;
97: PetscInt n,i,j,*rows;
98: PetscErrorCode ierr;
101: *keptrows = 0;
102: ii = a->i;
103: for (i=0; i<m; i++) {
104: n = ii[i+1] - ii[i];
105: if (!n) {
106: cnt++;
107: goto ok1;
108: }
109: aa = a->a + ii[i];
110: for (j=0; j<n; j++) {
111: if (aa[j] != 0.0) goto ok1;
112: }
113: cnt++;
114: ok1:;
115: }
116: if (!cnt) return(0);
117: PetscMalloc((A->rmap->n-cnt)*sizeof(PetscInt),&rows);
118: cnt = 0;
119: for (i=0; i<m; i++) {
120: n = ii[i+1] - ii[i];
121: if (!n) continue;
122: aa = a->a + ii[i];
123: for (j=0; j<n; j++) {
124: if (aa[j] != 0.0) {
125: rows[cnt++] = i;
126: break;
127: }
128: }
129: }
130: ISCreateGeneral(PETSC_COMM_SELF,cnt,rows,PETSC_OWN_POINTER,keptrows);
131: return(0);
132: }
136: PetscErrorCode MatDiagonalSet_SeqAIJ(Mat Y,Vec D,InsertMode is)
137: {
139: Mat_SeqAIJ *aij = (Mat_SeqAIJ*) Y->data;
140: PetscInt i,*diag, m = Y->rmap->n;
141: MatScalar *aa = aij->a;
142: PetscScalar *v;
143: PetscBool missing;
146: if (Y->assembled) {
147: MatMissingDiagonal_SeqAIJ(Y,&missing,PETSC_NULL);
148: if (!missing) {
149: diag = aij->diag;
150: VecGetArray(D,&v);
151: if (is == INSERT_VALUES) {
152: for (i=0; i<m; i++) {
153: aa[diag[i]] = v[i];
154: }
155: } else {
156: for (i=0; i<m; i++) {
157: aa[diag[i]] += v[i];
158: }
159: }
160: VecRestoreArray(D,&v);
161: return(0);
162: }
163: aij->idiagvalid = PETSC_FALSE;
164: aij->ibdiagvalid = PETSC_FALSE;
165: }
166: MatDiagonalSet_Default(Y,D,is);
167: return(0);
168: }
172: PetscErrorCode MatGetRowIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *m,PetscInt *ia[],PetscInt *ja[],PetscBool *done)
173: {
174: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
176: PetscInt i,ishift;
177:
179: *m = A->rmap->n;
180: if (!ia) return(0);
181: ishift = 0;
182: if (symmetric && !A->structurally_symmetric) {
183: MatToSymmetricIJ_SeqAIJ(A->rmap->n,a->i,a->j,ishift,oshift,ia,ja);
184: } else if (oshift == 1) {
185: PetscInt nz = a->i[A->rmap->n];
186: /* malloc space and add 1 to i and j indices */
187: PetscMalloc((A->rmap->n+1)*sizeof(PetscInt),ia);
188: for (i=0; i<A->rmap->n+1; i++) (*ia)[i] = a->i[i] + 1;
189: if (ja) {
190: PetscMalloc((nz+1)*sizeof(PetscInt),ja);
191: for (i=0; i<nz; i++) (*ja)[i] = a->j[i] + 1;
192: }
193: } else {
194: *ia = a->i;
195: if (ja) *ja = a->j;
196: }
197: return(0);
198: }
202: PetscErrorCode MatRestoreRowIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,PetscInt *ia[],PetscInt *ja[],PetscBool *done)
203: {
205:
207: if (!ia) return(0);
208: if ((symmetric && !A->structurally_symmetric) || oshift == 1) {
209: PetscFree(*ia);
210: if (ja) {PetscFree(*ja);}
211: }
212: return(0);
213: }
217: PetscErrorCode MatGetColumnIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *nn,PetscInt *ia[],PetscInt *ja[],PetscBool *done)
218: {
219: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
221: PetscInt i,*collengths,*cia,*cja,n = A->cmap->n,m = A->rmap->n;
222: PetscInt nz = a->i[m],row,*jj,mr,col;
225: *nn = n;
226: if (!ia) return(0);
227: if (symmetric) {
228: MatToSymmetricIJ_SeqAIJ(A->rmap->n,a->i,a->j,0,oshift,ia,ja);
229: } else {
230: PetscMalloc((n+1)*sizeof(PetscInt),&collengths);
231: PetscMemzero(collengths,n*sizeof(PetscInt));
232: PetscMalloc((n+1)*sizeof(PetscInt),&cia);
233: PetscMalloc((nz+1)*sizeof(PetscInt),&cja);
234: jj = a->j;
235: for (i=0; i<nz; i++) {
236: collengths[jj[i]]++;
237: }
238: cia[0] = oshift;
239: for (i=0; i<n; i++) {
240: cia[i+1] = cia[i] + collengths[i];
241: }
242: PetscMemzero(collengths,n*sizeof(PetscInt));
243: jj = a->j;
244: for (row=0; row<m; row++) {
245: mr = a->i[row+1] - a->i[row];
246: for (i=0; i<mr; i++) {
247: col = *jj++;
248: cja[cia[col] + collengths[col]++ - oshift] = row + oshift;
249: }
250: }
251: PetscFree(collengths);
252: *ia = cia; *ja = cja;
253: }
254: return(0);
255: }
259: PetscErrorCode MatRestoreColumnIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,PetscInt *ia[],PetscInt *ja[],PetscBool *done)
260: {
264: if (!ia) return(0);
266: PetscFree(*ia);
267: PetscFree(*ja);
268:
269: return(0);
270: }
274: PetscErrorCode MatSetValuesRow_SeqAIJ(Mat A,PetscInt row,const PetscScalar v[])
275: {
276: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
277: PetscInt *ai = a->i;
281: PetscMemcpy(a->a+ai[row],v,(ai[row+1]-ai[row])*sizeof(PetscScalar));
282: return(0);
283: }
287: PetscErrorCode MatSetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
288: {
289: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
290: PetscInt *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N;
291: PetscInt *imax = a->imax,*ai = a->i,*ailen = a->ilen;
293: PetscInt *aj = a->j,nonew = a->nonew,lastcol = -1;
294: MatScalar *ap,value,*aa = a->a;
295: PetscBool ignorezeroentries = a->ignorezeroentries;
296: PetscBool roworiented = a->roworiented;
300: for (k=0; k<m; k++) { /* loop over added rows */
301: row = im[k];
302: if (row < 0) continue;
303: #if defined(PETSC_USE_DEBUG)
304: 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);
305: #endif
306: rp = aj + ai[row]; ap = aa + ai[row];
307: rmax = imax[row]; nrow = ailen[row];
308: low = 0;
309: high = nrow;
310: for (l=0; l<n; l++) { /* loop over added columns */
311: if (in[l] < 0) continue;
312: #if defined(PETSC_USE_DEBUG)
313: 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);
314: #endif
315: col = in[l];
316: if (v) {
317: if (roworiented) {
318: value = v[l + k*n];
319: } else {
320: value = v[k + l*m];
321: }
322: } else {
323: value = 0.;
324: }
325: if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue;
327: if (col <= lastcol) low = 0; else high = nrow;
328: lastcol = col;
329: while (high-low > 5) {
330: t = (low+high)/2;
331: if (rp[t] > col) high = t;
332: else low = t;
333: }
334: for (i=low; i<high; i++) {
335: if (rp[i] > col) break;
336: if (rp[i] == col) {
337: if (is == ADD_VALUES) ap[i] += value;
338: else ap[i] = value;
339: low = i + 1;
340: goto noinsert;
341: }
342: }
343: if (value == 0.0 && ignorezeroentries) goto noinsert;
344: if (nonew == 1) goto noinsert;
345: if (nonew == -1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero at (%D,%D) in the matrix",row,col);
346: MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
347: N = nrow++ - 1; a->nz++; high++;
348: /* shift up all the later entries in this row */
349: for (ii=N; ii>=i; ii--) {
350: rp[ii+1] = rp[ii];
351: ap[ii+1] = ap[ii];
352: }
353: rp[i] = col;
354: ap[i] = value;
355: low = i + 1;
356: noinsert:;
357: }
358: ailen[row] = nrow;
359: }
360: A->same_nonzero = PETSC_FALSE;
361: return(0);
362: }
367: PetscErrorCode MatGetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],PetscScalar v[])
368: {
369: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
370: PetscInt *rp,k,low,high,t,row,nrow,i,col,l,*aj = a->j;
371: PetscInt *ai = a->i,*ailen = a->ilen;
372: MatScalar *ap,*aa = a->a;
375: for (k=0; k<m; k++) { /* loop over rows */
376: row = im[k];
377: if (row < 0) {v += n; continue;} /* SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative row: %D",row); */
378: 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);
379: rp = aj + ai[row]; ap = aa + ai[row];
380: nrow = ailen[row];
381: for (l=0; l<n; l++) { /* loop over columns */
382: if (in[l] < 0) {v++; continue;} /* SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column: %D",in[l]); */
383: 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);
384: col = in[l] ;
385: high = nrow; low = 0; /* assume unsorted */
386: while (high-low > 5) {
387: t = (low+high)/2;
388: if (rp[t] > col) high = t;
389: else low = t;
390: }
391: for (i=low; i<high; i++) {
392: if (rp[i] > col) break;
393: if (rp[i] == col) {
394: *v++ = ap[i];
395: goto finished;
396: }
397: }
398: *v++ = 0.0;
399: finished:;
400: }
401: }
402: return(0);
403: }
408: PetscErrorCode MatView_SeqAIJ_Binary(Mat A,PetscViewer viewer)
409: {
410: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
412: PetscInt i,*col_lens;
413: int fd;
416: PetscViewerBinaryGetDescriptor(viewer,&fd);
417: PetscMalloc((4+A->rmap->n)*sizeof(PetscInt),&col_lens);
418: col_lens[0] = MAT_FILE_CLASSID;
419: col_lens[1] = A->rmap->n;
420: col_lens[2] = A->cmap->n;
421: col_lens[3] = a->nz;
423: /* store lengths of each row and write (including header) to file */
424: for (i=0; i<A->rmap->n; i++) {
425: col_lens[4+i] = a->i[i+1] - a->i[i];
426: }
427: PetscBinaryWrite(fd,col_lens,4+A->rmap->n,PETSC_INT,PETSC_TRUE);
428: PetscFree(col_lens);
430: /* store column indices (zero start index) */
431: PetscBinaryWrite(fd,a->j,a->nz,PETSC_INT,PETSC_FALSE);
433: /* store nonzero values */
434: PetscBinaryWrite(fd,a->a,a->nz,PETSC_SCALAR,PETSC_FALSE);
435: return(0);
436: }
438: extern PetscErrorCode MatSeqAIJFactorInfo_Matlab(Mat,PetscViewer);
442: PetscErrorCode MatView_SeqAIJ_ASCII(Mat A,PetscViewer viewer)
443: {
444: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
445: PetscErrorCode ierr;
446: PetscInt i,j,m = A->rmap->n,shift=0;
447: const char *name;
448: PetscViewerFormat format;
451: PetscViewerGetFormat(viewer,&format);
452: if (format == PETSC_VIEWER_ASCII_MATLAB) {
453: PetscInt nofinalvalue = 0;
454: if ((a->i[m] == a->i[m-1]) || (a->j[a->nz-1] != A->cmap->n-!shift)) {
455: nofinalvalue = 1;
456: }
457: PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);
458: PetscViewerASCIIPrintf(viewer,"%% Size = %D %D \n",m,A->cmap->n);
459: PetscViewerASCIIPrintf(viewer,"%% Nonzeros = %D \n",a->nz);
460: PetscViewerASCIIPrintf(viewer,"zzz = zeros(%D,3);\n",a->nz+nofinalvalue);
461: PetscViewerASCIIPrintf(viewer,"zzz = [\n");
463: for (i=0; i<m; i++) {
464: for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
465: #if defined(PETSC_USE_COMPLEX)
466: PetscViewerASCIIPrintf(viewer,"%D %D %18.16e + %18.16ei \n",i+1,a->j[j]+!shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));
467: #else
468: PetscViewerASCIIPrintf(viewer,"%D %D %18.16e\n",i+1,a->j[j]+!shift,a->a[j]);
469: #endif
470: }
471: }
472: if (nofinalvalue) {
473: PetscViewerASCIIPrintf(viewer,"%D %D %18.16e\n",m,A->cmap->n,0.0);
474: }
475: PetscObjectGetName((PetscObject)A,&name);
476: PetscViewerASCIIPrintf(viewer,"];\n %s = spconvert(zzz);\n",name);
477: PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);
478: } else if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO) {
479: return(0);
480: } else if (format == PETSC_VIEWER_ASCII_COMMON) {
481: PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);
482: PetscObjectPrintClassNamePrefixType((PetscObject)A,viewer,"Matrix Object");
483: for (i=0; i<m; i++) {
484: PetscViewerASCIIPrintf(viewer,"row %D:",i);
485: for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
486: #if defined(PETSC_USE_COMPLEX)
487: if (PetscImaginaryPart(a->a[j]) > 0.0 && PetscRealPart(a->a[j]) != 0.0) {
488: PetscViewerASCIIPrintf(viewer," (%D, %G + %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));
489: } else if (PetscImaginaryPart(a->a[j]) < 0.0 && PetscRealPart(a->a[j]) != 0.0) {
490: PetscViewerASCIIPrintf(viewer," (%D, %G - %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),-PetscImaginaryPart(a->a[j]));
491: } else if (PetscRealPart(a->a[j]) != 0.0) {
492: PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,PetscRealPart(a->a[j]));
493: }
494: #else
495: if (a->a[j] != 0.0) {PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,a->a[j]);}
496: #endif
497: }
498: PetscViewerASCIIPrintf(viewer,"\n");
499: }
500: PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);
501: } else if (format == PETSC_VIEWER_ASCII_SYMMODU) {
502: PetscInt nzd=0,fshift=1,*sptr;
503: PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);
504: PetscObjectPrintClassNamePrefixType((PetscObject)A,viewer,"Matrix Object");
505: PetscMalloc((m+1)*sizeof(PetscInt),&sptr);
506: for (i=0; i<m; i++) {
507: sptr[i] = nzd+1;
508: for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
509: if (a->j[j] >= i) {
510: #if defined(PETSC_USE_COMPLEX)
511: if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) nzd++;
512: #else
513: if (a->a[j] != 0.0) nzd++;
514: #endif
515: }
516: }
517: }
518: sptr[m] = nzd+1;
519: PetscViewerASCIIPrintf(viewer," %D %D\n\n",m,nzd);
520: for (i=0; i<m+1; i+=6) {
521: 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]);}
522: 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]);}
523: else if (i+2<m) {PetscViewerASCIIPrintf(viewer," %D %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2],sptr[i+3]);}
524: else if (i+1<m) {PetscViewerASCIIPrintf(viewer," %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2]);}
525: else if (i<m) {PetscViewerASCIIPrintf(viewer," %D %D\n",sptr[i],sptr[i+1]);}
526: else {PetscViewerASCIIPrintf(viewer," %D\n",sptr[i]);}
527: }
528: PetscViewerASCIIPrintf(viewer,"\n");
529: PetscFree(sptr);
530: for (i=0; i<m; i++) {
531: for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
532: if (a->j[j] >= i) {PetscViewerASCIIPrintf(viewer," %D ",a->j[j]+fshift);}
533: }
534: PetscViewerASCIIPrintf(viewer,"\n");
535: }
536: PetscViewerASCIIPrintf(viewer,"\n");
537: for (i=0; i<m; i++) {
538: for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
539: if (a->j[j] >= i) {
540: #if defined(PETSC_USE_COMPLEX)
541: if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) {
542: PetscViewerASCIIPrintf(viewer," %18.16e %18.16e ",PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));
543: }
544: #else
545: if (a->a[j] != 0.0) {PetscViewerASCIIPrintf(viewer," %18.16e ",a->a[j]);}
546: #endif
547: }
548: }
549: PetscViewerASCIIPrintf(viewer,"\n");
550: }
551: PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);
552: } else if (format == PETSC_VIEWER_ASCII_DENSE) {
553: PetscInt cnt = 0,jcnt;
554: PetscScalar value;
556: PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);
557: PetscObjectPrintClassNamePrefixType((PetscObject)A,viewer,"Matrix Object");
558: for (i=0; i<m; i++) {
559: jcnt = 0;
560: for (j=0; j<A->cmap->n; j++) {
561: if (jcnt < a->i[i+1]-a->i[i] && j == a->j[cnt]) {
562: value = a->a[cnt++];
563: jcnt++;
564: } else {
565: value = 0.0;
566: }
567: #if defined(PETSC_USE_COMPLEX)
568: PetscViewerASCIIPrintf(viewer," %7.5e+%7.5e i ",PetscRealPart(value),PetscImaginaryPart(value));
569: #else
570: PetscViewerASCIIPrintf(viewer," %7.5e ",value);
571: #endif
572: }
573: PetscViewerASCIIPrintf(viewer,"\n");
574: }
575: PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);
576: } else if (format == PETSC_VIEWER_ASCII_MATRIXMARKET) {
577: PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);
578: PetscObjectPrintClassNamePrefixType((PetscObject)A,viewer,"Matrix Object");
579: #if defined(PETSC_USE_COMPLEX)
580: PetscViewerASCIIPrintf(viewer,"%%matrix complex general\n");
581: #else
582: PetscViewerASCIIPrintf(viewer,"%%matrix real general\n");
583: #endif
584: PetscViewerASCIIPrintf(viewer,"%D %D %D\n", m, A->cmap->n, a->nz);
585: for (i=0; i<m; i++) {
586: for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
587: #if defined(PETSC_USE_COMPLEX)
588: if (PetscImaginaryPart(a->a[j]) > 0.0) {
589: PetscViewerASCIIPrintf(viewer,"%D %D, %G %G\n", i+shift,a->j[j]+shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));
590: } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
591: PetscViewerASCIIPrintf(viewer,"%D %D, %G -%G\n", i+shift,a->j[j]+shift,PetscRealPart(a->a[j]),-PetscImaginaryPart(a->a[j]));
592: } else {
593: PetscViewerASCIIPrintf(viewer,"%D %D, %G\n", i+shift,a->j[j]+shift,PetscRealPart(a->a[j]));
594: }
595: #else
596: PetscViewerASCIIPrintf(viewer,"%D %D %G\n", i+shift, a->j[j]+shift, a->a[j]);
597: #endif
598: }
599: }
600: PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);
601: } else {
602: PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);
603: PetscObjectPrintClassNamePrefixType((PetscObject)A,viewer,"Matrix Object");
604: if (A->factortype){
605: for (i=0; i<m; i++) {
606: PetscViewerASCIIPrintf(viewer,"row %D:",i);
607: /* L part */
608: for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
609: #if defined(PETSC_USE_COMPLEX)
610: if (PetscImaginaryPart(a->a[j]) > 0.0) {
611: PetscViewerASCIIPrintf(viewer," (%D, %G + %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));
612: } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
613: PetscViewerASCIIPrintf(viewer," (%D, %G - %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),-PetscImaginaryPart(a->a[j]));
614: } else {
615: PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,PetscRealPart(a->a[j]));
616: }
617: #else
618: PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,a->a[j]);
619: #endif
620: }
621: /* diagonal */
622: j = a->diag[i];
623: #if defined(PETSC_USE_COMPLEX)
624: if (PetscImaginaryPart(a->a[j]) > 0.0) {
625: PetscViewerASCIIPrintf(viewer," (%D, %G + %G i)",a->j[j]+shift,PetscRealPart(1.0/a->a[j]),PetscImaginaryPart(1.0/a->a[j]));
626: } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
627: PetscViewerASCIIPrintf(viewer," (%D, %G - %G i)",a->j[j]+shift,PetscRealPart(1.0/a->a[j]),-PetscImaginaryPart(1.0/a->a[j]));
628: } else {
629: PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,PetscRealPart(1.0/a->a[j]));
630: }
631: #else
632: PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,1.0/a->a[j]);
633: #endif
635: /* U part */
636: for (j=a->diag[i+1]+1+shift; j<a->diag[i]+shift; j++) {
637: #if defined(PETSC_USE_COMPLEX)
638: if (PetscImaginaryPart(a->a[j]) > 0.0) {
639: PetscViewerASCIIPrintf(viewer," (%D, %G + %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));
640: } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
641: PetscViewerASCIIPrintf(viewer," (%D, %G - %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),-PetscImaginaryPart(a->a[j]));
642: } else {
643: PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,PetscRealPart(a->a[j]));
644: }
645: #else
646: PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,a->a[j]);
647: #endif
648: }
649: PetscViewerASCIIPrintf(viewer,"\n");
650: }
651: } else {
652: for (i=0; i<m; i++) {
653: PetscViewerASCIIPrintf(viewer,"row %D:",i);
654: for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
655: #if defined(PETSC_USE_COMPLEX)
656: if (PetscImaginaryPart(a->a[j]) > 0.0) {
657: PetscViewerASCIIPrintf(viewer," (%D, %G + %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));
658: } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
659: PetscViewerASCIIPrintf(viewer," (%D, %G - %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),-PetscImaginaryPart(a->a[j]));
660: } else {
661: PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,PetscRealPart(a->a[j]));
662: }
663: #else
664: PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,a->a[j]);
665: #endif
666: }
667: PetscViewerASCIIPrintf(viewer,"\n");
668: }
669: }
670: PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);
671: }
672: PetscViewerFlush(viewer);
673: return(0);
674: }
678: PetscErrorCode MatView_SeqAIJ_Draw_Zoom(PetscDraw draw,void *Aa)
679: {
680: Mat A = (Mat) Aa;
681: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
682: PetscErrorCode ierr;
683: PetscInt i,j,m = A->rmap->n,color;
684: PetscReal xl,yl,xr,yr,x_l,x_r,y_l,y_r,maxv = 0.0;
685: PetscViewer viewer;
686: PetscViewerFormat format;
689: PetscObjectQuery((PetscObject)A,"Zoomviewer",(PetscObject*)&viewer);
690: PetscViewerGetFormat(viewer,&format);
692: PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);
693: /* loop over matrix elements drawing boxes */
695: if (format != PETSC_VIEWER_DRAW_CONTOUR) {
696: /* Blue for negative, Cyan for zero and Red for positive */
697: color = PETSC_DRAW_BLUE;
698: for (i=0; i<m; i++) {
699: y_l = m - i - 1.0; y_r = y_l + 1.0;
700: for (j=a->i[i]; j<a->i[i+1]; j++) {
701: x_l = a->j[j] ; x_r = x_l + 1.0;
702: #if defined(PETSC_USE_COMPLEX)
703: if (PetscRealPart(a->a[j]) >= 0.) continue;
704: #else
705: if (a->a[j] >= 0.) continue;
706: #endif
707: PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);
708: }
709: }
710: color = PETSC_DRAW_CYAN;
711: for (i=0; i<m; i++) {
712: y_l = m - i - 1.0; y_r = y_l + 1.0;
713: for (j=a->i[i]; j<a->i[i+1]; j++) {
714: x_l = a->j[j]; x_r = x_l + 1.0;
715: if (a->a[j] != 0.) continue;
716: PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);
717: }
718: }
719: color = PETSC_DRAW_RED;
720: for (i=0; i<m; i++) {
721: y_l = m - i - 1.0; y_r = y_l + 1.0;
722: for (j=a->i[i]; j<a->i[i+1]; j++) {
723: x_l = a->j[j]; x_r = x_l + 1.0;
724: #if defined(PETSC_USE_COMPLEX)
725: if (PetscRealPart(a->a[j]) <= 0.) continue;
726: #else
727: if (a->a[j] <= 0.) continue;
728: #endif
729: PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);
730: }
731: }
732: } else {
733: /* use contour shading to indicate magnitude of values */
734: /* first determine max of all nonzero values */
735: PetscInt nz = a->nz,count;
736: PetscDraw popup;
737: PetscReal scale;
739: for (i=0; i<nz; i++) {
740: if (PetscAbsScalar(a->a[i]) > maxv) maxv = PetscAbsScalar(a->a[i]);
741: }
742: scale = (245.0 - PETSC_DRAW_BASIC_COLORS)/maxv;
743: PetscDrawGetPopup(draw,&popup);
744: if (popup) {PetscDrawScalePopup(popup,0.0,maxv);}
745: count = 0;
746: for (i=0; i<m; i++) {
747: y_l = m - i - 1.0; y_r = y_l + 1.0;
748: for (j=a->i[i]; j<a->i[i+1]; j++) {
749: x_l = a->j[j]; x_r = x_l + 1.0;
750: color = PETSC_DRAW_BASIC_COLORS + (PetscInt)(scale*PetscAbsScalar(a->a[count]));
751: PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);
752: count++;
753: }
754: }
755: }
756: return(0);
757: }
761: PetscErrorCode MatView_SeqAIJ_Draw(Mat A,PetscViewer viewer)
762: {
764: PetscDraw draw;
765: PetscReal xr,yr,xl,yl,h,w;
766: PetscBool isnull;
769: PetscViewerDrawGetDraw(viewer,0,&draw);
770: PetscDrawIsNull(draw,&isnull);
771: if (isnull) return(0);
773: PetscObjectCompose((PetscObject)A,"Zoomviewer",(PetscObject)viewer);
774: xr = A->cmap->n; yr = A->rmap->n; h = yr/10.0; w = xr/10.0;
775: xr += w; yr += h; xl = -w; yl = -h;
776: PetscDrawSetCoordinates(draw,xl,yl,xr,yr);
777: PetscDrawZoom(draw,MatView_SeqAIJ_Draw_Zoom,A);
778: PetscObjectCompose((PetscObject)A,"Zoomviewer",PETSC_NULL);
779: return(0);
780: }
784: PetscErrorCode MatView_SeqAIJ(Mat A,PetscViewer viewer)
785: {
787: PetscBool iascii,isbinary,isdraw;
790: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
791: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);
792: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);
793: if (iascii) {
794: MatView_SeqAIJ_ASCII(A,viewer);
795: } else if (isbinary) {
796: MatView_SeqAIJ_Binary(A,viewer);
797: } else if (isdraw) {
798: MatView_SeqAIJ_Draw(A,viewer);
799: } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported by SeqAIJ matrices",((PetscObject)viewer)->type_name);
800: MatView_SeqAIJ_Inode(A,viewer);
801: return(0);
802: }
806: PetscErrorCode MatAssemblyEnd_SeqAIJ(Mat A,MatAssemblyType mode)
807: {
808: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
810: PetscInt fshift = 0,i,j,*ai = a->i,*aj = a->j,*imax = a->imax;
811: PetscInt m = A->rmap->n,*ip,N,*ailen = a->ilen,rmax = 0;
812: MatScalar *aa = a->a,*ap;
813: PetscReal ratio=0.6;
816: if (mode == MAT_FLUSH_ASSEMBLY) return(0);
818: if (m) rmax = ailen[0]; /* determine row with most nonzeros */
819: for (i=1; i<m; i++) {
820: /* move each row back by the amount of empty slots (fshift) before it*/
821: fshift += imax[i-1] - ailen[i-1];
822: rmax = PetscMax(rmax,ailen[i]);
823: if (fshift) {
824: ip = aj + ai[i] ;
825: ap = aa + ai[i] ;
826: N = ailen[i];
827: for (j=0; j<N; j++) {
828: ip[j-fshift] = ip[j];
829: ap[j-fshift] = ap[j];
830: }
831: }
832: ai[i] = ai[i-1] + ailen[i-1];
833: }
834: if (m) {
835: fshift += imax[m-1] - ailen[m-1];
836: ai[m] = ai[m-1] + ailen[m-1];
837: }
838: /* reset ilen and imax for each row */
839: for (i=0; i<m; i++) {
840: ailen[i] = imax[i] = ai[i+1] - ai[i];
841: }
842: a->nz = ai[m];
843: 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);
845: MatMarkDiagonal_SeqAIJ(A);
846: PetscInfo4(A,"Matrix size: %D X %D; storage space: %D unneeded,%D used\n",m,A->cmap->n,fshift,a->nz);
847: PetscInfo1(A,"Number of mallocs during MatSetValues() is %D\n",a->reallocs);
848: PetscInfo1(A,"Maximum nonzeros in any row is %D\n",rmax);
849: A->info.mallocs += a->reallocs;
850: a->reallocs = 0;
851: A->info.nz_unneeded = (double)fshift;
852: a->rmax = rmax;
854: MatCheckCompressedRow(A,&a->compressedrow,a->i,m,ratio);
855: A->same_nonzero = PETSC_TRUE;
857: MatAssemblyEnd_SeqAIJ_Inode(A,mode);
859: a->idiagvalid = PETSC_FALSE;
860: a->ibdiagvalid = PETSC_FALSE;
861: return(0);
862: }
866: PetscErrorCode MatRealPart_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] = PetscRealPart(aa[i]);
874: a->idiagvalid = PETSC_FALSE;
875: a->ibdiagvalid = PETSC_FALSE;
876: return(0);
877: }
881: PetscErrorCode MatImaginaryPart_SeqAIJ(Mat A)
882: {
883: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
884: PetscInt i,nz = a->nz;
885: MatScalar *aa = a->a;
888: for (i=0; i<nz; i++) aa[i] = PetscImaginaryPart(aa[i]);
889: a->idiagvalid = PETSC_FALSE;
890: a->ibdiagvalid = PETSC_FALSE;
891: return(0);
892: }
896: PetscErrorCode MatZeroEntries_SeqAIJ(Mat A)
897: {
898: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
902: PetscMemzero(a->a,(a->i[A->rmap->n])*sizeof(PetscScalar));
903: a->idiagvalid = PETSC_FALSE;
904: a->ibdiagvalid = PETSC_FALSE;
905: return(0);
906: }
910: PetscErrorCode MatDestroy_SeqAIJ(Mat A)
911: {
912: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
916: #if defined(PETSC_USE_LOG)
917: PetscLogObjectState((PetscObject)A,"Rows=%D, Cols=%D, NZ=%D",A->rmap->n,A->cmap->n,a->nz);
918: #endif
919: MatSeqXAIJFreeAIJ(A,&a->a,&a->j,&a->i);
920: ISDestroy(&a->row);
921: ISDestroy(&a->col);
922: PetscFree(a->diag);
923: PetscFree(a->ibdiag);
924: PetscFree2(a->imax,a->ilen);
925: PetscFree3(a->idiag,a->mdiag,a->ssor_work);
926: PetscFree(a->solve_work);
927: ISDestroy(&a->icol);
928: PetscFree(a->saved_values);
929: ISColoringDestroy(&a->coloring);
930: PetscFree(a->xtoy);
931: MatDestroy(&a->XtoY);
932: PetscFree2(a->compressedrow.i,a->compressedrow.rindex);
933: PetscFree(a->matmult_abdense);
935: MatDestroy_SeqAIJ_Inode(A);
936: PetscFree(A->data);
938: PetscObjectChangeTypeName((PetscObject)A,0);
939: PetscObjectComposeFunctionDynamic((PetscObject)A,"MatSeqAIJSetColumnIndices_C","",PETSC_NULL);
940: PetscObjectComposeFunctionDynamic((PetscObject)A,"MatStoreValues_C","",PETSC_NULL);
941: PetscObjectComposeFunctionDynamic((PetscObject)A,"MatRetrieveValues_C","",PETSC_NULL);
942: PetscObjectComposeFunctionDynamic((PetscObject)A,"MatConvert_seqaij_seqsbaij_C","",PETSC_NULL);
943: PetscObjectComposeFunctionDynamic((PetscObject)A,"MatConvert_seqaij_seqbaij_C","",PETSC_NULL);
944: PetscObjectComposeFunctionDynamic((PetscObject)A,"MatConvert_seqaij_seqaijperm_C","",PETSC_NULL);
945: PetscObjectComposeFunctionDynamic((PetscObject)A,"MatIsTranspose_C","",PETSC_NULL);
946: PetscObjectComposeFunctionDynamic((PetscObject)A,"MatSeqAIJSetPreallocation_C","",PETSC_NULL);
947: PetscObjectComposeFunctionDynamic((PetscObject)A,"MatSeqAIJSetPreallocationCSR_C","",PETSC_NULL);
948: PetscObjectComposeFunctionDynamic((PetscObject)A,"MatReorderForNonzeroDiagonal_C","",PETSC_NULL);
949: return(0);
950: }
954: PetscErrorCode MatSetOption_SeqAIJ(Mat A,MatOption op,PetscBool flg)
955: {
956: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
960: switch (op) {
961: case MAT_ROW_ORIENTED:
962: a->roworiented = flg;
963: break;
964: case MAT_KEEP_NONZERO_PATTERN:
965: a->keepnonzeropattern = flg;
966: break;
967: case MAT_NEW_NONZERO_LOCATIONS:
968: a->nonew = (flg ? 0 : 1);
969: break;
970: case MAT_NEW_NONZERO_LOCATION_ERR:
971: a->nonew = (flg ? -1 : 0);
972: break;
973: case MAT_NEW_NONZERO_ALLOCATION_ERR:
974: a->nonew = (flg ? -2 : 0);
975: break;
976: case MAT_UNUSED_NONZERO_LOCATION_ERR:
977: a->nounused = (flg ? -1 : 0);
978: break;
979: case MAT_IGNORE_ZERO_ENTRIES:
980: a->ignorezeroentries = flg;
981: break;
982: case MAT_CHECK_COMPRESSED_ROW:
983: a->compressedrow.check = flg;
984: break;
985: case MAT_SPD:
986: A->spd_set = PETSC_TRUE;
987: A->spd = flg;
988: if (flg) {
989: A->symmetric = PETSC_TRUE;
990: A->structurally_symmetric = PETSC_TRUE;
991: A->symmetric_set = PETSC_TRUE;
992: A->structurally_symmetric_set = PETSC_TRUE;
993: }
994: break;
995: case MAT_SYMMETRIC:
996: case MAT_STRUCTURALLY_SYMMETRIC:
997: case MAT_HERMITIAN:
998: case MAT_SYMMETRY_ETERNAL:
999: case MAT_NEW_DIAGONALS:
1000: case MAT_IGNORE_OFF_PROC_ENTRIES:
1001: case MAT_USE_HASH_TABLE:
1002: PetscInfo1(A,"Option %s ignored\n",MatOptions[op]);
1003: break;
1004: case MAT_USE_INODES:
1005: /* Not an error because MatSetOption_SeqAIJ_Inode handles this one */
1006: break;
1007: default:
1008: SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"unknown option %d",op);
1009: }
1010: MatSetOption_SeqAIJ_Inode(A,op,flg);
1011: return(0);
1012: }
1016: PetscErrorCode MatGetDiagonal_SeqAIJ(Mat A,Vec v)
1017: {
1018: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1020: PetscInt i,j,n,*ai=a->i,*aj=a->j,nz;
1021: PetscScalar *aa=a->a,*x,zero=0.0;
1024: VecGetLocalSize(v,&n);
1025: if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
1027: if (A->factortype == MAT_FACTOR_ILU || A->factortype == MAT_FACTOR_LU){
1028: PetscInt *diag=a->diag;
1029: VecGetArray(v,&x);
1030: for (i=0; i<n; i++) x[i] = 1.0/aa[diag[i]];
1031: VecRestoreArray(v,&x);
1032: return(0);
1033: }
1035: VecSet(v,zero);
1036: VecGetArray(v,&x);
1037: for (i=0; i<n; i++) {
1038: nz = ai[i+1] - ai[i];
1039: if (!nz) x[i] = 0.0;
1040: for (j=ai[i]; j<ai[i+1]; j++){
1041: if (aj[j] == i) {
1042: x[i] = aa[j];
1043: break;
1044: }
1045: }
1046: }
1047: VecRestoreArray(v,&x);
1048: return(0);
1049: }
1051: #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h>
1054: PetscErrorCode MatMultTransposeAdd_SeqAIJ(Mat A,Vec xx,Vec zz,Vec yy)
1055: {
1056: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1057: PetscScalar *x,*y;
1058: PetscErrorCode ierr;
1059: PetscInt m = A->rmap->n;
1060: #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
1061: MatScalar *v;
1062: PetscScalar alpha;
1063: PetscInt n,i,j,*idx,*ii,*ridx=PETSC_NULL;
1064: Mat_CompressedRow cprow = a->compressedrow;
1065: PetscBool usecprow = cprow.use;
1066: #endif
1069: if (zz != yy) {VecCopy(zz,yy);}
1070: VecGetArray(xx,&x);
1071: VecGetArray(yy,&y);
1073: #if defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
1074: fortranmulttransposeaddaij_(&m,x,a->i,a->j,a->a,y);
1075: #else
1076: if (usecprow){
1077: m = cprow.nrows;
1078: ii = cprow.i;
1079: ridx = cprow.rindex;
1080: } else {
1081: ii = a->i;
1082: }
1083: for (i=0; i<m; i++) {
1084: idx = a->j + ii[i] ;
1085: v = a->a + ii[i] ;
1086: n = ii[i+1] - ii[i];
1087: if (usecprow){
1088: alpha = x[ridx[i]];
1089: } else {
1090: alpha = x[i];
1091: }
1092: for (j=0; j<n; j++) y[idx[j]] += alpha*v[j];
1093: }
1094: #endif
1095: PetscLogFlops(2.0*a->nz);
1096: VecRestoreArray(xx,&x);
1097: VecRestoreArray(yy,&y);
1098: return(0);
1099: }
1103: PetscErrorCode MatMultTranspose_SeqAIJ(Mat A,Vec xx,Vec yy)
1104: {
1108: VecSet(yy,0.0);
1109: MatMultTransposeAdd_SeqAIJ(A,xx,yy,yy);
1110: return(0);
1111: }
1113: #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h>
1116: PetscErrorCode MatMult_SeqAIJ(Mat A,Vec xx,Vec yy)
1117: {
1118: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1119: PetscScalar *y;
1120: const PetscScalar *x;
1121: const MatScalar *aa;
1122: PetscErrorCode ierr;
1123: PetscInt m=A->rmap->n;
1124: const PetscInt *aj,*ii,*ridx=PETSC_NULL;
1125: PetscInt n,i,nonzerorow=0;
1126: PetscScalar sum;
1127: PetscBool usecprow=a->compressedrow.use;
1129: #if defined(PETSC_HAVE_PRAGMA_DISJOINT)
1130: #pragma disjoint(*x,*y,*aa)
1131: #endif
1134: VecGetArrayRead(xx,&x);
1135: VecGetArray(yy,&y);
1136: aj = a->j;
1137: aa = a->a;
1138: ii = a->i;
1139: if (usecprow){ /* use compressed row format */
1140: m = a->compressedrow.nrows;
1141: ii = a->compressedrow.i;
1142: ridx = a->compressedrow.rindex;
1143: for (i=0; i<m; i++){
1144: n = ii[i+1] - ii[i];
1145: aj = a->j + ii[i];
1146: aa = a->a + ii[i];
1147: sum = 0.0;
1148: nonzerorow += (n>0);
1149: PetscSparseDensePlusDot(sum,x,aa,aj,n);
1150: /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */
1151: y[*ridx++] = sum;
1152: }
1153: } else { /* do not use compressed row format */
1154: #if defined(PETSC_USE_FORTRAN_KERNEL_MULTAIJ)
1155: fortranmultaij_(&m,x,ii,aj,aa,y);
1156: #else
1157: for (i=0; i<m; i++) {
1158: n = ii[i+1] - ii[i];
1159: aj = a->j + ii[i];
1160: aa = a->a + ii[i];
1161: sum = 0.0;
1162: nonzerorow += (n>0);
1163: PetscSparseDensePlusDot(sum,x,aa,aj,n);
1164: y[i] = sum;
1165: }
1166: #endif
1167: }
1168: PetscLogFlops(2.0*a->nz - nonzerorow);
1169: VecRestoreArrayRead(xx,&x);
1170: VecRestoreArray(yy,&y);
1171: return(0);
1172: }
1174: #include <../src/mat/impls/aij/seq/ftn-kernels/fmultadd.h>
1177: PetscErrorCode MatMultAdd_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz)
1178: {
1179: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1180: PetscScalar *y,*z;
1181: const PetscScalar *x;
1182: const MatScalar *aa;
1183: PetscErrorCode ierr;
1184: PetscInt m = A->rmap->n,*aj,*ii;
1185: PetscInt n,i,*ridx=PETSC_NULL;
1186: PetscScalar sum;
1187: PetscBool usecprow=a->compressedrow.use;
1190: VecGetArrayRead(xx,&x);
1191: VecGetArray(yy,&y);
1192: if (zz != yy) {
1193: VecGetArray(zz,&z);
1194: } else {
1195: z = y;
1196: }
1198: aj = a->j;
1199: aa = a->a;
1200: ii = a->i;
1201: if (usecprow){ /* use compressed row format */
1202: if (zz != yy){
1203: PetscMemcpy(z,y,m*sizeof(PetscScalar));
1204: }
1205: m = a->compressedrow.nrows;
1206: ii = a->compressedrow.i;
1207: ridx = a->compressedrow.rindex;
1208: for (i=0; i<m; i++){
1209: n = ii[i+1] - ii[i];
1210: aj = a->j + ii[i];
1211: aa = a->a + ii[i];
1212: sum = y[*ridx];
1213: PetscSparseDensePlusDot(sum,x,aa,aj,n);
1214: z[*ridx++] = sum;
1215: }
1216: } else { /* do not use compressed row format */
1217: #if defined(PETSC_USE_FORTRAN_KERNEL_MULTADDAIJ)
1218: fortranmultaddaij_(&m,x,ii,aj,aa,y,z);
1219: #else
1220: for (i=0; i<m; i++) {
1221: n = ii[i+1] - ii[i];
1222: aj = a->j + ii[i];
1223: aa = a->a + ii[i];
1224: sum = y[i];
1225: PetscSparseDensePlusDot(sum,x,aa,aj,n);
1226: z[i] = sum;
1227: }
1228: #endif
1229: }
1230: PetscLogFlops(2.0*a->nz);
1231: VecRestoreArrayRead(xx,&x);
1232: VecRestoreArray(yy,&y);
1233: if (zz != yy) {
1234: VecRestoreArray(zz,&z);
1235: }
1236: #if defined(PETSC_HAVE_CUSP)
1237: /*
1238: VecView(xx,0);
1239: VecView(zz,0);
1240: MatView(A,0);
1241: */
1242: #endif
1243: return(0);
1244: }
1246: /*
1247: Adds diagonal pointers to sparse matrix structure.
1248: */
1251: PetscErrorCode MatMarkDiagonal_SeqAIJ(Mat A)
1252: {
1253: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1255: PetscInt i,j,m = A->rmap->n;
1258: if (!a->diag) {
1259: PetscMalloc(m*sizeof(PetscInt),&a->diag);
1260: PetscLogObjectMemory(A, m*sizeof(PetscInt));
1261: }
1262: for (i=0; i<A->rmap->n; i++) {
1263: a->diag[i] = a->i[i+1];
1264: for (j=a->i[i]; j<a->i[i+1]; j++) {
1265: if (a->j[j] == i) {
1266: a->diag[i] = j;
1267: break;
1268: }
1269: }
1270: }
1271: return(0);
1272: }
1274: /*
1275: Checks for missing diagonals
1276: */
1279: PetscErrorCode MatMissingDiagonal_SeqAIJ(Mat A,PetscBool *missing,PetscInt *d)
1280: {
1281: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1282: PetscInt *diag,*jj = a->j,i;
1285: *missing = PETSC_FALSE;
1286: if (A->rmap->n > 0 && !jj) {
1287: *missing = PETSC_TRUE;
1288: if (d) *d = 0;
1289: PetscInfo(A,"Matrix has no entries therefore is missing diagonal");
1290: } else {
1291: diag = a->diag;
1292: for (i=0; i<A->rmap->n; i++) {
1293: if (jj[diag[i]] != i) {
1294: *missing = PETSC_TRUE;
1295: if (d) *d = i;
1296: PetscInfo1(A,"Matrix is missing diagonal number %D",i);
1297: break;
1298: }
1299: }
1300: }
1301: return(0);
1302: }
1304: EXTERN_C_BEGIN
1307: PetscErrorCode MatInvertDiagonal_SeqAIJ(Mat A,PetscScalar omega,PetscScalar fshift)
1308: {
1309: Mat_SeqAIJ *a = (Mat_SeqAIJ*) A->data;
1311: PetscInt i,*diag,m = A->rmap->n;
1312: MatScalar *v = a->a;
1313: PetscScalar *idiag,*mdiag;
1316: if (a->idiagvalid) return(0);
1317: MatMarkDiagonal_SeqAIJ(A);
1318: diag = a->diag;
1319: if (!a->idiag) {
1320: PetscMalloc3(m,PetscScalar,&a->idiag,m,PetscScalar,&a->mdiag,m,PetscScalar,&a->ssor_work);
1321: PetscLogObjectMemory(A, 3*m*sizeof(PetscScalar));
1322: v = a->a;
1323: }
1324: mdiag = a->mdiag;
1325: idiag = a->idiag;
1326:
1327: if (omega == 1.0 && !PetscAbsScalar(fshift)) {
1328: for (i=0; i<m; i++) {
1329: mdiag[i] = v[diag[i]];
1330: if (!PetscAbsScalar(mdiag[i])) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Zero diagonal on row %D",i);
1331: idiag[i] = 1.0/v[diag[i]];
1332: }
1333: PetscLogFlops(m);
1334: } else {
1335: for (i=0; i<m; i++) {
1336: mdiag[i] = v[diag[i]];
1337: idiag[i] = omega/(fshift + v[diag[i]]);
1338: }
1339: PetscLogFlops(2.0*m);
1340: }
1341: a->idiagvalid = PETSC_TRUE;
1342: return(0);
1343: }
1344: EXTERN_C_END
1346: #include <../src/mat/impls/aij/seq/ftn-kernels/frelax.h>
1349: PetscErrorCode MatSOR_SeqAIJ(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx)
1350: {
1351: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1352: PetscScalar *x,d,sum,*t,scale;
1353: const MatScalar *v = a->a,*idiag=0,*mdiag;
1354: const PetscScalar *b, *bs,*xb, *ts;
1355: PetscErrorCode ierr;
1356: PetscInt n = A->cmap->n,m = A->rmap->n,i;
1357: const PetscInt *idx,*diag;
1360: its = its*lits;
1362: if (fshift != a->fshift || omega != a->omega) a->idiagvalid = PETSC_FALSE; /* must recompute idiag[] */
1363: if (!a->idiagvalid) {MatInvertDiagonal_SeqAIJ(A,omega,fshift);}
1364: a->fshift = fshift;
1365: a->omega = omega;
1367: diag = a->diag;
1368: t = a->ssor_work;
1369: idiag = a->idiag;
1370: mdiag = a->mdiag;
1372: VecGetArray(xx,&x);
1373: VecGetArrayRead(bb,&b);
1374: CHKMEMQ;
1375: /* We count flops by assuming the upper triangular and lower triangular parts have the same number of nonzeros */
1376: if (flag == SOR_APPLY_UPPER) {
1377: /* apply (U + D/omega) to the vector */
1378: bs = b;
1379: for (i=0; i<m; i++) {
1380: d = fshift + mdiag[i];
1381: n = a->i[i+1] - diag[i] - 1;
1382: idx = a->j + diag[i] + 1;
1383: v = a->a + diag[i] + 1;
1384: sum = b[i]*d/omega;
1385: PetscSparseDensePlusDot(sum,bs,v,idx,n);
1386: x[i] = sum;
1387: }
1388: VecRestoreArray(xx,&x);
1389: VecRestoreArrayRead(bb,&b);
1390: PetscLogFlops(a->nz);
1391: return(0);
1392: }
1394: if (flag == SOR_APPLY_LOWER) {
1395: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"SOR_APPLY_LOWER is not implemented");
1396: } else if (flag & SOR_EISENSTAT) {
1397: /* Let A = L + U + D; where L is lower trianglar,
1398: U is upper triangular, E = D/omega; This routine applies
1400: (L + E)^{-1} A (U + E)^{-1}
1402: to a vector efficiently using Eisenstat's trick.
1403: */
1404: scale = (2.0/omega) - 1.0;
1406: /* x = (E + U)^{-1} b */
1407: for (i=m-1; i>=0; i--) {
1408: n = a->i[i+1] - diag[i] - 1;
1409: idx = a->j + diag[i] + 1;
1410: v = a->a + diag[i] + 1;
1411: sum = b[i];
1412: PetscSparseDenseMinusDot(sum,x,v,idx,n);
1413: x[i] = sum*idiag[i];
1414: }
1416: /* t = b - (2*E - D)x */
1417: v = a->a;
1418: for (i=0; i<m; i++) { t[i] = b[i] - scale*(v[*diag++])*x[i]; }
1420: /* t = (E + L)^{-1}t */
1421: ts = t;
1422: diag = a->diag;
1423: for (i=0; i<m; i++) {
1424: n = diag[i] - a->i[i];
1425: idx = a->j + a->i[i];
1426: v = a->a + a->i[i];
1427: sum = t[i];
1428: PetscSparseDenseMinusDot(sum,ts,v,idx,n);
1429: t[i] = sum*idiag[i];
1430: /* x = x + t */
1431: x[i] += t[i];
1432: }
1434: PetscLogFlops(6.0*m-1 + 2.0*a->nz);
1435: VecRestoreArray(xx,&x);
1436: VecRestoreArrayRead(bb,&b);
1437: return(0);
1438: }
1439: if (flag & SOR_ZERO_INITIAL_GUESS) {
1440: if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){
1441: for (i=0; i<m; i++) {
1442: n = diag[i] - a->i[i];
1443: idx = a->j + a->i[i];
1444: v = a->a + a->i[i];
1445: sum = b[i];
1446: PetscSparseDenseMinusDot(sum,x,v,idx,n);
1447: t[i] = sum;
1448: x[i] = sum*idiag[i];
1449: }
1450: xb = t;
1451: PetscLogFlops(a->nz);
1452: } else xb = b;
1453: if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){
1454: for (i=m-1; i>=0; i--) {
1455: n = a->i[i+1] - diag[i] - 1;
1456: idx = a->j + diag[i] + 1;
1457: v = a->a + diag[i] + 1;
1458: sum = xb[i];
1459: PetscSparseDenseMinusDot(sum,x,v,idx,n);
1460: if (xb == b) {
1461: x[i] = sum*idiag[i];
1462: } else {
1463: x[i] = (1-omega)*x[i] + sum*idiag[i];
1464: }
1465: }
1466: PetscLogFlops(a->nz);
1467: }
1468: its--;
1469: }
1470: while (its--) {
1471: if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){
1472: for (i=0; i<m; i++) {
1473: n = a->i[i+1] - a->i[i];
1474: idx = a->j + a->i[i];
1475: v = a->a + a->i[i];
1476: sum = b[i];
1477: PetscSparseDenseMinusDot(sum,x,v,idx,n);
1478: x[i] = (1. - omega)*x[i] + (sum + mdiag[i]*x[i])*idiag[i];
1479: }
1480: PetscLogFlops(2.0*a->nz);
1481: }
1482: if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){
1483: for (i=m-1; i>=0; i--) {
1484: n = a->i[i+1] - a->i[i];
1485: idx = a->j + a->i[i];
1486: v = a->a + a->i[i];
1487: sum = b[i];
1488: PetscSparseDenseMinusDot(sum,x,v,idx,n);
1489: x[i] = (1. - omega)*x[i] + (sum + mdiag[i]*x[i])*idiag[i];
1490: }
1491: PetscLogFlops(2.0*a->nz);
1492: }
1493: }
1494: VecRestoreArray(xx,&x);
1495: VecRestoreArrayRead(bb,&b);
1496: CHKMEMQ; return(0);
1497: }
1502: PetscErrorCode MatGetInfo_SeqAIJ(Mat A,MatInfoType flag,MatInfo *info)
1503: {
1504: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1507: info->block_size = 1.0;
1508: info->nz_allocated = (double)a->maxnz;
1509: info->nz_used = (double)a->nz;
1510: info->nz_unneeded = (double)(a->maxnz - a->nz);
1511: info->assemblies = (double)A->num_ass;
1512: info->mallocs = (double)A->info.mallocs;
1513: info->memory = ((PetscObject)A)->mem;
1514: if (A->factortype) {
1515: info->fill_ratio_given = A->info.fill_ratio_given;
1516: info->fill_ratio_needed = A->info.fill_ratio_needed;
1517: info->factor_mallocs = A->info.factor_mallocs;
1518: } else {
1519: info->fill_ratio_given = 0;
1520: info->fill_ratio_needed = 0;
1521: info->factor_mallocs = 0;
1522: }
1523: return(0);
1524: }
1528: PetscErrorCode MatZeroRows_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
1529: {
1530: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1531: PetscInt i,m = A->rmap->n - 1,d = 0;
1532: PetscErrorCode ierr;
1533: const PetscScalar *xx;
1534: PetscScalar *bb;
1535: PetscBool missing;
1538: if (x && b) {
1539: VecGetArrayRead(x,&xx);
1540: VecGetArray(b,&bb);
1541: for (i=0; i<N; i++) {
1542: if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
1543: bb[rows[i]] = diag*xx[rows[i]];
1544: }
1545: VecRestoreArrayRead(x,&xx);
1546: VecRestoreArray(b,&bb);
1547: }
1549: if (a->keepnonzeropattern) {
1550: for (i=0; i<N; i++) {
1551: if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
1552: PetscMemzero(&a->a[a->i[rows[i]]],a->ilen[rows[i]]*sizeof(PetscScalar));
1553: }
1554: if (diag != 0.0) {
1555: MatMissingDiagonal_SeqAIJ(A,&missing,&d);
1556: if (missing) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Matrix is missing diagonal entry in row %D",d);
1557: for (i=0; i<N; i++) {
1558: a->a[a->diag[rows[i]]] = diag;
1559: }
1560: }
1561: A->same_nonzero = PETSC_TRUE;
1562: } else {
1563: if (diag != 0.0) {
1564: for (i=0; i<N; i++) {
1565: if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
1566: if (a->ilen[rows[i]] > 0) {
1567: a->ilen[rows[i]] = 1;
1568: a->a[a->i[rows[i]]] = diag;
1569: a->j[a->i[rows[i]]] = rows[i];
1570: } else { /* in case row was completely empty */
1571: MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES);
1572: }
1573: }
1574: } else {
1575: for (i=0; i<N; i++) {
1576: if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
1577: a->ilen[rows[i]] = 0;
1578: }
1579: }
1580: A->same_nonzero = PETSC_FALSE;
1581: }
1582: MatAssemblyEnd_SeqAIJ(A,MAT_FINAL_ASSEMBLY);
1583: return(0);
1584: }
1588: PetscErrorCode MatZeroRowsColumns_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
1589: {
1590: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1591: PetscInt i,j,m = A->rmap->n - 1,d = 0;
1592: PetscErrorCode ierr;
1593: PetscBool missing,*zeroed,vecs = PETSC_FALSE;
1594: const PetscScalar *xx;
1595: PetscScalar *bb;
1598: if (x && b) {
1599: VecGetArrayRead(x,&xx);
1600: VecGetArray(b,&bb);
1601: vecs = PETSC_TRUE;
1602: }
1603: PetscMalloc(A->rmap->n*sizeof(PetscBool),&zeroed);
1604: PetscMemzero(zeroed,A->rmap->n*sizeof(PetscBool));
1605: for (i=0; i<N; i++) {
1606: if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
1607: PetscMemzero(&a->a[a->i[rows[i]]],a->ilen[rows[i]]*sizeof(PetscScalar));
1608: zeroed[rows[i]] = PETSC_TRUE;
1609: }
1610: for (i=0; i<A->rmap->n; i++) {
1611: if (!zeroed[i]) {
1612: for (j=a->i[i]; j<a->i[i+1]; j++) {
1613: if (zeroed[a->j[j]]) {
1614: if (vecs) bb[i] -= a->a[j]*xx[a->j[j]];
1615: a->a[j] = 0.0;
1616: }
1617: }
1618: } else if (vecs) bb[i] = diag*xx[i];
1619: }
1620: if (x && b) {
1621: VecRestoreArrayRead(x,&xx);
1622: VecRestoreArray(b,&bb);
1623: }
1624: PetscFree(zeroed);
1625: if (diag != 0.0) {
1626: MatMissingDiagonal_SeqAIJ(A,&missing,&d);
1627: if (missing) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Matrix is missing diagonal entry in row %D",d);
1628: for (i=0; i<N; i++) {
1629: a->a[a->diag[rows[i]]] = diag;
1630: }
1631: }
1632: A->same_nonzero = PETSC_TRUE;
1633: MatAssemblyEnd_SeqAIJ(A,MAT_FINAL_ASSEMBLY);
1634: return(0);
1635: }
1639: PetscErrorCode MatGetRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
1640: {
1641: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1642: PetscInt *itmp;
1645: if (row < 0 || row >= A->rmap->n) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row %D out of range",row);
1647: *nz = a->i[row+1] - a->i[row];
1648: if (v) *v = a->a + a->i[row];
1649: if (idx) {
1650: itmp = a->j + a->i[row];
1651: if (*nz) {
1652: *idx = itmp;
1653: }
1654: else *idx = 0;
1655: }
1656: return(0);
1657: }
1659: /* remove this function? */
1662: PetscErrorCode MatRestoreRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
1663: {
1665: return(0);
1666: }
1670: PetscErrorCode MatNorm_SeqAIJ(Mat A,NormType type,PetscReal *nrm)
1671: {
1672: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1673: MatScalar *v = a->a;
1674: PetscReal sum = 0.0;
1676: PetscInt i,j;
1679: if (type == NORM_FROBENIUS) {
1680: for (i=0; i<a->nz; i++) {
1681: #if defined(PETSC_USE_COMPLEX)
1682: sum += PetscRealPart(PetscConj(*v)*(*v)); v++;
1683: #else
1684: sum += (*v)*(*v); v++;
1685: #endif
1686: }
1687: *nrm = PetscSqrtReal(sum);
1688: } else if (type == NORM_1) {
1689: PetscReal *tmp;
1690: PetscInt *jj = a->j;
1691: PetscMalloc((A->cmap->n+1)*sizeof(PetscReal),&tmp);
1692: PetscMemzero(tmp,A->cmap->n*sizeof(PetscReal));
1693: *nrm = 0.0;
1694: for (j=0; j<a->nz; j++) {
1695: tmp[*jj++] += PetscAbsScalar(*v); v++;
1696: }
1697: for (j=0; j<A->cmap->n; j++) {
1698: if (tmp[j] > *nrm) *nrm = tmp[j];
1699: }
1700: PetscFree(tmp);
1701: } else if (type == NORM_INFINITY) {
1702: *nrm = 0.0;
1703: for (j=0; j<A->rmap->n; j++) {
1704: v = a->a + a->i[j];
1705: sum = 0.0;
1706: for (i=0; i<a->i[j+1]-a->i[j]; i++) {
1707: sum += PetscAbsScalar(*v); v++;
1708: }
1709: if (sum > *nrm) *nrm = sum;
1710: }
1711: } else {
1712: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for two norm");
1713: }
1714: return(0);
1715: }
1717: /* Merged from MatGetSymbolicTranspose_SeqAIJ() - replace MatGetSymbolicTranspose_SeqAIJ()? */
1720: PetscErrorCode MatTransposeSymbolic_SeqAIJ(Mat A,Mat *B)
1721: {
1723: PetscInt i,j,anzj;
1724: Mat_SeqAIJ *a=(Mat_SeqAIJ *)A->data,*b;
1725: PetscInt an=A->cmap->N,am=A->rmap->N;
1726: PetscInt *ati,*atj,*atfill,*ai=a->i,*aj=a->j;
1729: /* Allocate space for symbolic transpose info and work array */
1730: PetscMalloc((an+1)*sizeof(PetscInt),&ati);
1731: PetscMalloc(ai[am]*sizeof(PetscInt),&atj);
1732: PetscMalloc(an*sizeof(PetscInt),&atfill);
1733: PetscMemzero(ati,(an+1)*sizeof(PetscInt));
1735: /* Walk through aj and count ## of non-zeros in each row of A^T. */
1736: /* Note: offset by 1 for fast conversion into csr format. */
1737: for (i=0;i<ai[am];i++) {
1738: ati[aj[i]+1] += 1;
1739: }
1740: /* Form ati for csr format of A^T. */
1741: for (i=0;i<an;i++) {
1742: ati[i+1] += ati[i];
1743: }
1745: /* Copy ati into atfill so we have locations of the next free space in atj */
1746: PetscMemcpy(atfill,ati,an*sizeof(PetscInt));
1748: /* Walk through A row-wise and mark nonzero entries of A^T. */
1749: for (i=0;i<am;i++) {
1750: anzj = ai[i+1] - ai[i];
1751: for (j=0;j<anzj;j++) {
1752: atj[atfill[*aj]] = i;
1753: atfill[*aj++] += 1;
1754: }
1755: }
1757: /* Clean up temporary space and complete requests. */
1758: PetscFree(atfill);
1759: MatCreateSeqAIJWithArrays(((PetscObject)A)->comm,an,am,ati,atj,PETSC_NULL,B);
1760: (*B)->rmap->bs = A->cmap->bs;
1761: (*B)->cmap->bs = A->rmap->bs;
1763: b = (Mat_SeqAIJ *)((*B)->data);
1764: b->free_a = PETSC_FALSE;
1765: b->free_ij = PETSC_TRUE;
1766: b->nonew = 0;
1767: return(0);
1768: }
1772: PetscErrorCode MatTranspose_SeqAIJ(Mat A,MatReuse reuse,Mat *B)
1773: {
1774: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1775: Mat C;
1777: PetscInt i,*aj = a->j,*ai = a->i,m = A->rmap->n,len,*col;
1778: MatScalar *array = a->a;
1781: 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");
1783: if (reuse == MAT_INITIAL_MATRIX || *B == A) {
1784: PetscMalloc((1+A->cmap->n)*sizeof(PetscInt),&col);
1785: PetscMemzero(col,(1+A->cmap->n)*sizeof(PetscInt));
1786:
1787: for (i=0; i<ai[m]; i++) col[aj[i]] += 1;
1788: MatCreate(((PetscObject)A)->comm,&C);
1789: MatSetSizes(C,A->cmap->n,m,A->cmap->n,m);
1790: MatSetBlockSizes(C,A->cmap->bs,A->rmap->bs);
1791: MatSetType(C,((PetscObject)A)->type_name);
1792: MatSeqAIJSetPreallocation_SeqAIJ(C,0,col);
1793: PetscFree(col);
1794: } else {
1795: C = *B;
1796: }
1798: for (i=0; i<m; i++) {
1799: len = ai[i+1]-ai[i];
1800: MatSetValues_SeqAIJ(C,len,aj,1,&i,array,INSERT_VALUES);
1801: array += len;
1802: aj += len;
1803: }
1804: MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);
1805: MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);
1807: if (reuse == MAT_INITIAL_MATRIX || *B != A) {
1808: *B = C;
1809: } else {
1810: MatHeaderMerge(A,C);
1811: }
1812: return(0);
1813: }
1815: EXTERN_C_BEGIN
1818: PetscErrorCode MatIsTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool *f)
1819: {
1820: Mat_SeqAIJ *aij = (Mat_SeqAIJ *) A->data,*bij = (Mat_SeqAIJ*) A->data;
1821: PetscInt *adx,*bdx,*aii,*bii,*aptr,*bptr;
1822: MatScalar *va,*vb;
1824: PetscInt ma,na,mb,nb, i;
1827: bij = (Mat_SeqAIJ *) B->data;
1829: MatGetSize(A,&ma,&na);
1830: MatGetSize(B,&mb,&nb);
1831: if (ma!=nb || na!=mb){
1832: *f = PETSC_FALSE;
1833: return(0);
1834: }
1835: aii = aij->i; bii = bij->i;
1836: adx = aij->j; bdx = bij->j;
1837: va = aij->a; vb = bij->a;
1838: PetscMalloc(ma*sizeof(PetscInt),&aptr);
1839: PetscMalloc(mb*sizeof(PetscInt),&bptr);
1840: for (i=0; i<ma; i++) aptr[i] = aii[i];
1841: for (i=0; i<mb; i++) bptr[i] = bii[i];
1843: *f = PETSC_TRUE;
1844: for (i=0; i<ma; i++) {
1845: while (aptr[i]<aii[i+1]) {
1846: PetscInt idc,idr;
1847: PetscScalar vc,vr;
1848: /* column/row index/value */
1849: idc = adx[aptr[i]];
1850: idr = bdx[bptr[idc]];
1851: vc = va[aptr[i]];
1852: vr = vb[bptr[idc]];
1853: if (i!=idr || PetscAbsScalar(vc-vr) > tol) {
1854: *f = PETSC_FALSE;
1855: goto done;
1856: } else {
1857: aptr[i]++;
1858: if (B || i!=idc) bptr[idc]++;
1859: }
1860: }
1861: }
1862: done:
1863: PetscFree(aptr);
1864: PetscFree(bptr);
1865: return(0);
1866: }
1867: EXTERN_C_END
1869: EXTERN_C_BEGIN
1872: PetscErrorCode MatIsHermitianTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool *f)
1873: {
1874: Mat_SeqAIJ *aij = (Mat_SeqAIJ *) A->data,*bij = (Mat_SeqAIJ*) A->data;
1875: PetscInt *adx,*bdx,*aii,*bii,*aptr,*bptr;
1876: MatScalar *va,*vb;
1878: PetscInt ma,na,mb,nb, i;
1881: bij = (Mat_SeqAIJ *) B->data;
1883: MatGetSize(A,&ma,&na);
1884: MatGetSize(B,&mb,&nb);
1885: if (ma!=nb || na!=mb){
1886: *f = PETSC_FALSE;
1887: return(0);
1888: }
1889: aii = aij->i; bii = bij->i;
1890: adx = aij->j; bdx = bij->j;
1891: va = aij->a; vb = bij->a;
1892: PetscMalloc(ma*sizeof(PetscInt),&aptr);
1893: PetscMalloc(mb*sizeof(PetscInt),&bptr);
1894: for (i=0; i<ma; i++) aptr[i] = aii[i];
1895: for (i=0; i<mb; i++) bptr[i] = bii[i];
1897: *f = PETSC_TRUE;
1898: for (i=0; i<ma; i++) {
1899: while (aptr[i]<aii[i+1]) {
1900: PetscInt idc,idr;
1901: PetscScalar vc,vr;
1902: /* column/row index/value */
1903: idc = adx[aptr[i]];
1904: idr = bdx[bptr[idc]];
1905: vc = va[aptr[i]];
1906: vr = vb[bptr[idc]];
1907: if (i!=idr || PetscAbsScalar(vc-PetscConj(vr)) > tol) {
1908: *f = PETSC_FALSE;
1909: goto done;
1910: } else {
1911: aptr[i]++;
1912: if (B || i!=idc) bptr[idc]++;
1913: }
1914: }
1915: }
1916: done:
1917: PetscFree(aptr);
1918: PetscFree(bptr);
1919: return(0);
1920: }
1921: EXTERN_C_END
1925: PetscErrorCode MatIsSymmetric_SeqAIJ(Mat A,PetscReal tol,PetscBool *f)
1926: {
1929: MatIsTranspose_SeqAIJ(A,A,tol,f);
1930: return(0);
1931: }
1935: PetscErrorCode MatIsHermitian_SeqAIJ(Mat A,PetscReal tol,PetscBool *f)
1936: {
1939: MatIsHermitianTranspose_SeqAIJ(A,A,tol,f);
1940: return(0);
1941: }
1945: PetscErrorCode MatDiagonalScale_SeqAIJ(Mat A,Vec ll,Vec rr)
1946: {
1947: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1948: PetscScalar *l,*r,x;
1949: MatScalar *v;
1951: PetscInt i,j,m = A->rmap->n,n = A->cmap->n,M,nz = a->nz,*jj;
1954: if (ll) {
1955: /* The local size is used so that VecMPI can be passed to this routine
1956: by MatDiagonalScale_MPIAIJ */
1957: VecGetLocalSize(ll,&m);
1958: if (m != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Left scaling vector wrong length");
1959: VecGetArray(ll,&l);
1960: v = a->a;
1961: for (i=0; i<m; i++) {
1962: x = l[i];
1963: M = a->i[i+1] - a->i[i];
1964: for (j=0; j<M; j++) { (*v++) *= x;}
1965: }
1966: VecRestoreArray(ll,&l);
1967: PetscLogFlops(nz);
1968: }
1969: if (rr) {
1970: VecGetLocalSize(rr,&n);
1971: if (n != A->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Right scaling vector wrong length");
1972: VecGetArray(rr,&r);
1973: v = a->a; jj = a->j;
1974: for (i=0; i<nz; i++) {
1975: (*v++) *= r[*jj++];
1976: }
1977: VecRestoreArray(rr,&r);
1978: PetscLogFlops(nz);
1979: }
1980: a->idiagvalid = PETSC_FALSE;
1981: a->ibdiagvalid = PETSC_FALSE;
1982: return(0);
1983: }
1987: PetscErrorCode MatGetSubMatrix_SeqAIJ(Mat A,IS isrow,IS iscol,PetscInt csize,MatReuse scall,Mat *B)
1988: {
1989: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data,*c;
1991: PetscInt *smap,i,k,kstart,kend,oldcols = A->cmap->n,*lens;
1992: PetscInt row,mat_i,*mat_j,tcol,first,step,*mat_ilen,sum,lensi;
1993: const PetscInt *irow,*icol;
1994: PetscInt nrows,ncols;
1995: PetscInt *starts,*j_new,*i_new,*aj = a->j,*ai = a->i,ii,*ailen = a->ilen;
1996: MatScalar *a_new,*mat_a;
1997: Mat C;
1998: PetscBool stride,sorted;
2001: ISSorted(isrow,&sorted);
2002: if (!sorted) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"ISrow is not sorted");
2003: ISSorted(iscol,&sorted);
2004: if (!sorted) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"IScol is not sorted");
2006: ISGetIndices(isrow,&irow);
2007: ISGetLocalSize(isrow,&nrows);
2008: ISGetLocalSize(iscol,&ncols);
2010: ISStrideGetInfo(iscol,&first,&step);
2011: PetscObjectTypeCompare((PetscObject)iscol,ISSTRIDE,&stride);
2012: if (stride && step == 1) {
2013: /* special case of contiguous rows */
2014: PetscMalloc2(nrows,PetscInt,&lens,nrows,PetscInt,&starts);
2015: /* loop over new rows determining lens and starting points */
2016: for (i=0; i<nrows; i++) {
2017: kstart = ai[irow[i]];
2018: kend = kstart + ailen[irow[i]];
2019: for (k=kstart; k<kend; k++) {
2020: if (aj[k] >= first) {
2021: starts[i] = k;
2022: break;
2023: }
2024: }
2025: sum = 0;
2026: while (k < kend) {
2027: if (aj[k++] >= first+ncols) break;
2028: sum++;
2029: }
2030: lens[i] = sum;
2031: }
2032: /* create submatrix */
2033: if (scall == MAT_REUSE_MATRIX) {
2034: PetscInt n_cols,n_rows;
2035: MatGetSize(*B,&n_rows,&n_cols);
2036: if (n_rows != nrows || n_cols != ncols) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Reused submatrix wrong size");
2037: MatZeroEntries(*B);
2038: C = *B;
2039: } else {
2040: PetscInt rbs,cbs;
2041: MatCreate(((PetscObject)A)->comm,&C);
2042: MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);
2043: ISGetBlockSize(isrow,&rbs);
2044: ISGetBlockSize(iscol,&cbs);
2045: MatSetBlockSizes(C,rbs,cbs);
2046: MatSetType(C,((PetscObject)A)->type_name);
2047: MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);
2048: }
2049: c = (Mat_SeqAIJ*)C->data;
2051: /* loop over rows inserting into submatrix */
2052: a_new = c->a;
2053: j_new = c->j;
2054: i_new = c->i;
2056: for (i=0; i<nrows; i++) {
2057: ii = starts[i];
2058: lensi = lens[i];
2059: for (k=0; k<lensi; k++) {
2060: *j_new++ = aj[ii+k] - first;
2061: }
2062: PetscMemcpy(a_new,a->a + starts[i],lensi*sizeof(PetscScalar));
2063: a_new += lensi;
2064: i_new[i+1] = i_new[i] + lensi;
2065: c->ilen[i] = lensi;
2066: }
2067: PetscFree2(lens,starts);
2068: } else {
2069: ISGetIndices(iscol,&icol);
2070: PetscMalloc(oldcols*sizeof(PetscInt),&smap);
2071: PetscMemzero(smap,oldcols*sizeof(PetscInt));
2072: PetscMalloc((1+nrows)*sizeof(PetscInt),&lens);
2073: for (i=0; i<ncols; i++) {
2074: #if defined(PETSC_USE_DEBUG)
2075: 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);
2076: #endif
2077: smap[icol[i]] = i+1;
2078: }
2080: /* determine lens of each row */
2081: for (i=0; i<nrows; i++) {
2082: kstart = ai[irow[i]];
2083: kend = kstart + a->ilen[irow[i]];
2084: lens[i] = 0;
2085: for (k=kstart; k<kend; k++) {
2086: if (smap[aj[k]]) {
2087: lens[i]++;
2088: }
2089: }
2090: }
2091: /* Create and fill new matrix */
2092: if (scall == MAT_REUSE_MATRIX) {
2093: PetscBool equal;
2095: c = (Mat_SeqAIJ *)((*B)->data);
2096: if ((*B)->rmap->n != nrows || (*B)->cmap->n != ncols) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong size");
2097: PetscMemcmp(c->ilen,lens,(*B)->rmap->n*sizeof(PetscInt),&equal);
2098: if (!equal) {
2099: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong no of nonzeros");
2100: }
2101: PetscMemzero(c->ilen,(*B)->rmap->n*sizeof(PetscInt));
2102: C = *B;
2103: } else {
2104: PetscInt rbs,cbs;
2105: MatCreate(((PetscObject)A)->comm,&C);
2106: MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);
2107: ISGetBlockSize(isrow,&rbs);
2108: ISGetBlockSize(iscol,&cbs);
2109: MatSetBlockSizes(C,rbs,cbs);
2110: MatSetType(C,((PetscObject)A)->type_name);
2111: MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);
2112: }
2113: c = (Mat_SeqAIJ *)(C->data);
2114: for (i=0; i<nrows; i++) {
2115: row = irow[i];
2116: kstart = ai[row];
2117: kend = kstart + a->ilen[row];
2118: mat_i = c->i[i];
2119: mat_j = c->j + mat_i;
2120: mat_a = c->a + mat_i;
2121: mat_ilen = c->ilen + i;
2122: for (k=kstart; k<kend; k++) {
2123: if ((tcol=smap[a->j[k]])) {
2124: *mat_j++ = tcol - 1;
2125: *mat_a++ = a->a[k];
2126: (*mat_ilen)++;
2128: }
2129: }
2130: }
2131: /* Free work space */
2132: ISRestoreIndices(iscol,&icol);
2133: PetscFree(smap);
2134: PetscFree(lens);
2135: }
2136: MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);
2137: MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);
2139: ISRestoreIndices(isrow,&irow);
2140: *B = C;
2141: return(0);
2142: }
2146: PetscErrorCode MatGetMultiProcBlock_SeqAIJ(Mat mat,MPI_Comm subComm,MatReuse scall,Mat* subMat)
2147: {
2149: Mat B;
2152: MatCreate(subComm,&B);
2153: MatSetSizes(B,mat->rmap->n,mat->cmap->n,mat->rmap->n,mat->cmap->n);
2154: MatSetBlockSizes(B,mat->rmap->bs,mat->cmap->bs);
2155: MatSetType(B,MATSEQAIJ);
2156: MatDuplicateNoCreate_SeqAIJ(B,mat,MAT_COPY_VALUES,PETSC_TRUE);
2157: *subMat = B;
2158: return(0);
2159: }
2163: PetscErrorCode MatILUFactor_SeqAIJ(Mat inA,IS row,IS col,const MatFactorInfo *info)
2164: {
2165: Mat_SeqAIJ *a = (Mat_SeqAIJ*)inA->data;
2167: Mat outA;
2168: PetscBool row_identity,col_identity;
2171: if (info->levels != 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only levels=0 supported for in-place ilu");
2173: ISIdentity(row,&row_identity);
2174: ISIdentity(col,&col_identity);
2176: outA = inA;
2177: outA->factortype = MAT_FACTOR_LU;
2178: PetscObjectReference((PetscObject)row);
2179: ISDestroy(&a->row);
2180: a->row = row;
2181: PetscObjectReference((PetscObject)col);
2182: ISDestroy(&a->col);
2183: a->col = col;
2185: /* Create the inverse permutation so that it can be used in MatLUFactorNumeric() */
2186: ISDestroy(&a->icol);
2187: ISInvertPermutation(col,PETSC_DECIDE,&a->icol);
2188: PetscLogObjectParent(inA,a->icol);
2190: if (!a->solve_work) { /* this matrix may have been factored before */
2191: PetscMalloc((inA->rmap->n+1)*sizeof(PetscScalar),&a->solve_work);
2192: PetscLogObjectMemory(inA, (inA->rmap->n+1)*sizeof(PetscScalar));
2193: }
2195: MatMarkDiagonal_SeqAIJ(inA);
2196: if (row_identity && col_identity) {
2197: MatLUFactorNumeric_SeqAIJ_inplace(outA,inA,info);
2198: } else {
2199: MatLUFactorNumeric_SeqAIJ_InplaceWithPerm(outA,inA,info);
2200: }
2201: return(0);
2202: }
2206: PetscErrorCode MatScale_SeqAIJ(Mat inA,PetscScalar alpha)
2207: {
2208: Mat_SeqAIJ *a = (Mat_SeqAIJ*)inA->data;
2209: PetscScalar oalpha = alpha;
2211: PetscBLASInt one = 1,bnz = PetscBLASIntCast(a->nz);
2214: BLASscal_(&bnz,&oalpha,a->a,&one);
2215: PetscLogFlops(a->nz);
2216: a->idiagvalid = PETSC_FALSE;
2217: a->ibdiagvalid = PETSC_FALSE;
2218: return(0);
2219: }
2223: PetscErrorCode MatGetSubMatrices_SeqAIJ(Mat A,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *B[])
2224: {
2226: PetscInt i;
2229: if (scall == MAT_INITIAL_MATRIX) {
2230: PetscMalloc((n+1)*sizeof(Mat),B);
2231: }
2233: for (i=0; i<n; i++) {
2234: MatGetSubMatrix_SeqAIJ(A,irow[i],icol[i],PETSC_DECIDE,scall,&(*B)[i]);
2235: }
2236: return(0);
2237: }
2241: PetscErrorCode MatIncreaseOverlap_SeqAIJ(Mat A,PetscInt is_max,IS is[],PetscInt ov)
2242: {
2243: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
2245: PetscInt row,i,j,k,l,m,n,*nidx,isz,val;
2246: const PetscInt *idx;
2247: PetscInt start,end,*ai,*aj;
2248: PetscBT table;
2251: m = A->rmap->n;
2252: ai = a->i;
2253: aj = a->j;
2255: if (ov < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"illegal negative overlap value used");
2257: PetscMalloc((m+1)*sizeof(PetscInt),&nidx);
2258: PetscBTCreate(m,&table);
2260: for (i=0; i<is_max; i++) {
2261: /* Initialize the two local arrays */
2262: isz = 0;
2263: PetscBTMemzero(m,table);
2264:
2265: /* Extract the indices, assume there can be duplicate entries */
2266: ISGetIndices(is[i],&idx);
2267: ISGetLocalSize(is[i],&n);
2268:
2269: /* Enter these into the temp arrays. I.e., mark table[row], enter row into new index */
2270: for (j=0; j<n ; ++j){
2271: if(!PetscBTLookupSet(table,idx[j])) { nidx[isz++] = idx[j];}
2272: }
2273: ISRestoreIndices(is[i],&idx);
2274: ISDestroy(&is[i]);
2275:
2276: k = 0;
2277: for (j=0; j<ov; j++){ /* for each overlap */
2278: n = isz;
2279: for (; k<n ; k++){ /* do only those rows in nidx[k], which are not done yet */
2280: row = nidx[k];
2281: start = ai[row];
2282: end = ai[row+1];
2283: for (l = start; l<end ; l++){
2284: val = aj[l] ;
2285: if (!PetscBTLookupSet(table,val)) {nidx[isz++] = val;}
2286: }
2287: }
2288: }
2289: ISCreateGeneral(PETSC_COMM_SELF,isz,nidx,PETSC_COPY_VALUES,(is+i));
2290: }
2291: PetscBTDestroy(&table);
2292: PetscFree(nidx);
2293: return(0);
2294: }
2296: /* -------------------------------------------------------------- */
2299: PetscErrorCode MatPermute_SeqAIJ(Mat A,IS rowp,IS colp,Mat *B)
2300: {
2301: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
2303: PetscInt i,nz = 0,m = A->rmap->n,n = A->cmap->n;
2304: const PetscInt *row,*col;
2305: PetscInt *cnew,j,*lens;
2306: IS icolp,irowp;
2307: PetscInt *cwork = PETSC_NULL;
2308: PetscScalar *vwork = PETSC_NULL;
2311: ISInvertPermutation(rowp,PETSC_DECIDE,&irowp);
2312: ISGetIndices(irowp,&row);
2313: ISInvertPermutation(colp,PETSC_DECIDE,&icolp);
2314: ISGetIndices(icolp,&col);
2315:
2316: /* determine lengths of permuted rows */
2317: PetscMalloc((m+1)*sizeof(PetscInt),&lens);
2318: for (i=0; i<m; i++) {
2319: lens[row[i]] = a->i[i+1] - a->i[i];
2320: }
2321: MatCreate(((PetscObject)A)->comm,B);
2322: MatSetSizes(*B,m,n,m,n);
2323: MatSetBlockSizes(*B,A->rmap->bs,A->cmap->bs);
2324: MatSetType(*B,((PetscObject)A)->type_name);
2325: MatSeqAIJSetPreallocation_SeqAIJ(*B,0,lens);
2326: PetscFree(lens);
2328: PetscMalloc(n*sizeof(PetscInt),&cnew);
2329: for (i=0; i<m; i++) {
2330: MatGetRow_SeqAIJ(A,i,&nz,&cwork,&vwork);
2331: for (j=0; j<nz; j++) { cnew[j] = col[cwork[j]];}
2332: MatSetValues_SeqAIJ(*B,1,&row[i],nz,cnew,vwork,INSERT_VALUES);
2333: MatRestoreRow_SeqAIJ(A,i,&nz,&cwork,&vwork);
2334: }
2335: PetscFree(cnew);
2336: (*B)->assembled = PETSC_FALSE;
2337: MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);
2338: MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);
2339: ISRestoreIndices(irowp,&row);
2340: ISRestoreIndices(icolp,&col);
2341: ISDestroy(&irowp);
2342: ISDestroy(&icolp);
2343: return(0);
2344: }
2348: PetscErrorCode MatCopy_SeqAIJ(Mat A,Mat B,MatStructure str)
2349: {
2353: /* If the two matrices have the same copy implementation, use fast copy. */
2354: if (str == SAME_NONZERO_PATTERN && (A->ops->copy == B->ops->copy)) {
2355: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
2356: Mat_SeqAIJ *b = (Mat_SeqAIJ*)B->data;
2358: 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");
2359: PetscMemcpy(b->a,a->a,(a->i[A->rmap->n])*sizeof(PetscScalar));
2360: } else {
2361: MatCopy_Basic(A,B,str);
2362: }
2363: return(0);
2364: }
2368: PetscErrorCode MatSetUp_SeqAIJ(Mat A)
2369: {
2373: MatSeqAIJSetPreallocation_SeqAIJ(A,PETSC_DEFAULT,0);
2374: return(0);
2375: }
2379: PetscErrorCode MatGetArray_SeqAIJ(Mat A,PetscScalar *array[])
2380: {
2381: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
2383: *array = a->a;
2384: return(0);
2385: }
2389: PetscErrorCode MatRestoreArray_SeqAIJ(Mat A,PetscScalar *array[])
2390: {
2392: return(0);
2393: }
2397: PetscErrorCode MatFDColoringApply_SeqAIJ(Mat J,MatFDColoring coloring,Vec x1,MatStructure *flag,void *sctx)
2398: {
2399: PetscErrorCode (*f)(void*,Vec,Vec,void*) = (PetscErrorCode (*)(void*,Vec,Vec,void *))coloring->f;
2401: PetscInt k,N,start,end,l,row,col,srow,**vscaleforrow,m1,m2;
2402: PetscScalar dx,*y,*xx,*w3_array;
2403: PetscScalar *vscale_array;
2404: PetscReal epsilon = coloring->error_rel,umin = coloring->umin;
2405: Vec w1,w2,w3;
2406: void *fctx = coloring->fctx;
2407: PetscBool flg = PETSC_FALSE;
2410: if (!coloring->w1) {
2411: VecDuplicate(x1,&coloring->w1);
2412: PetscLogObjectParent(coloring,coloring->w1);
2413: VecDuplicate(x1,&coloring->w2);
2414: PetscLogObjectParent(coloring,coloring->w2);
2415: VecDuplicate(x1,&coloring->w3);
2416: PetscLogObjectParent(coloring,coloring->w3);
2417: }
2418: w1 = coloring->w1; w2 = coloring->w2; w3 = coloring->w3;
2420: MatSetUnfactored(J);
2421: PetscOptionsGetBool(((PetscObject)coloring)->prefix,"-mat_fd_coloring_dont_rezero",&flg,PETSC_NULL);
2422: if (flg) {
2423: PetscInfo(coloring,"Not calling MatZeroEntries()\n");
2424: } else {
2425: PetscBool assembled;
2426: MatAssembled(J,&assembled);
2427: if (assembled) {
2428: MatZeroEntries(J);
2429: }
2430: }
2432: VecGetOwnershipRange(x1,&start,&end);
2433: VecGetSize(x1,&N);
2435: /*
2436: This is a horrible, horrible, hack.
2437: */
2438: if (coloring->F) {
2439: VecGetLocalSize(coloring->F,&m1);
2440: VecGetLocalSize(w1,&m2);
2441: if (m1 != m2) {
2442: coloring->F = 0;
2443: }
2444: }
2446: if (coloring->F) {
2447: w1 = coloring->F;
2448: coloring->F = 0;
2449: } else {
2450: PetscLogEventBegin(MAT_FDColoringFunction,0,0,0,0);
2451: (*f)(sctx,x1,w1,fctx);
2452: PetscLogEventEnd(MAT_FDColoringFunction,0,0,0,0);
2453: }
2455: /*
2456: Compute all the scale factors and share with other processors
2457: */
2458: VecGetArray(x1,&xx);xx = xx - start;
2459: VecGetArray(coloring->vscale,&vscale_array);vscale_array = vscale_array - start;
2460: for (k=0; k<coloring->ncolors; k++) {
2461: /*
2462: Loop over each column associated with color adding the
2463: perturbation to the vector w3.
2464: */
2465: for (l=0; l<coloring->ncolumns[k]; l++) {
2466: col = coloring->columns[k][l]; /* column of the matrix we are probing for */
2467: dx = xx[col];
2468: if (dx == 0.0) dx = 1.0;
2469: #if !defined(PETSC_USE_COMPLEX)
2470: if (dx < umin && dx >= 0.0) dx = umin;
2471: else if (dx < 0.0 && dx > -umin) dx = -umin;
2472: #else
2473: if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0) dx = umin;
2474: else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
2475: #endif
2476: dx *= epsilon;
2477: vscale_array[col] = 1.0/dx;
2478: }
2479: }
2480: vscale_array = vscale_array + start;VecRestoreArray(coloring->vscale,&vscale_array);
2481: VecGhostUpdateBegin(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);
2482: VecGhostUpdateEnd(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);
2484: /* VecView(coloring->vscale,PETSC_VIEWER_STDOUT_WORLD);
2485: VecView(x1,PETSC_VIEWER_STDOUT_WORLD);*/
2487: if (coloring->vscaleforrow) vscaleforrow = coloring->vscaleforrow;
2488: else vscaleforrow = coloring->columnsforrow;
2490: VecGetArray(coloring->vscale,&vscale_array);
2491: /*
2492: Loop over each color
2493: */
2494: for (k=0; k<coloring->ncolors; k++) {
2495: coloring->currentcolor = k;
2496: VecCopy(x1,w3);
2497: VecGetArray(w3,&w3_array);w3_array = w3_array - start;
2498: /*
2499: Loop over each column associated with color adding the
2500: perturbation to the vector w3.
2501: */
2502: for (l=0; l<coloring->ncolumns[k]; l++) {
2503: col = coloring->columns[k][l]; /* column of the matrix we are probing for */
2504: dx = xx[col];
2505: if (dx == 0.0) dx = 1.0;
2506: #if !defined(PETSC_USE_COMPLEX)
2507: if (dx < umin && dx >= 0.0) dx = umin;
2508: else if (dx < 0.0 && dx > -umin) dx = -umin;
2509: #else
2510: if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0) dx = umin;
2511: else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
2512: #endif
2513: dx *= epsilon;
2514: if (!PetscAbsScalar(dx)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Computed 0 differencing parameter");
2515: w3_array[col] += dx;
2516: }
2517: w3_array = w3_array + start; VecRestoreArray(w3,&w3_array);
2519: /*
2520: Evaluate function at x1 + dx (here dx is a vector of perturbations)
2521: */
2523: PetscLogEventBegin(MAT_FDColoringFunction,0,0,0,0);
2524: (*f)(sctx,w3,w2,fctx);
2525: PetscLogEventEnd(MAT_FDColoringFunction,0,0,0,0);
2526: VecAXPY(w2,-1.0,w1);
2528: /*
2529: Loop over rows of vector, putting results into Jacobian matrix
2530: */
2531: VecGetArray(w2,&y);
2532: for (l=0; l<coloring->nrows[k]; l++) {
2533: row = coloring->rows[k][l];
2534: col = coloring->columnsforrow[k][l];
2535: y[row] *= vscale_array[vscaleforrow[k][l]];
2536: srow = row + start;
2537: MatSetValues_SeqAIJ(J,1,&srow,1,&col,y+row,INSERT_VALUES);
2538: }
2539: VecRestoreArray(w2,&y);
2540: }
2541: coloring->currentcolor = k;
2542: VecRestoreArray(coloring->vscale,&vscale_array);
2543: xx = xx + start; VecRestoreArray(x1,&xx);
2544: MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);
2545: MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);
2546: return(0);
2547: }
2549: /*
2550: Computes the number of nonzeros per row needed for preallocation when X and Y
2551: have different nonzero structure.
2552: */
2555: PetscErrorCode MatAXPYGetPreallocation_SeqAIJ(Mat Y,Mat X,PetscInt* nnz)
2556: {
2557: PetscInt i,m=Y->rmap->N;
2558: Mat_SeqAIJ *x = (Mat_SeqAIJ*)X->data;
2559: Mat_SeqAIJ *y = (Mat_SeqAIJ*)Y->data;
2560: const PetscInt *xi = x->i,*yi = y->i;
2563: /* Set the number of nonzeros in the new matrix */
2564: for(i=0; i<m; i++) {
2565: PetscInt j,k,nzx = xi[i+1] - xi[i],nzy = yi[i+1] - yi[i];
2566: const PetscInt *xj = x->j+xi[i],*yj = y->j+yi[i];
2567: nnz[i] = 0;
2568: for (j=0,k=0; j<nzx; j++) { /* Point in X */
2569: for (; k<nzy && yj[k]<xj[j]; k++) nnz[i]++; /* Catch up to X */
2570: if (k<nzy && yj[k]==xj[j]) k++; /* Skip duplicate */
2571: nnz[i]++;
2572: }
2573: for (; k<nzy; k++) nnz[i]++;
2574: }
2575: return(0);
2576: }
2580: PetscErrorCode MatAXPY_SeqAIJ(Mat Y,PetscScalar a,Mat X,MatStructure str)
2581: {
2583: PetscInt i;
2584: Mat_SeqAIJ *x = (Mat_SeqAIJ *)X->data,*y = (Mat_SeqAIJ *)Y->data;
2585: PetscBLASInt one=1,bnz = PetscBLASIntCast(x->nz);
2588: if (str == SAME_NONZERO_PATTERN) {
2589: PetscScalar alpha = a;
2590: BLASaxpy_(&bnz,&alpha,x->a,&one,y->a,&one);
2591: y->idiagvalid = PETSC_FALSE;
2592: y->ibdiagvalid = PETSC_FALSE;
2593: } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */
2594: if (y->xtoy && y->XtoY != X) {
2595: PetscFree(y->xtoy);
2596: MatDestroy(&y->XtoY);
2597: }
2598: if (!y->xtoy) { /* get xtoy */
2599: MatAXPYGetxtoy_Private(X->rmap->n,x->i,x->j,PETSC_NULL, y->i,y->j,PETSC_NULL, &y->xtoy);
2600: y->XtoY = X;
2601: PetscObjectReference((PetscObject)X);
2602: }
2603: for (i=0; i<x->nz; i++) y->a[y->xtoy[i]] += a*(x->a[i]);
2604: PetscInfo3(Y,"ratio of nnz(X)/nnz(Y): %d/%d = %G\n",x->nz,y->nz,(PetscReal)(x->nz)/(y->nz+1));
2605: } else {
2606: Mat B;
2607: PetscInt *nnz;
2608: PetscMalloc(Y->rmap->N*sizeof(PetscInt),&nnz);
2609: MatCreate(((PetscObject)Y)->comm,&B);
2610: PetscObjectSetName((PetscObject)B,((PetscObject)Y)->name);
2611: MatSetSizes(B,Y->rmap->n,Y->cmap->n,Y->rmap->N,Y->cmap->N);
2612: MatSetBlockSizes(B,Y->rmap->bs,Y->cmap->bs);
2613: MatSetType(B,(MatType) ((PetscObject)Y)->type_name);
2614: MatAXPYGetPreallocation_SeqAIJ(Y,X,nnz);
2615: MatSeqAIJSetPreallocation(B,0,nnz);
2616: MatAXPY_BasicWithPreallocation(B,Y,a,X,str);
2617: MatHeaderReplace(Y,B);
2618: PetscFree(nnz);
2619: }
2620: return(0);
2621: }
2625: PetscErrorCode MatConjugate_SeqAIJ(Mat mat)
2626: {
2627: #if defined(PETSC_USE_COMPLEX)
2628: Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data;
2629: PetscInt i,nz;
2630: PetscScalar *a;
2633: nz = aij->nz;
2634: a = aij->a;
2635: for (i=0; i<nz; i++) {
2636: a[i] = PetscConj(a[i]);
2637: }
2638: #else
2640: #endif
2641: return(0);
2642: }
2646: PetscErrorCode MatGetRowMaxAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[])
2647: {
2648: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
2650: PetscInt i,j,m = A->rmap->n,*ai,*aj,ncols,n;
2651: PetscReal atmp;
2652: PetscScalar *x;
2653: MatScalar *aa;
2656: if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2657: aa = a->a;
2658: ai = a->i;
2659: aj = a->j;
2661: VecSet(v,0.0);
2662: VecGetArray(v,&x);
2663: VecGetLocalSize(v,&n);
2664: if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
2665: for (i=0; i<m; i++) {
2666: ncols = ai[1] - ai[0]; ai++;
2667: x[i] = 0.0;
2668: for (j=0; j<ncols; j++){
2669: atmp = PetscAbsScalar(*aa);
2670: if (PetscAbsScalar(x[i]) < atmp) {x[i] = atmp; if (idx) idx[i] = *aj;}
2671: aa++; aj++;
2672: }
2673: }
2674: VecRestoreArray(v,&x);
2675: return(0);
2676: }
2680: PetscErrorCode MatGetRowMax_SeqAIJ(Mat A,Vec v,PetscInt idx[])
2681: {
2682: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
2684: PetscInt i,j,m = A->rmap->n,*ai,*aj,ncols,n;
2685: PetscScalar *x;
2686: MatScalar *aa;
2689: if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2690: aa = a->a;
2691: ai = a->i;
2692: aj = a->j;
2694: VecSet(v,0.0);
2695: VecGetArray(v,&x);
2696: VecGetLocalSize(v,&n);
2697: if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
2698: for (i=0; i<m; i++) {
2699: ncols = ai[1] - ai[0]; ai++;
2700: if (ncols == A->cmap->n) { /* row is dense */
2701: x[i] = *aa; if (idx) idx[i] = 0;
2702: } else { /* row is sparse so already KNOW maximum is 0.0 or higher */
2703: x[i] = 0.0;
2704: if (idx) {
2705: idx[i] = 0; /* in case ncols is zero */
2706: for (j=0;j<ncols;j++) { /* find first implicit 0.0 in the row */
2707: if (aj[j] > j) {
2708: idx[i] = j;
2709: break;
2710: }
2711: }
2712: }
2713: }
2714: for (j=0; j<ncols; j++){
2715: if (PetscRealPart(x[i]) < PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
2716: aa++; aj++;
2717: }
2718: }
2719: VecRestoreArray(v,&x);
2720: return(0);
2721: }
2725: PetscErrorCode MatGetRowMinAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[])
2726: {
2727: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
2729: PetscInt i,j,m = A->rmap->n,*ai,*aj,ncols,n;
2730: PetscReal atmp;
2731: PetscScalar *x;
2732: MatScalar *aa;
2735: if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2736: aa = a->a;
2737: ai = a->i;
2738: aj = a->j;
2740: VecSet(v,0.0);
2741: VecGetArray(v,&x);
2742: VecGetLocalSize(v,&n);
2743: 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);
2744: for (i=0; i<m; i++) {
2745: ncols = ai[1] - ai[0]; ai++;
2746: if (ncols) {
2747: /* Get first nonzero */
2748: for(j = 0; j < ncols; j++) {
2749: atmp = PetscAbsScalar(aa[j]);
2750: if (atmp > 1.0e-12) {x[i] = atmp; if (idx) idx[i] = aj[j]; break;}
2751: }
2752: if (j == ncols) {x[i] = PetscAbsScalar(*aa); if (idx) idx[i] = *aj;}
2753: } else {
2754: x[i] = 0.0; if (idx) idx[i] = 0;
2755: }
2756: for(j = 0; j < ncols; j++) {
2757: atmp = PetscAbsScalar(*aa);
2758: if (atmp > 1.0e-12 && PetscAbsScalar(x[i]) > atmp) {x[i] = atmp; if (idx) idx[i] = *aj;}
2759: aa++; aj++;
2760: }
2761: }
2762: VecRestoreArray(v,&x);
2763: return(0);
2764: }
2768: PetscErrorCode MatGetRowMin_SeqAIJ(Mat A,Vec v,PetscInt idx[])
2769: {
2770: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
2772: PetscInt i,j,m = A->rmap->n,*ai,*aj,ncols,n;
2773: PetscScalar *x;
2774: MatScalar *aa;
2777: if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2778: aa = a->a;
2779: ai = a->i;
2780: aj = a->j;
2782: VecSet(v,0.0);
2783: VecGetArray(v,&x);
2784: VecGetLocalSize(v,&n);
2785: if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
2786: for (i=0; i<m; i++) {
2787: ncols = ai[1] - ai[0]; ai++;
2788: if (ncols == A->cmap->n) { /* row is dense */
2789: x[i] = *aa; if (idx) idx[i] = 0;
2790: } else { /* row is sparse so already KNOW minimum is 0.0 or lower */
2791: x[i] = 0.0;
2792: if (idx) { /* find first implicit 0.0 in the row */
2793: idx[i] = 0; /* in case ncols is zero */
2794: for (j=0;j<ncols;j++) {
2795: if (aj[j] > j) {
2796: idx[i] = j;
2797: break;
2798: }
2799: }
2800: }
2801: }
2802: for (j=0; j<ncols; j++){
2803: if (PetscRealPart(x[i]) > PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
2804: aa++; aj++;
2805: }
2806: }
2807: VecRestoreArray(v,&x);
2808: return(0);
2809: }
2811: #include <petscblaslapack.h>
2812: #include <../src/mat/blockinvert.h>
2816: PetscErrorCode MatInvertBlockDiagonal_SeqAIJ(Mat A,const PetscScalar **values)
2817: {
2818: Mat_SeqAIJ *a = (Mat_SeqAIJ*) A->data;
2820: PetscInt i,bs = A->rmap->bs,mbs = A->rmap->n/A->rmap->bs,ipvt[5],bs2 = bs*bs,*v_pivots,ij[7],*IJ,j;
2821: MatScalar *diag,work[25],*v_work;
2822: PetscReal shift = 0.0;
2825: if (a->ibdiagvalid) {
2826: if (values) *values = a->ibdiag;
2827: return(0);
2828: }
2829: MatMarkDiagonal_SeqAIJ(A);
2830: if (!a->ibdiag) {
2831: PetscMalloc(bs2*mbs*sizeof(PetscScalar),&a->ibdiag);
2832: PetscLogObjectMemory(A,bs2*mbs*sizeof(PetscScalar));
2833: }
2834: diag = a->ibdiag;
2835: if (values) *values = a->ibdiag;
2836: /* factor and invert each block */
2837: switch (bs){
2838: case 1:
2839: for (i=0; i<mbs; i++) {
2840: MatGetValues(A,1,&i,1,&i,diag+i);
2841: diag[i] = (PetscScalar)1.0 / (diag[i] + shift);
2842: }
2843: break;
2844: case 2:
2845: for (i=0; i<mbs; i++) {
2846: ij[0] = 2*i; ij[1] = 2*i + 1;
2847: MatGetValues(A,2,ij,2,ij,diag);
2848: PetscKernel_A_gets_inverse_A_2(diag,shift);
2849: PetscKernel_A_gets_transpose_A_2(diag);
2850: diag += 4;
2851: }
2852: break;
2853: case 3:
2854: for (i=0; i<mbs; i++) {
2855: ij[0] = 3*i; ij[1] = 3*i + 1; ij[2] = 3*i + 2;
2856: MatGetValues(A,3,ij,3,ij,diag);
2857: PetscKernel_A_gets_inverse_A_3(diag,shift);
2858: PetscKernel_A_gets_transpose_A_3(diag);
2859: diag += 9;
2860: }
2861: break;
2862: case 4:
2863: for (i=0; i<mbs; i++) {
2864: ij[0] = 4*i; ij[1] = 4*i + 1; ij[2] = 4*i + 2; ij[3] = 4*i + 3;
2865: MatGetValues(A,4,ij,4,ij,diag);
2866: PetscKernel_A_gets_inverse_A_4(diag,shift);
2867: PetscKernel_A_gets_transpose_A_4(diag);
2868: diag += 16;
2869: }
2870: break;
2871: case 5:
2872: for (i=0; i<mbs; i++) {
2873: ij[0] = 5*i; ij[1] = 5*i + 1; ij[2] = 5*i + 2; ij[3] = 5*i + 3; ij[4] = 5*i + 4;
2874: MatGetValues(A,5,ij,5,ij,diag);
2875: PetscKernel_A_gets_inverse_A_5(diag,ipvt,work,shift);
2876: PetscKernel_A_gets_transpose_A_5(diag);
2877: diag += 25;
2878: }
2879: break;
2880: case 6:
2881: for (i=0; i<mbs; i++) {
2882: 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;
2883: MatGetValues(A,6,ij,6,ij,diag);
2884: PetscKernel_A_gets_inverse_A_6(diag,shift);
2885: PetscKernel_A_gets_transpose_A_6(diag);
2886: diag += 36;
2887: }
2888: break;
2889: case 7:
2890: for (i=0; i<mbs; i++) {
2891: 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;
2892: MatGetValues(A,7,ij,7,ij,diag);
2893: PetscKernel_A_gets_inverse_A_7(diag,shift);
2894: PetscKernel_A_gets_transpose_A_7(diag);
2895: diag += 49;
2896: }
2897: break;
2898: default:
2899: PetscMalloc3(bs,MatScalar,&v_work,bs,PetscInt,&v_pivots,bs,PetscInt,&IJ);
2900: for (i=0; i<mbs; i++) {
2901: for (j=0; j<bs; j++) {
2902: IJ[j] = bs*i + j;
2903: }
2904: MatGetValues(A,bs,IJ,bs,IJ,diag);
2905: PetscKernel_A_gets_inverse_A(bs,diag,v_pivots,v_work);
2906: PetscKernel_A_gets_transpose_A_N(diag,bs);
2907: diag += bs2;
2908: }
2909: PetscFree3(v_work,v_pivots,IJ);
2910: }
2911: a->ibdiagvalid = PETSC_TRUE;
2912: return(0);
2913: }
2915: extern PetscErrorCode MatFDColoringApply_AIJ(Mat,MatFDColoring,Vec,MatStructure*,void*);
2916: /* -------------------------------------------------------------------*/
2917: static struct _MatOps MatOps_Values = {MatSetValues_SeqAIJ,
2918: MatGetRow_SeqAIJ,
2919: MatRestoreRow_SeqAIJ,
2920: MatMult_SeqAIJ,
2921: /* 4*/ MatMultAdd_SeqAIJ,
2922: MatMultTranspose_SeqAIJ,
2923: MatMultTransposeAdd_SeqAIJ,
2924: 0,
2925: 0,
2926: 0,
2927: /*10*/ 0,
2928: MatLUFactor_SeqAIJ,
2929: 0,
2930: MatSOR_SeqAIJ,
2931: MatTranspose_SeqAIJ,
2932: /*15*/ MatGetInfo_SeqAIJ,
2933: MatEqual_SeqAIJ,
2934: MatGetDiagonal_SeqAIJ,
2935: MatDiagonalScale_SeqAIJ,
2936: MatNorm_SeqAIJ,
2937: /*20*/ 0,
2938: MatAssemblyEnd_SeqAIJ,
2939: MatSetOption_SeqAIJ,
2940: MatZeroEntries_SeqAIJ,
2941: /*24*/ MatZeroRows_SeqAIJ,
2942: 0,
2943: 0,
2944: 0,
2945: 0,
2946: /*29*/ MatSetUp_SeqAIJ,
2947: 0,
2948: 0,
2949: MatGetArray_SeqAIJ,
2950: MatRestoreArray_SeqAIJ,
2951: /*34*/ MatDuplicate_SeqAIJ,
2952: 0,
2953: 0,
2954: MatILUFactor_SeqAIJ,
2955: 0,
2956: /*39*/ MatAXPY_SeqAIJ,
2957: MatGetSubMatrices_SeqAIJ,
2958: MatIncreaseOverlap_SeqAIJ,
2959: MatGetValues_SeqAIJ,
2960: MatCopy_SeqAIJ,
2961: /*44*/ MatGetRowMax_SeqAIJ,
2962: MatScale_SeqAIJ,
2963: 0,
2964: MatDiagonalSet_SeqAIJ,
2965: MatZeroRowsColumns_SeqAIJ,
2966: /*49*/ 0,
2967: MatGetRowIJ_SeqAIJ,
2968: MatRestoreRowIJ_SeqAIJ,
2969: MatGetColumnIJ_SeqAIJ,
2970: MatRestoreColumnIJ_SeqAIJ,
2971: /*54*/ MatFDColoringCreate_SeqAIJ,
2972: 0,
2973: 0,
2974: MatPermute_SeqAIJ,
2975: 0,
2976: /*59*/ 0,
2977: MatDestroy_SeqAIJ,
2978: MatView_SeqAIJ,
2979: 0,
2980: 0,
2981: /*64*/ 0,
2982: 0,
2983: 0,
2984: 0,
2985: 0,
2986: /*69*/ MatGetRowMaxAbs_SeqAIJ,
2987: MatGetRowMinAbs_SeqAIJ,
2988: 0,
2989: MatSetColoring_SeqAIJ,
2990: #if defined(PETSC_HAVE_ADIC)
2991: MatSetValuesAdic_SeqAIJ,
2992: #else
2993: 0,
2994: #endif
2995: /*74*/ MatSetValuesAdifor_SeqAIJ,
2996: MatFDColoringApply_AIJ,
2997: 0,
2998: 0,
2999: 0,
3000: /*79*/ MatFindZeroDiagonals_SeqAIJ,
3001: 0,
3002: 0,
3003: 0,
3004: MatLoad_SeqAIJ,
3005: /*84*/ MatIsSymmetric_SeqAIJ,
3006: MatIsHermitian_SeqAIJ,
3007: 0,
3008: 0,
3009: 0,
3010: /*89*/ MatMatMult_SeqAIJ_SeqAIJ,
3011: MatMatMultSymbolic_SeqAIJ_SeqAIJ,
3012: MatMatMultNumeric_SeqAIJ_SeqAIJ,
3013: MatPtAP_Basic,
3014: MatPtAPSymbolic_SeqAIJ,
3015: /*94*/ MatPtAPNumeric_SeqAIJ,
3016: MatMatTransposeMult_SeqAIJ_SeqAIJ,
3017: MatMatTransposeMultSymbolic_SeqAIJ_SeqAIJ,
3018: MatMatTransposeMultNumeric_SeqAIJ_SeqAIJ,
3019: MatPtAPSymbolic_SeqAIJ_SeqAIJ,
3020: /*99*/ MatPtAPNumeric_SeqAIJ_SeqAIJ,
3021: 0,
3022: 0,
3023: MatConjugate_SeqAIJ,
3024: 0,
3025: /*104*/MatSetValuesRow_SeqAIJ,
3026: MatRealPart_SeqAIJ,
3027: MatImaginaryPart_SeqAIJ,
3028: 0,
3029: 0,
3030: /*109*/MatMatSolve_SeqAIJ,
3031: 0,
3032: MatGetRowMin_SeqAIJ,
3033: 0,
3034: MatMissingDiagonal_SeqAIJ,
3035: /*114*/0,
3036: 0,
3037: 0,
3038: 0,
3039: 0,
3040: /*119*/0,
3041: 0,
3042: 0,
3043: 0,
3044: MatGetMultiProcBlock_SeqAIJ,
3045: /*124*/MatFindNonzeroRows_SeqAIJ,
3046: MatGetColumnNorms_SeqAIJ,
3047: MatInvertBlockDiagonal_SeqAIJ,
3048: 0,
3049: 0,
3050: /*129*/0,
3051: MatTransposeMatMult_SeqAIJ_SeqAIJ,
3052: MatTransposeMatMultSymbolic_SeqAIJ_SeqAIJ,
3053: MatTransposeMatMultNumeric_SeqAIJ_SeqAIJ,
3054: MatTransposeColoringCreate_SeqAIJ,
3055: /*134*/MatTransColoringApplySpToDen_SeqAIJ,
3056: MatTransColoringApplyDenToSp_SeqAIJ,
3057: MatRARt_SeqAIJ_SeqAIJ,
3058: MatRARtSymbolic_SeqAIJ_SeqAIJ,
3059: MatRARtNumeric_SeqAIJ_SeqAIJ
3060: };
3062: EXTERN_C_BEGIN
3065: PetscErrorCode MatSeqAIJSetColumnIndices_SeqAIJ(Mat mat,PetscInt *indices)
3066: {
3067: Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data;
3068: PetscInt i,nz,n;
3072: nz = aij->maxnz;
3073: n = mat->rmap->n;
3074: for (i=0; i<nz; i++) {
3075: aij->j[i] = indices[i];
3076: }
3077: aij->nz = nz;
3078: for (i=0; i<n; i++) {
3079: aij->ilen[i] = aij->imax[i];
3080: }
3082: return(0);
3083: }
3084: EXTERN_C_END
3088: /*@
3089: MatSeqAIJSetColumnIndices - Set the column indices for all the rows
3090: in the matrix.
3092: Input Parameters:
3093: + mat - the SeqAIJ matrix
3094: - indices - the column indices
3096: Level: advanced
3098: Notes:
3099: This can be called if you have precomputed the nonzero structure of the
3100: matrix and want to provide it to the matrix object to improve the performance
3101: of the MatSetValues() operation.
3103: You MUST have set the correct numbers of nonzeros per row in the call to
3104: MatCreateSeqAIJ(), and the columns indices MUST be sorted.
3106: MUST be called before any calls to MatSetValues();
3108: The indices should start with zero, not one.
3110: @*/
3111: PetscErrorCode MatSeqAIJSetColumnIndices(Mat mat,PetscInt *indices)
3112: {
3118: PetscUseMethod(mat,"MatSeqAIJSetColumnIndices_C",(Mat,PetscInt *),(mat,indices));
3119: return(0);
3120: }
3122: /* ----------------------------------------------------------------------------------------*/
3124: EXTERN_C_BEGIN
3127: PetscErrorCode MatStoreValues_SeqAIJ(Mat mat)
3128: {
3129: Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data;
3131: size_t nz = aij->i[mat->rmap->n];
3134: if (aij->nonew != 1) {
3135: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
3136: }
3138: /* allocate space for values if not already there */
3139: if (!aij->saved_values) {
3140: PetscMalloc((nz+1)*sizeof(PetscScalar),&aij->saved_values);
3141: PetscLogObjectMemory(mat,(nz+1)*sizeof(PetscScalar));
3142: }
3144: /* copy values over */
3145: PetscMemcpy(aij->saved_values,aij->a,nz*sizeof(PetscScalar));
3146: return(0);
3147: }
3148: EXTERN_C_END
3152: /*@
3153: MatStoreValues - Stashes a copy of the matrix values; this allows, for
3154: example, reuse of the linear part of a Jacobian, while recomputing the
3155: nonlinear portion.
3157: Collect on Mat
3159: Input Parameters:
3160: . mat - the matrix (currently only AIJ matrices support this option)
3162: Level: advanced
3164: Common Usage, with SNESSolve():
3165: $ Create Jacobian matrix
3166: $ Set linear terms into matrix
3167: $ Apply boundary conditions to matrix, at this time matrix must have
3168: $ final nonzero structure (i.e. setting the nonlinear terms and applying
3169: $ boundary conditions again will not change the nonzero structure
3170: $ MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
3171: $ MatStoreValues(mat);
3172: $ Call SNESSetJacobian() with matrix
3173: $ In your Jacobian routine
3174: $ MatRetrieveValues(mat);
3175: $ Set nonlinear terms in matrix
3176:
3177: Common Usage without SNESSolve(), i.e. when you handle nonlinear solve yourself:
3178: $ // build linear portion of Jacobian
3179: $ MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
3180: $ MatStoreValues(mat);
3181: $ loop over nonlinear iterations
3182: $ MatRetrieveValues(mat);
3183: $ // call MatSetValues(mat,...) to set nonliner portion of Jacobian
3184: $ // call MatAssemblyBegin/End() on matrix
3185: $ Solve linear system with Jacobian
3186: $ endloop
3188: Notes:
3189: Matrix must already be assemblied before calling this routine
3190: Must set the matrix option MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); before
3191: calling this routine.
3193: When this is called multiple times it overwrites the previous set of stored values
3194: and does not allocated additional space.
3196: .seealso: MatRetrieveValues()
3198: @*/
3199: PetscErrorCode MatStoreValues(Mat mat)
3200: {
3205: if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3206: if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3207: PetscUseMethod(mat,"MatStoreValues_C",(Mat),(mat));
3208: return(0);
3209: }
3211: EXTERN_C_BEGIN
3214: PetscErrorCode MatRetrieveValues_SeqAIJ(Mat mat)
3215: {
3216: Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data;
3218: PetscInt nz = aij->i[mat->rmap->n];
3221: if (aij->nonew != 1) {
3222: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
3223: }
3224: if (!aij->saved_values) {
3225: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatStoreValues(A);first");
3226: }
3227: /* copy values over */
3228: PetscMemcpy(aij->a,aij->saved_values,nz*sizeof(PetscScalar));
3229: return(0);
3230: }
3231: EXTERN_C_END
3235: /*@
3236: MatRetrieveValues - Retrieves the copy of the matrix values; this allows, for
3237: example, reuse of the linear part of a Jacobian, while recomputing the
3238: nonlinear portion.
3240: Collect on Mat
3242: Input Parameters:
3243: . mat - the matrix (currently on AIJ matrices support this option)
3245: Level: advanced
3247: .seealso: MatStoreValues()
3249: @*/
3250: PetscErrorCode MatRetrieveValues(Mat mat)
3251: {
3256: if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3257: if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3258: PetscUseMethod(mat,"MatRetrieveValues_C",(Mat),(mat));
3259: return(0);
3260: }
3263: /* --------------------------------------------------------------------------------*/
3266: /*@C
3267: MatCreateSeqAIJ - Creates a sparse matrix in AIJ (compressed row) format
3268: (the default parallel PETSc format). For good matrix assembly performance
3269: the user should preallocate the matrix storage by setting the parameter nz
3270: (or the array nnz). By setting these parameters accurately, performance
3271: during matrix assembly can be increased by more than a factor of 50.
3273: Collective on MPI_Comm
3275: Input Parameters:
3276: + comm - MPI communicator, set to PETSC_COMM_SELF
3277: . m - number of rows
3278: . n - number of columns
3279: . nz - number of nonzeros per row (same for all rows)
3280: - nnz - array containing the number of nonzeros in the various rows
3281: (possibly different for each row) or PETSC_NULL
3283: Output Parameter:
3284: . A - the matrix
3286: It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(),
3287: MatXXXXSetPreallocation() paradgm instead of this routine directly.
3288: [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation]
3290: Notes:
3291: If nnz is given then nz is ignored
3293: The AIJ format (also called the Yale sparse matrix format or
3294: compressed row storage), is fully compatible with standard Fortran 77
3295: storage. That is, the stored row and column indices can begin at
3296: either one (as in Fortran) or zero. See the users' manual for details.
3298: Specify the preallocated storage with either nz or nnz (not both).
3299: Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory
3300: allocation. For large problems you MUST preallocate memory or you
3301: will get TERRIBLE performance, see the users' manual chapter on matrices.
3303: By default, this format uses inodes (identical nodes) when possible, to
3304: improve numerical efficiency of matrix-vector products and solves. We
3305: search for consecutive rows with the same nonzero structure, thereby
3306: reusing matrix information to achieve increased efficiency.
3308: Options Database Keys:
3309: + -mat_no_inode - Do not use inodes
3310: - -mat_inode_limit <limit> - Sets inode limit (max limit=5)
3312: Level: intermediate
3314: .seealso: MatCreate(), MatCreateAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays()
3316: @*/
3317: PetscErrorCode MatCreateSeqAIJ(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],Mat *A)
3318: {
3322: MatCreate(comm,A);
3323: MatSetSizes(*A,m,n,m,n);
3324: MatSetType(*A,MATSEQAIJ);
3325: MatSeqAIJSetPreallocation_SeqAIJ(*A,nz,nnz);
3326: return(0);
3327: }
3331: /*@C
3332: MatSeqAIJSetPreallocation - For good matrix assembly performance
3333: the user should preallocate the matrix storage by setting the parameter nz
3334: (or the array nnz). By setting these parameters accurately, performance
3335: during matrix assembly can be increased by more than a factor of 50.
3337: Collective on MPI_Comm
3339: Input Parameters:
3340: + B - The matrix-free
3341: . nz - number of nonzeros per row (same for all rows)
3342: - nnz - array containing the number of nonzeros in the various rows
3343: (possibly different for each row) or PETSC_NULL
3345: Notes:
3346: If nnz is given then nz is ignored
3348: The AIJ format (also called the Yale sparse matrix format or
3349: compressed row storage), is fully compatible with standard Fortran 77
3350: storage. That is, the stored row and column indices can begin at
3351: either one (as in Fortran) or zero. See the users' manual for details.
3353: Specify the preallocated storage with either nz or nnz (not both).
3354: Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory
3355: allocation. For large problems you MUST preallocate memory or you
3356: will get TERRIBLE performance, see the users' manual chapter on matrices.
3358: You can call MatGetInfo() to get information on how effective the preallocation was;
3359: for example the fields mallocs,nz_allocated,nz_used,nz_unneeded;
3360: You can also run with the option -info and look for messages with the string
3361: malloc in them to see if additional memory allocation was needed.
3363: Developers: Use nz of MAT_SKIP_ALLOCATION to not allocate any space for the matrix
3364: entries or columns indices
3366: By default, this format uses inodes (identical nodes) when possible, to
3367: improve numerical efficiency of matrix-vector products and solves. We
3368: search for consecutive rows with the same nonzero structure, thereby
3369: reusing matrix information to achieve increased efficiency.
3371: Options Database Keys:
3372: + -mat_no_inode - Do not use inodes
3373: . -mat_inode_limit <limit> - Sets inode limit (max limit=5)
3374: - -mat_aij_oneindex - Internally use indexing starting at 1
3375: rather than 0. Note that when calling MatSetValues(),
3376: the user still MUST index entries starting at 0!
3378: Level: intermediate
3380: .seealso: MatCreate(), MatCreateAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays(), MatGetInfo()
3382: @*/
3383: PetscErrorCode MatSeqAIJSetPreallocation(Mat B,PetscInt nz,const PetscInt nnz[])
3384: {
3390: PetscTryMethod(B,"MatSeqAIJSetPreallocation_C",(Mat,PetscInt,const PetscInt[]),(B,nz,nnz));
3391: return(0);
3392: }
3394: EXTERN_C_BEGIN
3397: PetscErrorCode MatSeqAIJSetPreallocation_SeqAIJ(Mat B,PetscInt nz,const PetscInt *nnz)
3398: {
3399: Mat_SeqAIJ *b;
3400: PetscBool skipallocation = PETSC_FALSE,realalloc = PETSC_FALSE;
3402: PetscInt i;
3405: if (nz >= 0 || nnz) realalloc = PETSC_TRUE;
3406: if (nz == MAT_SKIP_ALLOCATION) {
3407: skipallocation = PETSC_TRUE;
3408: nz = 0;
3409: }
3411: PetscLayoutSetUp(B->rmap);
3412: PetscLayoutSetUp(B->cmap);
3414: if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
3415: if (nz < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %d",nz);
3416: if (nnz) {
3417: for (i=0; i<B->rmap->n; i++) {
3418: 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]);
3419: 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);
3420: }
3421: }
3423: B->preallocated = PETSC_TRUE;
3424: b = (Mat_SeqAIJ*)B->data;
3426: if (!skipallocation) {
3427: if (!b->imax) {
3428: PetscMalloc2(B->rmap->n,PetscInt,&b->imax,B->rmap->n,PetscInt,&b->ilen);
3429: PetscLogObjectMemory(B,2*B->rmap->n*sizeof(PetscInt));
3430: }
3431: if (!nnz) {
3432: if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 10;
3433: else if (nz < 0) nz = 1;
3434: for (i=0; i<B->rmap->n; i++) b->imax[i] = nz;
3435: nz = nz*B->rmap->n;
3436: } else {
3437: nz = 0;
3438: for (i=0; i<B->rmap->n; i++) {b->imax[i] = nnz[i]; nz += nnz[i];}
3439: }
3440: /* b->ilen will count nonzeros in each row so far. */
3441: for (i=0; i<B->rmap->n; i++) { b->ilen[i] = 0; }
3443: /* allocate the matrix space */
3444: MatSeqXAIJFreeAIJ(B,&b->a,&b->j,&b->i);
3445: PetscMalloc3(nz,PetscScalar,&b->a,nz,PetscInt,&b->j,B->rmap->n+1,PetscInt,&b->i);
3446: PetscLogObjectMemory(B,(B->rmap->n+1)*sizeof(PetscInt)+nz*(sizeof(PetscScalar)+sizeof(PetscInt)));
3447: b->i[0] = 0;
3448: for (i=1; i<B->rmap->n+1; i++) {
3449: b->i[i] = b->i[i-1] + b->imax[i-1];
3450: }
3451: b->singlemalloc = PETSC_TRUE;
3452: b->free_a = PETSC_TRUE;
3453: b->free_ij = PETSC_TRUE;
3454: } else {
3455: b->free_a = PETSC_FALSE;
3456: b->free_ij = PETSC_FALSE;
3457: }
3459: b->nz = 0;
3460: b->maxnz = nz;
3461: B->info.nz_unneeded = (double)b->maxnz;
3462: if (realalloc) {MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);}
3463: return(0);
3464: }
3465: EXTERN_C_END
3467: #undef __FUNCT__
3469: /*@
3470: MatSeqAIJSetPreallocationCSR - Allocates memory for a sparse sequential matrix in AIJ format.
3472: Input Parameters:
3473: + B - the matrix
3474: . i - the indices into j for the start of each row (starts with zero)
3475: . j - the column indices for each row (starts with zero) these must be sorted for each row
3476: - v - optional values in the matrix
3478: Level: developer
3480: The i,j,v values are COPIED with this routine; to avoid the copy use MatCreateSeqAIJWithArrays()
3482: .keywords: matrix, aij, compressed row, sparse, sequential
3484: .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatSeqAIJSetPreallocation(), MatCreateSeqAIJ(), SeqAIJ
3485: @*/
3486: PetscErrorCode MatSeqAIJSetPreallocationCSR(Mat B,const PetscInt i[],const PetscInt j[],const PetscScalar v[])
3487: {
3493: PetscTryMethod(B,"MatSeqAIJSetPreallocationCSR_C",(Mat,const PetscInt[],const PetscInt[],const PetscScalar[]),(B,i,j,v));
3494: return(0);
3495: }
3497: EXTERN_C_BEGIN
3498: #undef __FUNCT__
3500: PetscErrorCode MatSeqAIJSetPreallocationCSR_SeqAIJ(Mat B,const PetscInt Ii[],const PetscInt J[],const PetscScalar v[])
3501: {
3502: PetscInt i;
3503: PetscInt m,n;
3504: PetscInt nz;
3505: PetscInt *nnz, nz_max = 0;
3506: PetscScalar *values;
3510: if (Ii[0]) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Ii[0] must be 0 it is %D", Ii[0]);
3512: PetscLayoutSetUp(B->rmap);
3513: PetscLayoutSetUp(B->cmap);
3515: MatGetSize(B, &m, &n);
3516: PetscMalloc((m+1) * sizeof(PetscInt), &nnz);
3517: for(i = 0; i < m; i++) {
3518: nz = Ii[i+1]- Ii[i];
3519: nz_max = PetscMax(nz_max, nz);
3520: if (nz < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Local row %D has a negative number of columns %D", i, nnz);
3521: nnz[i] = nz;
3522: }
3523: MatSeqAIJSetPreallocation(B, 0, nnz);
3524: PetscFree(nnz);
3526: if (v) {
3527: values = (PetscScalar*) v;
3528: } else {
3529: PetscMalloc(nz_max*sizeof(PetscScalar), &values);
3530: PetscMemzero(values, nz_max*sizeof(PetscScalar));
3531: }
3533: for(i = 0; i < m; i++) {
3534: nz = Ii[i+1] - Ii[i];
3535: MatSetValues_SeqAIJ(B, 1, &i, nz, J+Ii[i], values + (v ? Ii[i] : 0), INSERT_VALUES);
3536: }
3538: MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);
3539: MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);
3541: if (!v) {
3542: PetscFree(values);
3543: }
3544: MatSetOption(B,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);
3545: return(0);
3546: }
3547: EXTERN_C_END
3549: #include <../src/mat/impls/dense/seq/dense.h>
3550: #include <petsc-private/petscaxpy.h>
3554: /*
3555: Computes (B'*A')' since computing B*A directly is untenable
3557: n p p
3558: ( ) ( ) ( )
3559: m ( A ) * n ( B ) = m ( C )
3560: ( ) ( ) ( )
3562: */
3563: PetscErrorCode MatMatMultNumeric_SeqDense_SeqAIJ(Mat A,Mat B,Mat C)
3564: {
3565: PetscErrorCode ierr;
3566: Mat_SeqDense *sub_a = (Mat_SeqDense*)A->data;
3567: Mat_SeqAIJ *sub_b = (Mat_SeqAIJ*)B->data;
3568: Mat_SeqDense *sub_c = (Mat_SeqDense*)C->data;
3569: PetscInt i,n,m,q,p;
3570: const PetscInt *ii,*idx;
3571: const PetscScalar *b,*a,*a_q;
3572: PetscScalar *c,*c_q;
3575: m = A->rmap->n;
3576: n = A->cmap->n;
3577: p = B->cmap->n;
3578: a = sub_a->v;
3579: b = sub_b->a;
3580: c = sub_c->v;
3581: PetscMemzero(c,m*p*sizeof(PetscScalar));
3583: ii = sub_b->i;
3584: idx = sub_b->j;
3585: for (i=0; i<n; i++) {
3586: q = ii[i+1] - ii[i];
3587: while (q-->0) {
3588: c_q = c + m*(*idx);
3589: a_q = a + m*i;
3590: PetscAXPY(c_q,*b,a_q,m);
3591: idx++;
3592: b++;
3593: }
3594: }
3595: return(0);
3596: }
3600: PetscErrorCode MatMatMultSymbolic_SeqDense_SeqAIJ(Mat A,Mat B,PetscReal fill,Mat *C)
3601: {
3603: PetscInt m=A->rmap->n,n=B->cmap->n;
3604: Mat Cmat;
3607: 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);
3608: MatCreate(((PetscObject)A)->comm,&Cmat);
3609: MatSetSizes(Cmat,m,n,m,n);
3610: MatSetBlockSizes(Cmat,A->rmap->bs,B->cmap->bs);
3611: MatSetType(Cmat,MATSEQDENSE);
3612: MatSeqDenseSetPreallocation(Cmat,PETSC_NULL);
3613: Cmat->assembled = PETSC_TRUE;
3614: Cmat->ops->matmult = MatMatMult_SeqDense_SeqAIJ;
3615: *C = Cmat;
3616: return(0);
3617: }
3619: /* ----------------------------------------------------------------*/
3622: PetscErrorCode MatMatMult_SeqDense_SeqAIJ(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
3623: {
3627: if (scall == MAT_INITIAL_MATRIX){
3628: MatMatMultSymbolic_SeqDense_SeqAIJ(A,B,fill,C);
3629: }
3630: MatMatMultNumeric_SeqDense_SeqAIJ(A,B,*C);
3631: return(0);
3632: }
3635: /*MC
3636: MATSEQAIJ - MATSEQAIJ = "seqaij" - A matrix type to be used for sequential sparse matrices,
3637: based on compressed sparse row format.
3639: Options Database Keys:
3640: . -mat_type seqaij - sets the matrix type to "seqaij" during a call to MatSetFromOptions()
3642: Level: beginner
3644: .seealso: MatCreateSeqAIJ(), MatSetFromOptions(), MatSetType(), MatCreate(), MatType
3645: M*/
3647: EXTERN_C_BEGIN
3648: #if defined(PETSC_HAVE_PASTIX)
3649: extern PetscErrorCode MatGetFactor_seqaij_pastix(Mat,MatFactorType,Mat*);
3650: #endif
3651: #if defined(PETSC_HAVE_ESSL) && !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_REAL_SINGLE) && !defined(PETSC_USE_REAL___FLOAT128)
3652: extern PetscErrorCode MatGetFactor_seqaij_essl(Mat,MatFactorType,Mat *);
3653: #endif
3654: extern PetscErrorCode MatConvert_SeqAIJ_SeqAIJCRL(Mat,MatType,MatReuse,Mat*);
3655: extern PetscErrorCode MatGetFactor_seqaij_petsc(Mat,MatFactorType,Mat*);
3656: extern PetscErrorCode MatGetFactor_seqaij_bas(Mat,MatFactorType,Mat*);
3657: extern PetscErrorCode MatGetFactorAvailable_seqaij_petsc(Mat,MatFactorType,PetscBool *);
3658: #if defined(PETSC_HAVE_MUMPS)
3659: extern PetscErrorCode MatGetFactor_aij_mumps(Mat,MatFactorType,Mat*);
3660: #endif
3661: #if defined(PETSC_HAVE_SUPERLU)
3662: extern PetscErrorCode MatGetFactor_seqaij_superlu(Mat,MatFactorType,Mat*);
3663: #endif
3664: #if defined(PETSC_HAVE_SUPERLU_DIST)
3665: extern PetscErrorCode MatGetFactor_seqaij_superlu_dist(Mat,MatFactorType,Mat*);
3666: #endif
3667: #if defined(PETSC_HAVE_SPOOLES)
3668: extern PetscErrorCode MatGetFactor_seqaij_spooles(Mat,MatFactorType,Mat*);
3669: #endif
3670: #if defined(PETSC_HAVE_UMFPACK)
3671: extern PetscErrorCode MatGetFactor_seqaij_umfpack(Mat,MatFactorType,Mat*);
3672: #endif
3673: #if defined(PETSC_HAVE_CHOLMOD)
3674: extern PetscErrorCode MatGetFactor_seqaij_cholmod(Mat,MatFactorType,Mat*);
3675: #endif
3676: #if defined(PETSC_HAVE_LUSOL)
3677: extern PetscErrorCode MatGetFactor_seqaij_lusol(Mat,MatFactorType,Mat*);
3678: #endif
3679: #if defined(PETSC_HAVE_MATLAB_ENGINE)
3680: extern PetscErrorCode MatGetFactor_seqaij_matlab(Mat,MatFactorType,Mat*);
3681: extern PetscErrorCode MatlabEnginePut_SeqAIJ(PetscObject,void*);
3682: extern PetscErrorCode MatlabEngineGet_SeqAIJ(PetscObject,void*);
3683: #endif
3684: EXTERN_C_END
3687: EXTERN_C_BEGIN
3690: PetscErrorCode MatCreate_SeqAIJ(Mat B)
3691: {
3692: Mat_SeqAIJ *b;
3694: PetscMPIInt size;
3697: MPI_Comm_size(((PetscObject)B)->comm,&size);
3698: if (size > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Comm must be of size 1");
3700: PetscNewLog(B,Mat_SeqAIJ,&b);
3701: B->data = (void*)b;
3702: PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));
3703: b->row = 0;
3704: b->col = 0;
3705: b->icol = 0;
3706: b->reallocs = 0;
3707: b->ignorezeroentries = PETSC_FALSE;
3708: b->roworiented = PETSC_TRUE;
3709: b->nonew = 0;
3710: b->diag = 0;
3711: b->solve_work = 0;
3712: B->spptr = 0;
3713: b->saved_values = 0;
3714: b->idiag = 0;
3715: b->mdiag = 0;
3716: b->ssor_work = 0;
3717: b->omega = 1.0;
3718: b->fshift = 0.0;
3719: b->idiagvalid = PETSC_FALSE;
3720: b->ibdiagvalid = PETSC_FALSE;
3721: b->keepnonzeropattern = PETSC_FALSE;
3722: b->xtoy = 0;
3723: b->XtoY = 0;
3724: B->same_nonzero = PETSC_FALSE;
3726: PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);
3727: #if defined(PETSC_HAVE_MATLAB_ENGINE)
3728: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_matlab_C","MatGetFactor_seqaij_matlab",MatGetFactor_seqaij_matlab);
3729: PetscObjectComposeFunctionDynamic((PetscObject)B,"PetscMatlabEnginePut_C","MatlabEnginePut_SeqAIJ",MatlabEnginePut_SeqAIJ);
3730: PetscObjectComposeFunctionDynamic((PetscObject)B,"PetscMatlabEngineGet_C","MatlabEngineGet_SeqAIJ",MatlabEngineGet_SeqAIJ);
3731: #endif
3732: #if defined(PETSC_HAVE_PASTIX)
3733: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_pastix_C","MatGetFactor_seqaij_pastix",MatGetFactor_seqaij_pastix);
3734: #endif
3735: #if defined(PETSC_HAVE_ESSL) && !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_REAL_SINGLE) && !defined(PETSC_USE_REAL___FLOAT128)
3736: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_essl_C","MatGetFactor_seqaij_essl",MatGetFactor_seqaij_essl);
3737: #endif
3738: #if defined(PETSC_HAVE_SUPERLU)
3739: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_superlu_C","MatGetFactor_seqaij_superlu",MatGetFactor_seqaij_superlu);
3740: #endif
3741: #if defined(PETSC_HAVE_SUPERLU_DIST)
3742: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_superlu_dist_C","MatGetFactor_seqaij_superlu_dist",MatGetFactor_seqaij_superlu_dist);
3743: #endif
3744: #if defined(PETSC_HAVE_SPOOLES)
3745: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_spooles_C","MatGetFactor_seqaij_spooles",MatGetFactor_seqaij_spooles);
3746: #endif
3747: #if defined(PETSC_HAVE_MUMPS)
3748: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_mumps_C","MatGetFactor_aij_mumps",MatGetFactor_aij_mumps);
3749: #endif
3750: #if defined(PETSC_HAVE_UMFPACK)
3751: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_umfpack_C","MatGetFactor_seqaij_umfpack",MatGetFactor_seqaij_umfpack);
3752: #endif
3753: #if defined(PETSC_HAVE_CHOLMOD)
3754: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_cholmod_C","MatGetFactor_seqaij_cholmod",MatGetFactor_seqaij_cholmod);
3755: #endif
3756: #if defined(PETSC_HAVE_LUSOL)
3757: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_lusol_C","MatGetFactor_seqaij_lusol",MatGetFactor_seqaij_lusol);
3758: #endif
3759: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_petsc_C","MatGetFactor_seqaij_petsc",MatGetFactor_seqaij_petsc);
3760: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactorAvailable_petsc_C","MatGetFactorAvailable_seqaij_petsc",MatGetFactorAvailable_seqaij_petsc);
3761: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_bas_C","MatGetFactor_seqaij_bas",MatGetFactor_seqaij_bas);
3762: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqAIJSetColumnIndices_C","MatSeqAIJSetColumnIndices_SeqAIJ",MatSeqAIJSetColumnIndices_SeqAIJ);
3763: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatStoreValues_C","MatStoreValues_SeqAIJ",MatStoreValues_SeqAIJ);
3764: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatRetrieveValues_C","MatRetrieveValues_SeqAIJ",MatRetrieveValues_SeqAIJ);
3765: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_seqsbaij_C","MatConvert_SeqAIJ_SeqSBAIJ",MatConvert_SeqAIJ_SeqSBAIJ);
3766: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_seqbaij_C","MatConvert_SeqAIJ_SeqBAIJ",MatConvert_SeqAIJ_SeqBAIJ);
3767: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_seqaijperm_C","MatConvert_SeqAIJ_SeqAIJPERM",MatConvert_SeqAIJ_SeqAIJPERM);
3768: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_seqaijcrl_C","MatConvert_SeqAIJ_SeqAIJCRL",MatConvert_SeqAIJ_SeqAIJCRL);
3769: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatIsTranspose_C","MatIsTranspose_SeqAIJ",MatIsTranspose_SeqAIJ);
3770: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatIsHermitianTranspose_C","MatIsHermitianTranspose_SeqAIJ",MatIsTranspose_SeqAIJ);
3771: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqAIJSetPreallocation_C","MatSeqAIJSetPreallocation_SeqAIJ",MatSeqAIJSetPreallocation_SeqAIJ);
3772: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqAIJSetPreallocationCSR_C","MatSeqAIJSetPreallocationCSR_SeqAIJ",MatSeqAIJSetPreallocationCSR_SeqAIJ);
3773: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatReorderForNonzeroDiagonal_C","MatReorderForNonzeroDiagonal_SeqAIJ",MatReorderForNonzeroDiagonal_SeqAIJ);
3774: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatMatMult_seqdense_seqaij_C","MatMatMult_SeqDense_SeqAIJ",MatMatMult_SeqDense_SeqAIJ);
3775: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatMatMultSymbolic_seqdense_seqaij_C","MatMatMultSymbolic_SeqDense_SeqAIJ",MatMatMultSymbolic_SeqDense_SeqAIJ);
3776: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatMatMultNumeric_seqdense_seqaij_C","MatMatMultNumeric_SeqDense_SeqAIJ",MatMatMultNumeric_SeqDense_SeqAIJ);
3777: MatCreate_SeqAIJ_Inode(B);
3778: PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);
3779: return(0);
3780: }
3781: EXTERN_C_END
3785: /*
3786: Given a matrix generated with MatGetFactor() duplicates all the information in A into B
3787: */
3788: PetscErrorCode MatDuplicateNoCreate_SeqAIJ(Mat C,Mat A,MatDuplicateOption cpvalues,PetscBool mallocmatspace)
3789: {
3790: Mat_SeqAIJ *c,*a = (Mat_SeqAIJ*)A->data;
3792: PetscInt i,m = A->rmap->n;
3795: c = (Mat_SeqAIJ*)C->data;
3797: C->factortype = A->factortype;
3798: c->row = 0;
3799: c->col = 0;
3800: c->icol = 0;
3801: c->reallocs = 0;
3803: C->assembled = PETSC_TRUE;
3804:
3805: PetscLayoutReference(A->rmap,&C->rmap);
3806: PetscLayoutReference(A->cmap,&C->cmap);
3808: PetscMalloc2(m,PetscInt,&c->imax,m,PetscInt,&c->ilen);
3809: PetscLogObjectMemory(C, 2*m*sizeof(PetscInt));
3810: for (i=0; i<m; i++) {
3811: c->imax[i] = a->imax[i];
3812: c->ilen[i] = a->ilen[i];
3813: }
3815: /* allocate the matrix space */
3816: if (mallocmatspace){
3817: PetscMalloc3(a->i[m],PetscScalar,&c->a,a->i[m],PetscInt,&c->j,m+1,PetscInt,&c->i);
3818: PetscLogObjectMemory(C, a->i[m]*(sizeof(PetscScalar)+sizeof(PetscInt))+(m+1)*sizeof(PetscInt));
3819: c->singlemalloc = PETSC_TRUE;
3820: PetscMemcpy(c->i,a->i,(m+1)*sizeof(PetscInt));
3821: if (m > 0) {
3822: PetscMemcpy(c->j,a->j,(a->i[m])*sizeof(PetscInt));
3823: if (cpvalues == MAT_COPY_VALUES) {
3824: PetscMemcpy(c->a,a->a,(a->i[m])*sizeof(PetscScalar));
3825: } else {
3826: PetscMemzero(c->a,(a->i[m])*sizeof(PetscScalar));
3827: }
3828: }
3829: }
3831: c->ignorezeroentries = a->ignorezeroentries;
3832: c->roworiented = a->roworiented;
3833: c->nonew = a->nonew;
3834: if (a->diag) {
3835: PetscMalloc((m+1)*sizeof(PetscInt),&c->diag);
3836: PetscLogObjectMemory(C,(m+1)*sizeof(PetscInt));
3837: for (i=0; i<m; i++) {
3838: c->diag[i] = a->diag[i];
3839: }
3840: } else c->diag = 0;
3841: c->solve_work = 0;
3842: c->saved_values = 0;
3843: c->idiag = 0;
3844: c->ssor_work = 0;
3845: c->keepnonzeropattern = a->keepnonzeropattern;
3846: c->free_a = PETSC_TRUE;
3847: c->free_ij = PETSC_TRUE;
3848: c->xtoy = 0;
3849: c->XtoY = 0;
3851: c->rmax = a->rmax;
3852: c->nz = a->nz;
3853: c->maxnz = a->nz; /* Since we allocate exactly the right amount */
3854: C->preallocated = PETSC_TRUE;
3856: c->compressedrow.use = a->compressedrow.use;
3857: c->compressedrow.nrows = a->compressedrow.nrows;
3858: c->compressedrow.check = a->compressedrow.check;
3859: if (a->compressedrow.use){
3860: i = a->compressedrow.nrows;
3861: PetscMalloc2(i+1,PetscInt,&c->compressedrow.i,i,PetscInt,&c->compressedrow.rindex);
3862: PetscMemcpy(c->compressedrow.i,a->compressedrow.i,(i+1)*sizeof(PetscInt));
3863: PetscMemcpy(c->compressedrow.rindex,a->compressedrow.rindex,i*sizeof(PetscInt));
3864: } else {
3865: c->compressedrow.use = PETSC_FALSE;
3866: c->compressedrow.i = PETSC_NULL;
3867: c->compressedrow.rindex = PETSC_NULL;
3868: }
3869: C->same_nonzero = A->same_nonzero;
3870: MatDuplicate_SeqAIJ_Inode(A,cpvalues,&C);
3872: PetscFListDuplicate(((PetscObject)A)->qlist,&((PetscObject)C)->qlist);
3873: return(0);
3874: }
3878: PetscErrorCode MatDuplicate_SeqAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B)
3879: {
3883: MatCreate(((PetscObject)A)->comm,B);
3884: MatSetSizes(*B,A->rmap->n,A->cmap->n,A->rmap->n,A->cmap->n);
3885: MatSetBlockSizes(*B,A->rmap->bs,A->cmap->bs);
3886: MatSetType(*B,((PetscObject)A)->type_name);
3887: MatDuplicateNoCreate_SeqAIJ(*B,A,cpvalues,PETSC_TRUE);
3888: return(0);
3889: }
3893: PetscErrorCode MatLoad_SeqAIJ(Mat newMat, PetscViewer viewer)
3894: {
3895: Mat_SeqAIJ *a;
3897: PetscInt i,sum,nz,header[4],*rowlengths = 0,M,N,rows,cols;
3898: int fd;
3899: PetscMPIInt size;
3900: MPI_Comm comm;
3901: PetscInt bs = 1;
3902:
3904: PetscObjectGetComm((PetscObject)viewer,&comm);
3905: MPI_Comm_size(comm,&size);
3906: if (size > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"view must have one processor");
3908: PetscOptionsBegin(comm,PETSC_NULL,"Options for loading SEQAIJ matrix","Mat");
3909: PetscOptionsInt("-matload_block_size","Set the blocksize used to store the matrix","MatLoad",bs,&bs,PETSC_NULL);
3910: PetscOptionsEnd();
3912: PetscViewerBinaryGetDescriptor(viewer,&fd);
3913: PetscBinaryRead(fd,header,4,PETSC_INT);
3914: if (header[0] != MAT_FILE_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"not matrix object in file");
3915: M = header[1]; N = header[2]; nz = header[3];
3917: if (nz < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format on disk,cannot load as SeqAIJ");
3919: /* read in row lengths */
3920: PetscMalloc(M*sizeof(PetscInt),&rowlengths);
3921: PetscBinaryRead(fd,rowlengths,M,PETSC_INT);
3923: /* check if sum of rowlengths is same as nz */
3924: for (i=0,sum=0; i< M; i++) sum +=rowlengths[i];
3925: 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);
3927: /* set global size if not set already*/
3928: if (newMat->rmap->n < 0 && newMat->rmap->N < 0 && newMat->cmap->n < 0 && newMat->cmap->N < 0) {
3929: MatSetSizes(newMat,PETSC_DECIDE,PETSC_DECIDE,M,N);
3930: } else {
3931: /* if sizes and type are already set, check if the vector global sizes are correct */
3932: MatGetSize(newMat,&rows,&cols);
3933: if (rows < 0 && cols < 0){ /* user might provide local size instead of global size */
3934: MatGetLocalSize(newMat,&rows,&cols);
3935: }
3936: 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);
3937: }
3938: MatSeqAIJSetPreallocation_SeqAIJ(newMat,0,rowlengths);
3939: a = (Mat_SeqAIJ*)newMat->data;
3941: PetscBinaryRead(fd,a->j,nz,PETSC_INT);
3943: /* read in nonzero values */
3944: PetscBinaryRead(fd,a->a,nz,PETSC_SCALAR);
3946: /* set matrix "i" values */
3947: a->i[0] = 0;
3948: for (i=1; i<= M; i++) {
3949: a->i[i] = a->i[i-1] + rowlengths[i-1];
3950: a->ilen[i-1] = rowlengths[i-1];
3951: }
3952: PetscFree(rowlengths);
3954: MatAssemblyBegin(newMat,MAT_FINAL_ASSEMBLY);
3955: MatAssemblyEnd(newMat,MAT_FINAL_ASSEMBLY);
3956: if (bs > 1) {MatSetBlockSize(newMat,bs);}
3957: return(0);
3958: }
3962: PetscErrorCode MatEqual_SeqAIJ(Mat A,Mat B,PetscBool * flg)
3963: {
3964: Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data,*b = (Mat_SeqAIJ *)B->data;
3966: #if defined(PETSC_USE_COMPLEX)
3967: PetscInt k;
3968: #endif
3971: /* If the matrix dimensions are not equal,or no of nonzeros */
3972: if ((A->rmap->n != B->rmap->n) || (A->cmap->n != B->cmap->n) ||(a->nz != b->nz)) {
3973: *flg = PETSC_FALSE;
3974: return(0);
3975: }
3976:
3977: /* if the a->i are the same */
3978: PetscMemcmp(a->i,b->i,(A->rmap->n+1)*sizeof(PetscInt),flg);
3979: if (!*flg) return(0);
3980:
3981: /* if a->j are the same */
3982: PetscMemcmp(a->j,b->j,(a->nz)*sizeof(PetscInt),flg);
3983: if (!*flg) return(0);
3984:
3985: /* if a->a are the same */
3986: #if defined(PETSC_USE_COMPLEX)
3987: for (k=0; k<a->nz; k++){
3988: if (PetscRealPart(a->a[k]) != PetscRealPart(b->a[k]) || PetscImaginaryPart(a->a[k]) != PetscImaginaryPart(b->a[k])){
3989: *flg = PETSC_FALSE;
3990: return(0);
3991: }
3992: }
3993: #else
3994: PetscMemcmp(a->a,b->a,(a->nz)*sizeof(PetscScalar),flg);
3995: #endif
3996: return(0);
3997: }
4001: /*@
4002: MatCreateSeqAIJWithArrays - Creates an sequential AIJ matrix using matrix elements (in CSR format)
4003: provided by the user.
4005: Collective on MPI_Comm
4007: Input Parameters:
4008: + comm - must be an MPI communicator of size 1
4009: . m - number of rows
4010: . n - number of columns
4011: . i - row indices
4012: . j - column indices
4013: - a - matrix values
4015: Output Parameter:
4016: . mat - the matrix
4018: Level: intermediate
4020: Notes:
4021: The i, j, and a arrays are not copied by this routine, the user must free these arrays
4022: once the matrix is destroyed and not before
4024: You cannot set new nonzero locations into this matrix, that will generate an error.
4026: The i and j indices are 0 based
4028: The format which is used for the sparse matrix input, is equivalent to a
4029: row-major ordering.. i.e for the following matrix, the input data expected is
4030: as shown:
4032: 1 0 0
4033: 2 0 3
4034: 4 5 6
4036: i = {0,1,3,6} [size = nrow+1 = 3+1]
4037: j = {0,0,2,0,1,2} [size = nz = 6]; values must be sorted for each row
4038: v = {1,2,3,4,5,6} [size = nz = 6]
4040:
4041: .seealso: MatCreate(), MatCreateAIJ(), MatCreateSeqAIJ(), MatCreateMPIAIJWithArrays(), MatMPIAIJSetPreallocationCSR()
4043: @*/
4044: PetscErrorCode MatCreateSeqAIJWithArrays(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt* i,PetscInt*j,PetscScalar *a,Mat *mat)
4045: {
4047: PetscInt ii;
4048: Mat_SeqAIJ *aij;
4049: #if defined(PETSC_USE_DEBUG)
4050: PetscInt jj;
4051: #endif
4054: if (i[0]) {
4055: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0");
4056: }
4057: MatCreate(comm,mat);
4058: MatSetSizes(*mat,m,n,m,n);
4059: /* MatSetBlockSizes(*mat,,); */
4060: MatSetType(*mat,MATSEQAIJ);
4061: MatSeqAIJSetPreallocation_SeqAIJ(*mat,MAT_SKIP_ALLOCATION,0);
4062: aij = (Mat_SeqAIJ*)(*mat)->data;
4063: PetscMalloc2(m,PetscInt,&aij->imax,m,PetscInt,&aij->ilen);
4065: aij->i = i;
4066: aij->j = j;
4067: aij->a = a;
4068: aij->singlemalloc = PETSC_FALSE;
4069: aij->nonew = -1; /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/
4070: aij->free_a = PETSC_FALSE;
4071: aij->free_ij = PETSC_FALSE;
4073: for (ii=0; ii<m; ii++) {
4074: aij->ilen[ii] = aij->imax[ii] = i[ii+1] - i[ii];
4075: #if defined(PETSC_USE_DEBUG)
4076: 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]);
4077: for (jj=i[ii]+1; jj<i[ii+1]; jj++) {
4078: 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);
4079: 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);
4080: }
4081: #endif
4082: }
4083: #if defined(PETSC_USE_DEBUG)
4084: for (ii=0; ii<aij->i[m]; ii++) {
4085: if (j[ii] < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column index at location = %d index = %d",ii,j[ii]);
4086: 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]);
4087: }
4088: #endif
4090: MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);
4091: MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);
4092: return(0);
4093: }
4096: /*@C
4097: MatCreateSeqAIJFromTriple - Creates an sequential AIJ matrix using matrix elements (in COO format)
4098: provided by the user.
4100: Collective on MPI_Comm
4102: Input Parameters:
4103: + comm - must be an MPI communicator of size 1
4104: . m - number of rows
4105: . n - number of columns
4106: . i - row indices
4107: . j - column indices
4108: . a - matrix values
4109: . nz - number of nonzeros
4110: - idx - 0 or 1 based
4112: Output Parameter:
4113: . mat - the matrix
4115: Level: intermediate
4117: Notes:
4118: The i and j indices are 0 based
4120: The format which is used for the sparse matrix input, is equivalent to a
4121: row-major ordering.. i.e for the following matrix, the input data expected is
4122: as shown:
4124: 1 0 0
4125: 2 0 3
4126: 4 5 6
4128: i = {0,1,1,2,2,2}
4129: j = {0,0,2,0,1,2}
4130: v = {1,2,3,4,5,6}
4132:
4133: .seealso: MatCreate(), MatCreateAIJ(), MatCreateSeqAIJ(), MatCreateSeqAIJWithArrays(), MatMPIAIJSetPreallocationCSR()
4135: @*/
4136: PetscErrorCode MatCreateSeqAIJFromTriple(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt* i,PetscInt*j,PetscScalar *a,Mat *mat,PetscInt nz,PetscBool idx)
4137: {
4139: PetscInt ii, *nnz, one = 1,row,col;
4143: PetscMalloc(m*sizeof(PetscInt),&nnz);
4144: PetscMemzero(nnz,m*sizeof(PetscInt));
4145: for (ii = 0; ii < nz; ii++){
4146: nnz[i[ii]] += 1;
4147: }
4148: MatCreate(comm,mat);
4149: MatSetSizes(*mat,m,n,m,n);
4150: /* MatSetBlockSizes(*mat,,); */
4151: MatSetType(*mat,MATSEQAIJ);
4152: MatSeqAIJSetPreallocation_SeqAIJ(*mat,0,nnz);
4153: for (ii = 0; ii < nz; ii++){
4154: if (idx){
4155: row = i[ii] - 1;
4156: col = j[ii] - 1;
4157: } else {
4158: row = i[ii];
4159: col = j[ii];
4160: }
4161: MatSetValues(*mat,one,&row,one,&col,&a[ii],ADD_VALUES);
4162: }
4163: MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);
4164: MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);
4165: PetscFree(nnz);
4166: return(0);
4167: }
4171: PetscErrorCode MatSetColoring_SeqAIJ(Mat A,ISColoring coloring)
4172: {
4174: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
4177: if (coloring->ctype == IS_COLORING_GLOBAL) {
4178: ISColoringReference(coloring);
4179: a->coloring = coloring;
4180: } else if (coloring->ctype == IS_COLORING_GHOSTED) {
4181: PetscInt i,*larray;
4182: ISColoring ocoloring;
4183: ISColoringValue *colors;
4185: /* set coloring for diagonal portion */
4186: PetscMalloc(A->cmap->n*sizeof(PetscInt),&larray);
4187: for (i=0; i<A->cmap->n; i++) {
4188: larray[i] = i;
4189: }
4190: ISGlobalToLocalMappingApply(A->cmap->mapping,IS_GTOLM_MASK,A->cmap->n,larray,PETSC_NULL,larray);
4191: PetscMalloc(A->cmap->n*sizeof(ISColoringValue),&colors);
4192: for (i=0; i<A->cmap->n; i++) {
4193: colors[i] = coloring->colors[larray[i]];
4194: }
4195: PetscFree(larray);
4196: ISColoringCreate(PETSC_COMM_SELF,coloring->n,A->cmap->n,colors,&ocoloring);
4197: a->coloring = ocoloring;
4198: }
4199: return(0);
4200: }
4202: #if defined(PETSC_HAVE_ADIC)
4203: EXTERN_C_BEGIN
4204: #include <adic/ad_utils.h>
4205: EXTERN_C_END
4209: PetscErrorCode MatSetValuesAdic_SeqAIJ(Mat A,void *advalues)
4210: {
4211: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
4212: PetscInt m = A->rmap->n,*ii = a->i,*jj = a->j,nz,i,j,nlen;
4213: PetscScalar *v = a->a,*values = ((PetscScalar*)advalues)+1;
4214: ISColoringValue *color;
4217: if (!a->coloring) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Coloring not set for matrix");
4218: nlen = PetscADGetDerivTypeSize()/sizeof(PetscScalar);
4219: color = a->coloring->colors;
4220: /* loop over rows */
4221: for (i=0; i<m; i++) {
4222: nz = ii[i+1] - ii[i];
4223: /* loop over columns putting computed value into matrix */
4224: for (j=0; j<nz; j++) {
4225: *v++ = values[color[*jj++]];
4226: }
4227: values += nlen; /* jump to next row of derivatives */
4228: }
4229: return(0);
4230: }
4231: #endif
4235: PetscErrorCode MatSetValuesAdifor_SeqAIJ(Mat A,PetscInt nl,void *advalues)
4236: {
4237: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
4238: PetscInt m = A->rmap->n,*ii = a->i,*jj = a->j,nz,i,j;
4239: MatScalar *v = a->a;
4240: PetscScalar *values = (PetscScalar *)advalues;
4241: ISColoringValue *color;
4244: if (!a->coloring) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Coloring not set for matrix");
4245: color = a->coloring->colors;
4246: /* loop over rows */
4247: for (i=0; i<m; i++) {
4248: nz = ii[i+1] - ii[i];
4249: /* loop over columns putting computed value into matrix */
4250: for (j=0; j<nz; j++) {
4251: *v++ = values[color[*jj++]];
4252: }
4253: values += nl; /* jump to next row of derivatives */
4254: }
4255: return(0);
4256: }
4258: /*
4259: Special version for direct calls from Fortran
4260: */
4261: #include <petsc-private/fortranimpl.h>
4262: #if defined(PETSC_HAVE_FORTRAN_CAPS)
4263: #define matsetvaluesseqaij_ MATSETVALUESSEQAIJ
4264: #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
4265: #define matsetvaluesseqaij_ matsetvaluesseqaij
4266: #endif
4268: /* Change these macros so can be used in void function */
4269: #undef CHKERRQ
4270: #define CHKERRQ(ierr) CHKERRABORT(((PetscObject)A)->comm,ierr)
4271: #undef SETERRQ2
4272: #define SETERRQ2(comm,ierr,b,c,d) CHKERRABORT(comm,ierr)
4273: #undef SETERRQ3
4274: #define SETERRQ3(comm,ierr,b,c,d,e) CHKERRABORT(comm,ierr)
4276: EXTERN_C_BEGIN
4279: void PETSC_STDCALL matsetvaluesseqaij_(Mat *AA,PetscInt *mm,const PetscInt im[],PetscInt *nn,const PetscInt in[],const PetscScalar v[],InsertMode *isis, PetscErrorCode *_ierr)
4280: {
4281: Mat A = *AA;
4282: PetscInt m = *mm, n = *nn;
4283: InsertMode is = *isis;
4284: Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
4285: PetscInt *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N;
4286: PetscInt *imax,*ai,*ailen;
4288: PetscInt *aj,nonew = a->nonew,lastcol = -1;
4289: MatScalar *ap,value,*aa;
4290: PetscBool ignorezeroentries = a->ignorezeroentries;
4291: PetscBool roworiented = a->roworiented;
4294: MatCheckPreallocated(A,1);
4295: imax = a->imax;
4296: ai = a->i;
4297: ailen = a->ilen;
4298: aj = a->j;
4299: aa = a->a;
4301: for (k=0; k<m; k++) { /* loop over added rows */
4302: row = im[k];
4303: if (row < 0) continue;
4304: #if defined(PETSC_USE_DEBUG)
4305: if (row >= A->rmap->n) SETERRABORT(((PetscObject)A)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Row too large");
4306: #endif
4307: rp = aj + ai[row]; ap = aa + ai[row];
4308: rmax = imax[row]; nrow = ailen[row];
4309: low = 0;
4310: high = nrow;
4311: for (l=0; l<n; l++) { /* loop over added columns */
4312: if (in[l] < 0) continue;
4313: #if defined(PETSC_USE_DEBUG)
4314: if (in[l] >= A->cmap->n) SETERRABORT(((PetscObject)A)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Column too large");
4315: #endif
4316: col = in[l];
4317: if (roworiented) {
4318: value = v[l + k*n];
4319: } else {
4320: value = v[k + l*m];
4321: }
4322: if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue;
4324: if (col <= lastcol) low = 0; else high = nrow;
4325: lastcol = col;
4326: while (high-low > 5) {
4327: t = (low+high)/2;
4328: if (rp[t] > col) high = t;
4329: else low = t;
4330: }
4331: for (i=low; i<high; i++) {
4332: if (rp[i] > col) break;
4333: if (rp[i] == col) {
4334: if (is == ADD_VALUES) ap[i] += value;
4335: else ap[i] = value;
4336: goto noinsert;
4337: }
4338: }
4339: if (value == 0.0 && ignorezeroentries) goto noinsert;
4340: if (nonew == 1) goto noinsert;
4341: if (nonew == -1) SETERRABORT(((PetscObject)A)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero in the matrix");
4342: MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
4343: N = nrow++ - 1; a->nz++; high++;
4344: /* shift up all the later entries in this row */
4345: for (ii=N; ii>=i; ii--) {
4346: rp[ii+1] = rp[ii];
4347: ap[ii+1] = ap[ii];
4348: }
4349: rp[i] = col;
4350: ap[i] = value;
4351: noinsert:;
4352: low = i + 1;
4353: }
4354: ailen[row] = nrow;
4355: }
4356: A->same_nonzero = PETSC_FALSE;
4357: PetscFunctionReturnVoid();
4358: }
4359: EXTERN_C_END