Actual source code: aij.c

  1: #define PETSCMAT_DLL

  3: /*
  4:     Defines the basic matrix operations for the AIJ (compressed row)
  5:   matrix storage format.
  6: */

 8:  #include src/mat/impls/aij/seq/aij.h
 9:  #include src/inline/spops.h
 10:  #include src/inline/dot.h
 11:  #include petscbt.h

 15: PetscErrorCode  MatDiagonalSet_SeqAIJ(Mat Y,Vec D,InsertMode is)
 16: {
 18:   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*) Y->data;
 19:   PetscInt       i,*diag, m = Y->rmap.n;
 20:   PetscScalar    *v,*aa = aij->a;
 21:   PetscTruth     missing;

 24:   if (Y->assembled) {
 25:     MatMissingDiagonal_SeqAIJ(Y,&missing,PETSC_NULL);
 26:     if (!missing) {
 27:       diag = aij->diag;
 28:       VecGetArray(D,&v);
 29:       if (is == INSERT_VALUES) {
 30:         for (i=0; i<m; i++) {
 31:           aa[diag[i]] = v[i];
 32:         }
 33:       } else {
 34:         for (i=0; i<m; i++) {
 35:           aa[diag[i]] += v[i];
 36:         }
 37:       }
 38:       VecRestoreArray(D,&v);
 39:       return(0);
 40:     }
 41:   }
 42:   MatDiagonalSet_Default(Y,D,is);
 43:   return(0);
 44: }

 48: PetscErrorCode MatGetRowIJ_SeqAIJ(Mat A,PetscInt oshift,PetscTruth symmetric,PetscInt *m,PetscInt *ia[],PetscInt *ja[],PetscTruth *done)
 49: {
 50:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
 52:   PetscInt       i,ishift;
 53: 
 55:   *m     = A->rmap.n;
 56:   if (!ia) return(0);
 57:   ishift = 0;
 58:   if (symmetric && !A->structurally_symmetric) {
 59:     MatToSymmetricIJ_SeqAIJ(A->rmap.n,a->i,a->j,ishift,oshift,ia,ja);
 60:   } else if (oshift == 1) {
 61:     PetscInt nz = a->i[A->rmap.n];
 62:     /* malloc space and  add 1 to i and j indices */
 63:     PetscMalloc((A->rmap.n+1)*sizeof(PetscInt),ia);
 64:     PetscMalloc((nz+1)*sizeof(PetscInt),ja);
 65:     for (i=0; i<nz; i++) (*ja)[i] = a->j[i] + 1;
 66:     for (i=0; i<A->rmap.n+1; i++) (*ia)[i] = a->i[i] + 1;
 67:   } else {
 68:     *ia = a->i; *ja = a->j;
 69:   }
 70:   return(0);
 71: }

 75: PetscErrorCode MatRestoreRowIJ_SeqAIJ(Mat A,PetscInt oshift,PetscTruth symmetric,PetscInt *n,PetscInt *ia[],PetscInt *ja[],PetscTruth *done)
 76: {
 78: 
 80:   if (!ia) return(0);
 81:   if ((symmetric && !A->structurally_symmetric) || oshift == 1) {
 82:     PetscFree(*ia);
 83:     PetscFree(*ja);
 84:   }
 85:   return(0);
 86: }

 90: PetscErrorCode MatGetColumnIJ_SeqAIJ(Mat A,PetscInt oshift,PetscTruth symmetric,PetscInt *nn,PetscInt *ia[],PetscInt *ja[],PetscTruth *done)
 91: {
 92:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
 94:   PetscInt       i,*collengths,*cia,*cja,n = A->cmap.n,m = A->rmap.n;
 95:   PetscInt       nz = a->i[m],row,*jj,mr,col;
 96: 
 98:   *nn = n;
 99:   if (!ia) return(0);
100:   if (symmetric) {
101:     MatToSymmetricIJ_SeqAIJ(A->rmap.n,a->i,a->j,0,oshift,ia,ja);
102:   } else {
103:     PetscMalloc((n+1)*sizeof(PetscInt),&collengths);
104:     PetscMemzero(collengths,n*sizeof(PetscInt));
105:     PetscMalloc((n+1)*sizeof(PetscInt),&cia);
106:     PetscMalloc((nz+1)*sizeof(PetscInt),&cja);
107:     jj = a->j;
108:     for (i=0; i<nz; i++) {
109:       collengths[jj[i]]++;
110:     }
111:     cia[0] = oshift;
112:     for (i=0; i<n; i++) {
113:       cia[i+1] = cia[i] + collengths[i];
114:     }
115:     PetscMemzero(collengths,n*sizeof(PetscInt));
116:     jj   = a->j;
117:     for (row=0; row<m; row++) {
118:       mr = a->i[row+1] - a->i[row];
119:       for (i=0; i<mr; i++) {
120:         col = *jj++;
121:         cja[cia[col] + collengths[col]++ - oshift] = row + oshift;
122:       }
123:     }
124:     PetscFree(collengths);
125:     *ia = cia; *ja = cja;
126:   }
127:   return(0);
128: }

132: PetscErrorCode MatRestoreColumnIJ_SeqAIJ(Mat A,PetscInt oshift,PetscTruth symmetric,PetscInt *n,PetscInt *ia[],PetscInt *ja[],PetscTruth *done)
133: {

137:   if (!ia) return(0);

139:   PetscFree(*ia);
140:   PetscFree(*ja);
141: 
142:   return(0);
143: }

147: PetscErrorCode MatSetValuesRow_SeqAIJ(Mat A,PetscInt row,const PetscScalar v[])
148: {
149:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
150:   PetscInt       *ai = a->i;

154:   PetscMemcpy(a->a+ai[row],v,(ai[row+1]-ai[row])*sizeof(PetscScalar));
155:   return(0);
156: }

158: #define CHUNKSIZE   15

162: PetscErrorCode MatSetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
163: {
164:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
165:   PetscInt       *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N;
166:   PetscInt       *imax = a->imax,*ai = a->i,*ailen = a->ilen;
168:   PetscInt       *aj = a->j,nonew = a->nonew,lastcol = -1;
169:   PetscScalar    *ap,value,*aa = a->a;
170:   PetscTruth     ignorezeroentries = ((a->ignorezeroentries && is == ADD_VALUES) ? PETSC_TRUE:PETSC_FALSE);
171:   PetscTruth     roworiented = a->roworiented;

174:   for (k=0; k<m; k++) { /* loop over added rows */
175:     row  = im[k];
176:     if (row < 0) continue;
177: #if defined(PETSC_USE_DEBUG)  
178:     if (row >= A->rmap.n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",row,A->rmap.n-1);
179: #endif
180:     rp   = aj + ai[row]; ap = aa + ai[row];
181:     rmax = imax[row]; nrow = ailen[row];
182:     low  = 0;
183:     high = nrow;
184:     for (l=0; l<n; l++) { /* loop over added columns */
185:       if (in[l] < 0) continue;
186: #if defined(PETSC_USE_DEBUG)  
187:       if (in[l] >= A->cmap.n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",in[l],A->cmap.n-1);
188: #endif
189:       col = in[l];
190:       if (roworiented) {
191:         value = v[l + k*n];
192:       } else {
193:         value = v[k + l*m];
194:       }
195:       if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue;

197:       if (col <= lastcol) low = 0; else high = nrow;
198:       lastcol = col;
199:       while (high-low > 5) {
200:         t = (low+high)/2;
201:         if (rp[t] > col) high = t;
202:         else             low  = t;
203:       }
204:       for (i=low; i<high; i++) {
205:         if (rp[i] > col) break;
206:         if (rp[i] == col) {
207:           if (is == ADD_VALUES) ap[i] += value;
208:           else                  ap[i] = value;
209:           goto noinsert;
210:         }
211:       }
212:       if (value == 0.0 && ignorezeroentries) goto noinsert;
213:       if (nonew == 1) goto noinsert;
214:       if (nonew == -1) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero at (%D,%D) in the matrix",row,col);
215:       MatSeqXAIJReallocateAIJ(A,A->rmap.n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew);
216:       N = nrow++ - 1; a->nz++; high++;
217:       /* shift up all the later entries in this row */
218:       for (ii=N; ii>=i; ii--) {
219:         rp[ii+1] = rp[ii];
220:         ap[ii+1] = ap[ii];
221:       }
222:       rp[i] = col;
223:       ap[i] = value;
224:       noinsert:;
225:       low = i + 1;
226:     }
227:     ailen[row] = nrow;
228:   }
229:   A->same_nonzero = PETSC_FALSE;
230:   return(0);
231: }


236: PetscErrorCode MatGetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],PetscScalar v[])
237: {
238:   Mat_SeqAIJ   *a = (Mat_SeqAIJ*)A->data;
239:   PetscInt     *rp,k,low,high,t,row,nrow,i,col,l,*aj = a->j;
240:   PetscInt     *ai = a->i,*ailen = a->ilen;
241:   PetscScalar  *ap,*aa = a->a,zero = 0.0;

244:   for (k=0; k<m; k++) { /* loop over rows */
245:     row  = im[k];
246:     if (row < 0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Negative row: %D",row);
247:     if (row >= A->rmap.n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",row,A->rmap.n-1);
248:     rp   = aj + ai[row]; ap = aa + ai[row];
249:     nrow = ailen[row];
250:     for (l=0; l<n; l++) { /* loop over columns */
251:       if (in[l] < 0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Negative column: %D",in[l]);
252:       if (in[l] >= A->cmap.n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",in[l],A->cmap.n-1);
253:       col = in[l] ;
254:       high = nrow; low = 0; /* assume unsorted */
255:       while (high-low > 5) {
256:         t = (low+high)/2;
257:         if (rp[t] > col) high = t;
258:         else             low  = t;
259:       }
260:       for (i=low; i<high; i++) {
261:         if (rp[i] > col) break;
262:         if (rp[i] == col) {
263:           *v++ = ap[i];
264:           goto finished;
265:         }
266:       }
267:       *v++ = zero;
268:       finished:;
269:     }
270:   }
271:   return(0);
272: }


277: PetscErrorCode MatView_SeqAIJ_Binary(Mat A,PetscViewer viewer)
278: {
279:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
281:   PetscInt       i,*col_lens;
282:   int            fd;

285:   PetscViewerBinaryGetDescriptor(viewer,&fd);
286:   PetscMalloc((4+A->rmap.n)*sizeof(PetscInt),&col_lens);
287:   col_lens[0] = MAT_FILE_COOKIE;
288:   col_lens[1] = A->rmap.n;
289:   col_lens[2] = A->cmap.n;
290:   col_lens[3] = a->nz;

292:   /* store lengths of each row and write (including header) to file */
293:   for (i=0; i<A->rmap.n; i++) {
294:     col_lens[4+i] = a->i[i+1] - a->i[i];
295:   }
296:   PetscBinaryWrite(fd,col_lens,4+A->rmap.n,PETSC_INT,PETSC_TRUE);
297:   PetscFree(col_lens);

299:   /* store column indices (zero start index) */
300:   PetscBinaryWrite(fd,a->j,a->nz,PETSC_INT,PETSC_FALSE);

302:   /* store nonzero values */
303:   PetscBinaryWrite(fd,a->a,a->nz,PETSC_SCALAR,PETSC_FALSE);
304:   return(0);
305: }

307: EXTERN PetscErrorCode MatSeqAIJFactorInfo_Matlab(Mat,PetscViewer);

311: PetscErrorCode MatView_SeqAIJ_ASCII(Mat A,PetscViewer viewer)
312: {
313:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
314:   PetscErrorCode    ierr;
315:   PetscInt          i,j,m = A->rmap.n,shift=0;
316:   const char        *name;
317:   PetscViewerFormat format;

320:   PetscObjectGetName((PetscObject)A,&name);
321:   PetscViewerGetFormat(viewer,&format);
322:   if (format == PETSC_VIEWER_ASCII_MATLAB) {
323:     PetscInt nofinalvalue = 0;
324:     if ((a->i[m] == a->i[m-1]) || (a->j[a->nz-1] != A->cmap.n-!shift)) {
325:       nofinalvalue = 1;
326:     }
327:     PetscViewerASCIIUseTabs(viewer,PETSC_NO);
328:     PetscViewerASCIIPrintf(viewer,"%% Size = %D %D \n",m,A->cmap.n);
329:     PetscViewerASCIIPrintf(viewer,"%% Nonzeros = %D \n",a->nz);
330:     PetscViewerASCIIPrintf(viewer,"zzz = zeros(%D,3);\n",a->nz+nofinalvalue);
331:     PetscViewerASCIIPrintf(viewer,"zzz = [\n");

333:     for (i=0; i<m; i++) {
334:       for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
335: #if defined(PETSC_USE_COMPLEX)
336:         PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e + %18.16ei \n",i+1,a->j[j]+!shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));
337: #else
338:         PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e\n",i+1,a->j[j]+!shift,a->a[j]);
339: #endif
340:       }
341:     }
342:     if (nofinalvalue) {
343:       PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e\n",m,A->cmap.n,0.0);
344:     }
345:     PetscViewerASCIIPrintf(viewer,"];\n %s = spconvert(zzz);\n",name);
346:     PetscViewerASCIIUseTabs(viewer,PETSC_YES);
347:   } else if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO) {
348:      return(0);
349:   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
350:     PetscViewerASCIIUseTabs(viewer,PETSC_NO);
351:     for (i=0; i<m; i++) {
352:       PetscViewerASCIIPrintf(viewer,"row %D:",i);
353:       for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
354: #if defined(PETSC_USE_COMPLEX)
355:         if (PetscImaginaryPart(a->a[j]) > 0.0 && PetscRealPart(a->a[j]) != 0.0) {
356:           PetscViewerASCIIPrintf(viewer," (%D, %G + %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));
357:         } else if (PetscImaginaryPart(a->a[j]) < 0.0 && PetscRealPart(a->a[j]) != 0.0) {
358:           PetscViewerASCIIPrintf(viewer," (%D, %G - %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),-PetscImaginaryPart(a->a[j]));
359:         } else if (PetscRealPart(a->a[j]) != 0.0) {
360:           PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,PetscRealPart(a->a[j]));
361:         }
362: #else
363:         if (a->a[j] != 0.0) {PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,a->a[j]);}
364: #endif
365:       }
366:       PetscViewerASCIIPrintf(viewer,"\n");
367:     }
368:     PetscViewerASCIIUseTabs(viewer,PETSC_YES);
369:   } else if (format == PETSC_VIEWER_ASCII_SYMMODU) {
370:     PetscInt nzd=0,fshift=1,*sptr;
371:     PetscViewerASCIIUseTabs(viewer,PETSC_NO);
372:     PetscMalloc((m+1)*sizeof(PetscInt),&sptr);
373:     for (i=0; i<m; i++) {
374:       sptr[i] = nzd+1;
375:       for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
376:         if (a->j[j] >= i) {
377: #if defined(PETSC_USE_COMPLEX)
378:           if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) nzd++;
379: #else
380:           if (a->a[j] != 0.0) nzd++;
381: #endif
382:         }
383:       }
384:     }
385:     sptr[m] = nzd+1;
386:     PetscViewerASCIIPrintf(viewer," %D %D\n\n",m,nzd);
387:     for (i=0; i<m+1; i+=6) {
388:       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]);}
389:       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]);}
390:       else if (i+2<m) {PetscViewerASCIIPrintf(viewer," %D %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2],sptr[i+3]);}
391:       else if (i+1<m) {PetscViewerASCIIPrintf(viewer," %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2]);}
392:       else if (i<m)   {PetscViewerASCIIPrintf(viewer," %D %D\n",sptr[i],sptr[i+1]);}
393:       else            {PetscViewerASCIIPrintf(viewer," %D\n",sptr[i]);}
394:     }
395:     PetscViewerASCIIPrintf(viewer,"\n");
396:     PetscFree(sptr);
397:     for (i=0; i<m; i++) {
398:       for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
399:         if (a->j[j] >= i) {PetscViewerASCIIPrintf(viewer," %D ",a->j[j]+fshift);}
400:       }
401:       PetscViewerASCIIPrintf(viewer,"\n");
402:     }
403:     PetscViewerASCIIPrintf(viewer,"\n");
404:     for (i=0; i<m; i++) {
405:       for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
406:         if (a->j[j] >= i) {
407: #if defined(PETSC_USE_COMPLEX)
408:           if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) {
409:             PetscViewerASCIIPrintf(viewer," %18.16e %18.16e ",PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));
410:           }
411: #else
412:           if (a->a[j] != 0.0) {PetscViewerASCIIPrintf(viewer," %18.16e ",a->a[j]);}
413: #endif
414:         }
415:       }
416:       PetscViewerASCIIPrintf(viewer,"\n");
417:     }
418:     PetscViewerASCIIUseTabs(viewer,PETSC_YES);
419:   } else if (format == PETSC_VIEWER_ASCII_DENSE) {
420:     PetscInt         cnt = 0,jcnt;
421:     PetscScalar value;

423:     PetscViewerASCIIUseTabs(viewer,PETSC_NO);
424:     for (i=0; i<m; i++) {
425:       jcnt = 0;
426:       for (j=0; j<A->cmap.n; j++) {
427:         if (jcnt < a->i[i+1]-a->i[i] && j == a->j[cnt]) {
428:           value = a->a[cnt++];
429:           jcnt++;
430:         } else {
431:           value = 0.0;
432:         }
433: #if defined(PETSC_USE_COMPLEX)
434:         PetscViewerASCIIPrintf(viewer," %7.5e+%7.5e i ",PetscRealPart(value),PetscImaginaryPart(value));
435: #else
436:         PetscViewerASCIIPrintf(viewer," %7.5e ",value);
437: #endif
438:       }
439:       PetscViewerASCIIPrintf(viewer,"\n");
440:     }
441:     PetscViewerASCIIUseTabs(viewer,PETSC_YES);
442:   } else {
443:     PetscViewerASCIIUseTabs(viewer,PETSC_NO);
444:     for (i=0; i<m; i++) {
445:       PetscViewerASCIIPrintf(viewer,"row %D:",i);
446:       for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
447: #if defined(PETSC_USE_COMPLEX)
448:         if (PetscImaginaryPart(a->a[j]) > 0.0) {
449:           PetscViewerASCIIPrintf(viewer," (%D, %G + %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));
450:         } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
451:           PetscViewerASCIIPrintf(viewer," (%D, %G - %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),-PetscImaginaryPart(a->a[j]));
452:         } else {
453:           PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,PetscRealPart(a->a[j]));
454:         }
455: #else
456:         PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,a->a[j]);
457: #endif
458:       }
459:       PetscViewerASCIIPrintf(viewer,"\n");
460:     }
461:     PetscViewerASCIIUseTabs(viewer,PETSC_YES);
462:   }
463:   PetscViewerFlush(viewer);
464:   return(0);
465: }

469: PetscErrorCode MatView_SeqAIJ_Draw_Zoom(PetscDraw draw,void *Aa)
470: {
471:   Mat               A = (Mat) Aa;
472:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
473:   PetscErrorCode    ierr;
474:   PetscInt          i,j,m = A->rmap.n,color;
475:   PetscReal         xl,yl,xr,yr,x_l,x_r,y_l,y_r,maxv = 0.0;
476:   PetscViewer       viewer;
477:   PetscViewerFormat format;

480:   PetscObjectQuery((PetscObject)A,"Zoomviewer",(PetscObject*)&viewer);
481:   PetscViewerGetFormat(viewer,&format);

483:   PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);
484:   /* loop over matrix elements drawing boxes */

486:   if (format != PETSC_VIEWER_DRAW_CONTOUR) {
487:     /* Blue for negative, Cyan for zero and  Red for positive */
488:     color = PETSC_DRAW_BLUE;
489:     for (i=0; i<m; i++) {
490:       y_l = m - i - 1.0; y_r = y_l + 1.0;
491:       for (j=a->i[i]; j<a->i[i+1]; j++) {
492:         x_l = a->j[j] ; x_r = x_l + 1.0;
493: #if defined(PETSC_USE_COMPLEX)
494:         if (PetscRealPart(a->a[j]) >=  0.) continue;
495: #else
496:         if (a->a[j] >=  0.) continue;
497: #endif
498:         PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);
499:       }
500:     }
501:     color = PETSC_DRAW_CYAN;
502:     for (i=0; i<m; i++) {
503:       y_l = m - i - 1.0; y_r = y_l + 1.0;
504:       for (j=a->i[i]; j<a->i[i+1]; j++) {
505:         x_l = a->j[j]; x_r = x_l + 1.0;
506:         if (a->a[j] !=  0.) continue;
507:         PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);
508:       }
509:     }
510:     color = PETSC_DRAW_RED;
511:     for (i=0; i<m; i++) {
512:       y_l = m - i - 1.0; y_r = y_l + 1.0;
513:       for (j=a->i[i]; j<a->i[i+1]; j++) {
514:         x_l = a->j[j]; x_r = x_l + 1.0;
515: #if defined(PETSC_USE_COMPLEX)
516:         if (PetscRealPart(a->a[j]) <=  0.) continue;
517: #else
518:         if (a->a[j] <=  0.) continue;
519: #endif
520:         PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);
521:       }
522:     }
523:   } else {
524:     /* use contour shading to indicate magnitude of values */
525:     /* first determine max of all nonzero values */
526:     PetscInt    nz = a->nz,count;
527:     PetscDraw   popup;
528:     PetscReal scale;

530:     for (i=0; i<nz; i++) {
531:       if (PetscAbsScalar(a->a[i]) > maxv) maxv = PetscAbsScalar(a->a[i]);
532:     }
533:     scale = (245.0 - PETSC_DRAW_BASIC_COLORS)/maxv;
534:     PetscDrawGetPopup(draw,&popup);
535:     if (popup) {PetscDrawScalePopup(popup,0.0,maxv);}
536:     count = 0;
537:     for (i=0; i<m; i++) {
538:       y_l = m - i - 1.0; y_r = y_l + 1.0;
539:       for (j=a->i[i]; j<a->i[i+1]; j++) {
540:         x_l = a->j[j]; x_r = x_l + 1.0;
541:         color = PETSC_DRAW_BASIC_COLORS + (PetscInt)(scale*PetscAbsScalar(a->a[count]));
542:         PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);
543:         count++;
544:       }
545:     }
546:   }
547:   return(0);
548: }

552: PetscErrorCode MatView_SeqAIJ_Draw(Mat A,PetscViewer viewer)
553: {
555:   PetscDraw      draw;
556:   PetscReal      xr,yr,xl,yl,h,w;
557:   PetscTruth     isnull;

560:   PetscViewerDrawGetDraw(viewer,0,&draw);
561:   PetscDrawIsNull(draw,&isnull);
562:   if (isnull) return(0);

564:   PetscObjectCompose((PetscObject)A,"Zoomviewer",(PetscObject)viewer);
565:   xr  = A->cmap.n; yr = A->rmap.n; h = yr/10.0; w = xr/10.0;
566:   xr += w;    yr += h;  xl = -w;     yl = -h;
567:   PetscDrawSetCoordinates(draw,xl,yl,xr,yr);
568:   PetscDrawZoom(draw,MatView_SeqAIJ_Draw_Zoom,A);
569:   PetscObjectCompose((PetscObject)A,"Zoomviewer",PETSC_NULL);
570:   return(0);
571: }

575: PetscErrorCode MatView_SeqAIJ(Mat A,PetscViewer viewer)
576: {
578:   PetscTruth     issocket,iascii,isbinary,isdraw;

581:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_SOCKET,&issocket);
582:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
583:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_BINARY,&isbinary);
584:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_DRAW,&isdraw);
585:   if (iascii) {
586:     MatView_SeqAIJ_ASCII(A,viewer);
587: #if defined(PETSC_USE_SOCKET_VIEWER)
588:   } else if (issocket) {
589:     Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
590:     PetscViewerSocketPutSparse_Private(viewer,A->rmap.n,A->cmap.n,a->nz,a->a,a->i,a->j);
591: #endif
592:   } else if (isbinary) {
593:     MatView_SeqAIJ_Binary(A,viewer);
594:   } else if (isdraw) {
595:     MatView_SeqAIJ_Draw(A,viewer);
596:   } else {
597:     SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported by SeqAIJ matrices",((PetscObject)viewer)->type_name);
598:   }
599:   MatView_Inode(A,viewer);
600:   return(0);
601: }

605: PetscErrorCode MatAssemblyEnd_SeqAIJ(Mat A,MatAssemblyType mode)
606: {
607:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
609:   PetscInt       fshift = 0,i,j,*ai = a->i,*aj = a->j,*imax = a->imax;
610:   PetscInt       m = A->rmap.n,*ip,N,*ailen = a->ilen,rmax = 0;
611:   PetscScalar    *aa = a->a,*ap;
612:   PetscReal      ratio=0.6;

615:   if (mode == MAT_FLUSH_ASSEMBLY) return(0);

617:   if (m) rmax = ailen[0]; /* determine row with most nonzeros */
618:   for (i=1; i<m; i++) {
619:     /* move each row back by the amount of empty slots (fshift) before it*/
620:     fshift += imax[i-1] - ailen[i-1];
621:     rmax   = PetscMax(rmax,ailen[i]);
622:     if (fshift) {
623:       ip = aj + ai[i] ;
624:       ap = aa + ai[i] ;
625:       N  = ailen[i];
626:       for (j=0; j<N; j++) {
627:         ip[j-fshift] = ip[j];
628:         ap[j-fshift] = ap[j];
629:       }
630:     }
631:     ai[i] = ai[i-1] + ailen[i-1];
632:   }
633:   if (m) {
634:     fshift += imax[m-1] - ailen[m-1];
635:     ai[m]  = ai[m-1] + ailen[m-1];
636:   }
637:   /* reset ilen and imax for each row */
638:   for (i=0; i<m; i++) {
639:     ailen[i] = imax[i] = ai[i+1] - ai[i];
640:   }
641:   a->nz = ai[m];

643:   MatMarkDiagonal_SeqAIJ(A);
644:   PetscInfo4(A,"Matrix size: %D X %D; storage space: %D unneeded,%D used\n",m,A->cmap.n,fshift,a->nz);
645:   PetscInfo1(A,"Number of mallocs during MatSetValues() is %D\n",a->reallocs);
646:   PetscInfo1(A,"Maximum nonzeros in any row is %D\n",rmax);
647:   a->reallocs          = 0;
648:   A->info.nz_unneeded  = (double)fshift;
649:   a->rmax              = rmax;

651:   /* check for zero rows. If found a large number of zero rows, use CompressedRow functions */
652:   Mat_CheckCompressedRow(A,&a->compressedrow,a->i,m,ratio);
653:   A->same_nonzero = PETSC_TRUE;

655:   MatAssemblyEnd_Inode(A,mode);
656:   return(0);
657: }

661: PetscErrorCode MatRealPart_SeqAIJ(Mat A)
662: {
663:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
664:   PetscInt       i,nz = a->nz;
665:   PetscScalar    *aa = a->a;

668:   for (i=0; i<nz; i++) aa[i] = PetscRealPart(aa[i]);
669:   return(0);
670: }

674: PetscErrorCode MatImaginaryPart_SeqAIJ(Mat A)
675: {
676:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
677:   PetscInt       i,nz = a->nz;
678:   PetscScalar    *aa = a->a;

681:   for (i=0; i<nz; i++) aa[i] = PetscImaginaryPart(aa[i]);
682:   return(0);
683: }

687: PetscErrorCode MatZeroEntries_SeqAIJ(Mat A)
688: {
689:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;

693:   PetscMemzero(a->a,(a->i[A->rmap.n])*sizeof(PetscScalar));
694:   return(0);
695: }

699: PetscErrorCode MatDestroy_SeqAIJ(Mat A)
700: {
701:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;

705: #if defined(PETSC_USE_LOG)
706:   PetscLogObjectState((PetscObject)A,"Rows=%D, Cols=%D, NZ=%D",A->rmap.n,A->cmap.n,a->nz);
707: #endif
708:   MatSeqXAIJFreeAIJ(A,&a->a,&a->j,&a->i);
709:   if (a->row) {
710:     ISDestroy(a->row);
711:   }
712:   if (a->col) {
713:     ISDestroy(a->col);
714:   }
715:   PetscFree(a->diag);
716:   PetscFree2(a->imax,a->ilen);
717:   PetscFree(a->idiag);
718:   PetscFree(a->solve_work);
719:   if (a->icol) {ISDestroy(a->icol);}
720:   PetscFree(a->saved_values);
721:   if (a->coloring) {ISColoringDestroy(a->coloring);}
722:   PetscFree(a->xtoy);
723:   if (a->compressedrow.use){PetscFree(a->compressedrow.i);}

725:   MatDestroy_Inode(A);

727:   PetscFree(a);

729:   PetscObjectComposeFunctionDynamic((PetscObject)A,"MatSeqAIJSetColumnIndices_C","",PETSC_NULL);
730:   PetscObjectComposeFunctionDynamic((PetscObject)A,"MatStoreValues_C","",PETSC_NULL);
731:   PetscObjectComposeFunctionDynamic((PetscObject)A,"MatRetrieveValues_C","",PETSC_NULL);
732:   PetscObjectComposeFunctionDynamic((PetscObject)A,"MatConvert_seqaij_seqsbaij_C","",PETSC_NULL);
733:   PetscObjectComposeFunctionDynamic((PetscObject)A,"MatConvert_seqaij_seqbaij_C","",PETSC_NULL);
734:   PetscObjectComposeFunctionDynamic((PetscObject)A,"MatConvert_seqaij_seqcsrperm_C","",PETSC_NULL);
735:   PetscObjectComposeFunctionDynamic((PetscObject)A,"MatIsTranspose_C","",PETSC_NULL);
736:   PetscObjectComposeFunctionDynamic((PetscObject)A,"MatSeqAIJSetPreallocation_C","",PETSC_NULL);
737:   PetscObjectComposeFunctionDynamic((PetscObject)A,"MatSeqAIJSetPreallocationCSR_C","",PETSC_NULL);
738:   PetscObjectComposeFunctionDynamic((PetscObject)A,"MatReorderForNonzeroDiagonal_C","",PETSC_NULL);
739:   return(0);
740: }

744: PetscErrorCode MatCompress_SeqAIJ(Mat A)
745: {
747:   return(0);
748: }

752: PetscErrorCode MatSetOption_SeqAIJ(Mat A,MatOption op)
753: {
754:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;

758:   switch (op) {
759:     case MAT_ROW_ORIENTED:
760:       a->roworiented       = PETSC_TRUE;
761:       break;
762:     case MAT_KEEP_ZEROED_ROWS:
763:       a->keepzeroedrows    = PETSC_TRUE;
764:       break;
765:     case MAT_COLUMN_ORIENTED:
766:       a->roworiented       = PETSC_FALSE;
767:       break;
768:     case MAT_COLUMNS_SORTED:
769:       a->sorted            = PETSC_TRUE;
770:       break;
771:     case MAT_COLUMNS_UNSORTED:
772:       a->sorted            = PETSC_FALSE;
773:       break;
774:     case MAT_NO_NEW_NONZERO_LOCATIONS:
775:       a->nonew             = 1;
776:       break;
777:     case MAT_NEW_NONZERO_LOCATION_ERR:
778:       a->nonew             = -1;
779:       break;
780:     case MAT_NEW_NONZERO_ALLOCATION_ERR:
781:       a->nonew             = -2;
782:       break;
783:     case MAT_YES_NEW_NONZERO_LOCATIONS:
784:       a->nonew             = 0;
785:       break;
786:     case MAT_IGNORE_ZERO_ENTRIES:
787:       a->ignorezeroentries = PETSC_TRUE;
788:       break;
789:     case MAT_USE_COMPRESSEDROW:
790:       a->compressedrow.use = PETSC_TRUE;
791:       break;
792:     case MAT_DO_NOT_USE_COMPRESSEDROW:
793:       a->compressedrow.use = PETSC_FALSE;
794:       break;
795:     case MAT_ROWS_SORTED:
796:     case MAT_ROWS_UNSORTED:
797:     case MAT_YES_NEW_DIAGONALS:
798:     case MAT_IGNORE_OFF_PROC_ENTRIES:
799:     case MAT_USE_HASH_TABLE:
800:       PetscInfo(A,"Option ignored\n");
801:       break;
802:     case MAT_NO_NEW_DIAGONALS:
803:       SETERRQ(PETSC_ERR_SUP,"MAT_NO_NEW_DIAGONALS");
804:     default:
805:       break;
806:   }
807:   MatSetOption_Inode(A,op);
808:   return(0);
809: }

813: PetscErrorCode MatGetDiagonal_SeqAIJ(Mat A,Vec v)
814: {
815:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
817:   PetscInt       i,j,n;
818:   PetscScalar    *x,zero = 0.0;

821:   VecSet(v,zero);
822:   VecGetArray(v,&x);
823:   VecGetLocalSize(v,&n);
824:   if (n != A->rmap.n) SETERRQ(PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
825:   for (i=0; i<A->rmap.n; i++) {
826:     for (j=a->i[i]; j<a->i[i+1]; j++) {
827:       if (a->j[j] == i) {
828:         x[i] = a->a[j];
829:         break;
830:       }
831:     }
832:   }
833:   VecRestoreArray(v,&x);
834:   return(0);
835: }

839: PetscErrorCode MatMultTransposeAdd_SeqAIJ(Mat A,Vec xx,Vec zz,Vec yy)
840: {
841:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
842:   PetscScalar       *x,*y;
843:   PetscErrorCode    ierr;
844:   PetscInt          m = A->rmap.n;
845: #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
846:   PetscScalar       *v,alpha;
847:   PetscInt          n,i,*idx,*ii,*ridx=PETSC_NULL;
848:   Mat_CompressedRow cprow = a->compressedrow;
849:   PetscTruth        usecprow = cprow.use;
850: #endif

853:   if (zz != yy) {VecCopy(zz,yy);}
854:   VecGetArray(xx,&x);
855:   VecGetArray(yy,&y);

857: #if defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
858:   fortranmulttransposeaddaij_(&m,x,a->i,a->j,a->a,y);
859: #else
860:   if (usecprow){
861:     m    = cprow.nrows;
862:     ii   = cprow.i;
863:     ridx = cprow.rindex;
864:   } else {
865:     ii = a->i;
866:   }
867:   for (i=0; i<m; i++) {
868:     idx   = a->j + ii[i] ;
869:     v     = a->a + ii[i] ;
870:     n     = ii[i+1] - ii[i];
871:     if (usecprow){
872:       alpha = x[ridx[i]];
873:     } else {
874:       alpha = x[i];
875:     }
876:     while (n-->0) {y[*idx++] += alpha * *v++;}
877:   }
878: #endif
879:   PetscLogFlops(2*a->nz);
880:   VecRestoreArray(xx,&x);
881:   VecRestoreArray(yy,&y);
882:   return(0);
883: }

887: PetscErrorCode MatMultTranspose_SeqAIJ(Mat A,Vec xx,Vec yy)
888: {
889:   PetscScalar    zero = 0.0;

893:   VecSet(yy,zero);
894:   MatMultTransposeAdd_SeqAIJ(A,xx,yy,yy);
895:   return(0);
896: }


901: PetscErrorCode MatMult_SeqAIJ(Mat A,Vec xx,Vec yy)
902: {
903:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
904:   PetscScalar    *x,*y,*aa;
906:   PetscInt       m=A->rmap.n,*aj,*ii;
907:   PetscInt       n,i,j,*ridx=PETSC_NULL;
908:   PetscScalar    sum;
909:   PetscTruth     usecprow=a->compressedrow.use;
910: #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTAIJ)
911:   PetscInt       jrow;
912: #endif

914: #if defined(PETSC_HAVE_PRAGMA_DISJOINT)
915: #pragma disjoint(*x,*y,*aa)
916: #endif

919:   VecGetArray(xx,&x);
920:   VecGetArray(yy,&y);
921:   aj  = a->j;
922:   aa  = a->a;
923:   ii  = a->i;
924:   if (usecprow){ /* use compressed row format */
925:     m    = a->compressedrow.nrows;
926:     ii   = a->compressedrow.i;
927:     ridx = a->compressedrow.rindex;
928:     for (i=0; i<m; i++){
929:       n   = ii[i+1] - ii[i];
930:       aj  = a->j + ii[i];
931:       aa  = a->a + ii[i];
932:       sum = 0.0;
933:       for (j=0; j<n; j++) sum += (*aa++)*x[*aj++];
934:       y[*ridx++] = sum;
935:     }
936:   } else { /* do not use compressed row format */
937: #if defined(PETSC_USE_FORTRAN_KERNEL_MULTAIJ)
938:     fortranmultaij_(&m,x,ii,aj,aa,y);
939: #else
940:     for (i=0; i<m; i++) {
941:       jrow = ii[i];
942:       n    = ii[i+1] - jrow;
943:       sum  = 0.0;
944:       for (j=0; j<n; j++) {
945:         sum += aa[jrow]*x[aj[jrow]]; jrow++;
946:       }
947:       y[i] = sum;
948:     }
949: #endif
950:   }
951:   PetscLogFlops(2*a->nz - m);
952:   VecRestoreArray(xx,&x);
953:   VecRestoreArray(yy,&y);
954:   return(0);
955: }

959: PetscErrorCode MatMultAdd_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz)
960: {
961:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
962:   PetscScalar    *x,*y,*z,*aa;
964:   PetscInt       m = A->rmap.n,*aj,*ii;
965: #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTADDAIJ)
966:   PetscInt       n,i,jrow,j,*ridx=PETSC_NULL;
967:   PetscScalar    sum;
968:   PetscTruth     usecprow=a->compressedrow.use;
969: #endif

972:   VecGetArray(xx,&x);
973:   VecGetArray(yy,&y);
974:   if (zz != yy) {
975:     VecGetArray(zz,&z);
976:   } else {
977:     z = y;
978:   }

980:   aj  = a->j;
981:   aa  = a->a;
982:   ii  = a->i;
983: #if defined(PETSC_USE_FORTRAN_KERNEL_MULTADDAIJ)
984:   fortranmultaddaij_(&m,x,ii,aj,aa,y,z);
985: #else
986:   if (usecprow){ /* use compressed row format */
987:     if (zz != yy){
988:       PetscMemcpy(z,y,m*sizeof(PetscScalar));
989:     }
990:     m    = a->compressedrow.nrows;
991:     ii   = a->compressedrow.i;
992:     ridx = a->compressedrow.rindex;
993:     for (i=0; i<m; i++){
994:       n  = ii[i+1] - ii[i];
995:       aj  = a->j + ii[i];
996:       aa  = a->a + ii[i];
997:       sum = y[*ridx];
998:       for (j=0; j<n; j++) sum += (*aa++)*x[*aj++];
999:       z[*ridx++] = sum;
1000:     }
1001:   } else { /* do not use compressed row format */
1002:     for (i=0; i<m; i++) {
1003:       jrow = ii[i];
1004:       n    = ii[i+1] - jrow;
1005:       sum  = y[i];
1006:       for (j=0; j<n; j++) {
1007:         sum += aa[jrow]*x[aj[jrow]]; jrow++;
1008:       }
1009:       z[i] = sum;
1010:     }
1011:   }
1012: #endif
1013:   PetscLogFlops(2*a->nz);
1014:   VecRestoreArray(xx,&x);
1015:   VecRestoreArray(yy,&y);
1016:   if (zz != yy) {
1017:     VecRestoreArray(zz,&z);
1018:   }
1019:   return(0);
1020: }

1022: /*
1023:      Adds diagonal pointers to sparse matrix structure.
1024: */
1027: PetscErrorCode MatMarkDiagonal_SeqAIJ(Mat A)
1028: {
1029:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1031:   PetscInt       i,j,m = A->rmap.n;

1034:   if (!a->diag) {
1035:     PetscMalloc(m*sizeof(PetscInt),&a->diag);
1036:   }
1037:   for (i=0; i<A->rmap.n; i++) {
1038:     a->diag[i] = a->i[i+1];
1039:     for (j=a->i[i]; j<a->i[i+1]; j++) {
1040:       if (a->j[j] == i) {
1041:         a->diag[i] = j;
1042:         break;
1043:       }
1044:     }
1045:   }
1046:   return(0);
1047: }

1049: /*
1050:      Checks for missing diagonals
1051: */
1054: PetscErrorCode MatMissingDiagonal_SeqAIJ(Mat A,PetscTruth *missing,PetscInt *d)
1055: {
1056:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1057:   PetscInt       *diag,*jj = a->j,i;

1060:   *missing = PETSC_FALSE;
1061:   if (A->rmap.n > 0 && !jj) {
1062:     *missing  = PETSC_TRUE;
1063:     if (d) *d = 0;
1064:     PetscInfo(A,"Matrix has no entries therefor is missing diagonal");
1065:   } else {
1066:     diag = a->diag;
1067:     for (i=0; i<A->rmap.n; i++) {
1068:       if (jj[diag[i]] != i) {
1069:         *missing = PETSC_TRUE;
1070:         if (d) *d = i;
1071:         PetscInfo1(A,"Matrix is missing diagonal number %D",i);
1072:       }
1073:     }
1074:   }
1075:   return(0);
1076: }

1080: PetscErrorCode MatRelax_SeqAIJ(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx)
1081: {
1082:   Mat_SeqAIJ         *a = (Mat_SeqAIJ*)A->data;
1083:   PetscScalar        *x,d,*xs,sum,*t,scale,*idiag=0,*mdiag;
1084:   const PetscScalar  *v = a->a, *b, *bs,*xb, *ts;
1085:   PetscErrorCode     ierr;
1086:   PetscInt           n = A->cmap.n,m = A->rmap.n,i;
1087:   const PetscInt     *idx,*diag;

1090:   its = its*lits;
1091:   if (its <= 0) SETERRQ2(PETSC_ERR_ARG_WRONG,"Relaxation requires global its %D and local its %D both positive",its,lits);

1093:   diag = a->diag;
1094:   if (!a->idiag) {
1095:     PetscMalloc(3*m*sizeof(PetscScalar),&a->idiag);
1096:     a->ssor  = a->idiag + m;
1097:     mdiag    = a->ssor + m;

1099:     v        = a->a;

1101:     /* this is wrong when fshift omega changes each iteration */
1102:     if (omega == 1.0 && !fshift) {
1103:       for (i=0; i<m; i++) {
1104:         mdiag[i]    = v[diag[i]];
1105:         a->idiag[i] = 1.0/v[diag[i]];
1106:       }
1107:       PetscLogFlops(m);
1108:     } else {
1109:       for (i=0; i<m; i++) {
1110:         mdiag[i]    = v[diag[i]];
1111:         a->idiag[i] = omega/(fshift + v[diag[i]]);
1112:       }
1113:       PetscLogFlops(2*m);
1114:     }
1115:   }
1116:   t     = a->ssor;
1117:   idiag = a->idiag;
1118:   mdiag = a->idiag + 2*m;

1120:   VecGetArray(xx,&x);
1121:   if (xx != bb) {
1122:     VecGetArray(bb,(PetscScalar**)&b);
1123:   } else {
1124:     b = x;
1125:   }

1127:   /* We count flops by assuming the upper triangular and lower triangular parts have the same number of nonzeros */
1128:   xs   = x;
1129:   if (flag == SOR_APPLY_UPPER) {
1130:    /* apply (U + D/omega) to the vector */
1131:     bs = b;
1132:     for (i=0; i<m; i++) {
1133:         d    = fshift + a->a[diag[i]];
1134:         n    = a->i[i+1] - diag[i] - 1;
1135:         idx  = a->j + diag[i] + 1;
1136:         v    = a->a + diag[i] + 1;
1137:         sum  = b[i]*d/omega;
1138:         SPARSEDENSEDOT(sum,bs,v,idx,n);
1139:         x[i] = sum;
1140:     }
1141:     VecRestoreArray(xx,&x);
1142:     if (bb != xx) {VecRestoreArray(bb,(PetscScalar**)&b);}
1143:     PetscLogFlops(a->nz);
1144:     return(0);
1145:   }


1148:     /* Let  A = L + U + D; where L is lower trianglar,
1149:     U is upper triangular, E is diagonal; This routine applies

1151:             (L + E)^{-1} A (U + E)^{-1}

1153:     to a vector efficiently using Eisenstat's trick. This is for
1154:     the case of SSOR preconditioner, so E is D/omega where omega
1155:     is the relaxation factor.
1156:     */

1158:   if (flag == SOR_APPLY_LOWER) {
1159:     SETERRQ(PETSC_ERR_SUP,"SOR_APPLY_LOWER is not implemented");
1160:   } else if (flag & SOR_EISENSTAT) {
1161:     /* Let  A = L + U + D; where L is lower trianglar,
1162:     U is upper triangular, E is diagonal; This routine applies

1164:             (L + E)^{-1} A (U + E)^{-1}

1166:     to a vector efficiently using Eisenstat's trick. This is for
1167:     the case of SSOR preconditioner, so E is D/omega where omega
1168:     is the relaxation factor.
1169:     */
1170:     scale = (2.0/omega) - 1.0;

1172:     /*  x = (E + U)^{-1} b */
1173:     for (i=m-1; i>=0; i--) {
1174:       n    = a->i[i+1] - diag[i] - 1;
1175:       idx  = a->j + diag[i] + 1;
1176:       v    = a->a + diag[i] + 1;
1177:       sum  = b[i];
1178:       SPARSEDENSEMDOT(sum,xs,v,idx,n);
1179:       x[i] = sum*idiag[i];
1180:     }

1182:     /*  t = b - (2*E - D)x */
1183:     v = a->a;
1184:     for (i=0; i<m; i++) { t[i] = b[i] - scale*(v[*diag++])*x[i]; }

1186:     /*  t = (E + L)^{-1}t */
1187:     ts = t;
1188:     diag = a->diag;
1189:     for (i=0; i<m; i++) {
1190:       n    = diag[i] - a->i[i];
1191:       idx  = a->j + a->i[i];
1192:       v    = a->a + a->i[i];
1193:       sum  = t[i];
1194:       SPARSEDENSEMDOT(sum,ts,v,idx,n);
1195:       t[i] = sum*idiag[i];
1196:       /*  x = x + t */
1197:       x[i] += t[i];
1198:     }

1200:     PetscLogFlops(6*m-1 + 2*a->nz);
1201:     VecRestoreArray(xx,&x);
1202:     if (bb != xx) {VecRestoreArray(bb,(PetscScalar**)&b);}
1203:     return(0);
1204:   }
1205:   if (flag & SOR_ZERO_INITIAL_GUESS) {
1206:     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){
1207: #if defined(PETSC_USE_FORTRAN_KERNEL_RELAXAIJ)
1208:       fortranrelaxaijforwardzero_(&m,&omega,x,a->i,a->j,(PetscInt*)diag,idiag,a->a,(void*)b);
1209: #else
1210:       for (i=0; i<m; i++) {
1211:         n    = diag[i] - a->i[i];
1212:         idx  = a->j + a->i[i];
1213:         v    = a->a + a->i[i];
1214:         sum  = b[i];
1215:         SPARSEDENSEMDOT(sum,xs,v,idx,n);
1216:         x[i] = sum*idiag[i];
1217:       }
1218: #endif
1219:       xb = x;
1220:       PetscLogFlops(a->nz);
1221:     } else xb = b;
1222:     if ((flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) &&
1223:         (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP)) {
1224:       for (i=0; i<m; i++) {
1225:         x[i] *= mdiag[i];
1226:       }
1227:       PetscLogFlops(m);
1228:     }
1229:     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){
1230: #if defined(PETSC_USE_FORTRAN_KERNEL_RELAXAIJ)
1231:       fortranrelaxaijbackwardzero_(&m,&omega,x,a->i,a->j,(PetscInt*)diag,idiag,a->a,(void*)xb);
1232: #else
1233:       for (i=m-1; i>=0; i--) {
1234:         n    = a->i[i+1] - diag[i] - 1;
1235:         idx  = a->j + diag[i] + 1;
1236:         v    = a->a + diag[i] + 1;
1237:         sum  = xb[i];
1238:         SPARSEDENSEMDOT(sum,xs,v,idx,n);
1239:         x[i] = sum*idiag[i];
1240:       }
1241: #endif
1242:       PetscLogFlops(a->nz);
1243:     }
1244:     its--;
1245:   }
1246:   while (its--) {
1247:     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){
1248: #if defined(PETSC_USE_FORTRAN_KERNEL_RELAXAIJ)
1249:       fortranrelaxaijforward_(&m,&omega,x,a->i,a->j,(PetscInt*)diag,a->a,(void*)b);
1250: #else
1251:       for (i=0; i<m; i++) {
1252:         d    = fshift + a->a[diag[i]];
1253:         n    = a->i[i+1] - a->i[i];
1254:         idx  = a->j + a->i[i];
1255:         v    = a->a + a->i[i];
1256:         sum  = b[i];
1257:         SPARSEDENSEMDOT(sum,xs,v,idx,n);
1258:         x[i] = (1. - omega)*x[i] + (sum + mdiag[i]*x[i])*idiag[i];
1259:       }
1260: #endif 
1261:       PetscLogFlops(a->nz);
1262:     }
1263:     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){
1264: #if defined(PETSC_USE_FORTRAN_KERNEL_RELAXAIJ)
1265:       fortranrelaxaijbackward_(&m,&omega,x,a->i,a->j,(PetscInt*)diag,a->a,(void*)b);
1266: #else
1267:       for (i=m-1; i>=0; i--) {
1268:         d    = fshift + a->a[diag[i]];
1269:         n    = a->i[i+1] - a->i[i];
1270:         idx  = a->j + a->i[i];
1271:         v    = a->a + a->i[i];
1272:         sum  = b[i];
1273:         SPARSEDENSEMDOT(sum,xs,v,idx,n);
1274:         x[i] = (1. - omega)*x[i] + (sum + mdiag[i]*x[i])*idiag[i];
1275:       }
1276: #endif
1277:       PetscLogFlops(a->nz);
1278:     }
1279:   }
1280:   VecRestoreArray(xx,&x);
1281:   if (bb != xx) {VecRestoreArray(bb,(PetscScalar**)&b);}
1282:   return(0);
1283: }

1287: PetscErrorCode MatGetInfo_SeqAIJ(Mat A,MatInfoType flag,MatInfo *info)
1288: {
1289:   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;

1292:   info->rows_global    = (double)A->rmap.n;
1293:   info->columns_global = (double)A->cmap.n;
1294:   info->rows_local     = (double)A->rmap.n;
1295:   info->columns_local  = (double)A->cmap.n;
1296:   info->block_size     = 1.0;
1297:   info->nz_allocated   = (double)a->maxnz;
1298:   info->nz_used        = (double)a->nz;
1299:   info->nz_unneeded    = (double)(a->maxnz - a->nz);
1300:   info->assemblies     = (double)A->num_ass;
1301:   info->mallocs        = (double)a->reallocs;
1302:   info->memory         = A->mem;
1303:   if (A->factor) {
1304:     info->fill_ratio_given  = A->info.fill_ratio_given;
1305:     info->fill_ratio_needed = A->info.fill_ratio_needed;
1306:     info->factor_mallocs    = A->info.factor_mallocs;
1307:   } else {
1308:     info->fill_ratio_given  = 0;
1309:     info->fill_ratio_needed = 0;
1310:     info->factor_mallocs    = 0;
1311:   }
1312:   return(0);
1313: }

1317: PetscErrorCode MatZeroRows_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag)
1318: {
1319:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1320:   PetscInt       i,m = A->rmap.n - 1,d;
1322:   PetscTruth     missing;

1325:   if (a->keepzeroedrows) {
1326:     for (i=0; i<N; i++) {
1327:       if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
1328:       PetscMemzero(&a->a[a->i[rows[i]]],a->ilen[rows[i]]*sizeof(PetscScalar));
1329:     }
1330:     if (diag != 0.0) {
1331:       MatMissingDiagonal_SeqAIJ(A,&missing,&d);
1332:       if (missing) SETERRQ1(PETSC_ERR_ARG_WRONGSTATE,"Matrix is missing diagonal entry in row %D",d);
1333:       for (i=0; i<N; i++) {
1334:         a->a[a->diag[rows[i]]] = diag;
1335:       }
1336:     }
1337:     A->same_nonzero = PETSC_TRUE;
1338:   } else {
1339:     if (diag != 0.0) {
1340:       for (i=0; i<N; i++) {
1341:         if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
1342:         if (a->ilen[rows[i]] > 0) {
1343:           a->ilen[rows[i]]          = 1;
1344:           a->a[a->i[rows[i]]] = diag;
1345:           a->j[a->i[rows[i]]] = rows[i];
1346:         } else { /* in case row was completely empty */
1347:           MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES);
1348:         }
1349:       }
1350:     } else {
1351:       for (i=0; i<N; i++) {
1352:         if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
1353:         a->ilen[rows[i]] = 0;
1354:       }
1355:     }
1356:     A->same_nonzero = PETSC_FALSE;
1357:   }
1358:   MatAssemblyEnd_SeqAIJ(A,MAT_FINAL_ASSEMBLY);
1359:   return(0);
1360: }

1364: PetscErrorCode MatGetRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
1365: {
1366:   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1367:   PetscInt   *itmp;

1370:   if (row < 0 || row >= A->rmap.n) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Row %D out of range",row);

1372:   *nz = a->i[row+1] - a->i[row];
1373:   if (v) *v = a->a + a->i[row];
1374:   if (idx) {
1375:     itmp = a->j + a->i[row];
1376:     if (*nz) {
1377:       *idx = itmp;
1378:     }
1379:     else *idx = 0;
1380:   }
1381:   return(0);
1382: }

1384: /* remove this function? */
1387: PetscErrorCode MatRestoreRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
1388: {
1390:   return(0);
1391: }

1395: PetscErrorCode MatNorm_SeqAIJ(Mat A,NormType type,PetscReal *nrm)
1396: {
1397:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1398:   PetscScalar    *v = a->a;
1399:   PetscReal      sum = 0.0;
1401:   PetscInt       i,j;

1404:   if (type == NORM_FROBENIUS) {
1405:     for (i=0; i<a->nz; i++) {
1406: #if defined(PETSC_USE_COMPLEX)
1407:       sum += PetscRealPart(PetscConj(*v)*(*v)); v++;
1408: #else
1409:       sum += (*v)*(*v); v++;
1410: #endif
1411:     }
1412:     *nrm = sqrt(sum);
1413:   } else if (type == NORM_1) {
1414:     PetscReal *tmp;
1415:     PetscInt    *jj = a->j;
1416:     PetscMalloc((A->cmap.n+1)*sizeof(PetscReal),&tmp);
1417:     PetscMemzero(tmp,A->cmap.n*sizeof(PetscReal));
1418:     *nrm = 0.0;
1419:     for (j=0; j<a->nz; j++) {
1420:         tmp[*jj++] += PetscAbsScalar(*v);  v++;
1421:     }
1422:     for (j=0; j<A->cmap.n; j++) {
1423:       if (tmp[j] > *nrm) *nrm = tmp[j];
1424:     }
1425:     PetscFree(tmp);
1426:   } else if (type == NORM_INFINITY) {
1427:     *nrm = 0.0;
1428:     for (j=0; j<A->rmap.n; j++) {
1429:       v = a->a + a->i[j];
1430:       sum = 0.0;
1431:       for (i=0; i<a->i[j+1]-a->i[j]; i++) {
1432:         sum += PetscAbsScalar(*v); v++;
1433:       }
1434:       if (sum > *nrm) *nrm = sum;
1435:     }
1436:   } else {
1437:     SETERRQ(PETSC_ERR_SUP,"No support for two norm");
1438:   }
1439:   return(0);
1440: }

1444: PetscErrorCode MatTranspose_SeqAIJ(Mat A,Mat *B)
1445: {
1446:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1447:   Mat            C;
1449:   PetscInt       i,*aj = a->j,*ai = a->i,m = A->rmap.n,len,*col;
1450:   PetscScalar    *array = a->a;

1453:   if (!B && m != A->cmap.n) SETERRQ(PETSC_ERR_ARG_SIZ,"Square matrix only for in-place");
1454:   PetscMalloc((1+A->cmap.n)*sizeof(PetscInt),&col);
1455:   PetscMemzero(col,(1+A->cmap.n)*sizeof(PetscInt));
1456: 
1457:   for (i=0; i<ai[m]; i++) col[aj[i]] += 1;
1458:   MatCreate(A->comm,&C);
1459:   MatSetSizes(C,A->cmap.n,m,A->cmap.n,m);
1460:   MatSetType(C,A->type_name);
1461:   MatSeqAIJSetPreallocation_SeqAIJ(C,0,col);
1462:   PetscFree(col);
1463:   for (i=0; i<m; i++) {
1464:     len    = ai[i+1]-ai[i];
1465:     MatSetValues_SeqAIJ(C,len,aj,1,&i,array,INSERT_VALUES);
1466:     array += len;
1467:     aj    += len;
1468:   }

1470:   MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);
1471:   MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);

1473:   if (B) {
1474:     *B = C;
1475:   } else {
1476:     MatHeaderCopy(A,C);
1477:   }
1478:   return(0);
1479: }

1484: PetscErrorCode  MatIsTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscTruth *f)
1485: {
1486:   Mat_SeqAIJ     *aij = (Mat_SeqAIJ *) A->data,*bij = (Mat_SeqAIJ*) A->data;
1487:   PetscInt       *adx,*bdx,*aii,*bii,*aptr,*bptr; PetscScalar *va,*vb;
1489:   PetscInt       ma,na,mb,nb, i;

1492:   bij = (Mat_SeqAIJ *) B->data;
1493: 
1494:   MatGetSize(A,&ma,&na);
1495:   MatGetSize(B,&mb,&nb);
1496:   if (ma!=nb || na!=mb){
1497:     *f = PETSC_FALSE;
1498:     return(0);
1499:   }
1500:   aii = aij->i; bii = bij->i;
1501:   adx = aij->j; bdx = bij->j;
1502:   va  = aij->a; vb = bij->a;
1503:   PetscMalloc(ma*sizeof(PetscInt),&aptr);
1504:   PetscMalloc(mb*sizeof(PetscInt),&bptr);
1505:   for (i=0; i<ma; i++) aptr[i] = aii[i];
1506:   for (i=0; i<mb; i++) bptr[i] = bii[i];

1508:   *f = PETSC_TRUE;
1509:   for (i=0; i<ma; i++) {
1510:     while (aptr[i]<aii[i+1]) {
1511:       PetscInt         idc,idr;
1512:       PetscScalar vc,vr;
1513:       /* column/row index/value */
1514:       idc = adx[aptr[i]];
1515:       idr = bdx[bptr[idc]];
1516:       vc  = va[aptr[i]];
1517:       vr  = vb[bptr[idc]];
1518:       if (i!=idr || PetscAbsScalar(vc-vr) > tol) {
1519:         *f = PETSC_FALSE;
1520:         goto done;
1521:       } else {
1522:         aptr[i]++;
1523:         if (B || i!=idc) bptr[idc]++;
1524:       }
1525:     }
1526:   }
1527:  done:
1528:   PetscFree(aptr);
1529:   if (B) {
1530:     PetscFree(bptr);
1531:   }
1532:   return(0);
1533: }

1538: PetscErrorCode MatIsSymmetric_SeqAIJ(Mat A,PetscReal tol,PetscTruth *f)
1539: {
1542:   MatIsTranspose_SeqAIJ(A,A,tol,f);
1543:   return(0);
1544: }

1548: PetscErrorCode MatDiagonalScale_SeqAIJ(Mat A,Vec ll,Vec rr)
1549: {
1550:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1551:   PetscScalar    *l,*r,x,*v;
1553:   PetscInt       i,j,m = A->rmap.n,n = A->cmap.n,M,nz = a->nz,*jj;

1556:   if (ll) {
1557:     /* The local size is used so that VecMPI can be passed to this routine
1558:        by MatDiagonalScale_MPIAIJ */
1559:     VecGetLocalSize(ll,&m);
1560:     if (m != A->rmap.n) SETERRQ(PETSC_ERR_ARG_SIZ,"Left scaling vector wrong length");
1561:     VecGetArray(ll,&l);
1562:     v = a->a;
1563:     for (i=0; i<m; i++) {
1564:       x = l[i];
1565:       M = a->i[i+1] - a->i[i];
1566:       for (j=0; j<M; j++) { (*v++) *= x;}
1567:     }
1568:     VecRestoreArray(ll,&l);
1569:     PetscLogFlops(nz);
1570:   }
1571:   if (rr) {
1572:     VecGetLocalSize(rr,&n);
1573:     if (n != A->cmap.n) SETERRQ(PETSC_ERR_ARG_SIZ,"Right scaling vector wrong length");
1574:     VecGetArray(rr,&r);
1575:     v = a->a; jj = a->j;
1576:     for (i=0; i<nz; i++) {
1577:       (*v++) *= r[*jj++];
1578:     }
1579:     VecRestoreArray(rr,&r);
1580:     PetscLogFlops(nz);
1581:   }
1582:   return(0);
1583: }

1587: PetscErrorCode MatGetSubMatrix_SeqAIJ(Mat A,IS isrow,IS iscol,PetscInt csize,MatReuse scall,Mat *B)
1588: {
1589:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data,*c;
1591:   PetscInt       *smap,i,k,kstart,kend,oldcols = A->cmap.n,*lens;
1592:   PetscInt       row,mat_i,*mat_j,tcol,first,step,*mat_ilen,sum,lensi;
1593:   PetscInt       *irow,*icol,nrows,ncols;
1594:   PetscInt       *starts,*j_new,*i_new,*aj = a->j,*ai = a->i,ii,*ailen = a->ilen;
1595:   PetscScalar    *a_new,*mat_a;
1596:   Mat            C;
1597:   PetscTruth     stride;

1600:   ISSorted(isrow,(PetscTruth*)&i);
1601:   if (!i) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"ISrow is not sorted");
1602:   ISSorted(iscol,(PetscTruth*)&i);
1603:   if (!i) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"IScol is not sorted");

1605:   ISGetIndices(isrow,&irow);
1606:   ISGetLocalSize(isrow,&nrows);
1607:   ISGetLocalSize(iscol,&ncols);

1609:   ISStrideGetInfo(iscol,&first,&step);
1610:   ISStride(iscol,&stride);
1611:   if (stride && step == 1) {
1612:     /* special case of contiguous rows */
1613:     PetscMalloc((2*nrows+1)*sizeof(PetscInt),&lens);
1614:     starts = lens + nrows;
1615:     /* loop over new rows determining lens and starting points */
1616:     for (i=0; i<nrows; i++) {
1617:       kstart  = ai[irow[i]];
1618:       kend    = kstart + ailen[irow[i]];
1619:       for (k=kstart; k<kend; k++) {
1620:         if (aj[k] >= first) {
1621:           starts[i] = k;
1622:           break;
1623:         }
1624:       }
1625:       sum = 0;
1626:       while (k < kend) {
1627:         if (aj[k++] >= first+ncols) break;
1628:         sum++;
1629:       }
1630:       lens[i] = sum;
1631:     }
1632:     /* create submatrix */
1633:     if (scall == MAT_REUSE_MATRIX) {
1634:       PetscInt n_cols,n_rows;
1635:       MatGetSize(*B,&n_rows,&n_cols);
1636:       if (n_rows != nrows || n_cols != ncols) SETERRQ(PETSC_ERR_ARG_SIZ,"Reused submatrix wrong size");
1637:       MatZeroEntries(*B);
1638:       C = *B;
1639:     } else {
1640:       MatCreate(A->comm,&C);
1641:       MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);
1642:       MatSetType(C,A->type_name);
1643:       MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);
1644:     }
1645:     c = (Mat_SeqAIJ*)C->data;

1647:     /* loop over rows inserting into submatrix */
1648:     a_new    = c->a;
1649:     j_new    = c->j;
1650:     i_new    = c->i;

1652:     for (i=0; i<nrows; i++) {
1653:       ii    = starts[i];
1654:       lensi = lens[i];
1655:       for (k=0; k<lensi; k++) {
1656:         *j_new++ = aj[ii+k] - first;
1657:       }
1658:       PetscMemcpy(a_new,a->a + starts[i],lensi*sizeof(PetscScalar));
1659:       a_new      += lensi;
1660:       i_new[i+1]  = i_new[i] + lensi;
1661:       c->ilen[i]  = lensi;
1662:     }
1663:     PetscFree(lens);
1664:   } else {
1665:     ISGetIndices(iscol,&icol);
1666:     PetscMalloc((1+oldcols)*sizeof(PetscInt),&smap);
1667: 
1668:     PetscMalloc((1+nrows)*sizeof(PetscInt),&lens);
1669:     PetscMemzero(smap,oldcols*sizeof(PetscInt));
1670:     for (i=0; i<ncols; i++) smap[icol[i]] = i+1;
1671:     /* determine lens of each row */
1672:     for (i=0; i<nrows; i++) {
1673:       kstart  = ai[irow[i]];
1674:       kend    = kstart + a->ilen[irow[i]];
1675:       lens[i] = 0;
1676:       for (k=kstart; k<kend; k++) {
1677:         if (smap[aj[k]]) {
1678:           lens[i]++;
1679:         }
1680:       }
1681:     }
1682:     /* Create and fill new matrix */
1683:     if (scall == MAT_REUSE_MATRIX) {
1684:       PetscTruth equal;

1686:       c = (Mat_SeqAIJ *)((*B)->data);
1687:       if ((*B)->rmap.n  != nrows || (*B)->cmap.n != ncols) SETERRQ(PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong size");
1688:       PetscMemcmp(c->ilen,lens,(*B)->rmap.n*sizeof(PetscInt),&equal);
1689:       if (!equal) {
1690:         SETERRQ(PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong no of nonzeros");
1691:       }
1692:       PetscMemzero(c->ilen,(*B)->rmap.n*sizeof(PetscInt));
1693:       C = *B;
1694:     } else {
1695:       MatCreate(A->comm,&C);
1696:       MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);
1697:       MatSetType(C,A->type_name);
1698:       MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);
1699:     }
1700:     c = (Mat_SeqAIJ *)(C->data);
1701:     for (i=0; i<nrows; i++) {
1702:       row    = irow[i];
1703:       kstart = ai[row];
1704:       kend   = kstart + a->ilen[row];
1705:       mat_i  = c->i[i];
1706:       mat_j  = c->j + mat_i;
1707:       mat_a  = c->a + mat_i;
1708:       mat_ilen = c->ilen + i;
1709:       for (k=kstart; k<kend; k++) {
1710:         if ((tcol=smap[a->j[k]])) {
1711:           *mat_j++ = tcol - 1;
1712:           *mat_a++ = a->a[k];
1713:           (*mat_ilen)++;

1715:         }
1716:       }
1717:     }
1718:     /* Free work space */
1719:     ISRestoreIndices(iscol,&icol);
1720:     PetscFree(smap);
1721:     PetscFree(lens);
1722:   }
1723:   MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);
1724:   MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);

1726:   ISRestoreIndices(isrow,&irow);
1727:   *B = C;
1728:   return(0);
1729: }

1731: /*
1732: */
1735: PetscErrorCode MatILUFactor_SeqAIJ(Mat inA,IS row,IS col,MatFactorInfo *info)
1736: {
1737:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)inA->data;
1739:   Mat            outA;
1740:   PetscTruth     row_identity,col_identity;

1743:   if (info->levels != 0) SETERRQ(PETSC_ERR_SUP,"Only levels=0 supported for in-place ilu");
1744:   ISIdentity(row,&row_identity);
1745:   ISIdentity(col,&col_identity);
1746:   if (!row_identity || !col_identity) {
1747:     SETERRQ(PETSC_ERR_ARG_WRONG,"Row and column permutations must be identity for in-place ILU");
1748:   }

1750:   outA          = inA;
1751:   inA->factor   = FACTOR_LU;
1752:   a->row        = row;
1753:   a->col        = col;
1754:   PetscObjectReference((PetscObject)row);
1755:   PetscObjectReference((PetscObject)col);

1757:   /* Create the inverse permutation so that it can be used in MatLUFactorNumeric() */
1758:   if (a->icol) {ISDestroy(a->icol);} /* need to remove old one */
1759:   ISInvertPermutation(col,PETSC_DECIDE,&a->icol);
1760:   PetscLogObjectParent(inA,a->icol);

1762:   if (!a->solve_work) { /* this matrix may have been factored before */
1763:      PetscMalloc((inA->rmap.n+1)*sizeof(PetscScalar),&a->solve_work);
1764:   }

1766:   MatMarkDiagonal_SeqAIJ(inA);
1767:   MatLUFactorNumeric_SeqAIJ(inA,info,&outA);
1768:   return(0);
1769: }

1771:  #include petscblaslapack.h
1774: PetscErrorCode MatScale_SeqAIJ(Mat inA,PetscScalar alpha)
1775: {
1776:   Mat_SeqAIJ   *a = (Mat_SeqAIJ*)inA->data;
1777:   PetscBLASInt bnz = (PetscBLASInt)a->nz,one = 1;
1778:   PetscScalar oalpha = alpha;


1783:   BLASscal_(&bnz,&oalpha,a->a,&one);
1784:   PetscLogFlops(a->nz);
1785:   return(0);
1786: }

1790: PetscErrorCode MatGetSubMatrices_SeqAIJ(Mat A,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *B[])
1791: {
1793:   PetscInt       i;

1796:   if (scall == MAT_INITIAL_MATRIX) {
1797:     PetscMalloc((n+1)*sizeof(Mat),B);
1798:   }

1800:   for (i=0; i<n; i++) {
1801:     MatGetSubMatrix_SeqAIJ(A,irow[i],icol[i],PETSC_DECIDE,scall,&(*B)[i]);
1802:   }
1803:   return(0);
1804: }

1808: PetscErrorCode MatIncreaseOverlap_SeqAIJ(Mat A,PetscInt is_max,IS is[],PetscInt ov)
1809: {
1810:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1812:   PetscInt       row,i,j,k,l,m,n,*idx,*nidx,isz,val;
1813:   PetscInt       start,end,*ai,*aj;
1814:   PetscBT        table;

1817:   m     = A->rmap.n;
1818:   ai    = a->i;
1819:   aj    = a->j;

1821:   if (ov < 0)  SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"illegal negative overlap value used");

1823:   PetscMalloc((m+1)*sizeof(PetscInt),&nidx);
1824:   PetscBTCreate(m,table);

1826:   for (i=0; i<is_max; i++) {
1827:     /* Initialize the two local arrays */
1828:     isz  = 0;
1829:     PetscBTMemzero(m,table);
1830: 
1831:     /* Extract the indices, assume there can be duplicate entries */
1832:     ISGetIndices(is[i],&idx);
1833:     ISGetLocalSize(is[i],&n);
1834: 
1835:     /* Enter these into the temp arrays. I.e., mark table[row], enter row into new index */
1836:     for (j=0; j<n ; ++j){
1837:       if(!PetscBTLookupSet(table,idx[j])) { nidx[isz++] = idx[j];}
1838:     }
1839:     ISRestoreIndices(is[i],&idx);
1840:     ISDestroy(is[i]);
1841: 
1842:     k = 0;
1843:     for (j=0; j<ov; j++){ /* for each overlap */
1844:       n = isz;
1845:       for (; k<n ; k++){ /* do only those rows in nidx[k], which are not done yet */
1846:         row   = nidx[k];
1847:         start = ai[row];
1848:         end   = ai[row+1];
1849:         for (l = start; l<end ; l++){
1850:           val = aj[l] ;
1851:           if (!PetscBTLookupSet(table,val)) {nidx[isz++] = val;}
1852:         }
1853:       }
1854:     }
1855:     ISCreateGeneral(PETSC_COMM_SELF,isz,nidx,(is+i));
1856:   }
1857:   PetscBTDestroy(table);
1858:   PetscFree(nidx);
1859:   return(0);
1860: }

1862: /* -------------------------------------------------------------- */
1865: PetscErrorCode MatPermute_SeqAIJ(Mat A,IS rowp,IS colp,Mat *B)
1866: {
1867:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1869:   PetscInt       i,nz,m = A->rmap.n,n = A->cmap.n,*col;
1870:   PetscInt       *row,*cnew,j,*lens;
1871:   IS             icolp,irowp;
1872:   PetscInt       *cwork;
1873:   PetscScalar    *vwork;

1876:   ISInvertPermutation(rowp,PETSC_DECIDE,&irowp);
1877:   ISGetIndices(irowp,&row);
1878:   ISInvertPermutation(colp,PETSC_DECIDE,&icolp);
1879:   ISGetIndices(icolp,&col);
1880: 
1881:   /* determine lengths of permuted rows */
1882:   PetscMalloc((m+1)*sizeof(PetscInt),&lens);
1883:   for (i=0; i<m; i++) {
1884:     lens[row[i]] = a->i[i+1] - a->i[i];
1885:   }
1886:   MatCreate(A->comm,B);
1887:   MatSetSizes(*B,m,n,m,n);
1888:   MatSetType(*B,A->type_name);
1889:   MatSeqAIJSetPreallocation_SeqAIJ(*B,0,lens);
1890:   PetscFree(lens);

1892:   PetscMalloc(n*sizeof(PetscInt),&cnew);
1893:   for (i=0; i<m; i++) {
1894:     MatGetRow_SeqAIJ(A,i,&nz,&cwork,&vwork);
1895:     for (j=0; j<nz; j++) { cnew[j] = col[cwork[j]];}
1896:     MatSetValues_SeqAIJ(*B,1,&row[i],nz,cnew,vwork,INSERT_VALUES);
1897:     MatRestoreRow_SeqAIJ(A,i,&nz,&cwork,&vwork);
1898:   }
1899:   PetscFree(cnew);
1900:   (*B)->assembled     = PETSC_FALSE;
1901:   MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);
1902:   MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);
1903:   ISRestoreIndices(irowp,&row);
1904:   ISRestoreIndices(icolp,&col);
1905:   ISDestroy(irowp);
1906:   ISDestroy(icolp);
1907:   return(0);
1908: }

1912: PetscErrorCode MatCopy_SeqAIJ(Mat A,Mat B,MatStructure str)
1913: {

1917:   /* If the two matrices have the same copy implementation, use fast copy. */
1918:   if (str == SAME_NONZERO_PATTERN && (A->ops->copy == B->ops->copy)) {
1919:     Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1920:     Mat_SeqAIJ *b = (Mat_SeqAIJ*)B->data;

1922:     if (a->i[A->rmap.n] != b->i[B->rmap.n]) {
1923:       SETERRQ(PETSC_ERR_ARG_INCOMP,"Number of nonzeros in two matrices are different");
1924:     }
1925:     PetscMemcpy(b->a,a->a,(a->i[A->rmap.n])*sizeof(PetscScalar));
1926:   } else {
1927:     MatCopy_Basic(A,B,str);
1928:   }
1929:   return(0);
1930: }

1934: PetscErrorCode MatSetUpPreallocation_SeqAIJ(Mat A)
1935: {

1939:    MatSeqAIJSetPreallocation_SeqAIJ(A,PETSC_DEFAULT,0);
1940:   return(0);
1941: }

1945: PetscErrorCode MatGetArray_SeqAIJ(Mat A,PetscScalar *array[])
1946: {
1947:   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1949:   *array = a->a;
1950:   return(0);
1951: }

1955: PetscErrorCode MatRestoreArray_SeqAIJ(Mat A,PetscScalar *array[])
1956: {
1958:   return(0);
1959: }

1963: PetscErrorCode MatFDColoringApply_SeqAIJ(Mat J,MatFDColoring coloring,Vec x1,MatStructure *flag,void *sctx)
1964: {
1965:   PetscErrorCode (*f)(void*,Vec,Vec,void*) = (PetscErrorCode (*)(void*,Vec,Vec,void *))coloring->f;
1967:   PetscInt       k,N,start,end,l,row,col,srow,**vscaleforrow,m1,m2;
1968:   PetscScalar    dx,*y,*xx,*w3_array;
1969:   PetscScalar    *vscale_array;
1970:   PetscReal      epsilon = coloring->error_rel,umin = coloring->umin;
1971:   Vec            w1,w2,w3;
1972:   void           *fctx = coloring->fctx;
1973:   PetscTruth     flg;

1976:   if (!coloring->w1) {
1977:     VecDuplicate(x1,&coloring->w1);
1978:     PetscLogObjectParent(coloring,coloring->w1);
1979:     VecDuplicate(x1,&coloring->w2);
1980:     PetscLogObjectParent(coloring,coloring->w2);
1981:     VecDuplicate(x1,&coloring->w3);
1982:     PetscLogObjectParent(coloring,coloring->w3);
1983:   }
1984:   w1 = coloring->w1; w2 = coloring->w2; w3 = coloring->w3;

1986:   MatSetUnfactored(J);
1987:   PetscOptionsHasName(coloring->prefix,"-mat_fd_coloring_dont_rezero",&flg);
1988:   if (flg) {
1989:     PetscInfo(coloring,"Not calling MatZeroEntries()\n");
1990:   } else {
1991:     PetscTruth assembled;
1992:     MatAssembled(J,&assembled);
1993:     if (assembled) {
1994:       MatZeroEntries(J);
1995:     }
1996:   }

1998:   VecGetOwnershipRange(x1,&start,&end);
1999:   VecGetSize(x1,&N);

2001:   /*
2002:        This is a horrible, horrible, hack. See DMMGComputeJacobian_Multigrid() it inproperly sets
2003:      coloring->F for the coarser grids from the finest
2004:   */
2005:   if (coloring->F) {
2006:     VecGetLocalSize(coloring->F,&m1);
2007:     VecGetLocalSize(w1,&m2);
2008:     if (m1 != m2) {
2009:       coloring->F = 0;
2010:     }
2011:   }

2013:   if (coloring->F) {
2014:     w1          = coloring->F;
2015:     coloring->F = 0;
2016:   } else {
2018:     (*f)(sctx,x1,w1,fctx);
2020:   }

2022:   /* 
2023:       Compute all the scale factors and share with other processors
2024:   */
2025:   VecGetArray(x1,&xx);xx = xx - start;
2026:   VecGetArray(coloring->vscale,&vscale_array);vscale_array = vscale_array - start;
2027:   for (k=0; k<coloring->ncolors; k++) {
2028:     /*
2029:        Loop over each column associated with color adding the 
2030:        perturbation to the vector w3.
2031:     */
2032:     for (l=0; l<coloring->ncolumns[k]; l++) {
2033:       col = coloring->columns[k][l];    /* column of the matrix we are probing for */
2034:       dx  = xx[col];
2035:       if (dx == 0.0) dx = 1.0;
2036: #if !defined(PETSC_USE_COMPLEX)
2037:       if (dx < umin && dx >= 0.0)      dx = umin;
2038:       else if (dx < 0.0 && dx > -umin) dx = -umin;
2039: #else
2040:       if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0)     dx = umin;
2041:       else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
2042: #endif
2043:       dx                *= epsilon;
2044:       vscale_array[col] = 1.0/dx;
2045:     }
2046:   }
2047:   vscale_array = vscale_array + start;VecRestoreArray(coloring->vscale,&vscale_array);
2048:   VecGhostUpdateBegin(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);
2049:   VecGhostUpdateEnd(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);

2051:   /*  VecView(coloring->vscale,PETSC_VIEWER_STDOUT_WORLD);
2052:       VecView(x1,PETSC_VIEWER_STDOUT_WORLD);*/

2054:   if (coloring->vscaleforrow) vscaleforrow = coloring->vscaleforrow;
2055:   else                        vscaleforrow = coloring->columnsforrow;

2057:   VecGetArray(coloring->vscale,&vscale_array);
2058:   /*
2059:       Loop over each color
2060:   */
2061:   for (k=0; k<coloring->ncolors; k++) {
2062:     coloring->currentcolor = k;
2063:     VecCopy(x1,w3);
2064:     VecGetArray(w3,&w3_array);w3_array = w3_array - start;
2065:     /*
2066:        Loop over each column associated with color adding the 
2067:        perturbation to the vector w3.
2068:     */
2069:     for (l=0; l<coloring->ncolumns[k]; l++) {
2070:       col = coloring->columns[k][l];    /* column of the matrix we are probing for */
2071:       dx  = xx[col];
2072:       if (dx == 0.0) dx = 1.0;
2073: #if !defined(PETSC_USE_COMPLEX)
2074:       if (dx < umin && dx >= 0.0)      dx = umin;
2075:       else if (dx < 0.0 && dx > -umin) dx = -umin;
2076: #else
2077:       if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0)     dx = umin;
2078:       else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
2079: #endif
2080:       dx            *= epsilon;
2081:       if (!PetscAbsScalar(dx)) SETERRQ(PETSC_ERR_PLIB,"Computed 0 differencing parameter");
2082:       w3_array[col] += dx;
2083:     }
2084:     w3_array = w3_array + start; VecRestoreArray(w3,&w3_array);

2086:     /*
2087:        Evaluate function at x1 + dx (here dx is a vector of perturbations)
2088:     */

2091:     (*f)(sctx,w3,w2,fctx);
2093:     VecAXPY(w2,-1.0,w1);

2095:     /*
2096:        Loop over rows of vector, putting results into Jacobian matrix
2097:     */
2098:     VecGetArray(w2,&y);
2099:     for (l=0; l<coloring->nrows[k]; l++) {
2100:       row    = coloring->rows[k][l];
2101:       col    = coloring->columnsforrow[k][l];
2102:       y[row] *= vscale_array[vscaleforrow[k][l]];
2103:       srow   = row + start;
2104:       MatSetValues_SeqAIJ(J,1,&srow,1,&col,y+row,INSERT_VALUES);
2105:     }
2106:     VecRestoreArray(w2,&y);
2107:   }
2108:   coloring->currentcolor = k;
2109:   VecRestoreArray(coloring->vscale,&vscale_array);
2110:   xx = xx + start; VecRestoreArray(x1,&xx);
2111:   MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);
2112:   MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);
2113:   return(0);
2114: }

2116:  #include petscblaslapack.h
2119: PetscErrorCode MatAXPY_SeqAIJ(Mat Y,PetscScalar a,Mat X,MatStructure str)
2120: {
2122:   PetscInt       i;
2123:   Mat_SeqAIJ     *x  = (Mat_SeqAIJ *)X->data,*y = (Mat_SeqAIJ *)Y->data;
2124:   PetscBLASInt   one=1,bnz = (PetscBLASInt)x->nz;

2127:   if (str == SAME_NONZERO_PATTERN) {
2128:     PetscScalar alpha = a;
2129:     BLASaxpy_(&bnz,&alpha,x->a,&one,y->a,&one);
2130:   } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */
2131:     if (y->xtoy && y->XtoY != X) {
2132:       PetscFree(y->xtoy);
2133:       MatDestroy(y->XtoY);
2134:     }
2135:     if (!y->xtoy) { /* get xtoy */
2136:       MatAXPYGetxtoy_Private(X->rmap.n,x->i,x->j,PETSC_NULL, y->i,y->j,PETSC_NULL, &y->xtoy);
2137:       y->XtoY = X;
2138:     }
2139:     for (i=0; i<x->nz; i++) y->a[y->xtoy[i]] += a*(x->a[i]);
2140:     PetscInfo3(0,"ratio of nnz(X)/nnz(Y): %d/%d = %G\n",x->nz,y->nz,(PetscReal)(x->nz)/y->nz);
2141:   } else {
2142:     MatAXPY_Basic(Y,a,X,str);
2143:   }
2144:   return(0);
2145: }

2149: PetscErrorCode MatSetBlockSize_SeqAIJ(Mat A,PetscInt bs)
2150: {
2152:   return(0);
2153: }

2157: PetscErrorCode  MatConjugate_SeqAIJ(Mat mat)
2158: {
2159: #if defined(PETSC_USE_COMPLEX)
2160:   Mat_SeqAIJ  *aij = (Mat_SeqAIJ *)mat->data;
2161:   PetscInt    i,nz;
2162:   PetscScalar *a;

2165:   nz = aij->nz;
2166:   a  = aij->a;
2167:   for (i=0; i<nz; i++) {
2168:     a[i] = PetscConj(a[i]);
2169:   }
2170: #else
2172: #endif
2173:   return(0);
2174: }

2178: PetscErrorCode MatGetRowMax_SeqAIJ(Mat A,Vec v)
2179: {
2180:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
2182:   PetscInt       i,j,m = A->rmap.n,*ai,*aj,ncols,n;
2183:   PetscReal      atmp;
2184:   PetscScalar    *x,zero = 0.0;
2185:   MatScalar      *aa;

2188:   if (A->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2189:   aa   = a->a;
2190:   ai   = a->i;
2191:   aj   = a->j;

2193:   VecSet(v,zero);
2194:   VecGetArray(v,&x);
2195:   VecGetLocalSize(v,&n);
2196:   if (n != A->rmap.n) SETERRQ(PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
2197:   for (i=0; i<m; i++) {
2198:     ncols = ai[1] - ai[0]; ai++;
2199:     for (j=0; j<ncols; j++){
2200:       atmp = PetscAbsScalar(*aa); aa++;
2201:       if (PetscAbsScalar(x[i]) < atmp) x[i] = atmp;
2202:       aj++;
2203:     }
2204:   }
2205:   VecRestoreArray(v,&x);
2206:   return(0);
2207: }

2209: /* -------------------------------------------------------------------*/
2210: static struct _MatOps MatOps_Values = {MatSetValues_SeqAIJ,
2211:        MatGetRow_SeqAIJ,
2212:        MatRestoreRow_SeqAIJ,
2213:        MatMult_SeqAIJ,
2214: /* 4*/ MatMultAdd_SeqAIJ,
2215:        MatMultTranspose_SeqAIJ,
2216:        MatMultTransposeAdd_SeqAIJ,
2217:        MatSolve_SeqAIJ,
2218:        MatSolveAdd_SeqAIJ,
2219:        MatSolveTranspose_SeqAIJ,
2220: /*10*/ MatSolveTransposeAdd_SeqAIJ,
2221:        MatLUFactor_SeqAIJ,
2222:        0,
2223:        MatRelax_SeqAIJ,
2224:        MatTranspose_SeqAIJ,
2225: /*15*/ MatGetInfo_SeqAIJ,
2226:        MatEqual_SeqAIJ,
2227:        MatGetDiagonal_SeqAIJ,
2228:        MatDiagonalScale_SeqAIJ,
2229:        MatNorm_SeqAIJ,
2230: /*20*/ 0,
2231:        MatAssemblyEnd_SeqAIJ,
2232:        MatCompress_SeqAIJ,
2233:        MatSetOption_SeqAIJ,
2234:        MatZeroEntries_SeqAIJ,
2235: /*25*/ MatZeroRows_SeqAIJ,
2236:        MatLUFactorSymbolic_SeqAIJ,
2237:        MatLUFactorNumeric_SeqAIJ,
2238:        MatCholeskyFactorSymbolic_SeqAIJ,
2239:        MatCholeskyFactorNumeric_SeqAIJ,
2240: /*30*/ MatSetUpPreallocation_SeqAIJ,
2241:        MatILUFactorSymbolic_SeqAIJ,
2242:        MatICCFactorSymbolic_SeqAIJ,
2243:        MatGetArray_SeqAIJ,
2244:        MatRestoreArray_SeqAIJ,
2245: /*35*/ MatDuplicate_SeqAIJ,
2246:        0,
2247:        0,
2248:        MatILUFactor_SeqAIJ,
2249:        0,
2250: /*40*/ MatAXPY_SeqAIJ,
2251:        MatGetSubMatrices_SeqAIJ,
2252:        MatIncreaseOverlap_SeqAIJ,
2253:        MatGetValues_SeqAIJ,
2254:        MatCopy_SeqAIJ,
2255: /*45*/ 0,
2256:        MatScale_SeqAIJ,
2257:        0,
2258:        MatDiagonalSet_SeqAIJ,
2259:        MatILUDTFactor_SeqAIJ,
2260: /*50*/ MatSetBlockSize_SeqAIJ,
2261:        MatGetRowIJ_SeqAIJ,
2262:        MatRestoreRowIJ_SeqAIJ,
2263:        MatGetColumnIJ_SeqAIJ,
2264:        MatRestoreColumnIJ_SeqAIJ,
2265: /*55*/ MatFDColoringCreate_SeqAIJ,
2266:        0,
2267:        0,
2268:        MatPermute_SeqAIJ,
2269:        0,
2270: /*60*/ 0,
2271:        MatDestroy_SeqAIJ,
2272:        MatView_SeqAIJ,
2273:        0,
2274:        0,
2275: /*65*/ 0,
2276:        0,
2277:        0,
2278:        0,
2279:        0,
2280: /*70*/ MatGetRowMax_SeqAIJ,
2281:        0,
2282:        MatSetColoring_SeqAIJ,
2283: #if defined(PETSC_HAVE_ADIC)
2284:        MatSetValuesAdic_SeqAIJ,
2285: #else
2286:        0,
2287: #endif
2288:        MatSetValuesAdifor_SeqAIJ,
2289: /*75*/ 0,
2290:        0,
2291:        0,
2292:        0,
2293:        0,
2294: /*80*/ 0,
2295:        0,
2296:        0,
2297:        0,
2298:        MatLoad_SeqAIJ,
2299: /*85*/ MatIsSymmetric_SeqAIJ,
2300:        0,
2301:        0,
2302:        0,
2303:        0,
2304: /*90*/ MatMatMult_SeqAIJ_SeqAIJ,
2305:        MatMatMultSymbolic_SeqAIJ_SeqAIJ,
2306:        MatMatMultNumeric_SeqAIJ_SeqAIJ,
2307:        MatPtAP_Basic,
2308:        MatPtAPSymbolic_SeqAIJ,
2309: /*95*/ MatPtAPNumeric_SeqAIJ,
2310:        MatMatMultTranspose_SeqAIJ_SeqAIJ,
2311:        MatMatMultTransposeSymbolic_SeqAIJ_SeqAIJ,
2312:        MatMatMultTransposeNumeric_SeqAIJ_SeqAIJ,
2313:        MatPtAPSymbolic_SeqAIJ_SeqAIJ,
2314: /*100*/MatPtAPNumeric_SeqAIJ_SeqAIJ,
2315:        0,
2316:        0,
2317:        MatConjugate_SeqAIJ,
2318:        0,
2319: /*105*/MatSetValuesRow_SeqAIJ,
2320:        MatRealPart_SeqAIJ,
2321:        MatImaginaryPart_SeqAIJ,
2322:        0,
2323:        0,
2324: /*110*/MatMatSolve_SeqAIJ
2325: };

2330: PetscErrorCode  MatSeqAIJSetColumnIndices_SeqAIJ(Mat mat,PetscInt *indices)
2331: {
2332:   Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data;
2333:   PetscInt   i,nz,n;


2337:   nz = aij->maxnz;
2338:   n  = mat->cmap.n;
2339:   for (i=0; i<nz; i++) {
2340:     aij->j[i] = indices[i];
2341:   }
2342:   aij->nz = nz;
2343:   for (i=0; i<n; i++) {
2344:     aij->ilen[i] = aij->imax[i];
2345:   }

2347:   return(0);
2348: }

2353: /*@
2354:     MatSeqAIJSetColumnIndices - Set the column indices for all the rows
2355:        in the matrix.

2357:   Input Parameters:
2358: +  mat - the SeqAIJ matrix
2359: -  indices - the column indices

2361:   Level: advanced

2363:   Notes:
2364:     This can be called if you have precomputed the nonzero structure of the 
2365:   matrix and want to provide it to the matrix object to improve the performance
2366:   of the MatSetValues() operation.

2368:     You MUST have set the correct numbers of nonzeros per row in the call to 
2369:   MatCreateSeqAIJ(), and the columns indices MUST be sorted.

2371:     MUST be called before any calls to MatSetValues();

2373:     The indices should start with zero, not one.

2375: @*/
2376: PetscErrorCode  MatSeqAIJSetColumnIndices(Mat mat,PetscInt *indices)
2377: {
2378:   PetscErrorCode ierr,(*f)(Mat,PetscInt *);

2383:   PetscObjectQueryFunction((PetscObject)mat,"MatSeqAIJSetColumnIndices_C",(void (**)(void))&f);
2384:   if (f) {
2385:     (*f)(mat,indices);
2386:   } else {
2387:     SETERRQ(PETSC_ERR_SUP,"Wrong type of matrix to set column indices");
2388:   }
2389:   return(0);
2390: }

2392: /* ----------------------------------------------------------------------------------------*/

2397: PetscErrorCode  MatStoreValues_SeqAIJ(Mat mat)
2398: {
2399:   Mat_SeqAIJ     *aij = (Mat_SeqAIJ *)mat->data;
2401:   size_t         nz = aij->i[mat->rmap.n];

2404:   if (aij->nonew != 1) {
2405:     SETERRQ(PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NO_NEW_NONZERO_LOCATIONS);first");
2406:   }

2408:   /* allocate space for values if not already there */
2409:   if (!aij->saved_values) {
2410:     PetscMalloc((nz+1)*sizeof(PetscScalar),&aij->saved_values);
2411:   }

2413:   /* copy values over */
2414:   PetscMemcpy(aij->saved_values,aij->a,nz*sizeof(PetscScalar));
2415:   return(0);
2416: }

2421: /*@
2422:     MatStoreValues - Stashes a copy of the matrix values; this allows, for 
2423:        example, reuse of the linear part of a Jacobian, while recomputing the 
2424:        nonlinear portion.

2426:    Collect on Mat

2428:   Input Parameters:
2429: .  mat - the matrix (currently only AIJ matrices support this option)

2431:   Level: advanced

2433:   Common Usage, with SNESSolve():
2434: $    Create Jacobian matrix
2435: $    Set linear terms into matrix
2436: $    Apply boundary conditions to matrix, at this time matrix must have 
2437: $      final nonzero structure (i.e. setting the nonlinear terms and applying 
2438: $      boundary conditions again will not change the nonzero structure
2439: $    MatSetOption(mat,MAT_NO_NEW_NONZERO_LOCATIONS);
2440: $    MatStoreValues(mat);
2441: $    Call SNESSetJacobian() with matrix
2442: $    In your Jacobian routine
2443: $      MatRetrieveValues(mat);
2444: $      Set nonlinear terms in matrix
2445:  
2446:   Common Usage without SNESSolve(), i.e. when you handle nonlinear solve yourself:
2447: $    // build linear portion of Jacobian 
2448: $    MatSetOption(mat,MAT_NO_NEW_NONZERO_LOCATIONS);
2449: $    MatStoreValues(mat);
2450: $    loop over nonlinear iterations
2451: $       MatRetrieveValues(mat);
2452: $       // call MatSetValues(mat,...) to set nonliner portion of Jacobian 
2453: $       // call MatAssemblyBegin/End() on matrix
2454: $       Solve linear system with Jacobian
2455: $    endloop 

2457:   Notes:
2458:     Matrix must already be assemblied before calling this routine
2459:     Must set the matrix option MatSetOption(mat,MAT_NO_NEW_NONZERO_LOCATIONS); before 
2460:     calling this routine.

2462:     When this is called multiple times it overwrites the previous set of stored values
2463:     and does not allocated additional space.

2465: .seealso: MatRetrieveValues()

2467: @*/
2468: PetscErrorCode  MatStoreValues(Mat mat)
2469: {
2470:   PetscErrorCode ierr,(*f)(Mat);

2474:   if (!mat->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2475:   if (mat->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");

2477:   PetscObjectQueryFunction((PetscObject)mat,"MatStoreValues_C",(void (**)(void))&f);
2478:   if (f) {
2479:     (*f)(mat);
2480:   } else {
2481:     SETERRQ(PETSC_ERR_SUP,"Wrong type of matrix to store values");
2482:   }
2483:   return(0);
2484: }

2489: PetscErrorCode  MatRetrieveValues_SeqAIJ(Mat mat)
2490: {
2491:   Mat_SeqAIJ     *aij = (Mat_SeqAIJ *)mat->data;
2493:   PetscInt       nz = aij->i[mat->rmap.n];

2496:   if (aij->nonew != 1) {
2497:     SETERRQ(PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NO_NEW_NONZERO_LOCATIONS);first");
2498:   }
2499:   if (!aij->saved_values) {
2500:     SETERRQ(PETSC_ERR_ORDER,"Must call MatStoreValues(A);first");
2501:   }
2502:   /* copy values over */
2503:   PetscMemcpy(aij->a,aij->saved_values,nz*sizeof(PetscScalar));
2504:   return(0);
2505: }

2510: /*@
2511:     MatRetrieveValues - Retrieves the copy of the matrix values; this allows, for 
2512:        example, reuse of the linear part of a Jacobian, while recomputing the 
2513:        nonlinear portion.

2515:    Collect on Mat

2517:   Input Parameters:
2518: .  mat - the matrix (currently on AIJ matrices support this option)

2520:   Level: advanced

2522: .seealso: MatStoreValues()

2524: @*/
2525: PetscErrorCode  MatRetrieveValues(Mat mat)
2526: {
2527:   PetscErrorCode ierr,(*f)(Mat);

2531:   if (!mat->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2532:   if (mat->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");

2534:   PetscObjectQueryFunction((PetscObject)mat,"MatRetrieveValues_C",(void (**)(void))&f);
2535:   if (f) {
2536:     (*f)(mat);
2537:   } else {
2538:     SETERRQ(PETSC_ERR_SUP,"Wrong type of matrix to retrieve values");
2539:   }
2540:   return(0);
2541: }


2544: /* --------------------------------------------------------------------------------*/
2547: /*@C
2548:    MatCreateSeqAIJ - Creates a sparse matrix in AIJ (compressed row) format
2549:    (the default parallel PETSc format).  For good matrix assembly performance
2550:    the user should preallocate the matrix storage by setting the parameter nz
2551:    (or the array nnz).  By setting these parameters accurately, performance
2552:    during matrix assembly can be increased by more than a factor of 50.

2554:    Collective on MPI_Comm

2556:    Input Parameters:
2557: +  comm - MPI communicator, set to PETSC_COMM_SELF
2558: .  m - number of rows
2559: .  n - number of columns
2560: .  nz - number of nonzeros per row (same for all rows)
2561: -  nnz - array containing the number of nonzeros in the various rows 
2562:          (possibly different for each row) or PETSC_NULL

2564:    Output Parameter:
2565: .  A - the matrix 

2567:    Notes:
2568:    If nnz is given then nz is ignored

2570:    The AIJ format (also called the Yale sparse matrix format or
2571:    compressed row storage), is fully compatible with standard Fortran 77
2572:    storage.  That is, the stored row and column indices can begin at
2573:    either one (as in Fortran) or zero.  See the users' manual for details.

2575:    Specify the preallocated storage with either nz or nnz (not both).
2576:    Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory 
2577:    allocation.  For large problems you MUST preallocate memory or you 
2578:    will get TERRIBLE performance, see the users' manual chapter on matrices.

2580:    By default, this format uses inodes (identical nodes) when possible, to 
2581:    improve numerical efficiency of matrix-vector products and solves. We 
2582:    search for consecutive rows with the same nonzero structure, thereby
2583:    reusing matrix information to achieve increased efficiency.

2585:    Options Database Keys:
2586: +  -mat_no_inode  - Do not use inodes
2587: .  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
2588: -  -mat_aij_oneindex - Internally use indexing starting at 1
2589:         rather than 0.  Note that when calling MatSetValues(),
2590:         the user still MUST index entries starting at 0!

2592:    Level: intermediate

2594: .seealso: MatCreate(), MatCreateMPIAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays()

2596: @*/
2597: PetscErrorCode  MatCreateSeqAIJ(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],Mat *A)
2598: {

2602:   MatCreate(comm,A);
2603:   MatSetSizes(*A,m,n,m,n);
2604:   MatSetType(*A,MATSEQAIJ);
2605:   MatSeqAIJSetPreallocation_SeqAIJ(*A,nz,(PetscInt*)nnz);
2606:   return(0);
2607: }

2611: /*@C
2612:    MatSeqAIJSetPreallocation - For good matrix assembly performance
2613:    the user should preallocate the matrix storage by setting the parameter nz
2614:    (or the array nnz).  By setting these parameters accurately, performance
2615:    during matrix assembly can be increased by more than a factor of 50.

2617:    Collective on MPI_Comm

2619:    Input Parameters:
2620: +  B - The matrix
2621: .  nz - number of nonzeros per row (same for all rows)
2622: -  nnz - array containing the number of nonzeros in the various rows 
2623:          (possibly different for each row) or PETSC_NULL

2625:    Notes:
2626:      If nnz is given then nz is ignored

2628:     The AIJ format (also called the Yale sparse matrix format or
2629:    compressed row storage), is fully compatible with standard Fortran 77
2630:    storage.  That is, the stored row and column indices can begin at
2631:    either one (as in Fortran) or zero.  See the users' manual for details.

2633:    Specify the preallocated storage with either nz or nnz (not both).
2634:    Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory 
2635:    allocation.  For large problems you MUST preallocate memory or you 
2636:    will get TERRIBLE performance, see the users' manual chapter on matrices.

2638:    Developers: Use nz of MAT_SKIP_ALLOCATION to not allocate any space for the matrix
2639:    entries or columns indices

2641:    By default, this format uses inodes (identical nodes) when possible, to 
2642:    improve numerical efficiency of matrix-vector products and solves. We 
2643:    search for consecutive rows with the same nonzero structure, thereby
2644:    reusing matrix information to achieve increased efficiency.

2646:    Options Database Keys:
2647: +  -mat_no_inode  - Do not use inodes
2648: .  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
2649: -  -mat_aij_oneindex - Internally use indexing starting at 1
2650:         rather than 0.  Note that when calling MatSetValues(),
2651:         the user still MUST index entries starting at 0!

2653:    Level: intermediate

2655: .seealso: MatCreate(), MatCreateMPIAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays()

2657: @*/
2658: PetscErrorCode  MatSeqAIJSetPreallocation(Mat B,PetscInt nz,const PetscInt nnz[])
2659: {
2660:   PetscErrorCode ierr,(*f)(Mat,PetscInt,const PetscInt[]);

2663:   PetscObjectQueryFunction((PetscObject)B,"MatSeqAIJSetPreallocation_C",(void (**)(void))&f);
2664:   if (f) {
2665:     (*f)(B,nz,nnz);
2666:   }
2667:   return(0);
2668: }

2673: PetscErrorCode  MatSeqAIJSetPreallocation_SeqAIJ(Mat B,PetscInt nz,PetscInt *nnz)
2674: {
2675:   Mat_SeqAIJ     *b;
2676:   PetscTruth     skipallocation = PETSC_FALSE;
2678:   PetscInt       i;

2681: 
2682:   if (nz == MAT_SKIP_ALLOCATION) {
2683:     skipallocation = PETSC_TRUE;
2684:     nz             = 0;
2685:   }

2687:   B->rmap.bs = B->cmap.bs = 1;
2688:   PetscMapInitialize(B->comm,&B->rmap);
2689:   PetscMapInitialize(B->comm,&B->cmap);

2691:   if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
2692:   if (nz < 0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %d",nz);
2693:   if (nnz) {
2694:     for (i=0; i<B->rmap.n; i++) {
2695:       if (nnz[i] < 0) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be less than 0: local row %d value %d",i,nnz[i]);
2696:       if (nnz[i] > B->cmap.n) SETERRQ3(PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be greater than row length: local row %d value %d rowlength %d",i,nnz[i],B->cmap.n);
2697:     }
2698:   }

2700:   B->preallocated = PETSC_TRUE;
2701:   b = (Mat_SeqAIJ*)B->data;

2703:   if (!skipallocation) {
2704:     PetscMalloc2(B->rmap.n,PetscInt,&b->imax,B->rmap.n,PetscInt,&b->ilen);
2705:     if (!nnz) {
2706:       if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 10;
2707:       else if (nz <= 0)        nz = 1;
2708:       for (i=0; i<B->rmap.n; i++) b->imax[i] = nz;
2709:       nz = nz*B->rmap.n;
2710:     } else {
2711:       nz = 0;
2712:       for (i=0; i<B->rmap.n; i++) {b->imax[i] = nnz[i]; nz += nnz[i];}
2713:     }

2715:     /* b->ilen will count nonzeros in each row so far. */
2716:     for (i=0; i<B->rmap.n; i++) { b->ilen[i] = 0;}

2718:     /* allocate the matrix space */
2719:     PetscMalloc3(nz,PetscScalar,&b->a,nz,PetscInt,&b->j,B->rmap.n+1,PetscInt,&b->i);
2720:     b->i[0] = 0;
2721:     for (i=1; i<B->rmap.n+1; i++) {
2722:       b->i[i] = b->i[i-1] + b->imax[i-1];
2723:     }
2724:     b->singlemalloc = PETSC_TRUE;
2725:     b->free_a       = PETSC_TRUE;
2726:     b->free_ij      = PETSC_TRUE;
2727:   } else {
2728:     b->free_a       = PETSC_FALSE;
2729:     b->free_ij      = PETSC_FALSE;
2730:   }

2732:   b->nz                = 0;
2733:   b->maxnz             = nz;
2734:   B->info.nz_unneeded  = (double)b->maxnz;
2735:   return(0);
2736: }

2739: #undef  __FUNCT__
2741: /*@C
2742:    MatSeqAIJSetPreallocationCSR - Allocates memory for a sparse sequential matrix in AIJ format.  

2744:    Input Parameters:
2745: +  B - the matrix 
2746: .  i - the indices into j for the start of each row (starts with zero)
2747: .  j - the column indices for each row (starts with zero) these must be sorted for each row
2748: -  v - optional values in the matrix

2750:    Contributed by: Lisandro Dalchin

2752:    Level: developer

2754: .keywords: matrix, aij, compressed row, sparse, sequential

2756: .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatSeqAIJSetPreallocation(), MatCreateSeqAIJ(), SeqAIJ
2757: @*/
2758: PetscErrorCode MatSeqAIJSetPreallocationCSR(Mat B,const PetscInt i[],const PetscInt j[],const PetscScalar v[])
2759: {
2760:   PetscErrorCode (*f)(Mat,const PetscInt[],const PetscInt[],const PetscScalar[]);

2765:   PetscObjectQueryFunction((PetscObject)B,"MatSeqAIJSetPreallocationCSR_C",(void (**)(void))&f);
2766:   if (f) {
2767:     (*f)(B,i,j,v);
2768:   }
2769:   return(0);
2770: }

2773: #undef  __FUNCT__
2775: PetscErrorCode  MatSeqAIJSetPreallocationCSR_SeqAIJ(Mat B,const PetscInt Ii[],const PetscInt J[],const PetscScalar v[])
2776: {
2777:   PetscInt       i;
2778:   PetscInt       m,n;
2779:   PetscInt       nz;
2780:   PetscInt       *nnz, nz_max = 0;
2781:   PetscScalar    *values;

2785:   MatGetSize(B, &m, &n);

2787:   if (Ii[0]) {
2788:     SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE, "Ii[0] must be 0 it is %D", Ii[0]);
2789:   }
2790:   PetscMalloc((m+1) * sizeof(PetscInt), &nnz);
2791:   for(i = 0; i < m; i++) {
2792:     nz     = Ii[i+1]- Ii[i];
2793:     nz_max = PetscMax(nz_max, nz);
2794:     if (nz < 0) {
2795:       SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE, "Local row %D has a negative number of columns %D", i, nnz);
2796:     }
2797:     nnz[i] = nz;
2798:   }
2799:   MatSeqAIJSetPreallocation(B, 0, nnz);
2800:   PetscFree(nnz);

2802:   if (v) {
2803:     values = (PetscScalar*) v;
2804:   } else {
2805:     PetscMalloc((nz_max+1)*sizeof(PetscScalar), &values);
2806:     PetscMemzero(values, nz_max*sizeof(PetscScalar));
2807:   }

2809:   MatSetOption(B,MAT_COLUMNS_SORTED);

2811:   for(i = 0; i < m; i++) {
2812:     nz  = Ii[i+1] - Ii[i];
2813:     MatSetValues_SeqAIJ(B, 1, &i, nz, J+Ii[i], values + (v ? Ii[i] : 0), INSERT_VALUES);
2814:   }

2816:   MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);
2817:   MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);
2818:   MatSetOption(B,MAT_COLUMNS_UNSORTED);

2820:   if (!v) {
2821:     PetscFree(values);
2822:   }
2823:   return(0);
2824: }

2827: /*MC
2828:    MATSEQAIJ - MATSEQAIJ = "seqaij" - A matrix type to be used for sequential sparse matrices, 
2829:    based on compressed sparse row format.

2831:    Options Database Keys:
2832: . -mat_type seqaij - sets the matrix type to "seqaij" during a call to MatSetFromOptions()

2834:   Level: beginner

2836: .seealso: MatCreateSeqAIJ(), MatSetFromOptions(), MatSetType(), MatCreate(), MatType
2837: M*/


2846: PetscErrorCode  MatCreate_SeqAIJ(Mat B)
2847: {
2848:   Mat_SeqAIJ     *b;
2850:   PetscMPIInt    size;

2853:   MPI_Comm_size(B->comm,&size);
2854:   if (size > 1) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Comm must be of size 1");

2856:   PetscNew(Mat_SeqAIJ,&b);
2857:   B->data             = (void*)b;
2858:   PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));
2859:   B->factor           = 0;
2860:   B->mapping          = 0;
2861:   b->row              = 0;
2862:   b->col              = 0;
2863:   b->icol             = 0;
2864:   b->reallocs         = 0;
2865:   b->sorted            = PETSC_FALSE;
2866:   b->ignorezeroentries = PETSC_FALSE;
2867:   b->roworiented       = PETSC_TRUE;
2868:   b->nonew             = 0;
2869:   b->diag              = 0;
2870:   b->solve_work        = 0;
2871:   B->spptr             = 0;
2872:   b->saved_values      = 0;
2873:   b->idiag             = 0;
2874:   b->ssor              = 0;
2875:   b->keepzeroedrows    = PETSC_FALSE;
2876:   b->xtoy              = 0;
2877:   b->XtoY              = 0;
2878:   b->compressedrow.use     = PETSC_FALSE;
2879:   b->compressedrow.nrows   = B->rmap.n;
2880:   b->compressedrow.i       = PETSC_NULL;
2881:   b->compressedrow.rindex  = PETSC_NULL;
2882:   b->compressedrow.checked = PETSC_FALSE;
2883:   B->same_nonzero          = PETSC_FALSE;

2885:   PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);
2886:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqAIJSetColumnIndices_C",
2887:                                      "MatSeqAIJSetColumnIndices_SeqAIJ",
2888:                                      MatSeqAIJSetColumnIndices_SeqAIJ);
2889:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatStoreValues_C",
2890:                                      "MatStoreValues_SeqAIJ",
2891:                                      MatStoreValues_SeqAIJ);
2892:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatRetrieveValues_C",
2893:                                      "MatRetrieveValues_SeqAIJ",
2894:                                      MatRetrieveValues_SeqAIJ);
2895:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_seqsbaij_C",
2896:                                      "MatConvert_SeqAIJ_SeqSBAIJ",
2897:                                       MatConvert_SeqAIJ_SeqSBAIJ);
2898:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_seqbaij_C",
2899:                                      "MatConvert_SeqAIJ_SeqBAIJ",
2900:                                       MatConvert_SeqAIJ_SeqBAIJ);
2901:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_seqcsrperm_C",
2902:                                      "MatConvert_SeqAIJ_SeqCSRPERM",
2903:                                       MatConvert_SeqAIJ_SeqCSRPERM);
2904:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_seqcrl_C",
2905:                                      "MatConvert_SeqAIJ_SeqCRL",
2906:                                       MatConvert_SeqAIJ_SeqCRL);
2907:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatIsTranspose_C",
2908:                                      "MatIsTranspose_SeqAIJ",
2909:                                       MatIsTranspose_SeqAIJ);
2910:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqAIJSetPreallocation_C",
2911:                                      "MatSeqAIJSetPreallocation_SeqAIJ",
2912:                                       MatSeqAIJSetPreallocation_SeqAIJ);
2913:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqAIJSetPreallocationCSR_C",
2914:                                      "MatSeqAIJSetPreallocationCSR_SeqAIJ",
2915:                                       MatSeqAIJSetPreallocationCSR_SeqAIJ);
2916:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatReorderForNonzeroDiagonal_C",
2917:                                      "MatReorderForNonzeroDiagonal_SeqAIJ",
2918:                                       MatReorderForNonzeroDiagonal_SeqAIJ);
2919:   MatCreate_Inode(B);
2920:   PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);
2921:   return(0);
2922: }

2927: PetscErrorCode MatDuplicate_SeqAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B)
2928: {
2929:   Mat            C;
2930:   Mat_SeqAIJ     *c,*a = (Mat_SeqAIJ*)A->data;
2932:   PetscInt       i,m = A->rmap.n;

2935:   *B = 0;
2936:   MatCreate(A->comm,&C);
2937:   MatSetSizes(C,A->rmap.n,A->cmap.n,A->rmap.n,A->cmap.n);
2938:   MatSetType(C,A->type_name);
2939:   PetscMemcpy(C->ops,A->ops,sizeof(struct _MatOps));
2940: 
2941:   PetscMapCopy(A->comm,&A->rmap,&C->rmap);
2942:   PetscMapCopy(A->comm,&A->cmap,&C->cmap);

2944:   c = (Mat_SeqAIJ*)C->data;

2946:   C->factor           = A->factor;

2948:   c->row            = 0;
2949:   c->col            = 0;
2950:   c->icol           = 0;
2951:   c->reallocs       = 0;

2953:   C->assembled      = PETSC_TRUE;
2954: 
2955:   PetscMalloc2(m,PetscInt,&c->imax,m,PetscInt,&c->ilen);
2956:   for (i=0; i<m; i++) {
2957:     c->imax[i] = a->imax[i];
2958:     c->ilen[i] = a->ilen[i];
2959:   }

2961:   /* allocate the matrix space */
2962:   PetscMalloc3(a->i[m],PetscScalar,&c->a,a->i[m],PetscInt,&c->j,m+1,PetscInt,&c->i);
2963:   c->singlemalloc = PETSC_TRUE;
2964:   PetscMemcpy(c->i,a->i,(m+1)*sizeof(PetscInt));
2965:   if (m > 0) {
2966:     PetscMemcpy(c->j,a->j,(a->i[m])*sizeof(PetscInt));
2967:     if (cpvalues == MAT_COPY_VALUES) {
2968:       PetscMemcpy(c->a,a->a,(a->i[m])*sizeof(PetscScalar));
2969:     } else {
2970:       PetscMemzero(c->a,(a->i[m])*sizeof(PetscScalar));
2971:     }
2972:   }

2974:   c->sorted            = a->sorted;
2975:   c->ignorezeroentries = a->ignorezeroentries;
2976:   c->roworiented       = a->roworiented;
2977:   c->nonew             = a->nonew;
2978:   if (a->diag) {
2979:     PetscMalloc((m+1)*sizeof(PetscInt),&c->diag);
2980:     PetscLogObjectMemory(C,(m+1)*sizeof(PetscInt));
2981:     for (i=0; i<m; i++) {
2982:       c->diag[i] = a->diag[i];
2983:     }
2984:   } else c->diag        = 0;
2985:   c->solve_work         = 0;
2986:   c->saved_values          = 0;
2987:   c->idiag                 = 0;
2988:   c->ssor                  = 0;
2989:   c->keepzeroedrows        = a->keepzeroedrows;
2990:   c->free_a                = PETSC_TRUE;
2991:   c->free_ij               = PETSC_TRUE;
2992:   c->xtoy                  = 0;
2993:   c->XtoY                  = 0;

2995:   c->nz                 = a->nz;
2996:   c->maxnz              = a->maxnz;
2997:   C->preallocated       = PETSC_TRUE;

2999:   c->compressedrow.use     = a->compressedrow.use;
3000:   c->compressedrow.nrows   = a->compressedrow.nrows;
3001:   c->compressedrow.checked = a->compressedrow.checked;
3002:   if ( a->compressedrow.checked && a->compressedrow.use){
3003:     i = a->compressedrow.nrows;
3004:     PetscMalloc((2*i+1)*sizeof(PetscInt),&c->compressedrow.i);
3005:     c->compressedrow.rindex = c->compressedrow.i + i + 1;
3006:     PetscMemcpy(c->compressedrow.i,a->compressedrow.i,(i+1)*sizeof(PetscInt));
3007:     PetscMemcpy(c->compressedrow.rindex,a->compressedrow.rindex,i*sizeof(PetscInt));
3008:   } else {
3009:     c->compressedrow.use    = PETSC_FALSE;
3010:     c->compressedrow.i      = PETSC_NULL;
3011:     c->compressedrow.rindex = PETSC_NULL;
3012:   }
3013:   C->same_nonzero = A->same_nonzero;
3014:   MatDuplicate_Inode(A,cpvalues,&C);

3016:   *B = C;
3017:   PetscFListDuplicate(A->qlist,&C->qlist);
3018:   return(0);
3019: }

3023: PetscErrorCode MatLoad_SeqAIJ(PetscViewer viewer, MatType type,Mat *A)
3024: {
3025:   Mat_SeqAIJ     *a;
3026:   Mat            B;
3028:   PetscInt       i,sum,nz,header[4],*rowlengths = 0,M,N;
3029:   int            fd;
3030:   PetscMPIInt    size;
3031:   MPI_Comm       comm;
3032: 
3034:   PetscObjectGetComm((PetscObject)viewer,&comm);
3035:   MPI_Comm_size(comm,&size);
3036:   if (size > 1) SETERRQ(PETSC_ERR_ARG_SIZ,"view must have one processor");
3037:   PetscViewerBinaryGetDescriptor(viewer,&fd);
3038:   PetscBinaryRead(fd,header,4,PETSC_INT);
3039:   if (header[0] != MAT_FILE_COOKIE) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"not matrix object in file");
3040:   M = header[1]; N = header[2]; nz = header[3];

3042:   if (nz < 0) {
3043:     SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format on disk,cannot load as SeqAIJ");
3044:   }

3046:   /* read in row lengths */
3047:   PetscMalloc(M*sizeof(PetscInt),&rowlengths);
3048:   PetscBinaryRead(fd,rowlengths,M,PETSC_INT);

3050:   /* check if sum of rowlengths is same as nz */
3051:   for (i=0,sum=0; i< M; i++) sum +=rowlengths[i];
3052:   if (sum != nz) SETERRQ2(PETSC_ERR_FILE_READ,"Inconsistant matrix data in file. no-nonzeros = %d, sum-row-lengths = %d\n",nz,sum);

3054:   /* create our matrix */
3055:   MatCreate(comm,&B);
3056:   MatSetSizes(B,PETSC_DECIDE,PETSC_DECIDE,M,N);
3057:   MatSetType(B,type);
3058:   MatSeqAIJSetPreallocation_SeqAIJ(B,0,rowlengths);
3059:   a = (Mat_SeqAIJ*)B->data;

3061:   /* read in column indices and adjust for Fortran indexing*/
3062:   PetscBinaryRead(fd,a->j,nz,PETSC_INT);

3064:   /* read in nonzero values */
3065:   PetscBinaryRead(fd,a->a,nz,PETSC_SCALAR);

3067:   /* set matrix "i" values */
3068:   a->i[0] = 0;
3069:   for (i=1; i<= M; i++) {
3070:     a->i[i]      = a->i[i-1] + rowlengths[i-1];
3071:     a->ilen[i-1] = rowlengths[i-1];
3072:   }
3073:   PetscFree(rowlengths);

3075:   MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);
3076:   MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);
3077:   *A = B;
3078:   return(0);
3079: }

3083: PetscErrorCode MatEqual_SeqAIJ(Mat A,Mat B,PetscTruth* flg)
3084: {
3085:   Mat_SeqAIJ     *a = (Mat_SeqAIJ *)A->data,*b = (Mat_SeqAIJ *)B->data;

3089:   /* If the  matrix dimensions are not equal,or no of nonzeros */
3090:   if ((A->rmap.n != B->rmap.n) || (A->cmap.n != B->cmap.n) ||(a->nz != b->nz)) {
3091:     *flg = PETSC_FALSE;
3092:     return(0);
3093:   }
3094: 
3095:   /* if the a->i are the same */
3096:   PetscMemcmp(a->i,b->i,(A->rmap.n+1)*sizeof(PetscInt),flg);
3097:   if (!*flg) return(0);
3098: 
3099:   /* if a->j are the same */
3100:   PetscMemcmp(a->j,b->j,(a->nz)*sizeof(PetscInt),flg);
3101:   if (!*flg) return(0);
3102: 
3103:   /* if a->a are the same */
3104:   PetscMemcmp(a->a,b->a,(a->nz)*sizeof(PetscScalar),flg);

3106:   return(0);
3107: 
3108: }

3112: /*@
3113:      MatCreateSeqAIJWithArrays - Creates an sequential AIJ matrix using matrix elements (in CSR format)
3114:               provided by the user.

3116:       Collective on MPI_Comm

3118:    Input Parameters:
3119: +   comm - must be an MPI communicator of size 1
3120: .   m - number of rows
3121: .   n - number of columns
3122: .   i - row indices
3123: .   j - column indices
3124: -   a - matrix values

3126:    Output Parameter:
3127: .   mat - the matrix

3129:    Level: intermediate

3131:    Notes:
3132:        The i, j, and a arrays are not copied by this routine, the user must free these arrays
3133:     once the matrix is destroyed

3135:        You cannot set new nonzero locations into this matrix, that will generate an error.

3137:        The i and j indices are 0 based

3139: .seealso: MatCreate(), MatCreateMPIAIJ(), MatCreateSeqAIJ(), MatCreateMPIAIJWithArrays(), MatMPIAIJSetPreallocationCSR()

3141: @*/
3142: PetscErrorCode  MatCreateSeqAIJWithArrays(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt* i,PetscInt*j,PetscScalar *a,Mat *mat)
3143: {
3145:   PetscInt       ii;
3146:   Mat_SeqAIJ     *aij;

3149:   if (i[0]) {
3150:     SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0");
3151:   }
3152:   MatCreate(comm,mat);
3153:   MatSetSizes(*mat,m,n,m,n);
3154:   MatSetType(*mat,MATSEQAIJ);
3155:   MatSeqAIJSetPreallocation_SeqAIJ(*mat,MAT_SKIP_ALLOCATION,0);
3156:   aij  = (Mat_SeqAIJ*)(*mat)->data;
3157:   PetscMalloc2(m,PetscInt,&aij->imax,m,PetscInt,&aij->ilen);

3159:   aij->i = i;
3160:   aij->j = j;
3161:   aij->a = a;
3162:   aij->singlemalloc = PETSC_FALSE;
3163:   aij->nonew        = -1;             /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/
3164:   aij->free_a       = PETSC_FALSE;
3165:   aij->free_ij      = PETSC_FALSE;

3167:   for (ii=0; ii<m; ii++) {
3168:     aij->ilen[ii] = aij->imax[ii] = i[ii+1] - i[ii];
3169: #if defined(PETSC_USE_DEBUG)
3170:     if (i[ii+1] - i[ii] < 0) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Negative row length in i (row indices) row = %d length = %d",ii,i[ii+1] - i[ii]);
3171: #endif    
3172:   }
3173: #if defined(PETSC_USE_DEBUG)
3174:   for (ii=0; ii<aij->i[m]; ii++) {
3175:     if (j[ii] < 0) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Negative column index at location = %d index = %d",ii,j[ii]);
3176:     if (j[ii] > n - 1) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column index to large at location = %d index = %d",ii,j[ii]);
3177:   }
3178: #endif    

3180:   MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);
3181:   MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);
3182:   return(0);
3183: }

3187: PetscErrorCode MatSetColoring_SeqAIJ(Mat A,ISColoring coloring)
3188: {
3190:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;

3193:   if (coloring->ctype == IS_COLORING_LOCAL) {
3194:     ISColoringReference(coloring);
3195:     a->coloring = coloring;
3196:   } else if (coloring->ctype == IS_COLORING_GHOSTED) {
3197:     PetscInt             i,*larray;
3198:     ISColoring      ocoloring;
3199:     ISColoringValue *colors;

3201:     /* set coloring for diagonal portion */
3202:     PetscMalloc((A->cmap.n+1)*sizeof(PetscInt),&larray);
3203:     for (i=0; i<A->cmap.n; i++) {
3204:       larray[i] = i;
3205:     }
3206:     ISGlobalToLocalMappingApply(A->mapping,IS_GTOLM_MASK,A->cmap.n,larray,PETSC_NULL,larray);
3207:     PetscMalloc((A->cmap.n+1)*sizeof(ISColoringValue),&colors);
3208:     for (i=0; i<A->cmap.n; i++) {
3209:       colors[i] = coloring->colors[larray[i]];
3210:     }
3211:     PetscFree(larray);
3212:     ISColoringCreate(PETSC_COMM_SELF,coloring->n,A->cmap.n,colors,&ocoloring);
3213:     a->coloring = ocoloring;
3214:   }
3215:   return(0);
3216: }

3218: #if defined(PETSC_HAVE_ADIC)
3220: #include "adic/ad_utils.h"

3225: PetscErrorCode MatSetValuesAdic_SeqAIJ(Mat A,void *advalues)
3226: {
3227:   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3228:   PetscInt        m = A->rmap.n,*ii = a->i,*jj = a->j,nz,i,j,nlen;
3229:   PetscScalar     *v = a->a,*values = ((PetscScalar*)advalues)+1;
3230:   ISColoringValue *color;

3233:   if (!a->coloring) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Coloring not set for matrix");
3234:   nlen  = PetscADGetDerivTypeSize()/sizeof(PetscScalar);
3235:   color = a->coloring->colors;
3236:   /* loop over rows */
3237:   for (i=0; i<m; i++) {
3238:     nz = ii[i+1] - ii[i];
3239:     /* loop over columns putting computed value into matrix */
3240:     for (j=0; j<nz; j++) {
3241:       *v++ = values[color[*jj++]];
3242:     }
3243:     values += nlen; /* jump to next row of derivatives */
3244:   }
3245:   return(0);
3246: }
3247: #endif

3251: PetscErrorCode MatSetValuesAdifor_SeqAIJ(Mat A,PetscInt nl,void *advalues)
3252: {
3253:   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3254:   PetscInt             m = A->rmap.n,*ii = a->i,*jj = a->j,nz,i,j;
3255:   PetscScalar     *v = a->a,*values = (PetscScalar *)advalues;
3256:   ISColoringValue *color;

3259:   if (!a->coloring) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Coloring not set for matrix");
3260:   color = a->coloring->colors;
3261:   /* loop over rows */
3262:   for (i=0; i<m; i++) {
3263:     nz = ii[i+1] - ii[i];
3264:     /* loop over columns putting computed value into matrix */
3265:     for (j=0; j<nz; j++) {
3266:       *v++ = values[color[*jj++]];
3267:     }
3268:     values += nl; /* jump to next row of derivatives */
3269:   }
3270:   return(0);
3271: }

3273: /*
3274:     Special version for direct calls from Fortran 
3275: */
3276: #if defined(PETSC_HAVE_FORTRAN_CAPS)
3277: #define matsetvaluesseqaij_ MATSETVALUESSEQAIJ
3278: #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
3279: #define matsetvaluesseqaij_ matsetvaluesseqaij
3280: #endif

3282: /* Change these macros so can be used in void function */
3283: #undef CHKERRQ
3284: #define CHKERRQ(ierr) CHKERRABORT(A->comm,ierr) 
3285: #undef SETERRQ2
3286: #define SETERRQ2(ierr,b,c,d) CHKERRABORT(A->comm,ierr) 

3291: void PETSC_STDCALL matsetvaluesseqaij_(Mat *AA,PetscInt *mm,const PetscInt im[],PetscInt *nn,const PetscInt in[],const PetscScalar v[],InsertMode *isis, PetscErrorCode *_ierr)
3292: {
3293:   Mat            A = *AA;
3294:   PetscInt       m = *mm, n = *nn;
3295:   InsertMode     is = *isis;
3296:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
3297:   PetscInt       *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N;
3298:   PetscInt       *imax,*ai,*ailen;
3300:   PetscInt       *aj,nonew = a->nonew,lastcol = -1;
3301:   PetscScalar    *ap,value,*aa;
3302:   PetscTruth     ignorezeroentries = ((a->ignorezeroentries && is == ADD_VALUES) ? PETSC_TRUE:PETSC_FALSE);
3303:   PetscTruth     roworiented = a->roworiented;

3306:   MatPreallocated(A);
3307:   imax = a->imax;
3308:   ai = a->i;
3309:   ailen = a->ilen;
3310:   aj = a->j;
3311:   aa = a->a;

3313:   for (k=0; k<m; k++) { /* loop over added rows */
3314:     row  = im[k];
3315:     if (row < 0) continue;
3316: #if defined(PETSC_USE_DEBUG)  
3317:     if (row >= A->rmap.n) SETERRABORT(A->comm,PETSC_ERR_ARG_OUTOFRANGE,"Row too large");
3318: #endif
3319:     rp   = aj + ai[row]; ap = aa + ai[row];
3320:     rmax = imax[row]; nrow = ailen[row];
3321:     low  = 0;
3322:     high = nrow;
3323:     for (l=0; l<n; l++) { /* loop over added columns */
3324:       if (in[l] < 0) continue;
3325: #if defined(PETSC_USE_DEBUG)  
3326:       if (in[l] >= A->cmap.n) SETERRABORT(A->comm,PETSC_ERR_ARG_OUTOFRANGE,"Column too large");
3327: #endif
3328:       col = in[l];
3329:       if (roworiented) {
3330:         value = v[l + k*n];
3331:       } else {
3332:         value = v[k + l*m];
3333:       }
3334:       if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue;

3336:       if (col <= lastcol) low = 0; else high = nrow;
3337:       lastcol = col;
3338:       while (high-low > 5) {
3339:         t = (low+high)/2;
3340:         if (rp[t] > col) high = t;
3341:         else             low  = t;
3342:       }
3343:       for (i=low; i<high; i++) {
3344:         if (rp[i] > col) break;
3345:         if (rp[i] == col) {
3346:           if (is == ADD_VALUES) ap[i] += value;
3347:           else                  ap[i] = value;
3348:           goto noinsert;
3349:         }
3350:       }
3351:       if (value == 0.0 && ignorezeroentries) goto noinsert;
3352:       if (nonew == 1) goto noinsert;
3353:       if (nonew == -1) SETERRABORT(A->comm,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero in the matrix");
3354:       MatSeqXAIJReallocateAIJ(A,A->rmap.n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew);
3355:       N = nrow++ - 1; a->nz++; high++;
3356:       /* shift up all the later entries in this row */
3357:       for (ii=N; ii>=i; ii--) {
3358:         rp[ii+1] = rp[ii];
3359:         ap[ii+1] = ap[ii];
3360:       }
3361:       rp[i] = col;
3362:       ap[i] = value;
3363:       noinsert:;
3364:       low = i + 1;
3365:     }
3366:     ailen[row] = nrow;
3367:   }
3368:   A->same_nonzero = PETSC_FALSE;
3369:   PetscFunctionReturnVoid();
3370: }