xref: /petsc/src/mat/impls/adj/mpi/mpiadj.c (revision a2596bdbc30ea25b67c8aa9d27518270ab3efaa7)
1 #ifdef PETSC_RCS_HEADER
2 static char vcid[] = "$Id: adj.c,v 1.5 1997/08/22 15:14:50 bsmith Exp $";
3 #endif
4 
5 /*
6     Defines the basic matrix operations for the ADJ adjacency list matrix data-structure.
7 */
8 
9 #include "pinclude/pviewer.h"
10 #include "sys.h"
11 #include "src/mat/impls/adj/seq/adj.h"
12 #include "src/inline/bitarray.h"
13 
14 extern int MatToSymmetricIJ_SeqAIJ(int,int*,int*,int,int,int**,int**);
15 
16 #undef __FUNC__
17 #define __FUNC__ "MatGetRowIJ_SeqAdj"
18 int MatGetRowIJ_SeqAdj(Mat A,int oshift,PetscTruth symmetric,int *m,int **ia,int **ja,
19                            PetscTruth *done)
20 {
21   Mat_SeqAdj *a = (Mat_SeqAdj *) A->data;
22   int        ierr,i;
23 
24   *m     = A->m;
25   if (!ia) return 0;
26   if (symmetric && !a->symmetric) {
27     ierr = MatToSymmetricIJ_SeqAIJ(a->m,a->i,a->j,0,oshift,ia,ja); CHKERRQ(ierr);
28   } else if (oshift == 1) {
29     int nz = a->i[a->m] + 1;
30     /* malloc space and  add 1 to i and j indices */
31     *ia = (int *) PetscMalloc( (a->m+1)*sizeof(int) ); CHKPTRQ(*ia);
32     *ja = (int *) PetscMalloc( (nz+1)*sizeof(int) ); CHKPTRQ(*ja);
33     for ( i=0; i<nz; i++ )     (*ja)[i] = a->j[i] + 1;
34     for ( i=0; i<a->m+1; i++ ) (*ia)[i] = a->i[i] + 1;
35   } else {
36     *ia = a->i; *ja = a->j;
37   }
38 
39   return 0;
40 }
41 
42 #undef __FUNC__
43 #define __FUNC__ "MatRestoreRowIJ_SeqAdj"
44 int MatRestoreRowIJ_SeqAdj(Mat A,int oshift,PetscTruth symmetric,int *n,int **ia,int **ja,
45                                PetscTruth *done)
46 {
47   Mat_SeqAdj *a = (Mat_SeqAdj *) A->data;
48 
49   if (!ia) return 0;
50   if ((symmetric && !a->symmetric) || oshift == 1) {
51     PetscFree(*ia);
52     PetscFree(*ja);
53   }
54   return 0;
55 }
56 
57 #undef __FUNC__
58 #define __FUNC__ "MatView_SeqAdj_Binary"
59 extern int MatView_SeqAdj_Binary(Mat A,Viewer viewer)
60 {
61   Mat_SeqAdj *a = (Mat_SeqAdj *) A->data;
62   int        i, fd, *col_lens, ierr;
63   Scalar     *values;
64 
65   ierr        = ViewerBinaryGetDescriptor(viewer,&fd); CHKERRQ(ierr);
66   col_lens    = (int *) PetscMalloc( (4+a->m)*sizeof(int) ); CHKPTRQ(col_lens);
67   col_lens[0] = MAT_COOKIE;
68   col_lens[1] = a->m;
69   col_lens[2] = a->n;
70   col_lens[3] = a->nz;
71 
72   /* store lengths of each row and write (including header) to file */
73   for ( i=0; i<a->m; i++ ) {
74     col_lens[4+i] = a->i[i+1] - a->i[i];
75   }
76   ierr = PetscBinaryWrite(fd,col_lens,4+a->m,BINARY_INT,1); CHKERRQ(ierr);
77   PetscFree(col_lens);
78 
79   /* store column indices (zero start index) */
80   ierr = PetscBinaryWrite(fd,a->j,a->nz,BINARY_INT,0); CHKERRQ(ierr);
81 
82   /* store nonzero values */
83   values = (Scalar *) PetscMalloc( a->nz*sizeof(Scalar) );CHKPTRQ(values);
84   PetscMemzero(values,a->nz*sizeof(Scalar) );
85   ierr = PetscBinaryWrite(fd,values,a->nz,BINARY_SCALAR,0); CHKERRQ(ierr);
86   PetscFree(values);
87   return 0;
88 }
89 
90 #undef __FUNC__
91 #define __FUNC__ "MatView_SeqAdj_ASCII"
92 extern int MatView_SeqAdj_ASCII(Mat A,Viewer viewer)
93 {
94   Mat_SeqAdj  *a = (Mat_SeqAdj *) A->data;
95   int         ierr, i,j, m = a->m,  format;
96   FILE        *fd;
97   char        *outputname;
98 
99   ierr = ViewerASCIIGetPointer(viewer,&fd); CHKERRQ(ierr);
100   ierr = ViewerFileGetOutputname_Private(viewer,&outputname); CHKERRQ(ierr);
101   ierr = ViewerGetFormat(viewer,&format);
102   if (format == VIEWER_FORMAT_ASCII_INFO) {
103     return 0;
104   }
105   else if (format == VIEWER_FORMAT_ASCII_MATLAB) {
106     fprintf(fd,"%% Size = %d %d \n",m,a->n);
107     fprintf(fd,"%% Nonzeros = %d \n",a->nz);
108     fprintf(fd,"zzz = zeros(%d,3);\n",a->nz);
109     fprintf(fd,"zzz = [\n");
110 
111     for (i=0; i<m; i++) {
112       for ( j=a->i[i]; j<a->i[i+1]; j++ ) {
113 #if defined(PETSC_COMPLEX)
114         fprintf(fd,"%d %d  %18.16e + %18.16e i \n",i+1,a->j[j],0.0,0.0);
115 #else
116         fprintf(fd,"%d %d  %18.16e\n", i+1, a->j[j], 0.0);
117 #endif
118       }
119     }
120     fprintf(fd,"];\n %s = spconvert(zzz);\n",outputname);
121   }
122   else if (format == VIEWER_FORMAT_ASCII_COMMON) {
123     for ( i=0; i<m; i++ ) {
124       fprintf(fd,"row %d:",i);
125       for ( j=a->i[i]; j<a->i[i+1]; j++ ) {
126 #if defined(PETSC_COMPLEX)
127         fprintf(fd," %d %g + %g i",a->j[j],0.0,0.0);
128 #else
129         fprintf(fd," %d %g ",a->j[j],0.0);
130 #endif
131       }
132       fprintf(fd,"\n");
133     }
134   }
135   else {
136     for ( i=0; i<m; i++ ) {
137       fprintf(fd,"row %d:",i);
138       for ( j=a->i[i]; j<a->i[i+1]; j++ ) {
139 #if defined(PETSC_COMPLEX)
140         fprintf(fd," %d %g + %g i",a->j[j],0.0,0.0);
141 #else
142         fprintf(fd," %d %g ",a->j[j],0.0);
143 #endif
144       }
145       fprintf(fd,"\n");
146     }
147   }
148   fflush(fd);
149   return 0;
150 }
151 
152 #undef __FUNC__
153 #define __FUNC__ "MatView_SeqAdj_Draw"
154 extern int MatView_SeqAdj_Draw(Mat A,Viewer viewer)
155 {
156   Mat_SeqAdj  *a = (Mat_SeqAdj *) A->data;
157   int         ierr, i,j, m = a->m,color;
158   int         format;
159   double      xl,yl,xr,yr,w,h,x_l,x_r,y_l,y_r;
160   Draw        draw;
161   PetscTruth  isnull;
162 
163   ierr = ViewerDrawGetDraw(viewer,&draw); CHKERRQ(ierr);
164   ierr = DrawCheckResizedWindow(draw); CHKERRQ(ierr);
165   ierr = DrawClear(draw); CHKERRQ(ierr);
166   ierr = ViewerGetFormat(viewer,&format); CHKERRQ(ierr);
167   ierr = DrawIsNull(draw,&isnull); CHKERRQ(ierr); if (isnull) return 0;
168 
169   xr  = a->n; yr = a->m; h = yr/10.0; w = xr/10.0;
170   xr += w;    yr += h;  xl = -w;     yl = -h;
171   ierr = DrawSetCoordinates(draw,xl,yl,xr,yr); CHKERRQ(ierr);
172   /* loop over matrix elements drawing boxes */
173 
174   if (format != VIEWER_FORMAT_DRAW_CONTOUR) {
175     color = DRAW_BLUE;
176     for ( i=0; i<m; i++ ) {
177       y_l = m - i - 1.0; y_r = y_l + 1.0;
178       for ( j=a->i[i]; j<a->i[i+1]; j++ ) {
179         x_l = a->j[j]; x_r = x_l + 1.0;
180         DrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);
181       }
182     }
183   }
184   ierr = DrawPause(draw); CHKERRQ(ierr);
185   return 0;
186 }
187 
188 #undef __FUNC__
189 #define __FUNC__ "MatView_SeqAdj"
190 int MatView_SeqAdj(PetscObject obj,Viewer viewer)
191 {
192   Mat         A = (Mat) obj;
193   Mat_SeqAdj  *a = (Mat_SeqAdj*) A->data;
194   ViewerType  vtype;
195   int         ierr;
196 
197   ierr = ViewerGetType(viewer,&vtype); CHKERRQ(ierr);
198   if (vtype == MATLAB_VIEWER) {
199     Scalar *values;
200     values = (Scalar *) PetscMalloc(a->nz*sizeof(Scalar));CHKPTRQ(values);
201     PetscMemzero(values,a->nz*sizeof(Scalar));
202     ierr = ViewerMatlabPutSparse_Private(viewer,a->m,a->n,a->nz,values,a->i,a->j);CHKERRQ(ierr);
203     PetscFree(values);
204   }
205   else if (vtype == ASCII_FILE_VIEWER || vtype == ASCII_FILES_VIEWER){
206     return MatView_SeqAdj_ASCII(A,viewer);
207   }
208   else if (vtype == BINARY_FILE_VIEWER) {
209     return MatView_SeqAdj_Binary(A,viewer);
210   }
211   else if (vtype == DRAW_VIEWER) {
212     return MatView_SeqAdj_Draw(A,viewer);
213   }
214   return 0;
215 }
216 
217 
218 #undef __FUNC__
219 #define __FUNC__ "MatDestroy_SeqAdj"
220 int MatDestroy_SeqAdj(PetscObject obj)
221 {
222   Mat        A  = (Mat) obj;
223   Mat_SeqAdj *a = (Mat_SeqAdj *) A->data;
224 
225 #if defined(PETSC_LOG)
226   PLogObjectState(obj,"Rows=%d, Cols=%d, NZ=%d",a->m,a->n,a->nz);
227 #endif
228   if (a->diag) PetscFree(a->diag);
229   PetscFree(a->i);
230   PetscFree(a->j);
231   PetscFree(a);
232 
233   PLogObjectDestroy(A);
234   PetscHeaderDestroy(A);
235   return 0;
236 }
237 
238 
239 #undef __FUNC__
240 #define __FUNC__ "MatSetOption_SeqAdj"
241 int MatSetOption_SeqAdj(Mat A,MatOption op)
242 {
243   Mat_SeqAdj *a = (Mat_SeqAdj *) A->data;
244 
245   if (op == MAT_STRUCTURALLY_SYMMETRIC) {
246     a->symmetric = PETSC_TRUE;
247   } else {
248     PLogInfo(A,"Info:MatSetOption_SeqAdj:Option ignored\n");
249   }
250   return 0;
251 }
252 
253 
254 /*
255      Adds diagonal pointers to sparse matrix structure.
256 */
257 
258 #undef __FUNC__
259 #define __FUNC__ "MatMarkDiag_SeqAdj"
260 int MatMarkDiag_SeqAdj(Mat A)
261 {
262   Mat_SeqAdj *a = (Mat_SeqAdj *) A->data;
263   int        i,j, *diag, m = a->m;
264 
265   diag = (int *) PetscMalloc( (m+1)*sizeof(int)); CHKPTRQ(diag);
266   PLogObjectMemory(A,(m+1)*sizeof(int));
267   for ( i=0; i<a->m; i++ ) {
268     for ( j=a->i[i]; j<a->i[i+1]; j++ ) {
269       if (a->j[j] == i) {
270         diag[i] = j;
271         break;
272       }
273     }
274   }
275   a->diag = diag;
276   return 0;
277 }
278 
279 
280 #undef __FUNC__
281 #define __FUNC__ "MatGetInfo_SeqAdj"
282 int MatGetInfo_SeqAdj(Mat A,MatInfoType flag,MatInfo *info)
283 {
284   Mat_SeqAdj *a = (Mat_SeqAdj *) A->data;
285 
286   info->rows_global    = (double)a->m;
287   info->columns_global = (double)a->n;
288   info->rows_local     = (double)a->m;
289   info->columns_local  = (double)a->n;
290   info->block_size     = 1.0;
291   info->nz_allocated   = (double)a->nz;
292   info->nz_used        = (double)a->nz;
293   info->nz_unneeded    = 0.0;
294   /*  if (info->nz_unneeded != A->info.nz_unneeded)
295     printf("space descrepancy: maxnz-nz = %d, nz_unneeded = %d\n",(int)info->nz_unneeded,(int)A->info.nz_unneeded); */
296   info->assemblies     = 0.0;
297   info->mallocs        = 0.0;
298   info->memory         = A->mem;
299   if (A->factor) {
300     info->fill_ratio_given  = A->info.fill_ratio_given;
301     info->fill_ratio_needed = A->info.fill_ratio_needed;
302     info->factor_mallocs    = A->info.factor_mallocs;
303   } else {
304     info->fill_ratio_given  = 0;
305     info->fill_ratio_needed = 0;
306     info->factor_mallocs    = 0;
307   }
308   return 0;
309 }
310 
311 #undef __FUNC__
312 #define __FUNC__ "MatGetSize_SeqAdj"
313 int MatGetSize_SeqAdj(Mat A,int *m,int *n)
314 {
315   Mat_SeqAdj *a = (Mat_SeqAdj *) A->data;
316   *m = a->m; *n = a->n;
317   return 0;
318 }
319 
320 #undef __FUNC__
321 #define __FUNC__ "MatGetOwnershipRange_SeqAdj"
322 int MatGetOwnershipRange_SeqAdj(Mat A,int *m,int *n)
323 {
324   Mat_SeqAdj *a = (Mat_SeqAdj *) A->data;
325   *m = 0; *n = a->m;
326   return 0;
327 }
328 
329 #undef __FUNC__
330 #define __FUNC__ "MatGetRow_SeqAdj"
331 int MatGetRow_SeqAdj(Mat A,int row,int *nz,int **idx,Scalar **v)
332 {
333   Mat_SeqAdj *a = (Mat_SeqAdj *) A->data;
334   int        *itmp;
335 
336   if (row < 0 || row >= a->m) SETERRQ(1,0,"Row out of range");
337 
338   *nz = a->i[row+1] - a->i[row];
339   if (v) *v = PETSC_NULL;
340   if (idx) {
341     itmp = a->j + a->i[row];
342     if (*nz) {
343       *idx = itmp;
344     }
345     else *idx = 0;
346   }
347   return 0;
348 }
349 
350 #undef __FUNC__
351 #define __FUNC__ "MatRestoreRow_SeqAdj"
352 int MatRestoreRow_SeqAdj(Mat A,int row,int *nz,int **idx,Scalar **v)
353 {
354   return 0;
355 }
356 
357 #undef __FUNC__
358 #define __FUNC__ "MatGetBlockSize_SeqAdj"
359 int MatGetBlockSize_SeqAdj(Mat A, int *bs)
360 {
361   *bs = 1;
362   return 0;
363 }
364 
365 #undef __FUNC__
366 #define __FUNC__ "MatIncreaseOverlap_SeqAdj"
367 int MatIncreaseOverlap_SeqAdj(Mat A, int is_max, IS *is, int ov)
368 {
369   Mat_SeqAdj *a = (Mat_SeqAdj *) A->data;
370   int        row, i,j,k,l,m,n, *idx,ierr, *nidx, isz, val;
371   int        start, end, *ai, *aj;
372   char       *table;
373 
374   m     = a->m;
375   ai    = a->i;
376   aj    = a->j;
377 
378   if (ov < 0)  SETERRQ(1,0,"illegal overlap value used");
379 
380   table = (char *) PetscMalloc((m/BITSPERBYTE +1)*sizeof(char)); CHKPTRQ(table);
381   nidx  = (int *) PetscMalloc((m+1)*sizeof(int)); CHKPTRQ(nidx);
382 
383   for ( i=0; i<is_max; i++ ) {
384     /* Initialize the two local arrays */
385     isz  = 0;
386     PetscMemzero(table,(m/BITSPERBYTE +1)*sizeof(char));
387 
388     /* Extract the indices, assume there can be duplicate entries */
389     ierr = ISGetIndices(is[i],&idx);  CHKERRQ(ierr);
390     ierr = ISGetSize(is[i],&n);  CHKERRQ(ierr);
391 
392     /* Enter these into the temp arrays. I.e., mark table[row], enter row into new index */
393     for ( j=0; j<n ; ++j){
394       if(!BT_LOOKUP(table, idx[j])) { nidx[isz++] = idx[j];}
395     }
396     ierr = ISRestoreIndices(is[i],&idx);  CHKERRQ(ierr);
397     ierr = ISDestroy(is[i]); CHKERRQ(ierr);
398 
399     k = 0;
400     for ( j=0; j<ov; j++){ /* for each overlap */
401       n = isz;
402       for ( ; k<n ; k++){ /* do only those rows in nidx[k], which are not done yet */
403         row   = nidx[k];
404         start = ai[row];
405         end   = ai[row+1];
406         for ( l = start; l<end ; l++){
407           val = aj[l];
408           if (!BT_LOOKUP(table,val)) {nidx[isz++] = val;}
409         }
410       }
411     }
412     ierr = ISCreateGeneral(PETSC_COMM_SELF, isz, nidx, (is+i)); CHKERRQ(ierr);
413   }
414   PetscFree(table);
415   PetscFree(nidx);
416   return 0;
417 }
418 
419 #undef __FUNC__
420 #define __FUNC__ "MatEqual_SeqAdj"
421 int MatEqual_SeqAdj(Mat A,Mat B, PetscTruth* flg)
422 {
423   Mat_SeqAdj *a = (Mat_SeqAdj *)A->data, *b = (Mat_SeqAdj *)B->data;
424 
425   if (B->type != MATSEQADJ) SETERRQ(1,0,"Matrices must be same type");
426 
427   /* If the  matrix dimensions are not equal, or no of nonzeros */
428   if ((a->m != b->m ) || (a->n !=b->n) ||( a->nz != b->nz)) {
429     *flg = PETSC_FALSE; return 0;
430   }
431 
432   /* if the a->i are the same */
433   if (PetscMemcmp(a->i,b->i,(a->m+1)*sizeof(int))) {
434     *flg = PETSC_FALSE; return 0;
435   }
436 
437   /* if a->j are the same */
438   if (PetscMemcmp(a->j, b->j, (a->nz)*sizeof(int))) {
439     *flg = PETSC_FALSE; return 0;
440   }
441 
442   *flg = PETSC_TRUE;
443   return 0;
444 }
445 
446 #undef __FUNC__
447 #define __FUNC__ "MatPermute_SeqAdj"
448 int MatPermute_SeqAdj(Mat A, IS rowp, IS colp, Mat *B)
449 {
450   Mat_SeqAdj *a = (Mat_SeqAdj *) A->data;
451   Scalar     *vwork;
452   int        i, ierr, nz = a->nz, m = a->m, n = a->n, *cwork,*ii,*jj;
453   int        *row,*col,j,*lens;
454   IS         icolp,irowp;
455 
456   ierr = ISInvertPermutation(rowp,&irowp); CHKERRQ(ierr);
457   ierr = ISGetIndices(irowp,&row); CHKERRQ(ierr);
458   ierr = ISInvertPermutation(colp,&icolp); CHKERRQ(ierr);
459   ierr = ISGetIndices(icolp,&col); CHKERRQ(ierr);
460 
461   /* determine lengths of permuted rows */
462   lens = (int *) PetscMalloc( (m+1)*sizeof(int) ); CHKPTRQ(lens);
463   for (i=0; i<m; i++ ) {
464     lens[row[i]] = a->i[i+1] - a->i[i];
465   }
466 
467   ii = (int *) PetscMalloc((m+1)*sizeof(int));CHKPTRQ(ii);
468   jj = (int *) PetscMalloc((nz+1)*sizeof(int));CHKPTRQ(jj);
469   ii[0] = 0;
470   for (i=1; i<=m; i++ ) {
471     ii[i] = ii[i-1] + lens[i-1];
472   }
473   PetscFree(lens);
474 
475   for (i=0; i<m; i++) {
476     ierr = MatGetRow(A,i,&nz,&cwork,&vwork); CHKERRQ(ierr);
477     for (j=0; j<nz; j++ ) { jj[j+ii[row[i]]] = col[cwork[j]];}
478     ierr = MatRestoreRow(A,i,&nz,&cwork,&vwork); CHKERRQ(ierr);
479   }
480 
481   ierr = MatCreateSeqAdj(A->comm,m,n,ii,jj,B);CHKERRQ(ierr);
482 
483   ierr = ISRestoreIndices(irowp,&row); CHKERRQ(ierr);
484   ierr = ISRestoreIndices(icolp,&col); CHKERRQ(ierr);
485   ierr = ISDestroy(irowp); CHKERRQ(ierr);
486   ierr = ISDestroy(icolp); CHKERRQ(ierr);
487   return 0;
488 }
489 
490 /* -------------------------------------------------------------------*/
491 static struct _MatOps MatOps = {0,
492        MatGetRow_SeqAdj,MatRestoreRow_SeqAdj,
493        0,0,
494        0,0,
495        0,0,
496        0,0,
497        0,0,
498        0,
499        0,
500        MatGetInfo_SeqAdj,MatEqual_SeqAdj,
501        0,0,0,
502        0,0,
503        0,
504        MatSetOption_SeqAdj,0,0,
505        0,0,0,0,
506        MatGetSize_SeqAdj,MatGetSize_SeqAdj,MatGetOwnershipRange_SeqAdj,
507        0,0,
508        0,0,
509        0,0,0,
510        0,0,0,
511        0,MatIncreaseOverlap_SeqAdj,
512        0,0,
513        0,
514        0,0,0,
515        0,
516        MatGetBlockSize_SeqAdj,
517        MatGetRowIJ_SeqAdj,
518        MatRestoreRowIJ_SeqAdj,
519        0,
520        0,
521        0,
522        0,
523        0,
524        MatPermute_SeqAdj};
525 
526 
527 #undef __FUNC__
528 #define __FUNC__ "MatCreateSeqAdj"
529 /*@C
530    MatCreateSeqAdj - Creates a sparse matrix representing an adjacency list.
531      The matrix does not have numerical values associated with it, but is
532      intended for ordering (to reduce bandwidth etc) and partitioning.
533 
534    Input Parameters:
535 .  comm - MPI communicator, set to PETSC_COMM_SELF
536 .  m - number of rows
537 .  n - number of columns
538 .  i - the indices into j for the start of each row
539 .  j - the column indices for each row (sorted for each row)
540        The indices in i and j start with zero NOT one.
541 
542    Output Parameter:
543 .  A - the matrix
544 
545    Notes: You must free the ii and jj arrays yourself. PETSc will free them
546    when the matrix is destroyed.
547 
548 .  MatSetOptions() possible values - MAT_STRUCTURALLY_SYMMETRIC
549 
550 .seealso: MatCreate(), MatCreateMPIADJ(), MatGetReordering()
551 @*/
552 int MatCreateSeqAdj(MPI_Comm comm,int m,int n,int *i,int *j, Mat *A)
553 {
554   Mat        B;
555   Mat_SeqAdj *b;
556   int        ierr, flg,size;
557 
558   MPI_Comm_size(comm,&size);
559   if (size > 1) SETERRQ(1,0,"Comm must be of size 1");
560 
561   *A                  = 0;
562   PetscHeaderCreate(B,_p_Mat,MAT_COOKIE,MATSEQADJ,comm,MatDestroy,MatView);
563   PLogObjectCreate(B);
564   B->data             = (void *) (b = PetscNew(Mat_SeqAdj)); CHKPTRQ(b);
565   PetscMemzero(b,sizeof(Mat_SeqAdj));
566   PetscMemcpy(&B->ops,&MatOps,sizeof(struct _MatOps));
567   B->destroy          = MatDestroy_SeqAdj;
568   B->view             = MatView_SeqAdj;
569   B->factor           = 0;
570   B->lupivotthreshold = 1.0;
571   B->mapping          = 0;
572   B->assembled        = PETSC_FALSE;
573 
574   b->m = m; B->m = m; B->M = m;
575   b->n = n; B->n = n; B->N = n;
576 
577   b->j  = j;
578   b->i  = i;
579 
580   b->nz               = i[m];
581   b->diag             = 0;
582   b->symmetric        = PETSC_FALSE;
583 
584   *A = B;
585 
586   ierr = OptionsHasName(PETSC_NULL,"-help", &flg); CHKERRQ(ierr);
587   if (flg) {ierr = MatPrintHelp(B); CHKERRQ(ierr); }
588   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
589   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
590   return 0;
591 }
592 
593 #undef __FUNC__
594 #define __FUNC__ "MatLoad_SeqAdj"
595 int MatLoad_SeqAdj(Viewer viewer,MatType type,Mat *A)
596 {
597   int          i, nz, ierr, fd, header[4],size,*rowlengths = 0,M,N,*ii,*jj;
598   MPI_Comm     comm;
599 
600   PetscObjectGetComm((PetscObject) viewer,&comm);
601   MPI_Comm_size(comm,&size);
602   if (size > 1) SETERRQ(1,0,"view must have one processor");
603   ierr = ViewerBinaryGetDescriptor(viewer,&fd); CHKERRQ(ierr);
604   ierr = PetscBinaryRead(fd,header,4,BINARY_INT); CHKERRQ(ierr);
605   if (header[0] != MAT_COOKIE) SETERRQ(1,0,"not matrix object in file");
606   M = header[1]; N = header[2]; nz = header[3];
607 
608   /* read in row lengths */
609   rowlengths = (int*) PetscMalloc( M*sizeof(int) ); CHKPTRQ(rowlengths);
610   ierr = PetscBinaryRead(fd,rowlengths,M,BINARY_INT); CHKERRQ(ierr);
611 
612   /* create our matrix */
613   ii = (int *) PetscMalloc( (M+1)*sizeof(int) );CHKPTRQ(ii);
614   jj = (int *) PetscMalloc( (nz+1)*sizeof(int) ); CHKPTRQ(jj);
615 
616   /* read in column indices and adjust for Fortran indexing*/
617   ierr = PetscBinaryRead(fd,jj,nz,BINARY_INT); CHKERRQ(ierr);
618 
619   /* set matrix "i" values */
620   ii[0] = 0;
621   for ( i=1; i<= M; i++ ) {
622     ii[i]      = ii[i-1] + rowlengths[i-1];
623   }
624   PetscFree(rowlengths);
625 
626   ierr = MatCreateSeqAdj(comm,M,N,ii,jj,A); CHKERRQ(ierr);
627   return 0;
628 }
629 
630 
631