Actual source code: aij.c

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


  8: #include <../src/mat/impls/aij/seq/aij.h>          /*I "petscmat.h" I*/
  9: #include <petscblaslapack.h>
 10: #include <petscbt.h>


 15: PetscErrorCode MatGetColumnNorms_SeqAIJ(Mat A,NormType type,PetscReal *norms)
 16: {
 18:   PetscInt       i,m,n;
 19:   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;

 22:   MatGetSize(A,&m,&n);
 23:   PetscMemzero(norms,n*sizeof(PetscReal));
 24:   if (type == NORM_2) {
 25:     for (i=0; i<aij->i[m]; i++) {
 26:       norms[aij->j[i]] += PetscAbsScalar(aij->a[i]*aij->a[i]);
 27:     }
 28:   } else if (type == NORM_1) {
 29:     for (i=0; i<aij->i[m]; i++) {
 30:       norms[aij->j[i]] += PetscAbsScalar(aij->a[i]);
 31:     }
 32:   } else if (type == NORM_INFINITY) {
 33:     for (i=0; i<aij->i[m]; i++) {
 34:       norms[aij->j[i]] = PetscMax(PetscAbsScalar(aij->a[i]),norms[aij->j[i]]);
 35:     }
 36:   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Unknown NormType");

 38:   if (type == NORM_2) {
 39:     for (i=0; i<n; i++) norms[i] = PetscSqrtReal(norms[i]);
 40:   }
 41:   return(0);
 42: }

 46: PetscErrorCode MatFindZeroDiagonals_SeqAIJ(Mat A,IS *zrows)
 47: {
 48:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
 49:   const MatScalar   *aa = a->a;
 50:   PetscInt          i,m=A->rmap->n,cnt = 0;
 51:   const PetscInt    *jj = a->j,*diag;
 52:   PetscInt          *rows;
 53:   PetscErrorCode    ierr;

 56:   MatMarkDiagonal_SeqAIJ(A);
 57:   diag = a->diag;
 58:   for (i=0; i<m; i++) {
 59:     if ((jj[diag[i]] != i) || (aa[diag[i]] == 0.0)) {
 60:       cnt++;
 61:     }
 62:   }
 63:   PetscMalloc(cnt*sizeof(PetscInt),&rows);
 64:   cnt  = 0;
 65:   for (i=0; i<m; i++) {
 66:     if ((jj[diag[i]] != i) || (aa[diag[i]] == 0.0)) {
 67:       rows[cnt++] = i;
 68:     }
 69:   }
 70:   ISCreateGeneral(((PetscObject)A)->comm,cnt,rows,PETSC_OWN_POINTER,zrows);
 71:   return(0);
 72: }

 76: PetscErrorCode MatFindNonzeroRows_SeqAIJ(Mat A,IS *keptrows)
 77: {
 78:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
 79:   const MatScalar   *aa;
 80:   PetscInt          m=A->rmap->n,cnt = 0;
 81:   const PetscInt    *ii;
 82:   PetscInt          n,i,j,*rows;
 83:   PetscErrorCode    ierr;

 86:   *keptrows = 0;
 87:   ii        = a->i;
 88:   for (i=0; i<m; i++) {
 89:     n   = ii[i+1] - ii[i];
 90:     if (!n) {
 91:       cnt++;
 92:       goto ok1;
 93:     }
 94:     aa  = a->a + ii[i];
 95:     for (j=0; j<n; j++) {
 96:       if (aa[j] != 0.0) goto ok1;
 97:     }
 98:     cnt++;
 99:     ok1:;
100:   }
101:   if (!cnt) return(0);
102:   PetscMalloc((A->rmap->n-cnt)*sizeof(PetscInt),&rows);
103:   cnt  = 0;
104:   for (i=0; i<m; i++) {
105:     n   = ii[i+1] - ii[i];
106:     if (!n) continue;
107:     aa  = a->a + ii[i];
108:     for (j=0; j<n; j++) {
109:       if (aa[j] != 0.0) {
110:         rows[cnt++] = i;
111:         break;
112:       }
113:     }
114:   }
115:   ISCreateGeneral(PETSC_COMM_SELF,cnt,rows,PETSC_OWN_POINTER,keptrows);
116:   return(0);
117: }

121: PetscErrorCode  MatDiagonalSet_SeqAIJ(Mat Y,Vec D,InsertMode is)
122: {
124:   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*) Y->data;
125:   PetscInt       i,*diag, m = Y->rmap->n;
126:   MatScalar      *aa = aij->a;
127:   PetscScalar    *v;
128:   PetscBool      missing;

131:   if (Y->assembled) {
132:     MatMissingDiagonal_SeqAIJ(Y,&missing,PETSC_NULL);
133:     if (!missing) {
134:       diag = aij->diag;
135:       VecGetArray(D,&v);
136:       if (is == INSERT_VALUES) {
137:         for (i=0; i<m; i++) {
138:           aa[diag[i]] = v[i];
139:         }
140:       } else {
141:         for (i=0; i<m; i++) {
142:           aa[diag[i]] += v[i];
143:         }
144:       }
145:       VecRestoreArray(D,&v);
146:       return(0);
147:     }
148:   }
149:   MatDiagonalSet_Default(Y,D,is);
150:   return(0);
151: }

155: PetscErrorCode MatGetRowIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool  symmetric,PetscBool  inodecompressed,PetscInt *m,PetscInt *ia[],PetscInt *ja[],PetscBool  *done)
156: {
157:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
159:   PetscInt       i,ishift;
160: 
162:   *m     = A->rmap->n;
163:   if (!ia) return(0);
164:   ishift = 0;
165:   if (symmetric && !A->structurally_symmetric) {
166:     MatToSymmetricIJ_SeqAIJ(A->rmap->n,a->i,a->j,ishift,oshift,ia,ja);
167:   } else if (oshift == 1) {
168:     PetscInt nz = a->i[A->rmap->n];
169:     /* malloc space and  add 1 to i and j indices */
170:     PetscMalloc((A->rmap->n+1)*sizeof(PetscInt),ia);
171:     for (i=0; i<A->rmap->n+1; i++) (*ia)[i] = a->i[i] + 1;
172:     if (ja) {
173:       PetscMalloc((nz+1)*sizeof(PetscInt),ja);
174:       for (i=0; i<nz; i++) (*ja)[i] = a->j[i] + 1;
175:     }
176:   } else {
177:     *ia = a->i;
178:     if (ja) *ja = a->j;
179:   }
180:   return(0);
181: }

185: PetscErrorCode MatRestoreRowIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool  symmetric,PetscBool  inodecompressed,PetscInt *n,PetscInt *ia[],PetscInt *ja[],PetscBool  *done)
186: {
188: 
190:   if (!ia) return(0);
191:   if ((symmetric && !A->structurally_symmetric) || oshift == 1) {
192:     PetscFree(*ia);
193:     if (ja) {PetscFree(*ja);}
194:   }
195:   return(0);
196: }

200: PetscErrorCode MatGetColumnIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool  symmetric,PetscBool  inodecompressed,PetscInt *nn,PetscInt *ia[],PetscInt *ja[],PetscBool  *done)
201: {
202:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
204:   PetscInt       i,*collengths,*cia,*cja,n = A->cmap->n,m = A->rmap->n;
205:   PetscInt       nz = a->i[m],row,*jj,mr,col;

208:   *nn = n;
209:   if (!ia) return(0);
210:   if (symmetric) {
211:     MatToSymmetricIJ_SeqAIJ(A->rmap->n,a->i,a->j,0,oshift,ia,ja);
212:   } else {
213:     PetscMalloc((n+1)*sizeof(PetscInt),&collengths);
214:     PetscMemzero(collengths,n*sizeof(PetscInt));
215:     PetscMalloc((n+1)*sizeof(PetscInt),&cia);
216:     PetscMalloc((nz+1)*sizeof(PetscInt),&cja);
217:     jj = a->j;
218:     for (i=0; i<nz; i++) {
219:       collengths[jj[i]]++;
220:     }
221:     cia[0] = oshift;
222:     for (i=0; i<n; i++) {
223:       cia[i+1] = cia[i] + collengths[i];
224:     }
225:     PetscMemzero(collengths,n*sizeof(PetscInt));
226:     jj   = a->j;
227:     for (row=0; row<m; row++) {
228:       mr = a->i[row+1] - a->i[row];
229:       for (i=0; i<mr; i++) {
230:         col = *jj++;
231:         cja[cia[col] + collengths[col]++ - oshift] = row + oshift;
232:       }
233:     }
234:     PetscFree(collengths);
235:     *ia = cia; *ja = cja;
236:   }
237:   return(0);
238: }

242: PetscErrorCode MatRestoreColumnIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool  symmetric,PetscBool  inodecompressed,PetscInt *n,PetscInt *ia[],PetscInt *ja[],PetscBool  *done)
243: {

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

249:   PetscFree(*ia);
250:   PetscFree(*ja);
251: 
252:   return(0);
253: }

257: PetscErrorCode MatSetValuesRow_SeqAIJ(Mat A,PetscInt row,const PetscScalar v[])
258: {
259:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
260:   PetscInt       *ai = a->i;

264:   PetscMemcpy(a->a+ai[row],v,(ai[row+1]-ai[row])*sizeof(PetscScalar));
265:   return(0);
266: }

270: PetscErrorCode MatSetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
271: {
272:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
273:   PetscInt       *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N;
274:   PetscInt       *imax = a->imax,*ai = a->i,*ailen = a->ilen;
276:   PetscInt       *aj = a->j,nonew = a->nonew,lastcol = -1;
277:   MatScalar      *ap,value,*aa = a->a;
278:   PetscBool      ignorezeroentries = a->ignorezeroentries;
279:   PetscBool      roworiented = a->roworiented;

283:   for (k=0; k<m; k++) { /* loop over added rows */
284:     row  = im[k];
285:     if (row < 0) continue;
286: #if defined(PETSC_USE_DEBUG)  
287:     if (row >= A->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",row,A->rmap->n-1);
288: #endif
289:     rp   = aj + ai[row]; ap = aa + ai[row];
290:     rmax = imax[row]; nrow = ailen[row];
291:     low  = 0;
292:     high = nrow;
293:     for (l=0; l<n; l++) { /* loop over added columns */
294:       if (in[l] < 0) continue;
295: #if defined(PETSC_USE_DEBUG)  
296:       if (in[l] >= A->cmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",in[l],A->cmap->n-1);
297: #endif
298:       col = in[l];
299:       if (v) {
300:         if (roworiented) {
301:           value = v[l + k*n];
302:         } else {
303:           value = v[k + l*m];
304:         }
305:       } else {
306:         value = 0.;
307:       }
308:       if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue;

310:       if (col <= lastcol) low = 0; else high = nrow;
311:       lastcol = col;
312:       while (high-low > 5) {
313:         t = (low+high)/2;
314:         if (rp[t] > col) high = t;
315:         else             low  = t;
316:       }
317:       for (i=low; i<high; i++) {
318:         if (rp[i] > col) break;
319:         if (rp[i] == col) {
320:           if (is == ADD_VALUES) ap[i] += value;
321:           else                  ap[i] = value;
322:           low = i + 1;
323:           goto noinsert;
324:         }
325:       }
326:       if (value == 0.0 && ignorezeroentries) goto noinsert;
327:       if (nonew == 1) goto noinsert;
328:       if (nonew == -1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero at (%D,%D) in the matrix",row,col);
329:       MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
330:       N = nrow++ - 1; a->nz++; high++;
331:       /* shift up all the later entries in this row */
332:       for (ii=N; ii>=i; ii--) {
333:         rp[ii+1] = rp[ii];
334:         ap[ii+1] = ap[ii];
335:       }
336:       rp[i] = col;
337:       ap[i] = value;
338:       low   = i + 1;
339:       noinsert:;
340:     }
341:     ailen[row] = nrow;
342:   }
343:   A->same_nonzero = PETSC_FALSE;
344:   return(0);
345: }


350: PetscErrorCode MatGetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],PetscScalar v[])
351: {
352:   Mat_SeqAIJ   *a = (Mat_SeqAIJ*)A->data;
353:   PetscInt     *rp,k,low,high,t,row,nrow,i,col,l,*aj = a->j;
354:   PetscInt     *ai = a->i,*ailen = a->ilen;
355:   MatScalar    *ap,*aa = a->a;

358:   for (k=0; k<m; k++) { /* loop over rows */
359:     row  = im[k];
360:     if (row < 0) {v += n; continue;} /* SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative row: %D",row); */
361:     if (row >= A->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",row,A->rmap->n-1);
362:     rp   = aj + ai[row]; ap = aa + ai[row];
363:     nrow = ailen[row];
364:     for (l=0; l<n; l++) { /* loop over columns */
365:       if (in[l] < 0) {v++; continue;} /* SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column: %D",in[l]); */
366:       if (in[l] >= A->cmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",in[l],A->cmap->n-1);
367:       col = in[l] ;
368:       high = nrow; low = 0; /* assume unsorted */
369:       while (high-low > 5) {
370:         t = (low+high)/2;
371:         if (rp[t] > col) high = t;
372:         else             low  = t;
373:       }
374:       for (i=low; i<high; i++) {
375:         if (rp[i] > col) break;
376:         if (rp[i] == col) {
377:           *v++ = ap[i];
378:           goto finished;
379:         }
380:       }
381:       *v++ = 0.0;
382:       finished:;
383:     }
384:   }
385:   return(0);
386: }


391: PetscErrorCode MatView_SeqAIJ_Binary(Mat A,PetscViewer viewer)
392: {
393:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
395:   PetscInt       i,*col_lens;
396:   int            fd;

399:   PetscViewerBinaryGetDescriptor(viewer,&fd);
400:   PetscMalloc((4+A->rmap->n)*sizeof(PetscInt),&col_lens);
401:   col_lens[0] = MAT_FILE_CLASSID;
402:   col_lens[1] = A->rmap->n;
403:   col_lens[2] = A->cmap->n;
404:   col_lens[3] = a->nz;

406:   /* store lengths of each row and write (including header) to file */
407:   for (i=0; i<A->rmap->n; i++) {
408:     col_lens[4+i] = a->i[i+1] - a->i[i];
409:   }
410:   PetscBinaryWrite(fd,col_lens,4+A->rmap->n,PETSC_INT,PETSC_TRUE);
411:   PetscFree(col_lens);

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

416:   /* store nonzero values */
417:   PetscBinaryWrite(fd,a->a,a->nz,PETSC_SCALAR,PETSC_FALSE);
418:   return(0);
419: }


425: PetscErrorCode MatView_SeqAIJ_ASCII(Mat A,PetscViewer viewer)
426: {
427:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
428:   PetscErrorCode    ierr;
429:   PetscInt          i,j,m = A->rmap->n,shift=0;
430:   const char        *name;
431:   PetscViewerFormat format;

434:   PetscViewerGetFormat(viewer,&format);
435:   if (format == PETSC_VIEWER_ASCII_MATLAB) {
436:     PetscInt nofinalvalue = 0;
437:     if ((a->i[m] == a->i[m-1]) || (a->j[a->nz-1] != A->cmap->n-!shift)) {
438:       nofinalvalue = 1;
439:     }
440:     PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);
441:     PetscViewerASCIIPrintf(viewer,"%% Size = %D %D \n",m,A->cmap->n);
442:     PetscViewerASCIIPrintf(viewer,"%% Nonzeros = %D \n",a->nz);
443:     PetscViewerASCIIPrintf(viewer,"zzz = zeros(%D,3);\n",a->nz+nofinalvalue);
444:     PetscViewerASCIIPrintf(viewer,"zzz = [\n");

446:     for (i=0; i<m; i++) {
447:       for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
448: #if defined(PETSC_USE_COMPLEX)
449:         PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e + %18.16ei \n",i+1,a->j[j]+!shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));
450: #else
451:         PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e\n",i+1,a->j[j]+!shift,a->a[j]);
452: #endif
453:       }
454:     }
455:     if (nofinalvalue) {
456:       PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e\n",m,A->cmap->n,0.0);
457:     }
458:     PetscObjectGetName((PetscObject)A,&name);
459:     PetscViewerASCIIPrintf(viewer,"];\n %s = spconvert(zzz);\n",name);
460:     PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);
461:   } else if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO) {
462:      return(0);
463:   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
464:     PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);
465:     PetscObjectPrintClassNamePrefixType((PetscObject)A,viewer,"Matrix Object");
466:     for (i=0; i<m; i++) {
467:       PetscViewerASCIIPrintf(viewer,"row %D:",i);
468:       for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
469: #if defined(PETSC_USE_COMPLEX)
470:         if (PetscImaginaryPart(a->a[j]) > 0.0 && PetscRealPart(a->a[j]) != 0.0) {
471:           PetscViewerASCIIPrintf(viewer," (%D, %G + %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));
472:         } else if (PetscImaginaryPart(a->a[j]) < 0.0 && PetscRealPart(a->a[j]) != 0.0) {
473:           PetscViewerASCIIPrintf(viewer," (%D, %G - %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),-PetscImaginaryPart(a->a[j]));
474:         } else if (PetscRealPart(a->a[j]) != 0.0) {
475:           PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,PetscRealPart(a->a[j]));
476:         }
477: #else
478:         if (a->a[j] != 0.0) {PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,a->a[j]);}
479: #endif
480:       }
481:       PetscViewerASCIIPrintf(viewer,"\n");
482:     }
483:     PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);
484:   } else if (format == PETSC_VIEWER_ASCII_SYMMODU) {
485:     PetscInt nzd=0,fshift=1,*sptr;
486:     PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);
487:     PetscObjectPrintClassNamePrefixType((PetscObject)A,viewer,"Matrix Object");
488:     PetscMalloc((m+1)*sizeof(PetscInt),&sptr);
489:     for (i=0; i<m; i++) {
490:       sptr[i] = nzd+1;
491:       for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
492:         if (a->j[j] >= i) {
493: #if defined(PETSC_USE_COMPLEX)
494:           if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) nzd++;
495: #else
496:           if (a->a[j] != 0.0) nzd++;
497: #endif
498:         }
499:       }
500:     }
501:     sptr[m] = nzd+1;
502:     PetscViewerASCIIPrintf(viewer," %D %D\n\n",m,nzd);
503:     for (i=0; i<m+1; i+=6) {
504:       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]);}
505:       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]);}
506:       else if (i+2<m) {PetscViewerASCIIPrintf(viewer," %D %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2],sptr[i+3]);}
507:       else if (i+1<m) {PetscViewerASCIIPrintf(viewer," %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2]);}
508:       else if (i<m)   {PetscViewerASCIIPrintf(viewer," %D %D\n",sptr[i],sptr[i+1]);}
509:       else            {PetscViewerASCIIPrintf(viewer," %D\n",sptr[i]);}
510:     }
511:     PetscViewerASCIIPrintf(viewer,"\n");
512:     PetscFree(sptr);
513:     for (i=0; i<m; i++) {
514:       for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
515:         if (a->j[j] >= i) {PetscViewerASCIIPrintf(viewer," %D ",a->j[j]+fshift);}
516:       }
517:       PetscViewerASCIIPrintf(viewer,"\n");
518:     }
519:     PetscViewerASCIIPrintf(viewer,"\n");
520:     for (i=0; i<m; i++) {
521:       for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
522:         if (a->j[j] >= i) {
523: #if defined(PETSC_USE_COMPLEX)
524:           if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) {
525:             PetscViewerASCIIPrintf(viewer," %18.16e %18.16e ",PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));
526:           }
527: #else
528:           if (a->a[j] != 0.0) {PetscViewerASCIIPrintf(viewer," %18.16e ",a->a[j]);}
529: #endif
530:         }
531:       }
532:       PetscViewerASCIIPrintf(viewer,"\n");
533:     }
534:     PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);
535:   } else if (format == PETSC_VIEWER_ASCII_DENSE) {
536:     PetscInt         cnt = 0,jcnt;
537:     PetscScalar value;

539:     PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);
540:     PetscObjectPrintClassNamePrefixType((PetscObject)A,viewer,"Matrix Object");
541:     for (i=0; i<m; i++) {
542:       jcnt = 0;
543:       for (j=0; j<A->cmap->n; j++) {
544:         if (jcnt < a->i[i+1]-a->i[i] && j == a->j[cnt]) {
545:           value = a->a[cnt++];
546:           jcnt++;
547:         } else {
548:           value = 0.0;
549:         }
550: #if defined(PETSC_USE_COMPLEX)
551:         PetscViewerASCIIPrintf(viewer," %7.5e+%7.5e i ",PetscRealPart(value),PetscImaginaryPart(value));
552: #else
553:         PetscViewerASCIIPrintf(viewer," %7.5e ",value);
554: #endif
555:       }
556:       PetscViewerASCIIPrintf(viewer,"\n");
557:     }
558:     PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);
559:   } else if (format == PETSC_VIEWER_ASCII_MATRIXMARKET) {
560:     PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);
561:     PetscObjectPrintClassNamePrefixType((PetscObject)A,viewer,"Matrix Object");
562: #if defined(PETSC_USE_COMPLEX)
563:     PetscViewerASCIIPrintf(viewer,"%%matrix complex general\n");
564: #else
565:     PetscViewerASCIIPrintf(viewer,"%%matrix real general\n");
566: #endif
567:     PetscViewerASCIIPrintf(viewer,"%D %D %D\n", m, A->cmap->n, a->nz);
568:     for (i=0; i<m; i++) {
569:       for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
570: #if defined(PETSC_USE_COMPLEX)
571:         if (PetscImaginaryPart(a->a[j]) > 0.0) {
572:           PetscViewerASCIIPrintf(viewer,"%D %D, %G %G\n", i+shift,a->j[j]+shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));
573:         } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
574:           PetscViewerASCIIPrintf(viewer,"%D %D, %G -%G\n", i+shift,a->j[j]+shift,PetscRealPart(a->a[j]),-PetscImaginaryPart(a->a[j]));
575:         } else {
576:           PetscViewerASCIIPrintf(viewer,"%D %D, %G\n", i+shift,a->j[j]+shift,PetscRealPart(a->a[j]));
577:         }
578: #else
579:         PetscViewerASCIIPrintf(viewer,"%D %D %G\n", i+shift, a->j[j]+shift, a->a[j]);
580: #endif
581:       }
582:     }
583:     PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);
584:   } else {
585:     PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);
586:     PetscObjectPrintClassNamePrefixType((PetscObject)A,viewer,"Matrix Object");
587:     if (A->factortype){
588:       for (i=0; i<m; i++) {
589:         PetscViewerASCIIPrintf(viewer,"row %D:",i);
590:         /* L part */
591:         for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
592: #if defined(PETSC_USE_COMPLEX)
593:           if (PetscImaginaryPart(a->a[j]) > 0.0) {
594:             PetscViewerASCIIPrintf(viewer," (%D, %G + %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));
595:           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
596:             PetscViewerASCIIPrintf(viewer," (%D, %G - %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),-PetscImaginaryPart(a->a[j]));
597:           } else {
598:             PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,PetscRealPart(a->a[j]));
599:           }
600: #else
601:           PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,a->a[j]);
602: #endif
603:         }
604:         /* diagonal */
605:         j = a->diag[i];
606: #if defined(PETSC_USE_COMPLEX)
607:         if (PetscImaginaryPart(a->a[j]) > 0.0) {
608:             PetscViewerASCIIPrintf(viewer," (%D, %G + %G i)",a->j[j]+shift,PetscRealPart(1.0/a->a[j]),PetscImaginaryPart(1.0/a->a[j]));
609:           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
610:             PetscViewerASCIIPrintf(viewer," (%D, %G - %G i)",a->j[j]+shift,PetscRealPart(1.0/a->a[j]),-PetscImaginaryPart(1.0/a->a[j]));
611:           } else {
612:             PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,PetscRealPart(1.0/a->a[j]));
613:           }
614: #else
615:           PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,1.0/a->a[j]);
616: #endif

618:         /* U part */
619:         for (j=a->diag[i+1]+1+shift; j<a->diag[i]+shift; j++) {
620: #if defined(PETSC_USE_COMPLEX)
621:           if (PetscImaginaryPart(a->a[j]) > 0.0) {
622:             PetscViewerASCIIPrintf(viewer," (%D, %G + %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));
623:           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
624:             PetscViewerASCIIPrintf(viewer," (%D, %G - %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),-PetscImaginaryPart(a->a[j]));
625:           } else {
626:             PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,PetscRealPart(a->a[j]));
627:           }
628: #else
629:           PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,a->a[j]);
630: #endif
631: }
632:           PetscViewerASCIIPrintf(viewer,"\n");
633:         }
634:     } else {
635:       for (i=0; i<m; i++) {
636:         PetscViewerASCIIPrintf(viewer,"row %D:",i);
637:         for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
638: #if defined(PETSC_USE_COMPLEX)
639:           if (PetscImaginaryPart(a->a[j]) > 0.0) {
640:             PetscViewerASCIIPrintf(viewer," (%D, %G + %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));
641:           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
642:             PetscViewerASCIIPrintf(viewer," (%D, %G - %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),-PetscImaginaryPart(a->a[j]));
643:           } else {
644:             PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,PetscRealPart(a->a[j]));
645:           }
646: #else
647:           PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,a->a[j]);
648: #endif
649:         }
650:         PetscViewerASCIIPrintf(viewer,"\n");
651:       }
652:     }
653:     PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);
654:   }
655:   PetscViewerFlush(viewer);
656:   return(0);
657: }

661: PetscErrorCode MatView_SeqAIJ_Draw_Zoom(PetscDraw draw,void *Aa)
662: {
663:   Mat               A = (Mat) Aa;
664:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
665:   PetscErrorCode    ierr;
666:   PetscInt          i,j,m = A->rmap->n,color;
667:   PetscReal         xl,yl,xr,yr,x_l,x_r,y_l,y_r,maxv = 0.0;
668:   PetscViewer       viewer;
669:   PetscViewerFormat format;

672:   PetscObjectQuery((PetscObject)A,"Zoomviewer",(PetscObject*)&viewer);
673:   PetscViewerGetFormat(viewer,&format);

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

678:   if (format != PETSC_VIEWER_DRAW_CONTOUR) {
679:     /* Blue for negative, Cyan for zero and  Red for positive */
680:     color = PETSC_DRAW_BLUE;
681:     for (i=0; i<m; i++) {
682:       y_l = m - i - 1.0; y_r = y_l + 1.0;
683:       for (j=a->i[i]; j<a->i[i+1]; j++) {
684:         x_l = a->j[j] ; x_r = x_l + 1.0;
685: #if defined(PETSC_USE_COMPLEX)
686:         if (PetscRealPart(a->a[j]) >=  0.) continue;
687: #else
688:         if (a->a[j] >=  0.) continue;
689: #endif
690:         PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);
691:       }
692:     }
693:     color = PETSC_DRAW_CYAN;
694:     for (i=0; i<m; i++) {
695:       y_l = m - i - 1.0; y_r = y_l + 1.0;
696:       for (j=a->i[i]; j<a->i[i+1]; j++) {
697:         x_l = a->j[j]; x_r = x_l + 1.0;
698:         if (a->a[j] !=  0.) continue;
699:         PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);
700:       }
701:     }
702:     color = PETSC_DRAW_RED;
703:     for (i=0; i<m; i++) {
704:       y_l = m - i - 1.0; y_r = y_l + 1.0;
705:       for (j=a->i[i]; j<a->i[i+1]; j++) {
706:         x_l = a->j[j]; x_r = x_l + 1.0;
707: #if defined(PETSC_USE_COMPLEX)
708:         if (PetscRealPart(a->a[j]) <=  0.) continue;
709: #else
710:         if (a->a[j] <=  0.) continue;
711: #endif
712:         PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);
713:       }
714:     }
715:   } else {
716:     /* use contour shading to indicate magnitude of values */
717:     /* first determine max of all nonzero values */
718:     PetscInt    nz = a->nz,count;
719:     PetscDraw   popup;
720:     PetscReal scale;

722:     for (i=0; i<nz; i++) {
723:       if (PetscAbsScalar(a->a[i]) > maxv) maxv = PetscAbsScalar(a->a[i]);
724:     }
725:     scale = (245.0 - PETSC_DRAW_BASIC_COLORS)/maxv;
726:     PetscDrawGetPopup(draw,&popup);
727:     if (popup) {PetscDrawScalePopup(popup,0.0,maxv);}
728:     count = 0;
729:     for (i=0; i<m; i++) {
730:       y_l = m - i - 1.0; y_r = y_l + 1.0;
731:       for (j=a->i[i]; j<a->i[i+1]; j++) {
732:         x_l = a->j[j]; x_r = x_l + 1.0;
733:         color = PETSC_DRAW_BASIC_COLORS + (PetscInt)(scale*PetscAbsScalar(a->a[count]));
734:         PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);
735:         count++;
736:       }
737:     }
738:   }
739:   return(0);
740: }

744: PetscErrorCode MatView_SeqAIJ_Draw(Mat A,PetscViewer viewer)
745: {
747:   PetscDraw      draw;
748:   PetscReal      xr,yr,xl,yl,h,w;
749:   PetscBool      isnull;

752:   PetscViewerDrawGetDraw(viewer,0,&draw);
753:   PetscDrawIsNull(draw,&isnull);
754:   if (isnull) return(0);

756:   PetscObjectCompose((PetscObject)A,"Zoomviewer",(PetscObject)viewer);
757:   xr  = A->cmap->n; yr = A->rmap->n; h = yr/10.0; w = xr/10.0;
758:   xr += w;    yr += h;  xl = -w;     yl = -h;
759:   PetscDrawSetCoordinates(draw,xl,yl,xr,yr);
760:   PetscDrawZoom(draw,MatView_SeqAIJ_Draw_Zoom,A);
761:   PetscObjectCompose((PetscObject)A,"Zoomviewer",PETSC_NULL);
762:   return(0);
763: }

767: PetscErrorCode MatView_SeqAIJ(Mat A,PetscViewer viewer)
768: {
770:   PetscBool      iascii,isbinary,isdraw;

773:   PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
774:   PetscTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);
775:   PetscTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);
776:   if (iascii) {
777:     MatView_SeqAIJ_ASCII(A,viewer);
778:   } else if (isbinary) {
779:     MatView_SeqAIJ_Binary(A,viewer);
780:   } else if (isdraw) {
781:     MatView_SeqAIJ_Draw(A,viewer);
782:   } else {
783:     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported by SeqAIJ matrices",((PetscObject)viewer)->type_name);
784:   }
785:   MatView_SeqAIJ_Inode(A,viewer);
786:   return(0);
787: }

791: PetscErrorCode MatAssemblyEnd_SeqAIJ(Mat A,MatAssemblyType mode)
792: {
793:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
795:   PetscInt       fshift = 0,i,j,*ai = a->i,*aj = a->j,*imax = a->imax;
796:   PetscInt       m = A->rmap->n,*ip,N,*ailen = a->ilen,rmax = 0;
797:   MatScalar      *aa = a->a,*ap;
798:   PetscReal      ratio=0.6;

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

803:   if (m) rmax = ailen[0]; /* determine row with most nonzeros */
804:   for (i=1; i<m; i++) {
805:     /* move each row back by the amount of empty slots (fshift) before it*/
806:     fshift += imax[i-1] - ailen[i-1];
807:     rmax   = PetscMax(rmax,ailen[i]);
808:     if (fshift) {
809:       ip = aj + ai[i] ;
810:       ap = aa + ai[i] ;
811:       N  = ailen[i];
812:       for (j=0; j<N; j++) {
813:         ip[j-fshift] = ip[j];
814:         ap[j-fshift] = ap[j];
815:       }
816:     }
817:     ai[i] = ai[i-1] + ailen[i-1];
818:   }
819:   if (m) {
820:     fshift += imax[m-1] - ailen[m-1];
821:     ai[m]  = ai[m-1] + ailen[m-1];
822:   }
823:   /* reset ilen and imax for each row */
824:   for (i=0; i<m; i++) {
825:     ailen[i] = imax[i] = ai[i+1] - ai[i];
826:   }
827:   a->nz = ai[m];
828:   if (fshift && a->nounused == -1) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_PLIB, "Unused space detected in matrix: %D X %D, %D unneeded", m, A->cmap->n, fshift);

830:   MatMarkDiagonal_SeqAIJ(A);
831:   PetscInfo4(A,"Matrix size: %D X %D; storage space: %D unneeded,%D used\n",m,A->cmap->n,fshift,a->nz);
832:   PetscInfo1(A,"Number of mallocs during MatSetValues() is %D\n",a->reallocs);
833:   PetscInfo1(A,"Maximum nonzeros in any row is %D\n",rmax);
834:   A->info.mallocs     += a->reallocs;
835:   a->reallocs          = 0;
836:   A->info.nz_unneeded  = (double)fshift;
837:   a->rmax              = rmax;

839:   MatCheckCompressedRow(A,&a->compressedrow,a->i,m,ratio);
840:   A->same_nonzero = PETSC_TRUE;

842:   MatAssemblyEnd_SeqAIJ_Inode(A,mode);

844:   a->idiagvalid  = PETSC_FALSE;
845:   a->ibdiagvalid = PETSC_FALSE;
846:   return(0);
847: }

851: PetscErrorCode MatRealPart_SeqAIJ(Mat A)
852: {
853:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
854:   PetscInt       i,nz = a->nz;
855:   MatScalar      *aa = a->a;

858:   for (i=0; i<nz; i++) aa[i] = PetscRealPart(aa[i]);
859:   return(0);
860: }

864: PetscErrorCode MatImaginaryPart_SeqAIJ(Mat A)
865: {
866:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
867:   PetscInt       i,nz = a->nz;
868:   MatScalar      *aa = a->a;

871:   for (i=0; i<nz; i++) aa[i] = PetscImaginaryPart(aa[i]);
872:   return(0);
873: }

877: PetscErrorCode MatZeroEntries_SeqAIJ(Mat A)
878: {
879:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;

883:   PetscMemzero(a->a,(a->i[A->rmap->n])*sizeof(PetscScalar));
884:   return(0);
885: }

889: PetscErrorCode MatDestroy_SeqAIJ(Mat A)
890: {
891:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;

895: #if defined(PETSC_USE_LOG)
896:   PetscLogObjectState((PetscObject)A,"Rows=%D, Cols=%D, NZ=%D",A->rmap->n,A->cmap->n,a->nz);
897: #endif
898:   MatSeqXAIJFreeAIJ(A,&a->a,&a->j,&a->i);
899:   ISDestroy(&a->row);
900:   ISDestroy(&a->col);
901:   PetscFree(a->diag);
902:   PetscFree(a->ibdiag);
903:   PetscFree2(a->imax,a->ilen);
904:   PetscFree3(a->idiag,a->mdiag,a->ssor_work);
905:   PetscFree(a->solve_work);
906:   ISDestroy(&a->icol);
907:   PetscFree(a->saved_values);
908:   ISColoringDestroy(&a->coloring);
909:   PetscFree(a->xtoy);
910:   MatDestroy(&a->XtoY);
911:   PetscFree2(a->compressedrow.i,a->compressedrow.rindex);

913:   MatDestroy_SeqAIJ_Inode(A);
914:   PetscFree(A->data);

916:   PetscObjectChangeTypeName((PetscObject)A,0);
917:   PetscObjectComposeFunctionDynamic((PetscObject)A,"MatSeqAIJSetColumnIndices_C","",PETSC_NULL);
918:   PetscObjectComposeFunctionDynamic((PetscObject)A,"MatStoreValues_C","",PETSC_NULL);
919:   PetscObjectComposeFunctionDynamic((PetscObject)A,"MatRetrieveValues_C","",PETSC_NULL);
920:   PetscObjectComposeFunctionDynamic((PetscObject)A,"MatConvert_seqaij_seqsbaij_C","",PETSC_NULL);
921:   PetscObjectComposeFunctionDynamic((PetscObject)A,"MatConvert_seqaij_seqbaij_C","",PETSC_NULL);
922:   PetscObjectComposeFunctionDynamic((PetscObject)A,"MatConvert_seqaij_seqaijperm_C","",PETSC_NULL);
923:   PetscObjectComposeFunctionDynamic((PetscObject)A,"MatIsTranspose_C","",PETSC_NULL);
924:   PetscObjectComposeFunctionDynamic((PetscObject)A,"MatSeqAIJSetPreallocation_C","",PETSC_NULL);
925:   PetscObjectComposeFunctionDynamic((PetscObject)A,"MatSeqAIJSetPreallocationCSR_C","",PETSC_NULL);
926:   PetscObjectComposeFunctionDynamic((PetscObject)A,"MatReorderForNonzeroDiagonal_C","",PETSC_NULL);
927:   return(0);
928: }

932: PetscErrorCode MatSetOption_SeqAIJ(Mat A,MatOption op,PetscBool  flg)
933: {
934:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;

938:   switch (op) {
939:     case MAT_ROW_ORIENTED:
940:       a->roworiented       = flg;
941:       break;
942:     case MAT_KEEP_NONZERO_PATTERN:
943:       a->keepnonzeropattern    = flg;
944:       break;
945:     case MAT_NEW_NONZERO_LOCATIONS:
946:       a->nonew             = (flg ? 0 : 1);
947:       break;
948:     case MAT_NEW_NONZERO_LOCATION_ERR:
949:       a->nonew             = (flg ? -1 : 0);
950:       break;
951:     case MAT_NEW_NONZERO_ALLOCATION_ERR:
952:       a->nonew             = (flg ? -2 : 0);
953:       break;
954:     case MAT_UNUSED_NONZERO_LOCATION_ERR:
955:       a->nounused          = (flg ? -1 : 0);
956:       break;
957:     case MAT_IGNORE_ZERO_ENTRIES:
958:       a->ignorezeroentries = flg;
959:       break;
960:     case MAT_CHECK_COMPRESSED_ROW:
961:       a->compressedrow.check = flg;
962:       break;
963:     case MAT_SPD:
964:       A->spd_set                         = PETSC_TRUE;
965:       A->spd                             = flg;
966:       if (flg) {
967:         A->symmetric                     = PETSC_TRUE;
968:         A->structurally_symmetric        = PETSC_TRUE;
969:         A->symmetric_set                 = PETSC_TRUE;
970:         A->structurally_symmetric_set    = PETSC_TRUE;
971:       }
972:       break;
973:     case MAT_SYMMETRIC:
974:     case MAT_STRUCTURALLY_SYMMETRIC:
975:     case MAT_HERMITIAN:
976:     case MAT_SYMMETRY_ETERNAL:
977:     case MAT_NEW_DIAGONALS:
978:     case MAT_IGNORE_OFF_PROC_ENTRIES:
979:     case MAT_USE_HASH_TABLE:
980:       PetscInfo1(A,"Option %s ignored\n",MatOptions[op]);
981:       break;
982:     case MAT_USE_INODES:
983:       /* Not an error because MatSetOption_SeqAIJ_Inode handles this one */
984:       break;
985:     default:
986:       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"unknown option %d",op);
987:   }
988:   MatSetOption_SeqAIJ_Inode(A,op,flg);
989:   return(0);
990: }

994: PetscErrorCode MatGetDiagonal_SeqAIJ(Mat A,Vec v)
995: {
996:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
998:   PetscInt       i,j,n,*ai=a->i,*aj=a->j,nz;
999:   PetscScalar    *aa=a->a,*x,zero=0.0;

1002:   VecGetLocalSize(v,&n);
1003:   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");

1005:   if (A->factortype == MAT_FACTOR_ILU || A->factortype == MAT_FACTOR_LU){
1006:     PetscInt *diag=a->diag;
1007:     VecGetArray(v,&x);
1008:     for (i=0; i<n; i++) x[i] = 1.0/aa[diag[i]];
1009:     VecRestoreArray(v,&x);
1010:     return(0);
1011:   }

1013:   VecSet(v,zero);
1014:   VecGetArray(v,&x);
1015:   for (i=0; i<n; i++) {
1016:     nz = ai[i+1] - ai[i];
1017:     if (!nz) x[i] = 0.0;
1018:     for (j=ai[i]; j<ai[i+1]; j++){
1019:       if (aj[j] == i) {
1020:         x[i] = aa[j];
1021:         break;
1022:       }
1023:     }
1024:   }
1025:   VecRestoreArray(v,&x);
1026:   return(0);
1027: }

1029: #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h>
1032: PetscErrorCode MatMultTransposeAdd_SeqAIJ(Mat A,Vec xx,Vec zz,Vec yy)
1033: {
1034:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1035:   PetscScalar       *x,*y;
1036:   PetscErrorCode    ierr;
1037:   PetscInt          m = A->rmap->n;
1038: #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
1039:   MatScalar         *v;
1040:   PetscScalar       alpha;
1041:   PetscInt          n,i,j,*idx,*ii,*ridx=PETSC_NULL;
1042:   Mat_CompressedRow cprow = a->compressedrow;
1043:   PetscBool         usecprow = cprow.use;
1044: #endif

1047:   if (zz != yy) {VecCopy(zz,yy);}
1048:   VecGetArray(xx,&x);
1049:   VecGetArray(yy,&y);

1051: #if defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
1052:   fortranmulttransposeaddaij_(&m,x,a->i,a->j,a->a,y);
1053: #else
1054:   if (usecprow){
1055:     m    = cprow.nrows;
1056:     ii   = cprow.i;
1057:     ridx = cprow.rindex;
1058:   } else {
1059:     ii = a->i;
1060:   }
1061:   for (i=0; i<m; i++) {
1062:     idx   = a->j + ii[i] ;
1063:     v     = a->a + ii[i] ;
1064:     n     = ii[i+1] - ii[i];
1065:     if (usecprow){
1066:       alpha = x[ridx[i]];
1067:     } else {
1068:       alpha = x[i];
1069:     }
1070:     for (j=0; j<n; j++) y[idx[j]] += alpha*v[j];
1071:   }
1072: #endif
1073:   PetscLogFlops(2.0*a->nz);
1074:   VecRestoreArray(xx,&x);
1075:   VecRestoreArray(yy,&y);
1076:   return(0);
1077: }

1081: PetscErrorCode MatMultTranspose_SeqAIJ(Mat A,Vec xx,Vec yy)
1082: {

1086:   VecSet(yy,0.0);
1087:   MatMultTransposeAdd_SeqAIJ(A,xx,yy,yy);
1088:   return(0);
1089: }

1091: #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h>
1094: PetscErrorCode MatMult_SeqAIJ(Mat A,Vec xx,Vec yy)
1095: {
1096:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1097:   PetscScalar       *y;
1098:   const PetscScalar *x;
1099:   const MatScalar   *aa;
1100:   PetscErrorCode    ierr;
1101:   PetscInt          m=A->rmap->n;
1102:   const PetscInt    *aj,*ii,*ridx=PETSC_NULL;
1103:   PetscInt          n,i,nonzerorow=0;
1104:   PetscScalar       sum;
1105:   PetscBool         usecprow=a->compressedrow.use;

1107: #if defined(PETSC_HAVE_PRAGMA_DISJOINT)
1108: #pragma disjoint(*x,*y,*aa)
1109: #endif

1112:   VecGetArrayRead(xx,&x);
1113:   VecGetArray(yy,&y);
1114:   aj  = a->j;
1115:   aa  = a->a;
1116:   ii  = a->i;
1117:   if (usecprow){ /* use compressed row format */
1118:     m    = a->compressedrow.nrows;
1119:     ii   = a->compressedrow.i;
1120:     ridx = a->compressedrow.rindex;
1121:     for (i=0; i<m; i++){
1122:       n   = ii[i+1] - ii[i];
1123:       aj  = a->j + ii[i];
1124:       aa  = a->a + ii[i];
1125:       sum = 0.0;
1126:       nonzerorow += (n>0);
1127:       PetscSparseDensePlusDot(sum,x,aa,aj,n);
1128:       /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */
1129:       y[*ridx++] = sum;
1130:     }
1131:   } else { /* do not use compressed row format */
1132: #if defined(PETSC_USE_FORTRAN_KERNEL_MULTAIJ)
1133:     fortranmultaij_(&m,x,ii,aj,aa,y);
1134: #else
1135:     for (i=0; i<m; i++) {
1136:       n   = ii[i+1] - ii[i];
1137:       aj  = a->j + ii[i];
1138:       aa  = a->a + ii[i];
1139:       sum  = 0.0;
1140:       nonzerorow += (n>0);
1141:       PetscSparseDensePlusDot(sum,x,aa,aj,n);
1142:       y[i] = sum;
1143:     }
1144: #endif
1145:   }
1146:   PetscLogFlops(2.0*a->nz - nonzerorow);
1147:   VecRestoreArrayRead(xx,&x);
1148:   VecRestoreArray(yy,&y);
1149:   return(0);
1150: }

1152: #if defined(PETSC_HAVE_PTHREADCLASSES)

1154: //*******************
1155: #if defined(PETSC_HAVE_PTHREADCLASSES)
1157: void* DoCoreAffinity(void);

1159: typedef struct {
1160:   const MatScalar* matdata;
1161:   const PetscScalar* vecdata;
1162:   PetscScalar* vecout;
1163:   const PetscInt* colindnz;
1164:   const PetscInt* rownumnz;
1165:   PetscInt numrows;
1166:   const PetscInt* specidx;
1167:   PetscInt nzr;
1168: } MatMult_KernelData;

1170: void* MatMult_Kernel(void *arg)
1171: {
1172:   if(PetscUseThreadPool==PETSC_FALSE) {
1173:     DoCoreAffinity();
1174:   }
1175:   MatMult_KernelData *data = (MatMult_KernelData*)arg;
1176:   PetscScalar       sum;
1177:   const MatScalar   *aabase = data->matdata,*aa;
1178:   const PetscScalar *x = data->vecdata;
1179:   PetscScalar       *y = data->vecout;
1180:   const PetscInt    *ajbase = data->colindnz,*aj;
1181:   const PetscInt    *ii = data->rownumnz;
1182:   PetscInt          m  = data->numrows;
1183:   const PetscInt    *ridx = data->specidx;
1184:   PetscInt          i,n,nonzerorow = 0;

1186:   if(ridx!=NULL) {
1187:     for (i=0; i<m; i++){
1188:       n   = ii[i+1] - ii[i];
1189:       aj  = ajbase + ii[i];
1190:       aa  = aabase + ii[i];
1191:       sum = 0.0;
1192:       if(n>0) {
1193:         PetscSparseDensePlusDot(sum,x,aa,aj,n);
1194:         nonzerorow++;
1195:       }
1196:       y[*ridx++] = sum;
1197:     }
1198:   }
1199:   else {
1200:     PetscInt ibase = data->nzr;
1201:     for (i=0; i<m; i++) {
1202:       n   = ii[i+1] - ii[i];
1203:       aj  = ajbase + ii[i];
1204:       aa  = aabase + ii[i];
1205:       sum  = 0.0;
1206:       if(n>0) {
1207:         PetscSparseDensePlusDot(sum,x,aa,aj,n);
1208:         nonzerorow++;
1209:       }
1210:       y[i+ibase] = sum;
1211:     }
1212:   }
1213:   data->nzr = nonzerorow;
1214:   return NULL;
1215: }
1216: #endif


1223: PetscErrorCode MatMult_SeqAIJPThread(Mat A,Vec xx,Vec yy)
1224: {
1225:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1226:   PetscScalar       *y;
1227:   const PetscScalar *x;
1228:   PetscErrorCode    ierr;
1229:   PetscInt          m=A->rmap->n,nonzerorow=0;
1230:   PetscBool         usecprow=a->compressedrow.use;

1232: #if defined(PETSC_HAVE_PRAGMA_DISJOINT)
1233: #pragma disjoint(*x,*y,*aa)
1234: #endif

1237:   VecGetArrayRead(xx,&x);
1238:   VecGetArray(yy,&y);

1240:   if(usecprow) {
1241:     PetscInt          NumPerThread,iindex;
1242:     const MatScalar   *aa = a->a;
1243:     const PetscInt    *aj = a->j,*ii = a->compressedrow.i,*ridx=a->compressedrow.rindex;
1244:     PetscInt          i,iStartVal,iEndVal,iStartIndex,iEndIndex;
1245:     const PetscInt    iNumThreads = PetscMaxThreads;  //this number could be different
1246:     MatMult_KernelData* kerneldatap = (MatMult_KernelData*)malloc(iNumThreads*sizeof(MatMult_KernelData));
1247:     MatMult_KernelData** pdata = (MatMult_KernelData**)malloc(iNumThreads*sizeof(MatMult_KernelData*));

1249:     m    = a->compressedrow.nrows;
1250:     NumPerThread = ii[m]/iNumThreads;
1251:     iindex = 0;
1252:     for(i=0; i<iNumThreads;i++) {
1253:       iStartIndex = iindex;
1254:       iStartVal = ii[iStartIndex];
1255:       iEndVal = iStartVal;
1256:       //determine number of rows to process
1257:       while(iEndVal-iStartVal<NumPerThread) {
1258:         iindex++;
1259:         iEndVal = ii[iindex];
1260:       }
1261:       //determine whether to go back 1
1262:       if(iEndVal-iStartVal-NumPerThread>NumPerThread-(ii[iindex-1]-iStartVal)) {
1263:         iindex--;
1264:         iEndVal = ii[iindex];
1265:       }
1266:       iEndIndex = iindex;
1267:       kerneldatap[i].matdata  = aa;
1268:       kerneldatap[i].vecdata  = x;
1269:       kerneldatap[i].vecout   = y;
1270:       kerneldatap[i].colindnz = aj;
1271:       kerneldatap[i].rownumnz = ii + iStartIndex;
1272:       kerneldatap[i].numrows  = iEndIndex - iStartIndex + 1;
1273:       kerneldatap[i].specidx  = ridx + iStartVal;
1274:       kerneldatap[i].nzr      = 0;
1275:       pdata[i] = &kerneldatap[i];
1276:       iindex++;
1277:     }
1278:     MainJob(MatMult_Kernel,(void**)pdata,iNumThreads);
1279:     /* collect results */
1280:     for(i=0; i<iNumThreads; i++) {
1281:       nonzerorow += kerneldatap[i].nzr;
1282:     }
1283:     free(kerneldatap);
1284:     free(pdata);
1285:   }
1286:   else {
1287: #if defined(PETSC_USE_FORTRAN_KERNEL_MULTAIJ)
1288:   fortranmultaij_(&m,x,a->i,a->j,a->a,y);
1289: #else
1290:   PetscInt            i,iindex;
1291:     const MatScalar   *aa = a->a;
1292:     const PetscInt    *aj = a->j,*ii = a->i;
1293:     const PetscInt    iNumThreads = PetscMaxThreads;  //this number could be different
1294:     PetscInt          Q = m/iNumThreads;
1295:     PetscInt          R = m-Q*iNumThreads;
1296:     PetscBool         S;

1298:     MatMult_KernelData* kerneldatap = (MatMult_KernelData*)malloc(iNumThreads*sizeof(MatMult_KernelData));
1299:     MatMult_KernelData** pdata = (MatMult_KernelData**)malloc(iNumThreads*sizeof(MatMult_KernelData*));

1301:     iindex = 0;
1302:     for(i=0; i<iNumThreads;i++) {
1303:       S = (PetscBool)(i<R);
1304:       kerneldatap[i].matdata  = aa;
1305:       kerneldatap[i].vecdata  = x;
1306:       kerneldatap[i].vecout   = y;
1307:       kerneldatap[i].colindnz = aj;
1308:       kerneldatap[i].rownumnz = ii + iindex;
1309:       kerneldatap[i].numrows  = S?Q+1:Q;
1310:       kerneldatap[i].specidx  = PETSC_NULL;
1311:       kerneldatap[i].nzr      = iindex; //serves as the 'base' row (needed to access correctly into output vector y)
1312:       pdata[i] = &kerneldatap[i];
1313:       iindex += kerneldatap[i].numrows;
1314:     }
1315:     MainJob(MatMult_Kernel,(void**)pdata,iNumThreads);
1316:     //collect results
1317:     for(i=0; i<iNumThreads; i++) {
1318:       nonzerorow += kerneldatap[i].nzr;
1319:     }
1320:     free(kerneldatap);
1321:     free(pdata);
1322: #endif
1323:   }

1325:   PetscLogFlops(2.0*a->nz - nonzerorow);
1326:   VecRestoreArrayRead(xx,&x);
1327:   VecRestoreArray(yy,&y);
1328:   return(0);
1329: }
1330: //*******************
1331: #endif

1333: #include <../src/mat/impls/aij/seq/ftn-kernels/fmultadd.h>
1336: PetscErrorCode MatMultAdd_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz)
1337: {
1338:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1339:   PetscScalar       *y,*z;
1340:   const PetscScalar *x;
1341:   const MatScalar   *aa;
1342:   PetscErrorCode    ierr;
1343:   PetscInt          m = A->rmap->n,*aj,*ii;
1344:   PetscInt          n,i,*ridx=PETSC_NULL;
1345:   PetscScalar       sum;
1346:   PetscBool         usecprow=a->compressedrow.use;

1349:   VecGetArrayRead(xx,&x);
1350:   VecGetArray(yy,&y);
1351:   if (zz != yy) {
1352:     VecGetArray(zz,&z);
1353:   } else {
1354:     z = y;
1355:   }

1357:   aj  = a->j;
1358:   aa  = a->a;
1359:   ii  = a->i;
1360:   if (usecprow){ /* use compressed row format */
1361:     if (zz != yy){
1362:       PetscMemcpy(z,y,m*sizeof(PetscScalar));
1363:     }
1364:     m    = a->compressedrow.nrows;
1365:     ii   = a->compressedrow.i;
1366:     ridx = a->compressedrow.rindex;
1367:     for (i=0; i<m; i++){
1368:       n  = ii[i+1] - ii[i];
1369:       aj  = a->j + ii[i];
1370:       aa  = a->a + ii[i];
1371:       sum = y[*ridx];
1372:       PetscSparseDensePlusDot(sum,x,aa,aj,n);
1373:       z[*ridx++] = sum;
1374:     }
1375:   } else { /* do not use compressed row format */
1376: #if defined(PETSC_USE_FORTRAN_KERNEL_MULTADDAIJ)
1377:   fortranmultaddaij_(&m,x,ii,aj,aa,y,z);
1378: #else
1379:     for (i=0; i<m; i++) {
1380:       n    = ii[i+1] - ii[i];
1381:       aj  = a->j + ii[i];
1382:       aa  = a->a + ii[i];
1383:       sum  = y[i];
1384:       PetscSparseDensePlusDot(sum,x,aa,aj,n);
1385:       z[i] = sum;
1386:     }
1387: #endif
1388:   }
1389:   PetscLogFlops(2.0*a->nz);
1390:   VecRestoreArrayRead(xx,&x);
1391:   VecRestoreArray(yy,&y);
1392:   if (zz != yy) {
1393:     VecRestoreArray(zz,&z);
1394:   }
1395: #if defined(PETSC_HAVE_CUSP)
1396:   /*
1397:   VecView(xx,0);
1398:   VecView(zz,0);
1399:   MatView(A,0);
1400:   */
1401: #endif
1402:   return(0);
1403: }

1405: /*
1406:      Adds diagonal pointers to sparse matrix structure.
1407: */
1410: PetscErrorCode MatMarkDiagonal_SeqAIJ(Mat A)
1411: {
1412:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1414:   PetscInt       i,j,m = A->rmap->n;

1417:   if (!a->diag) {
1418:     PetscMalloc(m*sizeof(PetscInt),&a->diag);
1419:     PetscLogObjectMemory(A, m*sizeof(PetscInt));
1420:   }
1421:   for (i=0; i<A->rmap->n; i++) {
1422:     a->diag[i] = a->i[i+1];
1423:     for (j=a->i[i]; j<a->i[i+1]; j++) {
1424:       if (a->j[j] == i) {
1425:         a->diag[i] = j;
1426:         break;
1427:       }
1428:     }
1429:   }
1430:   return(0);
1431: }

1433: /*
1434:      Checks for missing diagonals
1435: */
1438: PetscErrorCode MatMissingDiagonal_SeqAIJ(Mat A,PetscBool  *missing,PetscInt *d)
1439: {
1440:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1441:   PetscInt       *diag,*jj = a->j,i;

1444:   *missing = PETSC_FALSE;
1445:   if (A->rmap->n > 0 && !jj) {
1446:     *missing  = PETSC_TRUE;
1447:     if (d) *d = 0;
1448:     PetscInfo(A,"Matrix has no entries therefor is missing diagonal");
1449:   } else {
1450:     diag = a->diag;
1451:     for (i=0; i<A->rmap->n; i++) {
1452:       if (jj[diag[i]] != i) {
1453:         *missing = PETSC_TRUE;
1454:         if (d) *d = i;
1455:         PetscInfo1(A,"Matrix is missing diagonal number %D",i);
1456:       }
1457:     }
1458:   }
1459:   return(0);
1460: }

1465: PetscErrorCode  MatInvertDiagonal_SeqAIJ(Mat A,PetscScalar omega,PetscScalar fshift)
1466: {
1467:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*) A->data;
1469:   PetscInt       i,*diag,m = A->rmap->n;
1470:   MatScalar      *v = a->a;
1471:   PetscScalar    *idiag,*mdiag;

1474:   if (a->idiagvalid) return(0);
1475:   MatMarkDiagonal_SeqAIJ(A);
1476:   diag = a->diag;
1477:   if (!a->idiag) {
1478:     PetscMalloc3(m,PetscScalar,&a->idiag,m,PetscScalar,&a->mdiag,m,PetscScalar,&a->ssor_work);
1479:     PetscLogObjectMemory(A, 3*m*sizeof(PetscScalar));
1480:     v        = a->a;
1481:   }
1482:   mdiag = a->mdiag;
1483:   idiag = a->idiag;
1484: 
1485:   if (omega == 1.0 && !PetscAbsScalar(fshift)) {
1486:     for (i=0; i<m; i++) {
1487:       mdiag[i] = v[diag[i]];
1488:       if (!PetscAbsScalar(mdiag[i])) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Zero diagonal on row %D",i);
1489:       idiag[i] = 1.0/v[diag[i]];
1490:     }
1491:     PetscLogFlops(m);
1492:   } else {
1493:     for (i=0; i<m; i++) {
1494:       mdiag[i] = v[diag[i]];
1495:       idiag[i] = omega/(fshift + v[diag[i]]);
1496:     }
1497:     PetscLogFlops(2.0*m);
1498:   }
1499:   a->idiagvalid = PETSC_TRUE;
1500:   return(0);
1501: }

1504: #include <../src/mat/impls/aij/seq/ftn-kernels/frelax.h>
1507: PetscErrorCode MatSOR_SeqAIJ(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx)
1508: {
1509:   Mat_SeqAIJ         *a = (Mat_SeqAIJ*)A->data;
1510:   PetscScalar        *x,d,sum,*t,scale;
1511:   const MatScalar    *v = a->a,*idiag=0,*mdiag;
1512:   const PetscScalar  *b, *bs,*xb, *ts;
1513:   PetscErrorCode     ierr;
1514:   PetscInt           n = A->cmap->n,m = A->rmap->n,i;
1515:   const PetscInt     *idx,*diag;

1518:   its = its*lits;

1520:   if (fshift != a->fshift || omega != a->omega) a->idiagvalid = PETSC_FALSE; /* must recompute idiag[] */
1521:   if (!a->idiagvalid) {MatInvertDiagonal_SeqAIJ(A,omega,fshift);}
1522:   a->fshift = fshift;
1523:   a->omega  = omega;

1525:   diag = a->diag;
1526:   t     = a->ssor_work;
1527:   idiag = a->idiag;
1528:   mdiag = a->mdiag;

1530:   VecGetArray(xx,&x);
1531:   VecGetArrayRead(bb,&b);
1532:   CHKMEMQ;
1533:   /* We count flops by assuming the upper triangular and lower triangular parts have the same number of nonzeros */
1534:   if (flag == SOR_APPLY_UPPER) {
1535:    /* apply (U + D/omega) to the vector */
1536:     bs = b;
1537:     for (i=0; i<m; i++) {
1538:         d    = fshift + mdiag[i];
1539:         n    = a->i[i+1] - diag[i] - 1;
1540:         idx  = a->j + diag[i] + 1;
1541:         v    = a->a + diag[i] + 1;
1542:         sum  = b[i]*d/omega;
1543:         PetscSparseDensePlusDot(sum,bs,v,idx,n);
1544:         x[i] = sum;
1545:     }
1546:     VecRestoreArray(xx,&x);
1547:     VecRestoreArrayRead(bb,&b);
1548:     PetscLogFlops(a->nz);
1549:     return(0);
1550:   }

1552:   if (flag == SOR_APPLY_LOWER) {
1553:     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"SOR_APPLY_LOWER is not implemented");
1554:   } else if (flag & SOR_EISENSTAT) {
1555:     /* Let  A = L + U + D; where L is lower trianglar,
1556:     U is upper triangular, E = D/omega; This routine applies

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

1560:     to a vector efficiently using Eisenstat's trick. 
1561:     */
1562:     scale = (2.0/omega) - 1.0;

1564:     /*  x = (E + U)^{-1} b */
1565:     for (i=m-1; i>=0; i--) {
1566:       n    = a->i[i+1] - diag[i] - 1;
1567:       idx  = a->j + diag[i] + 1;
1568:       v    = a->a + diag[i] + 1;
1569:       sum  = b[i];
1570:       PetscSparseDenseMinusDot(sum,x,v,idx,n);
1571:       x[i] = sum*idiag[i];
1572:     }

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

1578:     /*  t = (E + L)^{-1}t */
1579:     ts = t;
1580:     diag = a->diag;
1581:     for (i=0; i<m; i++) {
1582:       n    = diag[i] - a->i[i];
1583:       idx  = a->j + a->i[i];
1584:       v    = a->a + a->i[i];
1585:       sum  = t[i];
1586:       PetscSparseDenseMinusDot(sum,ts,v,idx,n);
1587:       t[i] = sum*idiag[i];
1588:       /*  x = x + t */
1589:       x[i] += t[i];
1590:     }

1592:     PetscLogFlops(6.0*m-1 + 2.0*a->nz);
1593:     VecRestoreArray(xx,&x);
1594:     VecRestoreArrayRead(bb,&b);
1595:     return(0);
1596:   }
1597:   if (flag & SOR_ZERO_INITIAL_GUESS) {
1598:     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){
1599:       for (i=0; i<m; i++) {
1600:         n    = diag[i] - a->i[i];
1601:         idx  = a->j + a->i[i];
1602:         v    = a->a + a->i[i];
1603:         sum  = b[i];
1604:         PetscSparseDenseMinusDot(sum,x,v,idx,n);
1605:         t[i] = sum;
1606:         x[i] = sum*idiag[i];
1607:       }
1608:       xb = t;
1609:       PetscLogFlops(a->nz);
1610:     } else xb = b;
1611:     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){
1612:       for (i=m-1; i>=0; i--) {
1613:         n    = a->i[i+1] - diag[i] - 1;
1614:         idx  = a->j + diag[i] + 1;
1615:         v    = a->a + diag[i] + 1;
1616:         sum  = xb[i];
1617:         PetscSparseDenseMinusDot(sum,x,v,idx,n);
1618:         if (xb == b) {
1619:           x[i] = sum*idiag[i];
1620:         } else {
1621:           x[i] = (1-omega)*x[i] + sum*idiag[i];
1622:         }
1623:       }
1624:       PetscLogFlops(a->nz);
1625:     }
1626:     its--;
1627:   }
1628:   while (its--) {
1629:     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){
1630:       for (i=0; i<m; i++) {
1631:         n    = a->i[i+1] - a->i[i];
1632:         idx  = a->j + a->i[i];
1633:         v    = a->a + a->i[i];
1634:         sum  = b[i];
1635:         PetscSparseDenseMinusDot(sum,x,v,idx,n);
1636:         x[i] = (1. - omega)*x[i] + (sum + mdiag[i]*x[i])*idiag[i];
1637:       }
1638:       PetscLogFlops(2.0*a->nz);
1639:     }
1640:     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){
1641:       for (i=m-1; i>=0; i--) {
1642:         n    = a->i[i+1] - a->i[i];
1643:         idx  = a->j + a->i[i];
1644:         v    = a->a + a->i[i];
1645:         sum  = b[i];
1646:         PetscSparseDenseMinusDot(sum,x,v,idx,n);
1647:         x[i] = (1. - omega)*x[i] + (sum + mdiag[i]*x[i])*idiag[i];
1648:       }
1649:       PetscLogFlops(2.0*a->nz);
1650:     }
1651:   }
1652:   VecRestoreArray(xx,&x);
1653:   VecRestoreArrayRead(bb,&b);
1654:   CHKMEMQ;  return(0);
1655: }


1660: PetscErrorCode MatGetInfo_SeqAIJ(Mat A,MatInfoType flag,MatInfo *info)
1661: {
1662:   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;

1665:   info->block_size     = 1.0;
1666:   info->nz_allocated   = (double)a->maxnz;
1667:   info->nz_used        = (double)a->nz;
1668:   info->nz_unneeded    = (double)(a->maxnz - a->nz);
1669:   info->assemblies     = (double)A->num_ass;
1670:   info->mallocs        = (double)A->info.mallocs;
1671:   info->memory         = ((PetscObject)A)->mem;
1672:   if (A->factortype) {
1673:     info->fill_ratio_given  = A->info.fill_ratio_given;
1674:     info->fill_ratio_needed = A->info.fill_ratio_needed;
1675:     info->factor_mallocs    = A->info.factor_mallocs;
1676:   } else {
1677:     info->fill_ratio_given  = 0;
1678:     info->fill_ratio_needed = 0;
1679:     info->factor_mallocs    = 0;
1680:   }
1681:   return(0);
1682: }

1686: PetscErrorCode MatZeroRows_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
1687: {
1688:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1689:   PetscInt          i,m = A->rmap->n - 1,d = 0;
1690:   PetscErrorCode    ierr;
1691:   const PetscScalar *xx;
1692:   PetscScalar       *bb;
1693:   PetscBool         missing;

1696:   if (x && b) {
1697:     VecGetArrayRead(x,&xx);
1698:     VecGetArray(b,&bb);
1699:     for (i=0; i<N; i++) {
1700:       if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
1701:       bb[rows[i]] = diag*xx[rows[i]];
1702:     }
1703:     VecRestoreArrayRead(x,&xx);
1704:     VecRestoreArray(b,&bb);
1705:   }

1707:   if (a->keepnonzeropattern) {
1708:     for (i=0; i<N; i++) {
1709:       if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
1710:       PetscMemzero(&a->a[a->i[rows[i]]],a->ilen[rows[i]]*sizeof(PetscScalar));
1711:     }
1712:     if (diag != 0.0) {
1713:       MatMissingDiagonal_SeqAIJ(A,&missing,&d);
1714:       if (missing) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Matrix is missing diagonal entry in row %D",d);
1715:       for (i=0; i<N; i++) {
1716:         a->a[a->diag[rows[i]]] = diag;
1717:       }
1718:     }
1719:     A->same_nonzero = PETSC_TRUE;
1720:   } else {
1721:     if (diag != 0.0) {
1722:       for (i=0; i<N; i++) {
1723:         if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
1724:         if (a->ilen[rows[i]] > 0) {
1725:           a->ilen[rows[i]]          = 1;
1726:           a->a[a->i[rows[i]]] = diag;
1727:           a->j[a->i[rows[i]]] = rows[i];
1728:         } else { /* in case row was completely empty */
1729:           MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES);
1730:         }
1731:       }
1732:     } else {
1733:       for (i=0; i<N; i++) {
1734:         if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
1735:         a->ilen[rows[i]] = 0;
1736:       }
1737:     }
1738:     A->same_nonzero = PETSC_FALSE;
1739:   }
1740:   MatAssemblyEnd_SeqAIJ(A,MAT_FINAL_ASSEMBLY);
1741:   return(0);
1742: }

1746: PetscErrorCode MatZeroRowsColumns_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
1747: {
1748:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1749:   PetscInt          i,j,m = A->rmap->n - 1,d = 0;
1750:   PetscErrorCode    ierr;
1751:   PetscBool         missing,*zeroed,vecs = PETSC_FALSE;
1752:   const PetscScalar *xx;
1753:   PetscScalar       *bb;

1756:   if (x && b) {
1757:     VecGetArrayRead(x,&xx);
1758:     VecGetArray(b,&bb);
1759:     vecs = PETSC_TRUE;
1760:   }
1761:   PetscMalloc(A->rmap->n*sizeof(PetscBool),&zeroed);
1762:   PetscMemzero(zeroed,A->rmap->n*sizeof(PetscBool));
1763:   for (i=0; i<N; i++) {
1764:     if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
1765:     PetscMemzero(&a->a[a->i[rows[i]]],a->ilen[rows[i]]*sizeof(PetscScalar));
1766:     zeroed[rows[i]] = PETSC_TRUE;
1767:   }
1768:   for (i=0; i<A->rmap->n; i++) {
1769:     if (!zeroed[i]) {
1770:       for (j=a->i[i]; j<a->i[i+1]; j++) {
1771:         if (zeroed[a->j[j]]) {
1772:           if (vecs) bb[i] -= a->a[j]*xx[a->j[j]];
1773:           a->a[j] = 0.0;
1774:         }
1775:       }
1776:     } else if (vecs) bb[i] = diag*xx[i];
1777:   }
1778:   if (x && b) {
1779:     VecRestoreArrayRead(x,&xx);
1780:     VecRestoreArray(b,&bb);
1781:   }
1782:   PetscFree(zeroed);
1783:   if (diag != 0.0) {
1784:     MatMissingDiagonal_SeqAIJ(A,&missing,&d);
1785:     if (missing) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Matrix is missing diagonal entry in row %D",d);
1786:     for (i=0; i<N; i++) {
1787:       a->a[a->diag[rows[i]]] = diag;
1788:     }
1789:   }
1790:   A->same_nonzero = PETSC_TRUE;
1791:   MatAssemblyEnd_SeqAIJ(A,MAT_FINAL_ASSEMBLY);
1792:   return(0);
1793: }

1797: PetscErrorCode MatGetRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
1798: {
1799:   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1800:   PetscInt   *itmp;

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

1805:   *nz = a->i[row+1] - a->i[row];
1806:   if (v) *v = a->a + a->i[row];
1807:   if (idx) {
1808:     itmp = a->j + a->i[row];
1809:     if (*nz) {
1810:       *idx = itmp;
1811:     }
1812:     else *idx = 0;
1813:   }
1814:   return(0);
1815: }

1817: /* remove this function? */
1820: PetscErrorCode MatRestoreRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
1821: {
1823:   return(0);
1824: }

1828: PetscErrorCode MatNorm_SeqAIJ(Mat A,NormType type,PetscReal *nrm)
1829: {
1830:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1831:   MatScalar      *v = a->a;
1832:   PetscReal      sum = 0.0;
1834:   PetscInt       i,j;

1837:   if (type == NORM_FROBENIUS) {
1838:     for (i=0; i<a->nz; i++) {
1839: #if defined(PETSC_USE_COMPLEX)
1840:       sum += PetscRealPart(PetscConj(*v)*(*v)); v++;
1841: #else
1842:       sum += (*v)*(*v); v++;
1843: #endif
1844:     }
1845:     *nrm = PetscSqrtReal(sum);
1846:   } else if (type == NORM_1) {
1847:     PetscReal *tmp;
1848:     PetscInt    *jj = a->j;
1849:     PetscMalloc((A->cmap->n+1)*sizeof(PetscReal),&tmp);
1850:     PetscMemzero(tmp,A->cmap->n*sizeof(PetscReal));
1851:     *nrm = 0.0;
1852:     for (j=0; j<a->nz; j++) {
1853:         tmp[*jj++] += PetscAbsScalar(*v);  v++;
1854:     }
1855:     for (j=0; j<A->cmap->n; j++) {
1856:       if (tmp[j] > *nrm) *nrm = tmp[j];
1857:     }
1858:     PetscFree(tmp);
1859:   } else if (type == NORM_INFINITY) {
1860:     *nrm = 0.0;
1861:     for (j=0; j<A->rmap->n; j++) {
1862:       v = a->a + a->i[j];
1863:       sum = 0.0;
1864:       for (i=0; i<a->i[j+1]-a->i[j]; i++) {
1865:         sum += PetscAbsScalar(*v); v++;
1866:       }
1867:       if (sum > *nrm) *nrm = sum;
1868:     }
1869:   } else {
1870:     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for two norm");
1871:   }
1872:   return(0);
1873: }

1877: PetscErrorCode MatTranspose_SeqAIJ(Mat A,MatReuse reuse,Mat *B)
1878: {
1879:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1880:   Mat            C;
1882:   PetscInt       i,*aj = a->j,*ai = a->i,m = A->rmap->n,len,*col;
1883:   MatScalar      *array = a->a;

1886:   if (reuse == MAT_REUSE_MATRIX && A == *B && m != A->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Square matrix only for in-place");

1888:   if (reuse == MAT_INITIAL_MATRIX || *B == A) {
1889:     PetscMalloc((1+A->cmap->n)*sizeof(PetscInt),&col);
1890:     PetscMemzero(col,(1+A->cmap->n)*sizeof(PetscInt));
1891: 
1892:     for (i=0; i<ai[m]; i++) col[aj[i]] += 1;
1893:     MatCreate(((PetscObject)A)->comm,&C);
1894:     MatSetSizes(C,A->cmap->n,m,A->cmap->n,m);
1895:     MatSetType(C,((PetscObject)A)->type_name);
1896:     MatSeqAIJSetPreallocation_SeqAIJ(C,0,col);
1897:     PetscFree(col);
1898:   } else {
1899:     C = *B;
1900:   }

1902:   for (i=0; i<m; i++) {
1903:     len    = ai[i+1]-ai[i];
1904:     MatSetValues_SeqAIJ(C,len,aj,1,&i,array,INSERT_VALUES);
1905:     array += len;
1906:     aj    += len;
1907:   }
1908:   MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);
1909:   MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);

1911:   if (reuse == MAT_INITIAL_MATRIX || *B != A) {
1912:     *B = C;
1913:   } else {
1914:     MatHeaderMerge(A,C);
1915:   }
1916:   return(0);
1917: }

1922: PetscErrorCode  MatIsTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool  *f)
1923: {
1924:   Mat_SeqAIJ     *aij = (Mat_SeqAIJ *) A->data,*bij = (Mat_SeqAIJ*) A->data;
1925:   PetscInt       *adx,*bdx,*aii,*bii,*aptr,*bptr;
1926:   MatScalar      *va,*vb;
1928:   PetscInt       ma,na,mb,nb, i;

1931:   bij = (Mat_SeqAIJ *) B->data;

1933:   MatGetSize(A,&ma,&na);
1934:   MatGetSize(B,&mb,&nb);
1935:   if (ma!=nb || na!=mb){
1936:     *f = PETSC_FALSE;
1937:     return(0);
1938:   }
1939:   aii = aij->i; bii = bij->i;
1940:   adx = aij->j; bdx = bij->j;
1941:   va  = aij->a; vb = bij->a;
1942:   PetscMalloc(ma*sizeof(PetscInt),&aptr);
1943:   PetscMalloc(mb*sizeof(PetscInt),&bptr);
1944:   for (i=0; i<ma; i++) aptr[i] = aii[i];
1945:   for (i=0; i<mb; i++) bptr[i] = bii[i];

1947:   *f = PETSC_TRUE;
1948:   for (i=0; i<ma; i++) {
1949:     while (aptr[i]<aii[i+1]) {
1950:       PetscInt         idc,idr;
1951:       PetscScalar vc,vr;
1952:       /* column/row index/value */
1953:       idc = adx[aptr[i]];
1954:       idr = bdx[bptr[idc]];
1955:       vc  = va[aptr[i]];
1956:       vr  = vb[bptr[idc]];
1957:       if (i!=idr || PetscAbsScalar(vc-vr) > tol) {
1958:         *f = PETSC_FALSE;
1959:         goto done;
1960:       } else {
1961:         aptr[i]++;
1962:         if (B || i!=idc) bptr[idc]++;
1963:       }
1964:     }
1965:   }
1966:  done:
1967:   PetscFree(aptr);
1968:   PetscFree(bptr);
1969:   return(0);
1970: }

1976: PetscErrorCode  MatIsHermitianTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool  *f)
1977: {
1978:   Mat_SeqAIJ     *aij = (Mat_SeqAIJ *) A->data,*bij = (Mat_SeqAIJ*) A->data;
1979:   PetscInt       *adx,*bdx,*aii,*bii,*aptr,*bptr;
1980:   MatScalar      *va,*vb;
1982:   PetscInt       ma,na,mb,nb, i;

1985:   bij = (Mat_SeqAIJ *) B->data;

1987:   MatGetSize(A,&ma,&na);
1988:   MatGetSize(B,&mb,&nb);
1989:   if (ma!=nb || na!=mb){
1990:     *f = PETSC_FALSE;
1991:     return(0);
1992:   }
1993:   aii = aij->i; bii = bij->i;
1994:   adx = aij->j; bdx = bij->j;
1995:   va  = aij->a; vb = bij->a;
1996:   PetscMalloc(ma*sizeof(PetscInt),&aptr);
1997:   PetscMalloc(mb*sizeof(PetscInt),&bptr);
1998:   for (i=0; i<ma; i++) aptr[i] = aii[i];
1999:   for (i=0; i<mb; i++) bptr[i] = bii[i];

2001:   *f = PETSC_TRUE;
2002:   for (i=0; i<ma; i++) {
2003:     while (aptr[i]<aii[i+1]) {
2004:       PetscInt         idc,idr;
2005:       PetscScalar vc,vr;
2006:       /* column/row index/value */
2007:       idc = adx[aptr[i]];
2008:       idr = bdx[bptr[idc]];
2009:       vc  = va[aptr[i]];
2010:       vr  = vb[bptr[idc]];
2011:       if (i!=idr || PetscAbsScalar(vc-PetscConj(vr)) > tol) {
2012:         *f = PETSC_FALSE;
2013:         goto done;
2014:       } else {
2015:         aptr[i]++;
2016:         if (B || i!=idc) bptr[idc]++;
2017:       }
2018:     }
2019:   }
2020:  done:
2021:   PetscFree(aptr);
2022:   PetscFree(bptr);
2023:   return(0);
2024: }

2029: PetscErrorCode MatIsSymmetric_SeqAIJ(Mat A,PetscReal tol,PetscBool  *f)
2030: {
2033:   MatIsTranspose_SeqAIJ(A,A,tol,f);
2034:   return(0);
2035: }

2039: PetscErrorCode MatIsHermitian_SeqAIJ(Mat A,PetscReal tol,PetscBool  *f)
2040: {
2043:   MatIsHermitianTranspose_SeqAIJ(A,A,tol,f);
2044:   return(0);
2045: }

2049: PetscErrorCode MatDiagonalScale_SeqAIJ(Mat A,Vec ll,Vec rr)
2050: {
2051:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
2052:   PetscScalar    *l,*r,x;
2053:   MatScalar      *v;
2055:   PetscInt       i,j,m = A->rmap->n,n = A->cmap->n,M,nz = a->nz,*jj;

2058:   if (ll) {
2059:     /* The local size is used so that VecMPI can be passed to this routine
2060:        by MatDiagonalScale_MPIAIJ */
2061:     VecGetLocalSize(ll,&m);
2062:     if (m != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Left scaling vector wrong length");
2063:     VecGetArray(ll,&l);
2064:     v = a->a;
2065:     for (i=0; i<m; i++) {
2066:       x = l[i];
2067:       M = a->i[i+1] - a->i[i];
2068:       for (j=0; j<M; j++) { (*v++) *= x;}
2069:     }
2070:     VecRestoreArray(ll,&l);
2071:     PetscLogFlops(nz);
2072:   }
2073:   if (rr) {
2074:     VecGetLocalSize(rr,&n);
2075:     if (n != A->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Right scaling vector wrong length");
2076:     VecGetArray(rr,&r);
2077:     v = a->a; jj = a->j;
2078:     for (i=0; i<nz; i++) {
2079:       (*v++) *= r[*jj++];
2080:     }
2081:     VecRestoreArray(rr,&r);
2082:     PetscLogFlops(nz);
2083:   }
2084:   return(0);
2085: }

2089: PetscErrorCode MatGetSubMatrix_SeqAIJ(Mat A,IS isrow,IS iscol,PetscInt csize,MatReuse scall,Mat *B)
2090: {
2091:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data,*c;
2093:   PetscInt       *smap,i,k,kstart,kend,oldcols = A->cmap->n,*lens;
2094:   PetscInt       row,mat_i,*mat_j,tcol,first,step,*mat_ilen,sum,lensi;
2095:   const PetscInt *irow,*icol;
2096:   PetscInt       nrows,ncols;
2097:   PetscInt       *starts,*j_new,*i_new,*aj = a->j,*ai = a->i,ii,*ailen = a->ilen;
2098:   MatScalar      *a_new,*mat_a;
2099:   Mat            C;
2100:   PetscBool      stride,sorted;

2103:   ISSorted(isrow,&sorted);
2104:   if (!sorted) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"ISrow is not sorted");
2105:   ISSorted(iscol,&sorted);
2106:   if (!sorted) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"IScol is not sorted");

2108:   ISGetIndices(isrow,&irow);
2109:   ISGetLocalSize(isrow,&nrows);
2110:   ISGetLocalSize(iscol,&ncols);

2112:   ISStrideGetInfo(iscol,&first,&step);
2113:   PetscTypeCompare((PetscObject)iscol,ISSTRIDE,&stride);
2114:   if (stride && step == 1) {
2115:     /* special case of contiguous rows */
2116:     PetscMalloc2(nrows,PetscInt,&lens,nrows,PetscInt,&starts);
2117:     /* loop over new rows determining lens and starting points */
2118:     for (i=0; i<nrows; i++) {
2119:       kstart  = ai[irow[i]];
2120:       kend    = kstart + ailen[irow[i]];
2121:       for (k=kstart; k<kend; k++) {
2122:         if (aj[k] >= first) {
2123:           starts[i] = k;
2124:           break;
2125:         }
2126:       }
2127:       sum = 0;
2128:       while (k < kend) {
2129:         if (aj[k++] >= first+ncols) break;
2130:         sum++;
2131:       }
2132:       lens[i] = sum;
2133:     }
2134:     /* create submatrix */
2135:     if (scall == MAT_REUSE_MATRIX) {
2136:       PetscInt n_cols,n_rows;
2137:       MatGetSize(*B,&n_rows,&n_cols);
2138:       if (n_rows != nrows || n_cols != ncols) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Reused submatrix wrong size");
2139:       MatZeroEntries(*B);
2140:       C = *B;
2141:     } else {
2142:       MatCreate(((PetscObject)A)->comm,&C);
2143:       MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);
2144:       MatSetType(C,((PetscObject)A)->type_name);
2145:       MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);
2146:     }
2147:     c = (Mat_SeqAIJ*)C->data;

2149:     /* loop over rows inserting into submatrix */
2150:     a_new    = c->a;
2151:     j_new    = c->j;
2152:     i_new    = c->i;

2154:     for (i=0; i<nrows; i++) {
2155:       ii    = starts[i];
2156:       lensi = lens[i];
2157:       for (k=0; k<lensi; k++) {
2158:         *j_new++ = aj[ii+k] - first;
2159:       }
2160:       PetscMemcpy(a_new,a->a + starts[i],lensi*sizeof(PetscScalar));
2161:       a_new      += lensi;
2162:       i_new[i+1]  = i_new[i] + lensi;
2163:       c->ilen[i]  = lensi;
2164:     }
2165:     PetscFree2(lens,starts);
2166:   } else {
2167:     ISGetIndices(iscol,&icol);
2168:     PetscMalloc(oldcols*sizeof(PetscInt),&smap);
2169:     PetscMemzero(smap,oldcols*sizeof(PetscInt));
2170:     PetscMalloc((1+nrows)*sizeof(PetscInt),&lens);
2171:     for (i=0; i<ncols; i++) {
2172: #if defined(PETSC_USE_DEBUG)
2173:       if (icol[i] >= oldcols) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Requesting column beyond largest column icol[%D] %D <= A->cmap->n %D",i,icol[i],oldcols);
2174: #endif
2175:       smap[icol[i]] = i+1;
2176:     }

2178:     /* determine lens of each row */
2179:     for (i=0; i<nrows; i++) {
2180:       kstart  = ai[irow[i]];
2181:       kend    = kstart + a->ilen[irow[i]];
2182:       lens[i] = 0;
2183:       for (k=kstart; k<kend; k++) {
2184:         if (smap[aj[k]]) {
2185:           lens[i]++;
2186:         }
2187:       }
2188:     }
2189:     /* Create and fill new matrix */
2190:     if (scall == MAT_REUSE_MATRIX) {
2191:       PetscBool  equal;

2193:       c = (Mat_SeqAIJ *)((*B)->data);
2194:       if ((*B)->rmap->n  != nrows || (*B)->cmap->n != ncols) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong size");
2195:       PetscMemcmp(c->ilen,lens,(*B)->rmap->n*sizeof(PetscInt),&equal);
2196:       if (!equal) {
2197:         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong no of nonzeros");
2198:       }
2199:       PetscMemzero(c->ilen,(*B)->rmap->n*sizeof(PetscInt));
2200:       C = *B;
2201:     } else {
2202:       MatCreate(((PetscObject)A)->comm,&C);
2203:       MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);
2204:       MatSetType(C,((PetscObject)A)->type_name);
2205:       MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);
2206:     }
2207:     c = (Mat_SeqAIJ *)(C->data);
2208:     for (i=0; i<nrows; i++) {
2209:       row    = irow[i];
2210:       kstart = ai[row];
2211:       kend   = kstart + a->ilen[row];
2212:       mat_i  = c->i[i];
2213:       mat_j  = c->j + mat_i;
2214:       mat_a  = c->a + mat_i;
2215:       mat_ilen = c->ilen + i;
2216:       for (k=kstart; k<kend; k++) {
2217:         if ((tcol=smap[a->j[k]])) {
2218:           *mat_j++ = tcol - 1;
2219:           *mat_a++ = a->a[k];
2220:           (*mat_ilen)++;

2222:         }
2223:       }
2224:     }
2225:     /* Free work space */
2226:     ISRestoreIndices(iscol,&icol);
2227:     PetscFree(smap);
2228:     PetscFree(lens);
2229:   }
2230:   MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);
2231:   MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);

2233:   ISRestoreIndices(isrow,&irow);
2234:   *B = C;
2235:   return(0);
2236: }

2240: PetscErrorCode  MatGetMultiProcBlock_SeqAIJ(Mat mat,MPI_Comm subComm,Mat* subMat)
2241: {
2243:   Mat            B;

2246:   MatCreate(subComm,&B);
2247:   MatSetSizes(B,mat->rmap->n,mat->cmap->n,mat->rmap->n,mat->cmap->n);
2248:   MatSetType(B,MATSEQAIJ);
2249:   MatDuplicateNoCreate_SeqAIJ(B,mat,MAT_COPY_VALUES,PETSC_TRUE);
2250:   *subMat = B;
2251:   return(0);
2252: }

2256: PetscErrorCode MatILUFactor_SeqAIJ(Mat inA,IS row,IS col,const MatFactorInfo *info)
2257: {
2258:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)inA->data;
2260:   Mat            outA;
2261:   PetscBool      row_identity,col_identity;

2264:   if (info->levels != 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only levels=0 supported for in-place ilu");

2266:   ISIdentity(row,&row_identity);
2267:   ISIdentity(col,&col_identity);

2269:   outA              = inA;
2270:   outA->factortype  = MAT_FACTOR_LU;
2271:   PetscObjectReference((PetscObject)row);
2272:   ISDestroy(&a->row);
2273:   a->row = row;
2274:   PetscObjectReference((PetscObject)col);
2275:   ISDestroy(&a->col);
2276:   a->col = col;

2278:   /* Create the inverse permutation so that it can be used in MatLUFactorNumeric() */
2279:   ISDestroy(&a->icol);
2280:   ISInvertPermutation(col,PETSC_DECIDE,&a->icol);
2281:   PetscLogObjectParent(inA,a->icol);

2283:   if (!a->solve_work) { /* this matrix may have been factored before */
2284:      PetscMalloc((inA->rmap->n+1)*sizeof(PetscScalar),&a->solve_work);
2285:      PetscLogObjectMemory(inA, (inA->rmap->n+1)*sizeof(PetscScalar));
2286:   }

2288:   MatMarkDiagonal_SeqAIJ(inA);
2289:   if (row_identity && col_identity) {
2290:     MatLUFactorNumeric_SeqAIJ_inplace(outA,inA,info);
2291:   } else {
2292:     MatLUFactorNumeric_SeqAIJ_InplaceWithPerm(outA,inA,info);
2293:   }
2294:   return(0);
2295: }

2299: PetscErrorCode MatScale_SeqAIJ(Mat inA,PetscScalar alpha)
2300: {
2301:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)inA->data;
2302:   PetscScalar    oalpha = alpha;
2304:   PetscBLASInt   one = 1,bnz = PetscBLASIntCast(a->nz);

2307:   BLASscal_(&bnz,&oalpha,a->a,&one);
2308:   PetscLogFlops(a->nz);
2309:   return(0);
2310: }

2314: PetscErrorCode MatGetSubMatrices_SeqAIJ(Mat A,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *B[])
2315: {
2317:   PetscInt       i;

2320:   if (scall == MAT_INITIAL_MATRIX) {
2321:     PetscMalloc((n+1)*sizeof(Mat),B);
2322:   }

2324:   for (i=0; i<n; i++) {
2325:     MatGetSubMatrix_SeqAIJ(A,irow[i],icol[i],PETSC_DECIDE,scall,&(*B)[i]);
2326:   }
2327:   return(0);
2328: }

2332: PetscErrorCode MatIncreaseOverlap_SeqAIJ(Mat A,PetscInt is_max,IS is[],PetscInt ov)
2333: {
2334:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
2336:   PetscInt       row,i,j,k,l,m,n,*nidx,isz,val;
2337:   const PetscInt *idx;
2338:   PetscInt       start,end,*ai,*aj;
2339:   PetscBT        table;

2342:   m     = A->rmap->n;
2343:   ai    = a->i;
2344:   aj    = a->j;

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

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

2351:   for (i=0; i<is_max; i++) {
2352:     /* Initialize the two local arrays */
2353:     isz  = 0;
2354:     PetscBTMemzero(m,table);
2355: 
2356:     /* Extract the indices, assume there can be duplicate entries */
2357:     ISGetIndices(is[i],&idx);
2358:     ISGetLocalSize(is[i],&n);
2359: 
2360:     /* Enter these into the temp arrays. I.e., mark table[row], enter row into new index */
2361:     for (j=0; j<n ; ++j){
2362:       if(!PetscBTLookupSet(table,idx[j])) { nidx[isz++] = idx[j];}
2363:     }
2364:     ISRestoreIndices(is[i],&idx);
2365:     ISDestroy(&is[i]);
2366: 
2367:     k = 0;
2368:     for (j=0; j<ov; j++){ /* for each overlap */
2369:       n = isz;
2370:       for (; k<n ; k++){ /* do only those rows in nidx[k], which are not done yet */
2371:         row   = nidx[k];
2372:         start = ai[row];
2373:         end   = ai[row+1];
2374:         for (l = start; l<end ; l++){
2375:           val = aj[l] ;
2376:           if (!PetscBTLookupSet(table,val)) {nidx[isz++] = val;}
2377:         }
2378:       }
2379:     }
2380:     ISCreateGeneral(PETSC_COMM_SELF,isz,nidx,PETSC_COPY_VALUES,(is+i));
2381:   }
2382:   PetscBTDestroy(table);
2383:   PetscFree(nidx);
2384:   return(0);
2385: }

2387: /* -------------------------------------------------------------- */
2390: PetscErrorCode MatPermute_SeqAIJ(Mat A,IS rowp,IS colp,Mat *B)
2391: {
2392:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
2394:   PetscInt       i,nz = 0,m = A->rmap->n,n = A->cmap->n;
2395:   const PetscInt *row,*col;
2396:   PetscInt       *cnew,j,*lens;
2397:   IS             icolp,irowp;
2398:   PetscInt       *cwork = PETSC_NULL;
2399:   PetscScalar    *vwork = PETSC_NULL;

2402:   ISInvertPermutation(rowp,PETSC_DECIDE,&irowp);
2403:   ISGetIndices(irowp,&row);
2404:   ISInvertPermutation(colp,PETSC_DECIDE,&icolp);
2405:   ISGetIndices(icolp,&col);
2406: 
2407:   /* determine lengths of permuted rows */
2408:   PetscMalloc((m+1)*sizeof(PetscInt),&lens);
2409:   for (i=0; i<m; i++) {
2410:     lens[row[i]] = a->i[i+1] - a->i[i];
2411:   }
2412:   MatCreate(((PetscObject)A)->comm,B);
2413:   MatSetSizes(*B,m,n,m,n);
2414:   MatSetType(*B,((PetscObject)A)->type_name);
2415:   MatSeqAIJSetPreallocation_SeqAIJ(*B,0,lens);
2416:   PetscFree(lens);

2418:   PetscMalloc(n*sizeof(PetscInt),&cnew);
2419:   for (i=0; i<m; i++) {
2420:     MatGetRow_SeqAIJ(A,i,&nz,&cwork,&vwork);
2421:     for (j=0; j<nz; j++) { cnew[j] = col[cwork[j]];}
2422:     MatSetValues_SeqAIJ(*B,1,&row[i],nz,cnew,vwork,INSERT_VALUES);
2423:     MatRestoreRow_SeqAIJ(A,i,&nz,&cwork,&vwork);
2424:   }
2425:   PetscFree(cnew);
2426:   (*B)->assembled     = PETSC_FALSE;
2427:   MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);
2428:   MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);
2429:   ISRestoreIndices(irowp,&row);
2430:   ISRestoreIndices(icolp,&col);
2431:   ISDestroy(&irowp);
2432:   ISDestroy(&icolp);
2433:   return(0);
2434: }

2438: PetscErrorCode MatCopy_SeqAIJ(Mat A,Mat B,MatStructure str)
2439: {

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

2448:     if (a->i[A->rmap->n] != b->i[B->rmap->n]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of nonzeros in two matrices are different");
2449:     PetscMemcpy(b->a,a->a,(a->i[A->rmap->n])*sizeof(PetscScalar));
2450:   } else {
2451:     MatCopy_Basic(A,B,str);
2452:   }
2453:   return(0);
2454: }

2458: PetscErrorCode MatSetUpPreallocation_SeqAIJ(Mat A)
2459: {

2463:    MatSeqAIJSetPreallocation_SeqAIJ(A,PETSC_DEFAULT,0);
2464:   return(0);
2465: }

2469: PetscErrorCode MatGetArray_SeqAIJ(Mat A,PetscScalar *array[])
2470: {
2471:   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
2473:   *array = a->a;
2474:   return(0);
2475: }

2479: PetscErrorCode MatRestoreArray_SeqAIJ(Mat A,PetscScalar *array[])
2480: {
2482:   return(0);
2483: }

2487: PetscErrorCode MatFDColoringApply_SeqAIJ(Mat J,MatFDColoring coloring,Vec x1,MatStructure *flag,void *sctx)
2488: {
2489:   PetscErrorCode (*f)(void*,Vec,Vec,void*) = (PetscErrorCode (*)(void*,Vec,Vec,void *))coloring->f;
2491:   PetscInt       k,N,start,end,l,row,col,srow,**vscaleforrow,m1,m2;
2492:   PetscScalar    dx,*y,*xx,*w3_array;
2493:   PetscScalar    *vscale_array;
2494:   PetscReal      epsilon = coloring->error_rel,umin = coloring->umin;
2495:   Vec            w1,w2,w3;
2496:   void           *fctx = coloring->fctx;
2497:   PetscBool      flg = PETSC_FALSE;

2500:   if (!coloring->w1) {
2501:     VecDuplicate(x1,&coloring->w1);
2502:     PetscLogObjectParent(coloring,coloring->w1);
2503:     VecDuplicate(x1,&coloring->w2);
2504:     PetscLogObjectParent(coloring,coloring->w2);
2505:     VecDuplicate(x1,&coloring->w3);
2506:     PetscLogObjectParent(coloring,coloring->w3);
2507:   }
2508:   w1 = coloring->w1; w2 = coloring->w2; w3 = coloring->w3;

2510:   MatSetUnfactored(J);
2511:   PetscOptionsGetBool(((PetscObject)coloring)->prefix,"-mat_fd_coloring_dont_rezero",&flg,PETSC_NULL);
2512:   if (flg) {
2513:     PetscInfo(coloring,"Not calling MatZeroEntries()\n");
2514:   } else {
2515:     PetscBool  assembled;
2516:     MatAssembled(J,&assembled);
2517:     if (assembled) {
2518:       MatZeroEntries(J);
2519:     }
2520:   }

2522:   VecGetOwnershipRange(x1,&start,&end);
2523:   VecGetSize(x1,&N);

2525:   /*
2526:        This is a horrible, horrible, hack. See DMMGComputeJacobian_Multigrid() it inproperly sets
2527:      coloring->F for the coarser grids from the finest
2528:   */
2529:   if (coloring->F) {
2530:     VecGetLocalSize(coloring->F,&m1);
2531:     VecGetLocalSize(w1,&m2);
2532:     if (m1 != m2) {
2533:       coloring->F = 0;
2534:     }
2535:   }

2537:   if (coloring->F) {
2538:     w1          = coloring->F;
2539:     coloring->F = 0;
2540:   } else {
2541:     PetscLogEventBegin(MAT_FDColoringFunction,0,0,0,0);
2542:     (*f)(sctx,x1,w1,fctx);
2543:     PetscLogEventEnd(MAT_FDColoringFunction,0,0,0,0);
2544:   }

2546:   /* 
2547:       Compute all the scale factors and share with other processors
2548:   */
2549:   VecGetArray(x1,&xx);xx = xx - start;
2550:   VecGetArray(coloring->vscale,&vscale_array);vscale_array = vscale_array - start;
2551:   for (k=0; k<coloring->ncolors; k++) {
2552:     /*
2553:        Loop over each column associated with color adding the 
2554:        perturbation to the vector w3.
2555:     */
2556:     for (l=0; l<coloring->ncolumns[k]; l++) {
2557:       col = coloring->columns[k][l];    /* column of the matrix we are probing for */
2558:       dx  = xx[col];
2559:       if (dx == 0.0) dx = 1.0;
2560: #if !defined(PETSC_USE_COMPLEX)
2561:       if (dx < umin && dx >= 0.0)      dx = umin;
2562:       else if (dx < 0.0 && dx > -umin) dx = -umin;
2563: #else
2564:       if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0)     dx = umin;
2565:       else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
2566: #endif
2567:       dx                *= epsilon;
2568:       vscale_array[col] = 1.0/dx;
2569:     }
2570:   }
2571:   vscale_array = vscale_array + start;VecRestoreArray(coloring->vscale,&vscale_array);
2572:   VecGhostUpdateBegin(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);
2573:   VecGhostUpdateEnd(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);

2575:   /*  VecView(coloring->vscale,PETSC_VIEWER_STDOUT_WORLD);
2576:       VecView(x1,PETSC_VIEWER_STDOUT_WORLD);*/

2578:   if (coloring->vscaleforrow) vscaleforrow = coloring->vscaleforrow;
2579:   else                        vscaleforrow = coloring->columnsforrow;

2581:   VecGetArray(coloring->vscale,&vscale_array);
2582:   /*
2583:       Loop over each color
2584:   */
2585:   for (k=0; k<coloring->ncolors; k++) {
2586:     coloring->currentcolor = k;
2587:     VecCopy(x1,w3);
2588:     VecGetArray(w3,&w3_array);w3_array = w3_array - start;
2589:     /*
2590:        Loop over each column associated with color adding the 
2591:        perturbation to the vector w3.
2592:     */
2593:     for (l=0; l<coloring->ncolumns[k]; l++) {
2594:       col = coloring->columns[k][l];    /* column of the matrix we are probing for */
2595:       dx  = xx[col];
2596:       if (dx == 0.0) dx = 1.0;
2597: #if !defined(PETSC_USE_COMPLEX)
2598:       if (dx < umin && dx >= 0.0)      dx = umin;
2599:       else if (dx < 0.0 && dx > -umin) dx = -umin;
2600: #else
2601:       if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0)     dx = umin;
2602:       else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
2603: #endif
2604:       dx            *= epsilon;
2605:       if (!PetscAbsScalar(dx)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Computed 0 differencing parameter");
2606:       w3_array[col] += dx;
2607:     }
2608:     w3_array = w3_array + start; VecRestoreArray(w3,&w3_array);

2610:     /*
2611:        Evaluate function at x1 + dx (here dx is a vector of perturbations)
2612:     */

2614:     PetscLogEventBegin(MAT_FDColoringFunction,0,0,0,0);
2615:     (*f)(sctx,w3,w2,fctx);
2616:     PetscLogEventEnd(MAT_FDColoringFunction,0,0,0,0);
2617:     VecAXPY(w2,-1.0,w1);

2619:     /*
2620:        Loop over rows of vector, putting results into Jacobian matrix
2621:     */
2622:     VecGetArray(w2,&y);
2623:     for (l=0; l<coloring->nrows[k]; l++) {
2624:       row    = coloring->rows[k][l];
2625:       col    = coloring->columnsforrow[k][l];
2626:       y[row] *= vscale_array[vscaleforrow[k][l]];
2627:       srow   = row + start;
2628:       MatSetValues_SeqAIJ(J,1,&srow,1,&col,y+row,INSERT_VALUES);
2629:     }
2630:     VecRestoreArray(w2,&y);
2631:   }
2632:   coloring->currentcolor = k;
2633:   VecRestoreArray(coloring->vscale,&vscale_array);
2634:   xx = xx + start; VecRestoreArray(x1,&xx);
2635:   MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);
2636:   MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);
2637:   return(0);
2638: }

2640: /* 
2641:    Computes the number of nonzeros per row needed for preallocation when X and Y 
2642:    have different nonzero structure. 
2643: */
2646: PetscErrorCode MatAXPYGetPreallocation_SeqAIJ(Mat Y,Mat X,PetscInt* nnz)
2647: {
2648:   PetscInt          i,m=Y->rmap->N;
2649:   Mat_SeqAIJ        *x = (Mat_SeqAIJ*)X->data;
2650:   Mat_SeqAIJ        *y = (Mat_SeqAIJ*)Y->data;
2651:   const PetscInt    *xi = x->i,*yi = y->i;

2654:   /* Set the number of nonzeros in the new matrix */
2655:   for(i=0; i<m; i++) {
2656:     PetscInt j,k,nzx = xi[i+1] - xi[i],nzy = yi[i+1] - yi[i];
2657:     const PetscInt *xj = x->j+xi[i],*yj = y->j+yi[i];
2658:     nnz[i] = 0;
2659:     for (j=0,k=0; j<nzx; j++) {                   /* Point in X */
2660:       for (; k<nzy && yj[k]<xj[j]; k++) nnz[i]++; /* Catch up to X */
2661:       if (k<nzy && yj[k]==xj[j]) k++;             /* Skip duplicate */
2662:       nnz[i]++;
2663:     }
2664:     for (; k<nzy; k++) nnz[i]++;
2665:   }
2666:   return(0);
2667: }

2671: PetscErrorCode MatAXPY_SeqAIJ(Mat Y,PetscScalar a,Mat X,MatStructure str)
2672: {
2674:   PetscInt       i;
2675:   Mat_SeqAIJ     *x  = (Mat_SeqAIJ *)X->data,*y = (Mat_SeqAIJ *)Y->data;
2676:   PetscBLASInt   one=1,bnz = PetscBLASIntCast(x->nz);

2679:   if (str == SAME_NONZERO_PATTERN) {
2680:     PetscScalar alpha = a;
2681:     BLASaxpy_(&bnz,&alpha,x->a,&one,y->a,&one);
2682:   } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */
2683:     if (y->xtoy && y->XtoY != X) {
2684:       PetscFree(y->xtoy);
2685:       MatDestroy(&y->XtoY);
2686:     }
2687:     if (!y->xtoy) { /* get xtoy */
2688:       MatAXPYGetxtoy_Private(X->rmap->n,x->i,x->j,PETSC_NULL, y->i,y->j,PETSC_NULL, &y->xtoy);
2689:       y->XtoY = X;
2690:       PetscObjectReference((PetscObject)X);
2691:     }
2692:     for (i=0; i<x->nz; i++) y->a[y->xtoy[i]] += a*(x->a[i]);
2693:     PetscInfo3(Y,"ratio of nnz(X)/nnz(Y): %d/%d = %G\n",x->nz,y->nz,(PetscReal)(x->nz)/y->nz);
2694:   } else {
2695:     Mat      B;
2696:     PetscInt *nnz;
2697:     PetscMalloc(Y->rmap->N*sizeof(PetscInt),&nnz);
2698:     MatCreate(((PetscObject)Y)->comm,&B);
2699:     PetscObjectSetName((PetscObject)B,((PetscObject)Y)->name);
2700:     MatSetSizes(B,Y->rmap->n,Y->cmap->n,Y->rmap->N,Y->cmap->N);
2701:     MatSetType(B,MATSEQAIJ);
2702:     MatAXPYGetPreallocation_SeqAIJ(Y,X,nnz);
2703:     MatSeqAIJSetPreallocation(B,PETSC_NULL,nnz);
2704:     MatAXPY_BasicWithPreallocation(B,Y,a,X,str);
2705:     MatHeaderReplace(Y,B);
2706:     PetscFree(nnz);
2707:   }
2708:   return(0);
2709: }

2713: PetscErrorCode MatSetBlockSize_SeqAIJ(Mat A,PetscInt bs)
2714: {

2718:   PetscLayoutSetBlockSize(A->rmap,bs);
2719:   PetscLayoutSetBlockSize(A->cmap,bs);
2720:   return(0);
2721: }

2725: PetscErrorCode  MatConjugate_SeqAIJ(Mat mat)
2726: {
2727: #if defined(PETSC_USE_COMPLEX)
2728:   Mat_SeqAIJ  *aij = (Mat_SeqAIJ *)mat->data;
2729:   PetscInt    i,nz;
2730:   PetscScalar *a;

2733:   nz = aij->nz;
2734:   a  = aij->a;
2735:   for (i=0; i<nz; i++) {
2736:     a[i] = PetscConj(a[i]);
2737:   }
2738: #else
2740: #endif
2741:   return(0);
2742: }

2746: PetscErrorCode MatGetRowMaxAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[])
2747: {
2748:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
2750:   PetscInt       i,j,m = A->rmap->n,*ai,*aj,ncols,n;
2751:   PetscReal      atmp;
2752:   PetscScalar    *x;
2753:   MatScalar      *aa;

2756:   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2757:   aa   = a->a;
2758:   ai   = a->i;
2759:   aj   = a->j;

2761:   VecSet(v,0.0);
2762:   VecGetArray(v,&x);
2763:   VecGetLocalSize(v,&n);
2764:   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
2765:   for (i=0; i<m; i++) {
2766:     ncols = ai[1] - ai[0]; ai++;
2767:     x[i] = 0.0;
2768:     for (j=0; j<ncols; j++){
2769:       atmp = PetscAbsScalar(*aa);
2770:       if (PetscAbsScalar(x[i]) < atmp) {x[i] = atmp; if (idx) idx[i] = *aj;}
2771:       aa++; aj++;
2772:     }
2773:   }
2774:   VecRestoreArray(v,&x);
2775:   return(0);
2776: }

2780: PetscErrorCode MatGetRowMax_SeqAIJ(Mat A,Vec v,PetscInt idx[])
2781: {
2782:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
2784:   PetscInt       i,j,m = A->rmap->n,*ai,*aj,ncols,n;
2785:   PetscScalar    *x;
2786:   MatScalar      *aa;

2789:   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2790:   aa   = a->a;
2791:   ai   = a->i;
2792:   aj   = a->j;

2794:   VecSet(v,0.0);
2795:   VecGetArray(v,&x);
2796:   VecGetLocalSize(v,&n);
2797:   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
2798:   for (i=0; i<m; i++) {
2799:     ncols = ai[1] - ai[0]; ai++;
2800:     if (ncols == A->cmap->n) { /* row is dense */
2801:       x[i] = *aa; if (idx) idx[i] = 0;
2802:     } else {  /* row is sparse so already KNOW maximum is 0.0 or higher */
2803:       x[i] = 0.0;
2804:       if (idx) {
2805:         idx[i] = 0; /* in case ncols is zero */
2806:         for (j=0;j<ncols;j++) { /* find first implicit 0.0 in the row */
2807:           if (aj[j] > j) {
2808:             idx[i] = j;
2809:             break;
2810:           }
2811:         }
2812:       }
2813:     }
2814:     for (j=0; j<ncols; j++){
2815:       if (PetscRealPart(x[i]) < PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
2816:       aa++; aj++;
2817:     }
2818:   }
2819:   VecRestoreArray(v,&x);
2820:   return(0);
2821: }

2825: PetscErrorCode MatGetRowMinAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[])
2826: {
2827:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
2829:   PetscInt       i,j,m = A->rmap->n,*ai,*aj,ncols,n;
2830:   PetscReal      atmp;
2831:   PetscScalar    *x;
2832:   MatScalar      *aa;

2835:   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2836:   aa   = a->a;
2837:   ai   = a->i;
2838:   aj   = a->j;

2840:   VecSet(v,0.0);
2841:   VecGetArray(v,&x);
2842:   VecGetLocalSize(v,&n);
2843:   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
2844:   for (i=0; i<m; i++) {
2845:     ncols = ai[1] - ai[0]; ai++;
2846:     if (ncols) {
2847:       /* Get first nonzero */
2848:       for(j = 0; j < ncols; j++) {
2849:         atmp = PetscAbsScalar(aa[j]);
2850:         if (atmp > 1.0e-12) {x[i] = atmp; if (idx) idx[i] = aj[j]; break;}
2851:       }
2852:       if (j == ncols) {x[i] = *aa; if (idx) idx[i] = *aj;}
2853:     } else {
2854:       x[i] = 0.0; if (idx) idx[i] = 0;
2855:     }
2856:     for(j = 0; j < ncols; j++) {
2857:       atmp = PetscAbsScalar(*aa);
2858:       if (atmp > 1.0e-12 && PetscAbsScalar(x[i]) > atmp) {x[i] = atmp; if (idx) idx[i] = *aj;}
2859:       aa++; aj++;
2860:     }
2861:   }
2862:   VecRestoreArray(v,&x);
2863:   return(0);
2864: }

2868: PetscErrorCode MatGetRowMin_SeqAIJ(Mat A,Vec v,PetscInt idx[])
2869: {
2870:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
2872:   PetscInt       i,j,m = A->rmap->n,*ai,*aj,ncols,n;
2873:   PetscScalar    *x;
2874:   MatScalar      *aa;

2877:   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2878:   aa   = a->a;
2879:   ai   = a->i;
2880:   aj   = a->j;

2882:   VecSet(v,0.0);
2883:   VecGetArray(v,&x);
2884:   VecGetLocalSize(v,&n);
2885:   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
2886:   for (i=0; i<m; i++) {
2887:     ncols = ai[1] - ai[0]; ai++;
2888:     if (ncols == A->cmap->n) { /* row is dense */
2889:       x[i] = *aa; if (idx) idx[i] = 0;
2890:     } else {  /* row is sparse so already KNOW minimum is 0.0 or lower */
2891:       x[i] = 0.0;
2892:       if (idx) {   /* find first implicit 0.0 in the row */
2893:         idx[i] = 0; /* in case ncols is zero */
2894:         for (j=0;j<ncols;j++) {
2895:           if (aj[j] > j) {
2896:             idx[i] = j;
2897:             break;
2898:           }
2899:         }
2900:       }
2901:     }
2902:     for (j=0; j<ncols; j++){
2903:       if (PetscRealPart(x[i]) > PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
2904:       aa++; aj++;
2905:     }
2906:   }
2907:   VecRestoreArray(v,&x);
2908:   return(0);
2909: }

2911: #include <petscblaslapack.h>
2912: #include <../src/mat/blockinvert.h>

2916: PetscErrorCode  MatInvertBlockDiagonal_SeqAIJ(Mat A,PetscScalar **values)
2917: {
2918:   Mat_SeqAIJ    *a = (Mat_SeqAIJ*) A->data;
2920:   PetscInt       i,bs = A->rmap->bs,mbs = A->rmap->n/A->rmap->bs,ipvt[5],bs2 = bs*bs,*v_pivots,ij[7],*IJ,j;
2921:   MatScalar      *diag,work[25],*v_work;
2922:   PetscReal      shift = 0.0;

2925:   if (a->ibdiagvalid) {
2926:     if (values) *values = a->ibdiag;
2927:     return(0);
2928:   }
2929:   MatMarkDiagonal_SeqAIJ(A);
2930:   if (!a->ibdiag) {
2931:     PetscMalloc(bs2*mbs*sizeof(PetscScalar),&a->ibdiag);
2932:     PetscLogObjectMemory(A,bs2*mbs*sizeof(PetscScalar));
2933:   }
2934:   diag    = a->ibdiag;
2935:   if (values) *values = a->ibdiag;
2936:   /* factor and invert each block */
2937:   switch (bs){
2938:     case 1:
2939:       for (i=0; i<mbs; i++) {
2940:         MatGetValues(A,1,&i,1,&i,diag+i);
2941:         diag[i] = (PetscScalar)1.0 / (diag[i] + shift);
2942:       }
2943:       break;
2944:     case 2:
2945:       for (i=0; i<mbs; i++) {
2946:         ij[0] = 2*i; ij[1] = 2*i + 1;
2947:         MatGetValues(A,2,ij,2,ij,diag);
2948:         Kernel_A_gets_inverse_A_2(diag,shift);
2949:         diag  += 4;
2950:       }
2951:       break;
2952:     case 3:
2953:       for (i=0; i<mbs; i++) {
2954:         ij[0] = 3*i; ij[1] = 3*i + 1; ij[2] = 3*i + 2;
2955:         MatGetValues(A,3,ij,3,ij,diag);
2956:         Kernel_A_gets_inverse_A_3(diag,shift);
2957:         diag    += 9;
2958:       }
2959:       break;
2960:     case 4:
2961:       for (i=0; i<mbs; i++) {
2962:         ij[0] = 4*i; ij[1] = 4*i + 1; ij[2] = 4*i + 2; ij[3] = 4*i + 3;
2963:         MatGetValues(A,4,ij,4,ij,diag);
2964:         Kernel_A_gets_inverse_A_4(diag,shift);
2965:         diag  += 16;
2966:       }
2967:       break;
2968:     case 5:
2969:       for (i=0; i<mbs; i++) {
2970:         ij[0] = 5*i; ij[1] = 5*i + 1; ij[2] = 5*i + 2; ij[3] = 5*i + 3; ij[4] = 5*i + 4;
2971:         MatGetValues(A,5,ij,5,ij,diag);
2972:         Kernel_A_gets_inverse_A_5(diag,ipvt,work,shift);
2973:         diag  += 25;
2974:       }
2975:       break;
2976:     case 6:
2977:       for (i=0; i<mbs; i++) {
2978:         ij[0] = 6*i; ij[1] = 6*i + 1; ij[2] = 6*i + 2; ij[3] = 6*i + 3; ij[4] = 6*i + 4; ij[5] = 6*i + 5;
2979:         MatGetValues(A,6,ij,6,ij,diag);
2980:         Kernel_A_gets_inverse_A_6(diag,shift);
2981:         diag  += 36;
2982:       }
2983:       break;
2984:     case 7:
2985:       for (i=0; i<mbs; i++) {
2986:         ij[0] = 7*i; ij[1] = 7*i + 1; ij[2] = 7*i + 2; ij[3] = 7*i + 3; ij[4] = 7*i + 4; ij[5] = 7*i + 5; ij[5] = 7*i + 6;
2987:         MatGetValues(A,7,ij,7,ij,diag);
2988:         Kernel_A_gets_inverse_A_7(diag,shift);
2989:         diag  += 49;
2990:       }
2991:       break;
2992:     default:
2993:       PetscMalloc3(bs,MatScalar,&v_work,bs,PetscInt,&v_pivots,bs,PetscInt,&IJ);
2994:       for (i=0; i<mbs; i++) {
2995:         for (j=0; j<bs; j++) {
2996:           IJ[j] = bs*i + j;
2997:         }
2998:         MatGetValues(A,bs,IJ,bs,IJ,diag);
2999:         Kernel_A_gets_inverse_A(bs,diag,v_pivots,v_work);
3000:         diag  += bs2;
3001:       }
3002:       PetscFree3(v_work,v_pivots,IJ);
3003:   }
3004:   a->ibdiagvalid = PETSC_TRUE;
3005:   return(0);
3006: }

3009: /* -------------------------------------------------------------------*/
3010: static struct _MatOps MatOps_Values = {MatSetValues_SeqAIJ,
3011:        MatGetRow_SeqAIJ,
3012:        MatRestoreRow_SeqAIJ,
3013:        MatMult_SeqAIJ,
3014: /* 4*/ MatMultAdd_SeqAIJ,
3015:        MatMultTranspose_SeqAIJ,
3016:        MatMultTransposeAdd_SeqAIJ,
3017:        0,
3018:        0,
3019:        0,
3020: /*10*/ 0,
3021:        MatLUFactor_SeqAIJ,
3022:        0,
3023:        MatSOR_SeqAIJ,
3024:        MatTranspose_SeqAIJ,
3025: /*15*/ MatGetInfo_SeqAIJ,
3026:        MatEqual_SeqAIJ,
3027:        MatGetDiagonal_SeqAIJ,
3028:        MatDiagonalScale_SeqAIJ,
3029:        MatNorm_SeqAIJ,
3030: /*20*/ 0,
3031:        MatAssemblyEnd_SeqAIJ,
3032:        MatSetOption_SeqAIJ,
3033:        MatZeroEntries_SeqAIJ,
3034: /*24*/ MatZeroRows_SeqAIJ,
3035:        0,
3036:        0,
3037:        0,
3038:        0,
3039: /*29*/ MatSetUpPreallocation_SeqAIJ,
3040:        0,
3041:        0,
3042:        MatGetArray_SeqAIJ,
3043:        MatRestoreArray_SeqAIJ,
3044: /*34*/ MatDuplicate_SeqAIJ,
3045:        0,
3046:        0,
3047:        MatILUFactor_SeqAIJ,
3048:        0,
3049: /*39*/ MatAXPY_SeqAIJ,
3050:        MatGetSubMatrices_SeqAIJ,
3051:        MatIncreaseOverlap_SeqAIJ,
3052:        MatGetValues_SeqAIJ,
3053:        MatCopy_SeqAIJ,
3054: /*44*/ MatGetRowMax_SeqAIJ,
3055:        MatScale_SeqAIJ,
3056:        0,
3057:        MatDiagonalSet_SeqAIJ,
3058:        MatZeroRowsColumns_SeqAIJ,
3059: /*49*/ MatSetBlockSize_SeqAIJ,
3060:        MatGetRowIJ_SeqAIJ,
3061:        MatRestoreRowIJ_SeqAIJ,
3062:        MatGetColumnIJ_SeqAIJ,
3063:        MatRestoreColumnIJ_SeqAIJ,
3064: /*54*/ MatFDColoringCreate_SeqAIJ,
3065:        0,
3066:        0,
3067:        MatPermute_SeqAIJ,
3068:        0,
3069: /*59*/ 0,
3070:        MatDestroy_SeqAIJ,
3071:        MatView_SeqAIJ,
3072:        0,
3073:        0,
3074: /*64*/ 0,
3075:        0,
3076:        0,
3077:        0,
3078:        0,
3079: /*69*/ MatGetRowMaxAbs_SeqAIJ,
3080:        MatGetRowMinAbs_SeqAIJ,
3081:        0,
3082:        MatSetColoring_SeqAIJ,
3083: #if defined(PETSC_HAVE_ADIC)
3084:        MatSetValuesAdic_SeqAIJ,
3085: #else
3086:        0,
3087: #endif
3088: /*74*/ MatSetValuesAdifor_SeqAIJ,
3089:        MatFDColoringApply_AIJ,
3090:        0,
3091:        0,
3092:        0,
3093: /*79*/ MatFindZeroDiagonals_SeqAIJ,
3094:        0,
3095:        0,
3096:        0,
3097:        MatLoad_SeqAIJ,
3098: /*84*/ MatIsSymmetric_SeqAIJ,
3099:        MatIsHermitian_SeqAIJ,
3100:        0,
3101:        0,
3102:        0,
3103: /*89*/ MatMatMult_SeqAIJ_SeqAIJ,
3104:        MatMatMultSymbolic_SeqAIJ_SeqAIJ,
3105:        MatMatMultNumeric_SeqAIJ_SeqAIJ,
3106:        MatPtAP_Basic,
3107:        MatPtAPSymbolic_SeqAIJ,
3108: /*94*/ MatPtAPNumeric_SeqAIJ,
3109:        MatMatMultTranspose_SeqAIJ_SeqAIJ,
3110:        MatMatMultTransposeSymbolic_SeqAIJ_SeqAIJ,
3111:        MatMatMultTransposeNumeric_SeqAIJ_SeqAIJ,
3112:        MatPtAPSymbolic_SeqAIJ_SeqAIJ,
3113: /*99*/ MatPtAPNumeric_SeqAIJ_SeqAIJ,
3114:        0,
3115:        0,
3116:        MatConjugate_SeqAIJ,
3117:        0,
3118: /*104*/MatSetValuesRow_SeqAIJ,
3119:        MatRealPart_SeqAIJ,
3120:        MatImaginaryPart_SeqAIJ,
3121:        0,
3122:        0,
3123: /*109*/MatMatSolve_SeqAIJ,
3124:        0,
3125:        MatGetRowMin_SeqAIJ,
3126:        0,
3127:        MatMissingDiagonal_SeqAIJ,
3128: /*114*/0,
3129:        0,
3130:        0,
3131:        0,
3132:        0,
3133: /*119*/0,
3134:        0,
3135:        0,
3136:        0,
3137:        MatGetMultiProcBlock_SeqAIJ,
3138: /*124*/MatFindNonzeroRows_SeqAIJ,
3139:        MatGetColumnNorms_SeqAIJ,
3140:        MatInvertBlockDiagonal_SeqAIJ,
3141:        0,
3142:        0,
3143: /*129*/0
3144: };

3149: PetscErrorCode  MatSeqAIJSetColumnIndices_SeqAIJ(Mat mat,PetscInt *indices)
3150: {
3151:   Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data;
3152:   PetscInt   i,nz,n;


3156:   nz = aij->maxnz;
3157:   n  = mat->rmap->n;
3158:   for (i=0; i<nz; i++) {
3159:     aij->j[i] = indices[i];
3160:   }
3161:   aij->nz = nz;
3162:   for (i=0; i<n; i++) {
3163:     aij->ilen[i] = aij->imax[i];
3164:   }

3166:   return(0);
3167: }

3172: /*@
3173:     MatSeqAIJSetColumnIndices - Set the column indices for all the rows
3174:        in the matrix.

3176:   Input Parameters:
3177: +  mat - the SeqAIJ matrix
3178: -  indices - the column indices

3180:   Level: advanced

3182:   Notes:
3183:     This can be called if you have precomputed the nonzero structure of the 
3184:   matrix and want to provide it to the matrix object to improve the performance
3185:   of the MatSetValues() operation.

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

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

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

3194: @*/
3195: PetscErrorCode  MatSeqAIJSetColumnIndices(Mat mat,PetscInt *indices)
3196: {

3202:   PetscUseMethod(mat,"MatSeqAIJSetColumnIndices_C",(Mat,PetscInt *),(mat,indices));
3203:   return(0);
3204: }

3206: /* ----------------------------------------------------------------------------------------*/

3211: PetscErrorCode  MatStoreValues_SeqAIJ(Mat mat)
3212: {
3213:   Mat_SeqAIJ     *aij = (Mat_SeqAIJ *)mat->data;
3215:   size_t         nz = aij->i[mat->rmap->n];

3218:   if (aij->nonew != 1) {
3219:     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
3220:   }

3222:   /* allocate space for values if not already there */
3223:   if (!aij->saved_values) {
3224:     PetscMalloc((nz+1)*sizeof(PetscScalar),&aij->saved_values);
3225:     PetscLogObjectMemory(mat,(nz+1)*sizeof(PetscScalar));
3226:   }

3228:   /* copy values over */
3229:   PetscMemcpy(aij->saved_values,aij->a,nz*sizeof(PetscScalar));
3230:   return(0);
3231: }

3236: /*@
3237:     MatStoreValues - Stashes a copy of the matrix values; this allows, for 
3238:        example, reuse of the linear part of a Jacobian, while recomputing the 
3239:        nonlinear portion.

3241:    Collect on Mat

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

3246:   Level: advanced

3248:   Common Usage, with SNESSolve():
3249: $    Create Jacobian matrix
3250: $    Set linear terms into matrix
3251: $    Apply boundary conditions to matrix, at this time matrix must have 
3252: $      final nonzero structure (i.e. setting the nonlinear terms and applying 
3253: $      boundary conditions again will not change the nonzero structure
3254: $    MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
3255: $    MatStoreValues(mat);
3256: $    Call SNESSetJacobian() with matrix
3257: $    In your Jacobian routine
3258: $      MatRetrieveValues(mat);
3259: $      Set nonlinear terms in matrix
3260:  
3261:   Common Usage without SNESSolve(), i.e. when you handle nonlinear solve yourself:
3262: $    // build linear portion of Jacobian 
3263: $    MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
3264: $    MatStoreValues(mat);
3265: $    loop over nonlinear iterations
3266: $       MatRetrieveValues(mat);
3267: $       // call MatSetValues(mat,...) to set nonliner portion of Jacobian 
3268: $       // call MatAssemblyBegin/End() on matrix
3269: $       Solve linear system with Jacobian
3270: $    endloop 

3272:   Notes:
3273:     Matrix must already be assemblied before calling this routine
3274:     Must set the matrix option MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); before 
3275:     calling this routine.

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

3280: .seealso: MatRetrieveValues()

3282: @*/
3283: PetscErrorCode  MatStoreValues(Mat mat)
3284: {

3289:   if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3290:   if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3291:   PetscUseMethod(mat,"MatStoreValues_C",(Mat),(mat));
3292:   return(0);
3293: }

3298: PetscErrorCode  MatRetrieveValues_SeqAIJ(Mat mat)
3299: {
3300:   Mat_SeqAIJ     *aij = (Mat_SeqAIJ *)mat->data;
3302:   PetscInt       nz = aij->i[mat->rmap->n];

3305:   if (aij->nonew != 1) {
3306:     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
3307:   }
3308:   if (!aij->saved_values) {
3309:     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatStoreValues(A);first");
3310:   }
3311:   /* copy values over */
3312:   PetscMemcpy(aij->a,aij->saved_values,nz*sizeof(PetscScalar));
3313:   return(0);
3314: }

3319: /*@
3320:     MatRetrieveValues - Retrieves the copy of the matrix values; this allows, for 
3321:        example, reuse of the linear part of a Jacobian, while recomputing the 
3322:        nonlinear portion.

3324:    Collect on Mat

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

3329:   Level: advanced

3331: .seealso: MatStoreValues()

3333: @*/
3334: PetscErrorCode  MatRetrieveValues(Mat mat)
3335: {

3340:   if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3341:   if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3342:   PetscUseMethod(mat,"MatRetrieveValues_C",(Mat),(mat));
3343:   return(0);
3344: }


3347: /* --------------------------------------------------------------------------------*/
3350: /*@C
3351:    MatCreateSeqAIJ - Creates a sparse matrix in AIJ (compressed row) format
3352:    (the default parallel PETSc format).  For good matrix assembly performance
3353:    the user should preallocate the matrix storage by setting the parameter nz
3354:    (or the array nnz).  By setting these parameters accurately, performance
3355:    during matrix assembly can be increased by more than a factor of 50.

3357:    Collective on MPI_Comm

3359:    Input Parameters:
3360: +  comm - MPI communicator, set to PETSC_COMM_SELF
3361: .  m - number of rows
3362: .  n - number of columns
3363: .  nz - number of nonzeros per row (same for all rows)
3364: -  nnz - array containing the number of nonzeros in the various rows 
3365:          (possibly different for each row) or PETSC_NULL

3367:    Output Parameter:
3368: .  A - the matrix 

3370:    It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(),
3371:    MatXXXXSetPreallocation() paradgm instead of this routine directly.
3372:    [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation]

3374:    Notes:
3375:    If nnz is given then nz is ignored

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

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

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

3392:    Options Database Keys:
3393: +  -mat_no_inode  - Do not use inodes
3394: -  -mat_inode_limit <limit> - Sets inode limit (max limit=5)

3396:    Level: intermediate

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

3400: @*/
3401: PetscErrorCode  MatCreateSeqAIJ(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],Mat *A)
3402: {

3406:   MatCreate(comm,A);
3407:   MatSetSizes(*A,m,n,m,n);
3408:   MatSetType(*A,MATSEQAIJ);
3409:   MatSeqAIJSetPreallocation_SeqAIJ(*A,nz,nnz);
3410:   return(0);
3411: }

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

3421:    Collective on MPI_Comm

3423:    Input Parameters:
3424: +  B - The matrix-free
3425: .  nz - number of nonzeros per row (same for all rows)
3426: -  nnz - array containing the number of nonzeros in the various rows 
3427:          (possibly different for each row) or PETSC_NULL

3429:    Notes:
3430:      If nnz is given then nz is ignored

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

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

3442:    You can call MatGetInfo() to get information on how effective the preallocation was;
3443:    for example the fields mallocs,nz_allocated,nz_used,nz_unneeded;
3444:    You can also run with the option -info and look for messages with the string 
3445:    malloc in them to see if additional memory allocation was needed.

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

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

3455:    Options Database Keys:
3456: +  -mat_no_inode  - Do not use inodes
3457: .  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
3458: -  -mat_aij_oneindex - Internally use indexing starting at 1
3459:         rather than 0.  Note that when calling MatSetValues(),
3460:         the user still MUST index entries starting at 0!

3462:    Level: intermediate

3464: .seealso: MatCreate(), MatCreateMPIAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays(), MatGetInfo()

3466: @*/
3467: PetscErrorCode  MatSeqAIJSetPreallocation(Mat B,PetscInt nz,const PetscInt nnz[])
3468: {

3472:   PetscTryMethod(B,"MatSeqAIJSetPreallocation_C",(Mat,PetscInt,const PetscInt[]),(B,nz,nnz));
3473:   return(0);
3474: }

3479: PetscErrorCode  MatSeqAIJSetPreallocation_SeqAIJ(Mat B,PetscInt nz,const PetscInt *nnz)
3480: {
3481:   Mat_SeqAIJ     *b;
3482:   PetscBool      skipallocation = PETSC_FALSE;
3484:   PetscInt       i;

3487: 
3488:   if (nz == MAT_SKIP_ALLOCATION) {
3489:     skipallocation = PETSC_TRUE;
3490:     nz             = 0;
3491:   }

3493:   PetscLayoutSetBlockSize(B->rmap,1);
3494:   PetscLayoutSetBlockSize(B->cmap,1);
3495:   PetscLayoutSetUp(B->rmap);
3496:   PetscLayoutSetUp(B->cmap);

3498:   if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
3499:   if (nz < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %d",nz);
3500:   if (nnz) {
3501:     for (i=0; i<B->rmap->n; i++) {
3502:       if (nnz[i] < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be less than 0: local row %d value %d",i,nnz[i]);
3503:       if (nnz[i] > B->cmap->n) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be greater than row length: local row %d value %d rowlength %d",i,nnz[i],B->cmap->n);
3504:     }
3505:   }

3507:   B->preallocated = PETSC_TRUE;
3508:   b = (Mat_SeqAIJ*)B->data;

3510:   if (!skipallocation) {
3511:     if (!b->imax) {
3512:       PetscMalloc2(B->rmap->n,PetscInt,&b->imax,B->rmap->n,PetscInt,&b->ilen);
3513:       PetscLogObjectMemory(B,2*B->rmap->n*sizeof(PetscInt));
3514:     }
3515:     if (!nnz) {
3516:       if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 10;
3517:       else if (nz < 0) nz = 1;
3518:       for (i=0; i<B->rmap->n; i++) b->imax[i] = nz;
3519:       nz = nz*B->rmap->n;
3520:     } else {
3521:       nz = 0;
3522:       for (i=0; i<B->rmap->n; i++) {b->imax[i] = nnz[i]; nz += nnz[i];}
3523:     }
3524:     /* b->ilen will count nonzeros in each row so far. */
3525:     for (i=0; i<B->rmap->n; i++) { b->ilen[i] = 0; }

3527:     /* allocate the matrix space */
3528:     MatSeqXAIJFreeAIJ(B,&b->a,&b->j,&b->i);
3529:     PetscMalloc3(nz,PetscScalar,&b->a,nz,PetscInt,&b->j,B->rmap->n+1,PetscInt,&b->i);
3530:     PetscLogObjectMemory(B,(B->rmap->n+1)*sizeof(PetscInt)+nz*(sizeof(PetscScalar)+sizeof(PetscInt)));
3531:     b->i[0] = 0;
3532:     for (i=1; i<B->rmap->n+1; i++) {
3533:       b->i[i] = b->i[i-1] + b->imax[i-1];
3534:     }
3535:     b->singlemalloc = PETSC_TRUE;
3536:     b->free_a       = PETSC_TRUE;
3537:     b->free_ij      = PETSC_TRUE;
3538:   } else {
3539:     b->free_a       = PETSC_FALSE;
3540:     b->free_ij      = PETSC_FALSE;
3541:   }

3543:   b->nz                = 0;
3544:   b->maxnz             = nz;
3545:   B->info.nz_unneeded  = (double)b->maxnz;
3546:   return(0);
3547: }

3550: #undef  __FUNCT__
3552: /*@
3553:    MatSeqAIJSetPreallocationCSR - Allocates memory for a sparse sequential matrix in AIJ format.  

3555:    Input Parameters:
3556: +  B - the matrix 
3557: .  i - the indices into j for the start of each row (starts with zero)
3558: .  j - the column indices for each row (starts with zero) these must be sorted for each row
3559: -  v - optional values in the matrix

3561:    Level: developer

3563:    The i,j,v values are COPIED with this routine; to avoid the copy use MatCreateSeqAIJWithArrays()

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

3567: .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatSeqAIJSetPreallocation(), MatCreateSeqAIJ(), SeqAIJ
3568: @*/
3569: PetscErrorCode MatSeqAIJSetPreallocationCSR(Mat B,const PetscInt i[],const PetscInt j[],const PetscScalar v[])
3570: {

3575:   PetscTryMethod(B,"MatSeqAIJSetPreallocationCSR_C",(Mat,const PetscInt[],const PetscInt[],const PetscScalar[]),(B,i,j,v));
3576:   return(0);
3577: }

3580: #undef  __FUNCT__
3582: PetscErrorCode  MatSeqAIJSetPreallocationCSR_SeqAIJ(Mat B,const PetscInt Ii[],const PetscInt J[],const PetscScalar v[])
3583: {
3584:   PetscInt       i;
3585:   PetscInt       m,n;
3586:   PetscInt       nz;
3587:   PetscInt       *nnz, nz_max = 0;
3588:   PetscScalar    *values;

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

3594:   if (Ii[0]) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Ii[0] must be 0 it is %D", Ii[0]);
3595:   PetscMalloc((m+1) * sizeof(PetscInt), &nnz);
3596:   for(i = 0; i < m; i++) {
3597:     nz     = Ii[i+1]- Ii[i];
3598:     nz_max = PetscMax(nz_max, nz);
3599:     if (nz < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Local row %D has a negative number of columns %D", i, nnz);
3600:     nnz[i] = nz;
3601:   }
3602:   MatSeqAIJSetPreallocation(B, 0, nnz);
3603:   PetscFree(nnz);

3605:   if (v) {
3606:     values = (PetscScalar*) v;
3607:   } else {
3608:     PetscMalloc(nz_max*sizeof(PetscScalar), &values);
3609:     PetscMemzero(values, nz_max*sizeof(PetscScalar));
3610:   }

3612:   for(i = 0; i < m; i++) {
3613:     nz  = Ii[i+1] - Ii[i];
3614:     MatSetValues_SeqAIJ(B, 1, &i, nz, J+Ii[i], values + (v ? Ii[i] : 0), INSERT_VALUES);
3615:   }

3617:   MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);
3618:   MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);

3620:   if (!v) {
3621:     PetscFree(values);
3622:   }
3623:   return(0);
3624: }

3627: #include <../src/mat/impls/dense/seq/dense.h>
3628: #include <private/petscaxpy.h>

3632: /*
3633:     Computes (B'*A')' since computing B*A directly is untenable

3635:                n                       p                          p
3636:         (              )       (              )         (                  )
3637:       m (      A       )  *  n (       B      )   =   m (         C        )
3638:         (              )       (              )         (                  )

3640: */
3641: PetscErrorCode MatMatMultNumeric_SeqDense_SeqAIJ(Mat A,Mat B,Mat C)
3642: {
3643:   PetscErrorCode     ierr;
3644:   Mat_SeqDense       *sub_a = (Mat_SeqDense*)A->data;
3645:   Mat_SeqAIJ         *sub_b = (Mat_SeqAIJ*)B->data;
3646:   Mat_SeqDense       *sub_c = (Mat_SeqDense*)C->data;
3647:   PetscInt           i,n,m,q,p;
3648:   const PetscInt     *ii,*idx;
3649:   const PetscScalar  *b,*a,*a_q;
3650:   PetscScalar        *c,*c_q;

3653:   m = A->rmap->n;
3654:   n = A->cmap->n;
3655:   p = B->cmap->n;
3656:   a = sub_a->v;
3657:   b = sub_b->a;
3658:   c = sub_c->v;
3659:   PetscMemzero(c,m*p*sizeof(PetscScalar));

3661:   ii  = sub_b->i;
3662:   idx = sub_b->j;
3663:   for (i=0; i<n; i++) {
3664:     q = ii[i+1] - ii[i];
3665:     while (q-->0) {
3666:       c_q = c + m*(*idx);
3667:       a_q = a + m*i;
3668:       PetscAXPY(c_q,*b,a_q,m);
3669:       idx++;
3670:       b++;
3671:     }
3672:   }
3673:   return(0);
3674: }

3678: PetscErrorCode MatMatMultSymbolic_SeqDense_SeqAIJ(Mat A,Mat B,PetscReal fill,Mat *C)
3679: {
3681:   PetscInt       m=A->rmap->n,n=B->cmap->n;
3682:   Mat            Cmat;

3685:   if (A->cmap->n != B->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"A->cmap->n %d != B->rmap->n %d\n",A->cmap->n,B->rmap->n);
3686:   MatCreate(((PetscObject)A)->comm,&Cmat);
3687:   MatSetSizes(Cmat,m,n,m,n);
3688:   MatSetType(Cmat,MATSEQDENSE);
3689:   MatSeqDenseSetPreallocation(Cmat,PETSC_NULL);
3690:   Cmat->assembled = PETSC_TRUE;
3691:   *C = Cmat;
3692:   return(0);
3693: }

3695: /* ----------------------------------------------------------------*/
3698: PetscErrorCode MatMatMult_SeqDense_SeqAIJ(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
3699: {

3703:   if (scall == MAT_INITIAL_MATRIX){
3704:     MatMatMultSymbolic_SeqDense_SeqAIJ(A,B,fill,C);
3705:   }
3706:   MatMatMultNumeric_SeqDense_SeqAIJ(A,B,*C);
3707:   return(0);
3708: }


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

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

3718:   Level: beginner

3720: .seealso: MatCreateSeqAIJ(), MatSetFromOptions(), MatSetType(), MatCreate(), MatType
3721: M*/

3724: #if defined(PETSC_HAVE_PASTIX)
3726: #endif
3727: #if defined(PETSC_HAVE_ESSL) && !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_REAL_SINGLE) && !defined(PETSC_USE_REAL___FLOAT128)
3729: #endif
3734: #if defined(PETSC_HAVE_MUMPS)
3736: #endif
3737: #if defined(PETSC_HAVE_SUPERLU)
3739: #endif
3740: #if defined(PETSC_HAVE_SUPERLU_DIST)
3742: #endif
3743: #if defined(PETSC_HAVE_SPOOLES)
3745: #endif
3746: #if defined(PETSC_HAVE_UMFPACK)
3748: #endif
3749: #if defined(PETSC_HAVE_CHOLMOD)
3751: #endif
3752: #if defined(PETSC_HAVE_LUSOL)
3754: #endif
3755: #if defined(PETSC_HAVE_MATLAB_ENGINE)
3759: #endif

3765: PetscErrorCode  MatCreate_SeqAIJ(Mat B)
3766: {
3767:   Mat_SeqAIJ     *b;
3769:   PetscMPIInt    size;

3772:   MPI_Comm_size(((PetscObject)B)->comm,&size);
3773:   if (size > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Comm must be of size 1");

3775:   PetscNewLog(B,Mat_SeqAIJ,&b);
3776:   B->data             = (void*)b;
3777:   PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));
3778:   b->row              = 0;
3779:   b->col              = 0;
3780:   b->icol             = 0;
3781:   b->reallocs         = 0;
3782:   b->ignorezeroentries = PETSC_FALSE;
3783:   b->roworiented       = PETSC_TRUE;
3784:   b->nonew             = 0;
3785:   b->diag              = 0;
3786:   b->solve_work        = 0;
3787:   B->spptr             = 0;
3788:   b->saved_values      = 0;
3789:   b->idiag             = 0;
3790:   b->mdiag             = 0;
3791:   b->ssor_work         = 0;
3792:   b->omega             = 1.0;
3793:   b->fshift            = 0.0;
3794:   b->idiagvalid        = PETSC_FALSE;
3795:   b->ibdiagvalid       = PETSC_FALSE;
3796:   b->keepnonzeropattern    = PETSC_FALSE;
3797:   b->xtoy              = 0;
3798:   b->XtoY              = 0;
3799:   B->same_nonzero          = PETSC_FALSE;

3801:   PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);
3802: #if defined(PETSC_HAVE_MATLAB_ENGINE)
3803:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_matlab_C","MatGetFactor_seqaij_matlab",MatGetFactor_seqaij_matlab);
3804:   PetscObjectComposeFunctionDynamic((PetscObject)B,"PetscMatlabEnginePut_C","MatlabEnginePut_SeqAIJ",MatlabEnginePut_SeqAIJ);
3805:   PetscObjectComposeFunctionDynamic((PetscObject)B,"PetscMatlabEngineGet_C","MatlabEngineGet_SeqAIJ",MatlabEngineGet_SeqAIJ);
3806: #endif
3807: #if defined(PETSC_HAVE_PASTIX)
3808:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_pastix_C","MatGetFactor_seqaij_pastix",MatGetFactor_seqaij_pastix);
3809: #endif
3810: #if defined(PETSC_HAVE_ESSL) && !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_REAL_SINGLE) && !defined(PETSC_USE_REAL___FLOAT128)
3811:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_essl_C","MatGetFactor_seqaij_essl",MatGetFactor_seqaij_essl);
3812: #endif
3813: #if defined(PETSC_HAVE_SUPERLU)
3814:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_superlu_C","MatGetFactor_seqaij_superlu",MatGetFactor_seqaij_superlu);
3815: #endif
3816: #if defined(PETSC_HAVE_SUPERLU_DIST)
3817:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_superlu_dist_C","MatGetFactor_seqaij_superlu_dist",MatGetFactor_seqaij_superlu_dist);
3818: #endif
3819: #if defined(PETSC_HAVE_SPOOLES)
3820:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_spooles_C","MatGetFactor_seqaij_spooles",MatGetFactor_seqaij_spooles);
3821: #endif
3822: #if defined(PETSC_HAVE_MUMPS)
3823:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_mumps_C","MatGetFactor_aij_mumps",MatGetFactor_aij_mumps);
3824: #endif
3825: #if defined(PETSC_HAVE_UMFPACK)
3826:     PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_umfpack_C","MatGetFactor_seqaij_umfpack",MatGetFactor_seqaij_umfpack);
3827: #endif
3828: #if defined(PETSC_HAVE_CHOLMOD)
3829:     PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_cholmod_C","MatGetFactor_seqaij_cholmod",MatGetFactor_seqaij_cholmod);
3830: #endif
3831: #if defined(PETSC_HAVE_LUSOL)
3832:     PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_lusol_C","MatGetFactor_seqaij_lusol",MatGetFactor_seqaij_lusol);
3833: #endif
3834:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_petsc_C","MatGetFactor_seqaij_petsc",MatGetFactor_seqaij_petsc);
3835:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactorAvailable_petsc_C","MatGetFactorAvailable_seqaij_petsc",MatGetFactorAvailable_seqaij_petsc);
3836:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_bas_C","MatGetFactor_seqaij_bas",MatGetFactor_seqaij_bas);
3837:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqAIJSetColumnIndices_C","MatSeqAIJSetColumnIndices_SeqAIJ",MatSeqAIJSetColumnIndices_SeqAIJ);
3838:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatStoreValues_C","MatStoreValues_SeqAIJ",MatStoreValues_SeqAIJ);
3839:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatRetrieveValues_C","MatRetrieveValues_SeqAIJ",MatRetrieveValues_SeqAIJ);
3840:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_seqsbaij_C","MatConvert_SeqAIJ_SeqSBAIJ",MatConvert_SeqAIJ_SeqSBAIJ);
3841:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_seqbaij_C","MatConvert_SeqAIJ_SeqBAIJ",MatConvert_SeqAIJ_SeqBAIJ);
3842:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_seqaijperm_C","MatConvert_SeqAIJ_SeqAIJPERM",MatConvert_SeqAIJ_SeqAIJPERM);
3843:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_seqaijcrl_C","MatConvert_SeqAIJ_SeqAIJCRL",MatConvert_SeqAIJ_SeqAIJCRL);
3844:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatIsTranspose_C","MatIsTranspose_SeqAIJ",MatIsTranspose_SeqAIJ);
3845:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatIsHermitianTranspose_C","MatIsHermitianTranspose_SeqAIJ",MatIsTranspose_SeqAIJ);
3846:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqAIJSetPreallocation_C","MatSeqAIJSetPreallocation_SeqAIJ",MatSeqAIJSetPreallocation_SeqAIJ);
3847:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqAIJSetPreallocationCSR_C","MatSeqAIJSetPreallocationCSR_SeqAIJ",MatSeqAIJSetPreallocationCSR_SeqAIJ);
3848:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatReorderForNonzeroDiagonal_C","MatReorderForNonzeroDiagonal_SeqAIJ",MatReorderForNonzeroDiagonal_SeqAIJ);
3849:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatMatMult_seqdense_seqaij_C","MatMatMult_SeqDense_SeqAIJ",MatMatMult_SeqDense_SeqAIJ);
3850:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatMatMultSymbolic_seqdense_seqaij_C","MatMatMultSymbolic_SeqDense_SeqAIJ",MatMatMultSymbolic_SeqDense_SeqAIJ);
3851:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatMatMultNumeric_seqdense_seqaij_C","MatMatMultNumeric_SeqDense_SeqAIJ",MatMatMultNumeric_SeqDense_SeqAIJ);
3852:   MatCreate_SeqAIJ_Inode(B);
3853:   PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);
3854:   return(0);
3855: }

3858: #if defined(PETSC_HAVE_PTHREADCLASSES)
3862: PetscErrorCode  MatCreate_SeqAIJPThread(Mat B)
3863: {

3867:   MatCreate_SeqAIJ(B);
3868:   PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));
3869:   B->ops->mult = MatMult_SeqAIJPThread;
3870:   PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJPTHREAD);
3871:   return(0);
3872: }
3874: #endif

3878: /*
3879:     Given a matrix generated with MatGetFactor() duplicates all the information in A into B
3880: */
3881: PetscErrorCode MatDuplicateNoCreate_SeqAIJ(Mat C,Mat A,MatDuplicateOption cpvalues,PetscBool  mallocmatspace)
3882: {
3883:   Mat_SeqAIJ     *c,*a = (Mat_SeqAIJ*)A->data;
3885:   PetscInt       i,m = A->rmap->n;

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

3890:   C->factortype     = A->factortype;
3891:   c->row            = 0;
3892:   c->col            = 0;
3893:   c->icol           = 0;
3894:   c->reallocs       = 0;

3896:   C->assembled      = PETSC_TRUE;
3897: 
3898:   PetscLayoutReference(A->rmap,&C->rmap);
3899:   PetscLayoutReference(A->cmap,&C->cmap);

3901:   PetscMalloc2(m,PetscInt,&c->imax,m,PetscInt,&c->ilen);
3902:   PetscLogObjectMemory(C, 2*m*sizeof(PetscInt));
3903:   for (i=0; i<m; i++) {
3904:     c->imax[i] = a->imax[i];
3905:     c->ilen[i] = a->ilen[i];
3906:   }

3908:   /* allocate the matrix space */
3909:   if (mallocmatspace){
3910:     PetscMalloc3(a->i[m],PetscScalar,&c->a,a->i[m],PetscInt,&c->j,m+1,PetscInt,&c->i);
3911:     PetscLogObjectMemory(C, a->i[m]*(sizeof(PetscScalar)+sizeof(PetscInt))+(m+1)*sizeof(PetscInt));
3912:     c->singlemalloc = PETSC_TRUE;
3913:     PetscMemcpy(c->i,a->i,(m+1)*sizeof(PetscInt));
3914:     if (m > 0) {
3915:       PetscMemcpy(c->j,a->j,(a->i[m])*sizeof(PetscInt));
3916:       if (cpvalues == MAT_COPY_VALUES) {
3917:         PetscMemcpy(c->a,a->a,(a->i[m])*sizeof(PetscScalar));
3918:       } else {
3919:         PetscMemzero(c->a,(a->i[m])*sizeof(PetscScalar));
3920:       }
3921:     }
3922:   }

3924:   c->ignorezeroentries = a->ignorezeroentries;
3925:   c->roworiented       = a->roworiented;
3926:   c->nonew             = a->nonew;
3927:   if (a->diag) {
3928:     PetscMalloc((m+1)*sizeof(PetscInt),&c->diag);
3929:     PetscLogObjectMemory(C,(m+1)*sizeof(PetscInt));
3930:     for (i=0; i<m; i++) {
3931:       c->diag[i] = a->diag[i];
3932:     }
3933:   } else c->diag           = 0;
3934:   c->solve_work            = 0;
3935:   c->saved_values          = 0;
3936:   c->idiag                 = 0;
3937:   c->ssor_work             = 0;
3938:   c->keepnonzeropattern    = a->keepnonzeropattern;
3939:   c->free_a                = PETSC_TRUE;
3940:   c->free_ij               = PETSC_TRUE;
3941:   c->xtoy                  = 0;
3942:   c->XtoY                  = 0;

3944:   c->nz                 = a->nz;
3945:   c->maxnz              = a->nz; /* Since we allocate exactly the right amount */
3946:   C->preallocated       = PETSC_TRUE;

3948:   c->compressedrow.use     = a->compressedrow.use;
3949:   c->compressedrow.nrows   = a->compressedrow.nrows;
3950:   c->compressedrow.check   = a->compressedrow.check;
3951:   if (a->compressedrow.use){
3952:     i = a->compressedrow.nrows;
3953:     PetscMalloc2(i+1,PetscInt,&c->compressedrow.i,i,PetscInt,&c->compressedrow.rindex);
3954:     PetscMemcpy(c->compressedrow.i,a->compressedrow.i,(i+1)*sizeof(PetscInt));
3955:     PetscMemcpy(c->compressedrow.rindex,a->compressedrow.rindex,i*sizeof(PetscInt));
3956:   } else {
3957:     c->compressedrow.use    = PETSC_FALSE;
3958:     c->compressedrow.i      = PETSC_NULL;
3959:     c->compressedrow.rindex = PETSC_NULL;
3960:   }
3961:   C->same_nonzero = A->same_nonzero;
3962:   MatDuplicate_SeqAIJ_Inode(A,cpvalues,&C);

3964:   PetscFListDuplicate(((PetscObject)A)->qlist,&((PetscObject)C)->qlist);
3965:   return(0);
3966: }

3970: PetscErrorCode MatDuplicate_SeqAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B)
3971: {

3975:   MatCreate(((PetscObject)A)->comm,B);
3976:   MatSetSizes(*B,A->rmap->n,A->cmap->n,A->rmap->n,A->cmap->n);
3977:   MatSetType(*B,MATSEQAIJ);
3978:   MatDuplicateNoCreate_SeqAIJ(*B,A,cpvalues,PETSC_TRUE);
3979:   return(0);
3980: }

3984: PetscErrorCode MatLoad_SeqAIJ(Mat newMat, PetscViewer viewer)
3985: {
3986:   Mat_SeqAIJ     *a;
3988:   PetscInt       i,sum,nz,header[4],*rowlengths = 0,M,N,rows,cols;
3989:   int            fd;
3990:   PetscMPIInt    size;
3991:   MPI_Comm       comm;
3992:   PetscInt       bs = 1;
3993: 
3995:   PetscObjectGetComm((PetscObject)viewer,&comm);
3996:   MPI_Comm_size(comm,&size);
3997:   if (size > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"view must have one processor");

3999:   PetscOptionsBegin(comm,PETSC_NULL,"Options for loading SEQAIJ matrix","Mat");
4000:   PetscOptionsInt("-matload_block_size","Set the blocksize used to store the matrix","MatLoad",bs,&bs,PETSC_NULL);
4001:   PetscOptionsEnd();

4003:   PetscViewerBinaryGetDescriptor(viewer,&fd);
4004:   PetscBinaryRead(fd,header,4,PETSC_INT);
4005:   if (header[0] != MAT_FILE_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"not matrix object in file");
4006:   M = header[1]; N = header[2]; nz = header[3];

4008:   if (nz < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format on disk,cannot load as SeqAIJ");

4010:   /* read in row lengths */
4011:   PetscMalloc(M*sizeof(PetscInt),&rowlengths);
4012:   PetscBinaryRead(fd,rowlengths,M,PETSC_INT);

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

4018:   /* set global size if not set already*/
4019:   if (newMat->rmap->n < 0 && newMat->rmap->N < 0 && newMat->cmap->n < 0 && newMat->cmap->N < 0) {
4020:     MatSetSizes(newMat,PETSC_DECIDE,PETSC_DECIDE,M,N);
4021:   } else {
4022:     /* if sizes and type are already set, check if the vector global sizes are correct */
4023:     MatGetSize(newMat,&rows,&cols);
4024:     if (rows < 0 && cols < 0){ /* user might provide local size instead of global size */
4025:       MatGetLocalSize(newMat,&rows,&cols);
4026:     }
4027:     if (M != rows ||  N != cols) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED, "Matrix in file of different length (%d, %d) than the input matrix (%d, %d)",M,N,rows,cols);
4028:   }
4029:   MatSeqAIJSetPreallocation_SeqAIJ(newMat,0,rowlengths);
4030:   a = (Mat_SeqAIJ*)newMat->data;

4032:   PetscBinaryRead(fd,a->j,nz,PETSC_INT);

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

4037:   /* set matrix "i" values */
4038:   a->i[0] = 0;
4039:   for (i=1; i<= M; i++) {
4040:     a->i[i]      = a->i[i-1] + rowlengths[i-1];
4041:     a->ilen[i-1] = rowlengths[i-1];
4042:   }
4043:   PetscFree(rowlengths);

4045:   MatAssemblyBegin(newMat,MAT_FINAL_ASSEMBLY);
4046:   MatAssemblyEnd(newMat,MAT_FINAL_ASSEMBLY);
4047:   if (bs > 1) {MatSetBlockSize(newMat,bs);}
4048:   return(0);
4049: }

4053: PetscErrorCode MatEqual_SeqAIJ(Mat A,Mat B,PetscBool * flg)
4054: {
4055:   Mat_SeqAIJ     *a = (Mat_SeqAIJ *)A->data,*b = (Mat_SeqAIJ *)B->data;
4057: #if defined(PETSC_USE_COMPLEX)
4058:   PetscInt k;
4059: #endif

4062:   /* If the  matrix dimensions are not equal,or no of nonzeros */
4063:   if ((A->rmap->n != B->rmap->n) || (A->cmap->n != B->cmap->n) ||(a->nz != b->nz)) {
4064:     *flg = PETSC_FALSE;
4065:     return(0);
4066:   }
4067: 
4068:   /* if the a->i are the same */
4069:   PetscMemcmp(a->i,b->i,(A->rmap->n+1)*sizeof(PetscInt),flg);
4070:   if (!*flg) return(0);
4071: 
4072:   /* if a->j are the same */
4073:   PetscMemcmp(a->j,b->j,(a->nz)*sizeof(PetscInt),flg);
4074:   if (!*flg) return(0);
4075: 
4076:   /* if a->a are the same */
4077: #if defined(PETSC_USE_COMPLEX)
4078:   for (k=0; k<a->nz; k++){
4079:     if (PetscRealPart(a->a[k]) != PetscRealPart(b->a[k]) || PetscImaginaryPart(a->a[k]) != PetscImaginaryPart(b->a[k])){
4080:       *flg = PETSC_FALSE;
4081:       return(0);
4082:     }
4083:   }
4084: #else
4085:   PetscMemcmp(a->a,b->a,(a->nz)*sizeof(PetscScalar),flg);
4086: #endif
4087:   return(0);
4088: }

4092: /*@
4093:      MatCreateSeqAIJWithArrays - Creates an sequential AIJ matrix using matrix elements (in CSR format)
4094:               provided by the user.

4096:       Collective on MPI_Comm

4098:    Input Parameters:
4099: +   comm - must be an MPI communicator of size 1
4100: .   m - number of rows
4101: .   n - number of columns
4102: .   i - row indices
4103: .   j - column indices
4104: -   a - matrix values

4106:    Output Parameter:
4107: .   mat - the matrix

4109:    Level: intermediate

4111:    Notes:
4112:        The i, j, and a arrays are not copied by this routine, the user must free these arrays
4113:     once the matrix is destroyed and not before

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

4117:        The i and j indices are 0 based

4119:        The format which is used for the sparse matrix input, is equivalent to a
4120:     row-major ordering.. i.e for the following matrix, the input data expected is
4121:     as shown:

4123:         1 0 0
4124:         2 0 3
4125:         4 5 6

4127:         i =  {0,1,3,6}  [size = nrow+1  = 3+1]
4128:         j =  {0,0,2,0,1,2}  [size = nz = 6]; values must be sorted for each row
4129:         v =  {1,2,3,4,5,6}  [size = nz = 6]

4131:         
4132: .seealso: MatCreate(), MatCreateMPIAIJ(), MatCreateSeqAIJ(), MatCreateMPIAIJWithArrays(), MatMPIAIJSetPreallocationCSR()

4134: @*/
4135: PetscErrorCode  MatCreateSeqAIJWithArrays(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt* i,PetscInt*j,PetscScalar *a,Mat *mat)
4136: {
4138:   PetscInt       ii;
4139:   Mat_SeqAIJ     *aij;
4140: #if defined(PETSC_USE_DEBUG)
4141:   PetscInt       jj;
4142: #endif

4145:   if (i[0]) {
4146:     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0");
4147:   }
4148:   MatCreate(comm,mat);
4149:   MatSetSizes(*mat,m,n,m,n);
4150:   MatSetType(*mat,MATSEQAIJ);
4151:   MatSeqAIJSetPreallocation_SeqAIJ(*mat,MAT_SKIP_ALLOCATION,0);
4152:   aij  = (Mat_SeqAIJ*)(*mat)->data;
4153:   PetscMalloc2(m,PetscInt,&aij->imax,m,PetscInt,&aij->ilen);

4155:   aij->i = i;
4156:   aij->j = j;
4157:   aij->a = a;
4158:   aij->singlemalloc = PETSC_FALSE;
4159:   aij->nonew        = -1;             /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/
4160:   aij->free_a       = PETSC_FALSE;
4161:   aij->free_ij      = PETSC_FALSE;

4163:   for (ii=0; ii<m; ii++) {
4164:     aij->ilen[ii] = aij->imax[ii] = i[ii+1] - i[ii];
4165: #if defined(PETSC_USE_DEBUG)
4166:     if (i[ii+1] - i[ii] < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative row length in i (row indices) row = %d length = %d",ii,i[ii+1] - i[ii]);
4167:     for (jj=i[ii]+1; jj<i[ii+1]; jj++) {
4168:       if (j[jj] < j[jj-1]) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column entry number %D (actual colum %D) in row %D is not sorted",jj-i[ii],j[jj],ii);
4169:       if (j[jj] == j[jj]-1) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column entry number %D (actual colum %D) in row %D is identical to previous entry",jj-i[ii],j[jj],ii);
4170:     }
4171: #endif    
4172:   }
4173: #if defined(PETSC_USE_DEBUG)
4174:   for (ii=0; ii<aij->i[m]; ii++) {
4175:     if (j[ii] < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column index at location = %d index = %d",ii,j[ii]);
4176:     if (j[ii] > n - 1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column index to large at location = %d index = %d",ii,j[ii]);
4177:   }
4178: #endif    

4180:   MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);
4181:   MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);
4182:   return(0);
4183: }

4187: PetscErrorCode MatSetColoring_SeqAIJ(Mat A,ISColoring coloring)
4188: {
4190:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;

4193:   if (coloring->ctype == IS_COLORING_GLOBAL) {
4194:     ISColoringReference(coloring);
4195:     a->coloring = coloring;
4196:   } else if (coloring->ctype == IS_COLORING_GHOSTED) {
4197:     PetscInt             i,*larray;
4198:     ISColoring      ocoloring;
4199:     ISColoringValue *colors;

4201:     /* set coloring for diagonal portion */
4202:     PetscMalloc(A->cmap->n*sizeof(PetscInt),&larray);
4203:     for (i=0; i<A->cmap->n; i++) {
4204:       larray[i] = i;
4205:     }
4206:     ISGlobalToLocalMappingApply(A->cmap->mapping,IS_GTOLM_MASK,A->cmap->n,larray,PETSC_NULL,larray);
4207:     PetscMalloc(A->cmap->n*sizeof(ISColoringValue),&colors);
4208:     for (i=0; i<A->cmap->n; i++) {
4209:       colors[i] = coloring->colors[larray[i]];
4210:     }
4211:     PetscFree(larray);
4212:     ISColoringCreate(PETSC_COMM_SELF,coloring->n,A->cmap->n,colors,&ocoloring);
4213:     a->coloring = ocoloring;
4214:   }
4215:   return(0);
4216: }

4218: #if defined(PETSC_HAVE_ADIC)
4220: #include <adic/ad_utils.h>

4225: PetscErrorCode MatSetValuesAdic_SeqAIJ(Mat A,void *advalues)
4226: {
4227:   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
4228:   PetscInt        m = A->rmap->n,*ii = a->i,*jj = a->j,nz,i,j,nlen;
4229:   PetscScalar     *v = a->a,*values = ((PetscScalar*)advalues)+1;
4230:   ISColoringValue *color;

4233:   if (!a->coloring) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Coloring not set for matrix");
4234:   nlen  = PetscADGetDerivTypeSize()/sizeof(PetscScalar);
4235:   color = a->coloring->colors;
4236:   /* loop over rows */
4237:   for (i=0; i<m; i++) {
4238:     nz = ii[i+1] - ii[i];
4239:     /* loop over columns putting computed value into matrix */
4240:     for (j=0; j<nz; j++) {
4241:       *v++ = values[color[*jj++]];
4242:     }
4243:     values += nlen; /* jump to next row of derivatives */
4244:   }
4245:   return(0);
4246: }
4247: #endif

4251: PetscErrorCode MatSetValuesAdifor_SeqAIJ(Mat A,PetscInt nl,void *advalues)
4252: {
4253:   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
4254:   PetscInt         m = A->rmap->n,*ii = a->i,*jj = a->j,nz,i,j;
4255:   MatScalar       *v = a->a;
4256:   PetscScalar     *values = (PetscScalar *)advalues;
4257:   ISColoringValue *color;

4260:   if (!a->coloring) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Coloring not set for matrix");
4261:   color = a->coloring->colors;
4262:   /* loop over rows */
4263:   for (i=0; i<m; i++) {
4264:     nz = ii[i+1] - ii[i];
4265:     /* loop over columns putting computed value into matrix */
4266:     for (j=0; j<nz; j++) {
4267:       *v++ = values[color[*jj++]];
4268:     }
4269:     values += nl; /* jump to next row of derivatives */
4270:   }
4271:   return(0);
4272: }

4274: /*
4275:     Special version for direct calls from Fortran 
4276: */
4277: #include <private/fortranimpl.h>
4278: #if defined(PETSC_HAVE_FORTRAN_CAPS)
4279: #define matsetvaluesseqaij_ MATSETVALUESSEQAIJ
4280: #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
4281: #define matsetvaluesseqaij_ matsetvaluesseqaij
4282: #endif

4284: /* Change these macros so can be used in void function */
4285: #undef CHKERRQ
4286: #define CHKERRQ(ierr) CHKERRABORT(((PetscObject)A)->comm,ierr) 
4287: #undef SETERRQ2
4288: #define SETERRQ2(comm,ierr,b,c,d) CHKERRABORT(comm,ierr) 

4293: void PETSC_STDCALL matsetvaluesseqaij_(Mat *AA,PetscInt *mm,const PetscInt im[],PetscInt *nn,const PetscInt in[],const PetscScalar v[],InsertMode *isis, PetscErrorCode *_ierr)
4294: {
4295:   Mat            A = *AA;
4296:   PetscInt       m = *mm, n = *nn;
4297:   InsertMode     is = *isis;
4298:   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
4299:   PetscInt       *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N;
4300:   PetscInt       *imax,*ai,*ailen;
4302:   PetscInt       *aj,nonew = a->nonew,lastcol = -1;
4303:   MatScalar      *ap,value,*aa;
4304:   PetscBool      ignorezeroentries = a->ignorezeroentries;
4305:   PetscBool      roworiented = a->roworiented;

4308:   MatPreallocated(A);
4309:   imax = a->imax;
4310:   ai = a->i;
4311:   ailen = a->ilen;
4312:   aj = a->j;
4313:   aa = a->a;

4315:   for (k=0; k<m; k++) { /* loop over added rows */
4316:     row  = im[k];
4317:     if (row < 0) continue;
4318: #if defined(PETSC_USE_DEBUG)  
4319:     if (row >= A->rmap->n) SETERRABORT(((PetscObject)A)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Row too large");
4320: #endif
4321:     rp   = aj + ai[row]; ap = aa + ai[row];
4322:     rmax = imax[row]; nrow = ailen[row];
4323:     low  = 0;
4324:     high = nrow;
4325:     for (l=0; l<n; l++) { /* loop over added columns */
4326:       if (in[l] < 0) continue;
4327: #if defined(PETSC_USE_DEBUG)  
4328:       if (in[l] >= A->cmap->n) SETERRABORT(((PetscObject)A)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Column too large");
4329: #endif
4330:       col = in[l];
4331:       if (roworiented) {
4332:         value = v[l + k*n];
4333:       } else {
4334:         value = v[k + l*m];
4335:       }
4336:       if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue;

4338:       if (col <= lastcol) low = 0; else high = nrow;
4339:       lastcol = col;
4340:       while (high-low > 5) {
4341:         t = (low+high)/2;
4342:         if (rp[t] > col) high = t;
4343:         else             low  = t;
4344:       }
4345:       for (i=low; i<high; i++) {
4346:         if (rp[i] > col) break;
4347:         if (rp[i] == col) {
4348:           if (is == ADD_VALUES) ap[i] += value;
4349:           else                  ap[i] = value;
4350:           goto noinsert;
4351:         }
4352:       }
4353:       if (value == 0.0 && ignorezeroentries) goto noinsert;
4354:       if (nonew == 1) goto noinsert;
4355:       if (nonew == -1) SETERRABORT(((PetscObject)A)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero in the matrix");
4356:       MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
4357:       N = nrow++ - 1; a->nz++; high++;
4358:       /* shift up all the later entries in this row */
4359:       for (ii=N; ii>=i; ii--) {
4360:         rp[ii+1] = rp[ii];
4361:         ap[ii+1] = ap[ii];
4362:       }
4363:       rp[i] = col;
4364:       ap[i] = value;
4365:       noinsert:;
4366:       low = i + 1;
4367:     }
4368:     ailen[row] = nrow;
4369:   }
4370:   A->same_nonzero = PETSC_FALSE;
4371:   PetscFunctionReturnVoid();
4372: }