xref: /petsc/src/mat/impls/baij/seq/baij.c (revision 5ef9f2a5cf905ed65136deff0c9e7fca368161b7)
1a5eb4965SSatish Balay #ifdef PETSC_RCS_HEADER
2*5ef9f2a5SBarry Smith static char vcid[] = "$Id: baij.c,v 1.155 1999/01/19 18:44:51 bsmith Exp bsmith $";
32593348eSBarry Smith #endif
42593348eSBarry Smith 
52593348eSBarry Smith /*
6b6490206SBarry Smith     Defines the basic matrix operations for the BAIJ (compressed row)
72593348eSBarry Smith   matrix storage format.
82593348eSBarry Smith */
93369ce9aSBarry Smith #include "sys.h"
1070f55243SBarry Smith #include "src/mat/impls/baij/seq/baij.h"
111a6a6d98SBarry Smith #include "src/vec/vecimpl.h"
121a6a6d98SBarry Smith #include "src/inline/spops.h"
133b547af2SSatish Balay 
142d61bbb3SSatish Balay #define CHUNKSIZE  10
15de6a44a3SBarry Smith 
16be5855fcSBarry Smith /*
17be5855fcSBarry Smith      Checks for missing diagonals
18be5855fcSBarry Smith */
19be5855fcSBarry Smith #undef __FUNC__
20be5855fcSBarry Smith #define __FUNC__ "MatMissingDiag_SeqBAIJ"
21be5855fcSBarry Smith int MatMissingDiag_SeqBAIJ(Mat A)
22be5855fcSBarry Smith {
23be5855fcSBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
24be5855fcSBarry Smith   int         *diag = a->diag, *jj = a->j,i;
25be5855fcSBarry Smith 
26be5855fcSBarry Smith   PetscFunctionBegin;
270e8e8aceSBarry Smith   for ( i=0; i<a->mbs; i++ ) {
28be5855fcSBarry Smith     if (jj[diag[i]] != i) {
29be5855fcSBarry Smith       SETERRQ1(1,1,"Matrix is missing diagonal number %d",i);
30be5855fcSBarry Smith     }
31be5855fcSBarry Smith   }
32be5855fcSBarry Smith   PetscFunctionReturn(0);
33be5855fcSBarry Smith }
34be5855fcSBarry Smith 
355615d1e5SSatish Balay #undef __FUNC__
365615d1e5SSatish Balay #define __FUNC__ "MatMarkDiag_SeqBAIJ"
37de6a44a3SBarry Smith int MatMarkDiag_SeqBAIJ(Mat A)
38de6a44a3SBarry Smith {
39de6a44a3SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
407fc0212eSBarry Smith   int         i,j, *diag, m = a->mbs;
41de6a44a3SBarry Smith 
423a40ed3dSBarry Smith   PetscFunctionBegin;
43de6a44a3SBarry Smith   diag = (int *) PetscMalloc( (m+1)*sizeof(int)); CHKPTRQ(diag);
44de6a44a3SBarry Smith   PLogObjectMemory(A,(m+1)*sizeof(int));
457fc0212eSBarry Smith   for ( i=0; i<m; i++ ) {
46ecc615b2SBarry Smith     diag[i] = a->i[i+1];
47de6a44a3SBarry Smith     for ( j=a->i[i]; j<a->i[i+1]; j++ ) {
48de6a44a3SBarry Smith       if (a->j[j] == i) {
49de6a44a3SBarry Smith         diag[i] = j;
50de6a44a3SBarry Smith         break;
51de6a44a3SBarry Smith       }
52de6a44a3SBarry Smith     }
53de6a44a3SBarry Smith   }
54de6a44a3SBarry Smith   a->diag = diag;
553a40ed3dSBarry Smith   PetscFunctionReturn(0);
56de6a44a3SBarry Smith }
572593348eSBarry Smith 
582593348eSBarry Smith 
593b2fbd54SBarry Smith extern int MatToSymmetricIJ_SeqAIJ(int,int*,int*,int,int,int**,int**);
603b2fbd54SBarry Smith 
615615d1e5SSatish Balay #undef __FUNC__
625615d1e5SSatish Balay #define __FUNC__ "MatGetRowIJ_SeqBAIJ"
633b2fbd54SBarry Smith static int MatGetRowIJ_SeqBAIJ(Mat A,int oshift,PetscTruth symmetric,int *nn,int **ia,int **ja,
643b2fbd54SBarry Smith                             PetscTruth *done)
653b2fbd54SBarry Smith {
663b2fbd54SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
673b2fbd54SBarry Smith   int         ierr, n = a->mbs,i;
683b2fbd54SBarry Smith 
693a40ed3dSBarry Smith   PetscFunctionBegin;
703b2fbd54SBarry Smith   *nn = n;
713a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
723b2fbd54SBarry Smith   if (symmetric) {
733b2fbd54SBarry Smith     ierr = MatToSymmetricIJ_SeqAIJ(n,a->i,a->j,0,oshift,ia,ja);CHKERRQ(ierr);
743b2fbd54SBarry Smith   } else if (oshift == 1) {
753b2fbd54SBarry Smith     /* temporarily add 1 to i and j indices */
763b2fbd54SBarry Smith     int nz = a->i[n] + 1;
773b2fbd54SBarry Smith     for ( i=0; i<nz; i++ ) a->j[i]++;
783b2fbd54SBarry Smith     for ( i=0; i<n+1; i++ ) a->i[i]++;
793b2fbd54SBarry Smith     *ia = a->i; *ja = a->j;
803b2fbd54SBarry Smith   } else {
813b2fbd54SBarry Smith     *ia = a->i; *ja = a->j;
823b2fbd54SBarry Smith   }
833b2fbd54SBarry Smith 
843a40ed3dSBarry Smith   PetscFunctionReturn(0);
853b2fbd54SBarry Smith }
863b2fbd54SBarry Smith 
875615d1e5SSatish Balay #undef __FUNC__
88d4bb536fSBarry Smith #define __FUNC__ "MatRestoreRowIJ_SeqBAIJ"
893b2fbd54SBarry Smith static int MatRestoreRowIJ_SeqBAIJ(Mat A,int oshift,PetscTruth symmetric,int *nn,int **ia,int **ja,
903b2fbd54SBarry Smith                                 PetscTruth *done)
913b2fbd54SBarry Smith {
923b2fbd54SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
933b2fbd54SBarry Smith   int         i,n = a->mbs;
943b2fbd54SBarry Smith 
953a40ed3dSBarry Smith   PetscFunctionBegin;
963a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
973b2fbd54SBarry Smith   if (symmetric) {
983b2fbd54SBarry Smith     PetscFree(*ia);
993b2fbd54SBarry Smith     PetscFree(*ja);
100af5da2bfSBarry Smith   } else if (oshift == 1) {
1013b2fbd54SBarry Smith     int nz = a->i[n];
1023b2fbd54SBarry Smith     for ( i=0; i<nz; i++ ) a->j[i]--;
1033b2fbd54SBarry Smith     for ( i=0; i<n+1; i++ ) a->i[i]--;
1043b2fbd54SBarry Smith   }
1053a40ed3dSBarry Smith   PetscFunctionReturn(0);
1063b2fbd54SBarry Smith }
1073b2fbd54SBarry Smith 
1082d61bbb3SSatish Balay #undef __FUNC__
1092d61bbb3SSatish Balay #define __FUNC__ "MatGetBlockSize_SeqBAIJ"
1102d61bbb3SSatish Balay int MatGetBlockSize_SeqBAIJ(Mat mat, int *bs)
1112d61bbb3SSatish Balay {
1122d61bbb3SSatish Balay   Mat_SeqBAIJ *baij = (Mat_SeqBAIJ *) mat->data;
1132d61bbb3SSatish Balay 
1142d61bbb3SSatish Balay   PetscFunctionBegin;
1152d61bbb3SSatish Balay   *bs = baij->bs;
1162d61bbb3SSatish Balay   PetscFunctionReturn(0);
1172d61bbb3SSatish Balay }
1182d61bbb3SSatish Balay 
1192d61bbb3SSatish Balay 
1202d61bbb3SSatish Balay #undef __FUNC__
1212d61bbb3SSatish Balay #define __FUNC__ "MatDestroy_SeqBAIJ"
122e1311b90SBarry Smith int MatDestroy_SeqBAIJ(Mat A)
1232d61bbb3SSatish Balay {
1242d61bbb3SSatish Balay   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
125e51c0b9cSSatish Balay   int         ierr;
1262d61bbb3SSatish Balay 
12794d884c6SBarry Smith   if (--A->refct > 0) PetscFunctionReturn(0);
12894d884c6SBarry Smith 
12994d884c6SBarry Smith   if (A->mapping) {
13094d884c6SBarry Smith     ierr = ISLocalToGlobalMappingDestroy(A->mapping); CHKERRQ(ierr);
13194d884c6SBarry Smith   }
13294d884c6SBarry Smith   if (A->bmapping) {
13394d884c6SBarry Smith     ierr = ISLocalToGlobalMappingDestroy(A->bmapping); CHKERRQ(ierr);
13494d884c6SBarry Smith   }
13561b13de0SBarry Smith   if (A->rmap) {
13661b13de0SBarry Smith     ierr = MapDestroy(A->rmap);CHKERRQ(ierr);
13761b13de0SBarry Smith   }
13861b13de0SBarry Smith   if (A->cmap) {
13961b13de0SBarry Smith     ierr = MapDestroy(A->cmap);CHKERRQ(ierr);
14061b13de0SBarry Smith   }
1412d61bbb3SSatish Balay #if defined(USE_PETSC_LOG)
142e1311b90SBarry Smith   PLogObjectState((PetscObject) A,"Rows=%d, Cols=%d, NZ=%d",a->m,a->n,a->nz);
1432d61bbb3SSatish Balay #endif
1442d61bbb3SSatish Balay   PetscFree(a->a);
1452d61bbb3SSatish Balay   if (!a->singlemalloc) { PetscFree(a->i); PetscFree(a->j);}
1462d61bbb3SSatish Balay   if (a->diag) PetscFree(a->diag);
1472d61bbb3SSatish Balay   if (a->ilen) PetscFree(a->ilen);
1482d61bbb3SSatish Balay   if (a->imax) PetscFree(a->imax);
1492d61bbb3SSatish Balay   if (a->solve_work) PetscFree(a->solve_work);
1502d61bbb3SSatish Balay   if (a->mult_work) PetscFree(a->mult_work);
151e51c0b9cSSatish Balay   if (a->icol) {ierr = ISDestroy(a->icol);CHKERRQ(ierr);}
1522d61bbb3SSatish Balay   PetscFree(a);
1532d61bbb3SSatish Balay   PLogObjectDestroy(A);
1542d61bbb3SSatish Balay   PetscHeaderDestroy(A);
1552d61bbb3SSatish Balay   PetscFunctionReturn(0);
1562d61bbb3SSatish Balay }
1572d61bbb3SSatish Balay 
1582d61bbb3SSatish Balay #undef __FUNC__
1592d61bbb3SSatish Balay #define __FUNC__ "MatSetOption_SeqBAIJ"
1602d61bbb3SSatish Balay int MatSetOption_SeqBAIJ(Mat A,MatOption op)
1612d61bbb3SSatish Balay {
1622d61bbb3SSatish Balay   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
1632d61bbb3SSatish Balay 
1642d61bbb3SSatish Balay   PetscFunctionBegin;
1652d61bbb3SSatish Balay   if      (op == MAT_ROW_ORIENTED)                 a->roworiented = 1;
1662d61bbb3SSatish Balay   else if (op == MAT_COLUMN_ORIENTED)              a->roworiented = 0;
1672d61bbb3SSatish Balay   else if (op == MAT_COLUMNS_SORTED)               a->sorted      = 1;
1682d61bbb3SSatish Balay   else if (op == MAT_COLUMNS_UNSORTED)             a->sorted      = 0;
1692d61bbb3SSatish Balay   else if (op == MAT_NO_NEW_NONZERO_LOCATIONS)     a->nonew       = 1;
1702d61bbb3SSatish Balay   else if (op == MAT_NEW_NONZERO_LOCATION_ERROR)   a->nonew       = -1;
1712d61bbb3SSatish Balay   else if (op == MAT_NEW_NONZERO_ALLOCATION_ERROR) a->nonew       = -2;
1722d61bbb3SSatish Balay   else if (op == MAT_YES_NEW_NONZERO_LOCATIONS)    a->nonew       = 0;
1732d61bbb3SSatish Balay   else if (op == MAT_ROWS_SORTED ||
1742d61bbb3SSatish Balay            op == MAT_ROWS_UNSORTED ||
1752d61bbb3SSatish Balay            op == MAT_SYMMETRIC ||
1762d61bbb3SSatish Balay            op == MAT_STRUCTURALLY_SYMMETRIC ||
1772d61bbb3SSatish Balay            op == MAT_YES_NEW_DIAGONALS ||
178b51ba29fSSatish Balay            op == MAT_IGNORE_OFF_PROC_ENTRIES ||
179b51ba29fSSatish Balay            op == MAT_USE_HASH_TABLE) {
180981c4779SBarry Smith     PLogInfo(A,"MatSetOption_SeqBAIJ:Option ignored\n");
1812d61bbb3SSatish Balay   } else if (op == MAT_NO_NEW_DIAGONALS) {
1822d61bbb3SSatish Balay     SETERRQ(PETSC_ERR_SUP,0,"MAT_NO_NEW_DIAGONALS");
1832d61bbb3SSatish Balay   } else {
1842d61bbb3SSatish Balay     SETERRQ(PETSC_ERR_SUP,0,"unknown option");
1852d61bbb3SSatish Balay   }
1862d61bbb3SSatish Balay   PetscFunctionReturn(0);
1872d61bbb3SSatish Balay }
1882d61bbb3SSatish Balay 
1892d61bbb3SSatish Balay 
1902d61bbb3SSatish Balay #undef __FUNC__
1912d61bbb3SSatish Balay #define __FUNC__ "MatGetSize_SeqBAIJ"
1922d61bbb3SSatish Balay int MatGetSize_SeqBAIJ(Mat A,int *m,int *n)
1932d61bbb3SSatish Balay {
1942d61bbb3SSatish Balay   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
1952d61bbb3SSatish Balay 
1962d61bbb3SSatish Balay   PetscFunctionBegin;
1972d61bbb3SSatish Balay   if (m) *m = a->m;
1982d61bbb3SSatish Balay   if (n) *n = a->n;
1992d61bbb3SSatish Balay   PetscFunctionReturn(0);
2002d61bbb3SSatish Balay }
2012d61bbb3SSatish Balay 
2022d61bbb3SSatish Balay #undef __FUNC__
2032d61bbb3SSatish Balay #define __FUNC__ "MatGetOwnershipRange_SeqBAIJ"
2042d61bbb3SSatish Balay int MatGetOwnershipRange_SeqBAIJ(Mat A,int *m,int *n)
2052d61bbb3SSatish Balay {
2062d61bbb3SSatish Balay   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
2072d61bbb3SSatish Balay 
2082d61bbb3SSatish Balay   PetscFunctionBegin;
2092d61bbb3SSatish Balay   *m = 0; *n = a->m;
2102d61bbb3SSatish Balay   PetscFunctionReturn(0);
2112d61bbb3SSatish Balay }
2122d61bbb3SSatish Balay 
2132d61bbb3SSatish Balay #undef __FUNC__
2142d61bbb3SSatish Balay #define __FUNC__ "MatGetRow_SeqBAIJ"
2152d61bbb3SSatish Balay int MatGetRow_SeqBAIJ(Mat A,int row,int *nz,int **idx,Scalar **v)
2162d61bbb3SSatish Balay {
2172d61bbb3SSatish Balay   Mat_SeqBAIJ  *a = (Mat_SeqBAIJ *) A->data;
2182d61bbb3SSatish Balay   int          itmp,i,j,k,M,*ai,*aj,bs,bn,bp,*idx_i,bs2;
2193f1db9ecSBarry Smith   MatScalar    *aa,*aa_i;
2203f1db9ecSBarry Smith   Scalar       *v_i;
2212d61bbb3SSatish Balay 
2222d61bbb3SSatish Balay   PetscFunctionBegin;
2232d61bbb3SSatish Balay   bs  = a->bs;
2242d61bbb3SSatish Balay   ai  = a->i;
2252d61bbb3SSatish Balay   aj  = a->j;
2262d61bbb3SSatish Balay   aa  = a->a;
2272d61bbb3SSatish Balay   bs2 = a->bs2;
2282d61bbb3SSatish Balay 
2292d61bbb3SSatish Balay   if (row < 0 || row >= a->m) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Row out of range");
2302d61bbb3SSatish Balay 
2312d61bbb3SSatish Balay   bn  = row/bs;   /* Block number */
2322d61bbb3SSatish Balay   bp  = row % bs; /* Block Position */
2332d61bbb3SSatish Balay   M   = ai[bn+1] - ai[bn];
2342d61bbb3SSatish Balay   *nz = bs*M;
2352d61bbb3SSatish Balay 
2362d61bbb3SSatish Balay   if (v) {
2372d61bbb3SSatish Balay     *v = 0;
2382d61bbb3SSatish Balay     if (*nz) {
2392d61bbb3SSatish Balay       *v = (Scalar *) PetscMalloc( (*nz)*sizeof(Scalar) ); CHKPTRQ(*v);
2402d61bbb3SSatish Balay       for ( i=0; i<M; i++ ) { /* for each block in the block row */
2412d61bbb3SSatish Balay         v_i  = *v + i*bs;
2422d61bbb3SSatish Balay         aa_i = aa + bs2*(ai[bn] + i);
2432d61bbb3SSatish Balay         for ( j=bp,k=0; j<bs2; j+=bs,k++ ) {v_i[k] = aa_i[j];}
2442d61bbb3SSatish Balay       }
2452d61bbb3SSatish Balay     }
2462d61bbb3SSatish Balay   }
2472d61bbb3SSatish Balay 
2482d61bbb3SSatish Balay   if (idx) {
2492d61bbb3SSatish Balay     *idx = 0;
2502d61bbb3SSatish Balay     if (*nz) {
2512d61bbb3SSatish Balay       *idx = (int *) PetscMalloc( (*nz)*sizeof(int) ); CHKPTRQ(*idx);
2522d61bbb3SSatish Balay       for ( i=0; i<M; i++ ) { /* for each block in the block row */
2532d61bbb3SSatish Balay         idx_i = *idx + i*bs;
2542d61bbb3SSatish Balay         itmp  = bs*aj[ai[bn] + i];
2552d61bbb3SSatish Balay         for ( j=0; j<bs; j++ ) {idx_i[j] = itmp++;}
2562d61bbb3SSatish Balay       }
2572d61bbb3SSatish Balay     }
2582d61bbb3SSatish Balay   }
2592d61bbb3SSatish Balay   PetscFunctionReturn(0);
2602d61bbb3SSatish Balay }
2612d61bbb3SSatish Balay 
2622d61bbb3SSatish Balay #undef __FUNC__
2632d61bbb3SSatish Balay #define __FUNC__ "MatRestoreRow_SeqBAIJ"
2642d61bbb3SSatish Balay int MatRestoreRow_SeqBAIJ(Mat A,int row,int *nz,int **idx,Scalar **v)
2652d61bbb3SSatish Balay {
2662d61bbb3SSatish Balay   PetscFunctionBegin;
2672d61bbb3SSatish Balay   if (idx) {if (*idx) PetscFree(*idx);}
2682d61bbb3SSatish Balay   if (v)   {if (*v)   PetscFree(*v);}
2692d61bbb3SSatish Balay   PetscFunctionReturn(0);
2702d61bbb3SSatish Balay }
2712d61bbb3SSatish Balay 
2722d61bbb3SSatish Balay #undef __FUNC__
2732d61bbb3SSatish Balay #define __FUNC__ "MatTranspose_SeqBAIJ"
2742d61bbb3SSatish Balay int MatTranspose_SeqBAIJ(Mat A,Mat *B)
2752d61bbb3SSatish Balay {
2762d61bbb3SSatish Balay   Mat_SeqBAIJ *a=(Mat_SeqBAIJ *)A->data;
2772d61bbb3SSatish Balay   Mat         C;
2782d61bbb3SSatish Balay   int         i,j,k,ierr,*aj=a->j,*ai=a->i,bs=a->bs,mbs=a->mbs,nbs=a->nbs,len,*col;
2792d61bbb3SSatish Balay   int         *rows,*cols,bs2=a->bs2;
2803f1db9ecSBarry Smith   MatScalar   *array = a->a;
2812d61bbb3SSatish Balay 
2822d61bbb3SSatish Balay   PetscFunctionBegin;
2832d61bbb3SSatish Balay   if (B==PETSC_NULL && mbs!=nbs) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Square matrix only for in-place");
2842d61bbb3SSatish Balay   col = (int *) PetscMalloc((1+nbs)*sizeof(int)); CHKPTRQ(col);
2852d61bbb3SSatish Balay   PetscMemzero(col,(1+nbs)*sizeof(int));
2862d61bbb3SSatish Balay 
2872d61bbb3SSatish Balay   for ( i=0; i<ai[mbs]; i++ ) col[aj[i]] += 1;
2882d61bbb3SSatish Balay   ierr = MatCreateSeqBAIJ(A->comm,bs,a->n,a->m,PETSC_NULL,col,&C); CHKERRQ(ierr);
2892d61bbb3SSatish Balay   PetscFree(col);
2902d61bbb3SSatish Balay   rows = (int *) PetscMalloc(2*bs*sizeof(int)); CHKPTRQ(rows);
2912d61bbb3SSatish Balay   cols = rows + bs;
2922d61bbb3SSatish Balay   for ( i=0; i<mbs; i++ ) {
2932d61bbb3SSatish Balay     cols[0] = i*bs;
2942d61bbb3SSatish Balay     for (k=1; k<bs; k++ ) cols[k] = cols[k-1] + 1;
2952d61bbb3SSatish Balay     len = ai[i+1] - ai[i];
2962d61bbb3SSatish Balay     for ( j=0; j<len; j++ ) {
2972d61bbb3SSatish Balay       rows[0] = (*aj++)*bs;
2982d61bbb3SSatish Balay       for (k=1; k<bs; k++ ) rows[k] = rows[k-1] + 1;
2992d61bbb3SSatish Balay       ierr = MatSetValues(C,bs,rows,bs,cols,array,INSERT_VALUES); CHKERRQ(ierr);
3002d61bbb3SSatish Balay       array += bs2;
3012d61bbb3SSatish Balay     }
3022d61bbb3SSatish Balay   }
3032d61bbb3SSatish Balay   PetscFree(rows);
3042d61bbb3SSatish Balay 
3052d61bbb3SSatish Balay   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
3062d61bbb3SSatish Balay   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
3072d61bbb3SSatish Balay 
3082d61bbb3SSatish Balay   if (B != PETSC_NULL) {
3092d61bbb3SSatish Balay     *B = C;
3102d61bbb3SSatish Balay   } else {
311f830108cSBarry Smith     PetscOps *Abops;
312cc2dc46cSBarry Smith     MatOps   Aops;
313f830108cSBarry Smith 
3142d61bbb3SSatish Balay     /* This isn't really an in-place transpose */
3152d61bbb3SSatish Balay     PetscFree(a->a);
3162d61bbb3SSatish Balay     if (!a->singlemalloc) {PetscFree(a->i); PetscFree(a->j);}
3172d61bbb3SSatish Balay     if (a->diag) PetscFree(a->diag);
3182d61bbb3SSatish Balay     if (a->ilen) PetscFree(a->ilen);
3192d61bbb3SSatish Balay     if (a->imax) PetscFree(a->imax);
3202d61bbb3SSatish Balay     if (a->solve_work) PetscFree(a->solve_work);
3212d61bbb3SSatish Balay     PetscFree(a);
322f830108cSBarry Smith 
3237413bad6SBarry Smith 
3247413bad6SBarry Smith     ierr = MapDestroy(A->rmap);CHKERRQ(ierr);
3257413bad6SBarry Smith     ierr = MapDestroy(A->cmap);CHKERRQ(ierr);
3267413bad6SBarry Smith 
327f830108cSBarry Smith     /*
328f830108cSBarry Smith        This is horrible, horrible code. We need to keep the
329f830108cSBarry Smith       A pointers for the bops and ops but copy everything
330f830108cSBarry Smith       else from C.
331f830108cSBarry Smith     */
332f830108cSBarry Smith     Abops    = A->bops;
333f830108cSBarry Smith     Aops     = A->ops;
3342d61bbb3SSatish Balay     PetscMemcpy(A,C,sizeof(struct _p_Mat));
335f830108cSBarry Smith     A->bops  = Abops;
336f830108cSBarry Smith     A->ops   = Aops;
33727a8da17SBarry Smith     A->qlist = 0;
338f830108cSBarry Smith 
3392d61bbb3SSatish Balay     PetscHeaderDestroy(C);
3402d61bbb3SSatish Balay   }
3412d61bbb3SSatish Balay   PetscFunctionReturn(0);
3422d61bbb3SSatish Balay }
3432d61bbb3SSatish Balay 
3442d61bbb3SSatish Balay 
3452d61bbb3SSatish Balay 
3463b2fbd54SBarry Smith 
3475615d1e5SSatish Balay #undef __FUNC__
348d4bb536fSBarry Smith #define __FUNC__ "MatView_SeqBAIJ_Binary"
349b6490206SBarry Smith static int MatView_SeqBAIJ_Binary(Mat A,Viewer viewer)
3502593348eSBarry Smith {
351b6490206SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
3529df24120SSatish Balay   int         i, fd, *col_lens, ierr, bs = a->bs,count,*jj,j,k,l,bs2=a->bs2;
353b6490206SBarry Smith   Scalar      *aa;
3542593348eSBarry Smith 
3553a40ed3dSBarry Smith   PetscFunctionBegin;
35690ace30eSBarry Smith   ierr = ViewerBinaryGetDescriptor(viewer,&fd); CHKERRQ(ierr);
3572593348eSBarry Smith   col_lens = (int *) PetscMalloc((4+a->m)*sizeof(int));CHKPTRQ(col_lens);
3582593348eSBarry Smith   col_lens[0] = MAT_COOKIE;
3593b2fbd54SBarry Smith 
3602593348eSBarry Smith   col_lens[1] = a->m;
3612593348eSBarry Smith   col_lens[2] = a->n;
3627e67e3f9SSatish Balay   col_lens[3] = a->nz*bs2;
3632593348eSBarry Smith 
3642593348eSBarry Smith   /* store lengths of each row and write (including header) to file */
365b6490206SBarry Smith   count = 0;
366b6490206SBarry Smith   for ( i=0; i<a->mbs; i++ ) {
367b6490206SBarry Smith     for ( j=0; j<bs; j++ ) {
368b6490206SBarry Smith       col_lens[4+count++] = bs*(a->i[i+1] - a->i[i]);
369b6490206SBarry Smith     }
3702593348eSBarry Smith   }
3710752156aSBarry Smith   ierr = PetscBinaryWrite(fd,col_lens,4+a->m,PETSC_INT,1); CHKERRQ(ierr);
3722593348eSBarry Smith   PetscFree(col_lens);
3732593348eSBarry Smith 
3742593348eSBarry Smith   /* store column indices (zero start index) */
37566963ce1SSatish Balay   jj = (int *) PetscMalloc( (a->nz+1)*bs2*sizeof(int) ); CHKPTRQ(jj);
376b6490206SBarry Smith   count = 0;
377b6490206SBarry Smith   for ( i=0; i<a->mbs; i++ ) {
378b6490206SBarry Smith     for ( j=0; j<bs; j++ ) {
379b6490206SBarry Smith       for ( k=a->i[i]; k<a->i[i+1]; k++ ) {
380b6490206SBarry Smith         for ( l=0; l<bs; l++ ) {
381b6490206SBarry Smith           jj[count++] = bs*a->j[k] + l;
3822593348eSBarry Smith         }
3832593348eSBarry Smith       }
384b6490206SBarry Smith     }
385b6490206SBarry Smith   }
3860752156aSBarry Smith   ierr = PetscBinaryWrite(fd,jj,bs2*a->nz,PETSC_INT,0); CHKERRQ(ierr);
387b6490206SBarry Smith   PetscFree(jj);
3882593348eSBarry Smith 
3892593348eSBarry Smith   /* store nonzero values */
39066963ce1SSatish Balay   aa = (Scalar *) PetscMalloc((a->nz+1)*bs2*sizeof(Scalar)); CHKPTRQ(aa);
391b6490206SBarry Smith   count = 0;
392b6490206SBarry Smith   for ( i=0; i<a->mbs; i++ ) {
393b6490206SBarry Smith     for ( j=0; j<bs; j++ ) {
394b6490206SBarry Smith       for ( k=a->i[i]; k<a->i[i+1]; k++ ) {
395b6490206SBarry Smith         for ( l=0; l<bs; l++ ) {
3967e67e3f9SSatish Balay           aa[count++] = a->a[bs2*k + l*bs + j];
397b6490206SBarry Smith         }
398b6490206SBarry Smith       }
399b6490206SBarry Smith     }
400b6490206SBarry Smith   }
4010752156aSBarry Smith   ierr = PetscBinaryWrite(fd,aa,bs2*a->nz,PETSC_SCALAR,0); CHKERRQ(ierr);
402b6490206SBarry Smith   PetscFree(aa);
4033a40ed3dSBarry Smith   PetscFunctionReturn(0);
4042593348eSBarry Smith }
4052593348eSBarry Smith 
4065615d1e5SSatish Balay #undef __FUNC__
407d4bb536fSBarry Smith #define __FUNC__ "MatView_SeqBAIJ_ASCII"
408b6490206SBarry Smith static int MatView_SeqBAIJ_ASCII(Mat A,Viewer viewer)
4092593348eSBarry Smith {
410b6490206SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
4119df24120SSatish Balay   int         ierr, i,j,format,bs = a->bs,k,l,bs2=a->bs2;
4122593348eSBarry Smith   FILE        *fd;
4132593348eSBarry Smith   char        *outputname;
4142593348eSBarry Smith 
4153a40ed3dSBarry Smith   PetscFunctionBegin;
41690ace30eSBarry Smith   ierr = ViewerASCIIGetPointer(viewer,&fd); CHKERRQ(ierr);
41777ed5343SBarry Smith   ierr = ViewerGetOutputname(viewer,&outputname);CHKERRQ(ierr);
41890ace30eSBarry Smith   ierr = ViewerGetFormat(viewer,&format);
419639f9d9dSBarry Smith   if (format == VIEWER_FORMAT_ASCII_INFO || format == VIEWER_FORMAT_ASCII_INFO_LONG) {
4200ef38995SBarry Smith     ViewerASCIIPrintf(viewer,"  block size is %d\n",bs);
4210ef38995SBarry Smith   } else if (format == VIEWER_FORMAT_ASCII_MATLAB) {
4227b2a1423SBarry Smith     SETERRQ(PETSC_ERR_SUP,0,"Socket format not supported");
4230ef38995SBarry Smith   } else if (format == VIEWER_FORMAT_ASCII_COMMON) {
42444cd7ae7SLois Curfman McInnes     for ( i=0; i<a->mbs; i++ ) {
42544cd7ae7SLois Curfman McInnes       for ( j=0; j<bs; j++ ) {
42644cd7ae7SLois Curfman McInnes         fprintf(fd,"row %d:",i*bs+j);
42744cd7ae7SLois Curfman McInnes         for ( k=a->i[i]; k<a->i[i+1]; k++ ) {
42844cd7ae7SLois Curfman McInnes           for ( l=0; l<bs; l++ ) {
4293a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX)
4300ef38995SBarry Smith             if (PetscImaginary(a->a[bs2*k + l*bs + j]) > 0.0 && PetscReal(a->a[bs2*k + l*bs + j]) != 0.0) {
43144cd7ae7SLois Curfman McInnes               fprintf(fd," %d %g + %g i",bs*a->j[k]+l,
432e20fef11SSatish Balay                       PetscReal(a->a[bs2*k + l*bs + j]),PetscImaginary(a->a[bs2*k + l*bs + j]));
4330ef38995SBarry Smith             } else if (PetscImaginary(a->a[bs2*k + l*bs + j]) < 0.0 && PetscReal(a->a[bs2*k + l*bs + j]) != 0.0) {
434766eeae4SLois Curfman McInnes               fprintf(fd," %d %g - %g i",bs*a->j[k]+l,
435e20fef11SSatish Balay                       PetscReal(a->a[bs2*k + l*bs + j]),-PetscImaginary(a->a[bs2*k + l*bs + j]));
4360ef38995SBarry Smith             } else if (PetscReal(a->a[bs2*k + l*bs + j]) != 0.0) {
437e20fef11SSatish Balay               fprintf(fd," %d %g ",bs*a->j[k]+l,PetscReal(a->a[bs2*k + l*bs + j]));
4380ef38995SBarry Smith             }
43944cd7ae7SLois Curfman McInnes #else
4400ef38995SBarry Smith             if (a->a[bs2*k + l*bs + j] != 0.0) {
44144cd7ae7SLois Curfman McInnes               fprintf(fd," %d %g ",bs*a->j[k]+l,a->a[bs2*k + l*bs + j]);
4420ef38995SBarry Smith             }
44344cd7ae7SLois Curfman McInnes #endif
44444cd7ae7SLois Curfman McInnes           }
44544cd7ae7SLois Curfman McInnes         }
44644cd7ae7SLois Curfman McInnes         fprintf(fd,"\n");
44744cd7ae7SLois Curfman McInnes       }
44844cd7ae7SLois Curfman McInnes     }
4490ef38995SBarry Smith   } else {
450b6490206SBarry Smith     for ( i=0; i<a->mbs; i++ ) {
451b6490206SBarry Smith       for ( j=0; j<bs; j++ ) {
452b6490206SBarry Smith         fprintf(fd,"row %d:",i*bs+j);
453b6490206SBarry Smith         for ( k=a->i[i]; k<a->i[i+1]; k++ ) {
454b6490206SBarry Smith           for ( l=0; l<bs; l++ ) {
4553a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX)
456e20fef11SSatish Balay             if (PetscImaginary(a->a[bs2*k + l*bs + j]) > 0.0) {
45788685aaeSLois Curfman McInnes               fprintf(fd," %d %g + %g i",bs*a->j[k]+l,
458e20fef11SSatish Balay                 PetscReal(a->a[bs2*k + l*bs + j]),PetscImaginary(a->a[bs2*k + l*bs + j]));
4590ef38995SBarry Smith             } else if (PetscImaginary(a->a[bs2*k + l*bs + j]) < 0.0) {
460766eeae4SLois Curfman McInnes               fprintf(fd," %d %g - %g i",bs*a->j[k]+l,
461e20fef11SSatish Balay                 PetscReal(a->a[bs2*k + l*bs + j]),-PetscImaginary(a->a[bs2*k + l*bs + j]));
4620ef38995SBarry Smith             } else {
463e20fef11SSatish Balay               fprintf(fd," %d %g ",bs*a->j[k]+l,PetscReal(a->a[bs2*k + l*bs + j]));
46488685aaeSLois Curfman McInnes             }
46588685aaeSLois Curfman McInnes #else
4667e67e3f9SSatish Balay             fprintf(fd," %d %g ",bs*a->j[k]+l,a->a[bs2*k + l*bs + j]);
46788685aaeSLois Curfman McInnes #endif
4682593348eSBarry Smith           }
4692593348eSBarry Smith         }
4702593348eSBarry Smith         fprintf(fd,"\n");
4712593348eSBarry Smith       }
4722593348eSBarry Smith     }
473b6490206SBarry Smith   }
4742593348eSBarry Smith   fflush(fd);
4753a40ed3dSBarry Smith   PetscFunctionReturn(0);
4762593348eSBarry Smith }
4772593348eSBarry Smith 
4785615d1e5SSatish Balay #undef __FUNC__
47977ed5343SBarry Smith #define __FUNC__ "MatView_SeqBAIJ_Draw_Zoom"
48077ed5343SBarry Smith static int MatView_SeqBAIJ_Draw_Zoom(Draw draw,void *Aa)
4813270192aSSatish Balay {
48277ed5343SBarry Smith   Mat          A = (Mat) Aa;
4833270192aSSatish Balay   Mat_SeqBAIJ  *a=(Mat_SeqBAIJ *) A->data;
4847dce120fSSatish Balay   int          row,ierr,i,j,k,l,mbs=a->mbs,color,bs=a->bs,bs2=a->bs2,rank;
485fae8c767SSatish Balay   double       xl,yl,xr,yr,x_l,x_r,y_l,y_r;
4863f1db9ecSBarry Smith   MatScalar    *aa;
48777ed5343SBarry Smith   MPI_Comm     comm;
48877ed5343SBarry Smith   Viewer       viewer;
4893270192aSSatish Balay 
4903a40ed3dSBarry Smith   PetscFunctionBegin;
49177ed5343SBarry Smith   /*
49277ed5343SBarry Smith       This is nasty. If this is called from an originally parallel matrix
49377ed5343SBarry Smith    then all processes call this, but only the first has the matrix so the
49477ed5343SBarry Smith    rest should return immediately.
49577ed5343SBarry Smith   */
49677ed5343SBarry Smith   ierr = PetscObjectGetComm((PetscObject)draw,&comm);CHKERRQ(ierr);
49777ed5343SBarry Smith   MPI_Comm_rank(comm,&rank);
49877ed5343SBarry Smith   if (rank) PetscFunctionReturn(0);
4993270192aSSatish Balay 
50077ed5343SBarry Smith   ierr = PetscObjectQuery((PetscObject)A,"Zoomviewer",(PetscObject*) &viewer);CHKERRQ(ierr);
50177ed5343SBarry Smith 
50277ed5343SBarry Smith   ierr = DrawGetCoordinates(draw,&xl,&yl,&xr,&yr); CHKERRQ(ierr);
50377ed5343SBarry Smith 
5043270192aSSatish Balay   /* loop over matrix elements drawing boxes */
5053270192aSSatish Balay   color = DRAW_BLUE;
5063270192aSSatish Balay   for ( i=0,row=0; i<mbs; i++,row+=bs ) {
5073270192aSSatish Balay     for ( j=a->i[i]; j<a->i[i+1]; j++ ) {
5083270192aSSatish Balay       y_l = a->m - row - 1.0; y_r = y_l + 1.0;
5093270192aSSatish Balay       x_l = a->j[j]*bs; x_r = x_l + 1.0;
5103270192aSSatish Balay       aa = a->a + j*bs2;
5113270192aSSatish Balay       for ( k=0; k<bs; k++ ) {
5123270192aSSatish Balay         for ( l=0; l<bs; l++ ) {
5133270192aSSatish Balay           if (PetscReal(*aa++) >=  0.) continue;
514b34f160eSSatish Balay           DrawRectangle(draw,x_l+k,y_l-l,x_r+k,y_r-l,color,color,color,color);
5153270192aSSatish Balay         }
5163270192aSSatish Balay       }
5173270192aSSatish Balay     }
5183270192aSSatish Balay   }
5193270192aSSatish Balay   color = DRAW_CYAN;
5203270192aSSatish Balay   for ( i=0,row=0; i<mbs; i++,row+=bs ) {
5213270192aSSatish Balay     for ( j=a->i[i]; j<a->i[i+1]; j++ ) {
5223270192aSSatish Balay       y_l = a->m - row - 1.0; y_r = y_l + 1.0;
5233270192aSSatish Balay       x_l = a->j[j]*bs; x_r = x_l + 1.0;
5243270192aSSatish Balay       aa = a->a + j*bs2;
5253270192aSSatish Balay       for ( k=0; k<bs; k++ ) {
5263270192aSSatish Balay         for ( l=0; l<bs; l++ ) {
5273270192aSSatish Balay           if (PetscReal(*aa++) != 0.) continue;
528b34f160eSSatish Balay           DrawRectangle(draw,x_l+k,y_l-l,x_r+k,y_r-l,color,color,color,color);
5293270192aSSatish Balay         }
5303270192aSSatish Balay       }
5313270192aSSatish Balay     }
5323270192aSSatish Balay   }
5333270192aSSatish Balay 
5343270192aSSatish Balay   color = DRAW_RED;
5353270192aSSatish Balay   for ( i=0,row=0; i<mbs; i++,row+=bs ) {
5363270192aSSatish Balay     for ( j=a->i[i]; j<a->i[i+1]; j++ ) {
5373270192aSSatish Balay       y_l = a->m - row - 1.0; y_r = y_l + 1.0;
5383270192aSSatish Balay       x_l = a->j[j]*bs; x_r = x_l + 1.0;
5393270192aSSatish Balay       aa = a->a + j*bs2;
5403270192aSSatish Balay       for ( k=0; k<bs; k++ ) {
5413270192aSSatish Balay         for ( l=0; l<bs; l++ ) {
5423270192aSSatish Balay           if (PetscReal(*aa++) <= 0.) continue;
543b34f160eSSatish Balay           DrawRectangle(draw,x_l+k,y_l-l,x_r+k,y_r-l,color,color,color,color);
5443270192aSSatish Balay         }
5453270192aSSatish Balay       }
5463270192aSSatish Balay     }
5473270192aSSatish Balay   }
54877ed5343SBarry Smith   PetscFunctionReturn(0);
54977ed5343SBarry Smith }
5503270192aSSatish Balay 
55177ed5343SBarry Smith #undef __FUNC__
55277ed5343SBarry Smith #define __FUNC__ "MatView_SeqBAIJ_Draw"
55377ed5343SBarry Smith static int MatView_SeqBAIJ_Draw(Mat A,Viewer viewer)
55477ed5343SBarry Smith {
55577ed5343SBarry Smith   Mat_SeqBAIJ  *a=(Mat_SeqBAIJ *) A->data;
5567dce120fSSatish Balay   int          ierr;
5577dce120fSSatish Balay   double       xl,yl,xr,yr,w,h;
55877ed5343SBarry Smith   Draw         draw;
55977ed5343SBarry Smith   PetscTruth   isnull;
5603270192aSSatish Balay 
56177ed5343SBarry Smith   PetscFunctionBegin;
56277ed5343SBarry Smith 
56377ed5343SBarry Smith   ierr = ViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
56477ed5343SBarry Smith   ierr = DrawIsNull(draw,&isnull); CHKERRQ(ierr); if (isnull) PetscFunctionReturn(0);
56577ed5343SBarry Smith 
56677ed5343SBarry Smith   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",(PetscObject)viewer);CHKERRQ(ierr);
56777ed5343SBarry Smith   xr  = a->n; yr = a->m; h = yr/10.0; w = xr/10.0;
56877ed5343SBarry Smith   xr += w;    yr += h;  xl = -w;     yl = -h;
5693270192aSSatish Balay   ierr = DrawSetCoordinates(draw,xl,yl,xr,yr); CHKERRQ(ierr);
57077ed5343SBarry Smith   ierr = DrawZoom(draw,MatView_SeqBAIJ_Draw_Zoom,A); CHKERRQ(ierr);
57177ed5343SBarry Smith   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",PETSC_NULL);CHKERRQ(ierr);
5723a40ed3dSBarry Smith   PetscFunctionReturn(0);
5733270192aSSatish Balay }
5743270192aSSatish Balay 
5755615d1e5SSatish Balay #undef __FUNC__
576d4bb536fSBarry Smith #define __FUNC__ "MatView_SeqBAIJ"
577e1311b90SBarry Smith int MatView_SeqBAIJ(Mat A,Viewer viewer)
5782593348eSBarry Smith {
57919bcc07fSBarry Smith   ViewerType  vtype;
58019bcc07fSBarry Smith   int         ierr;
5812593348eSBarry Smith 
5823a40ed3dSBarry Smith   PetscFunctionBegin;
58319bcc07fSBarry Smith   ierr = ViewerGetType(viewer,&vtype); CHKERRQ(ierr);
5847b2a1423SBarry Smith   if (PetscTypeCompare(vtype,SOCKET_VIEWER)) {
5857b2a1423SBarry Smith     SETERRQ(PETSC_ERR_SUP,0,"Socket viewer not supported");
5863f1db9ecSBarry Smith   } else if (PetscTypeCompare(vtype,ASCII_VIEWER)){
5873a40ed3dSBarry Smith     ierr = MatView_SeqBAIJ_ASCII(A,viewer);CHKERRQ(ierr);
5883f1db9ecSBarry Smith   } else if (PetscTypeCompare(vtype,BINARY_VIEWER)) {
5893a40ed3dSBarry Smith     ierr = MatView_SeqBAIJ_Binary(A,viewer);CHKERRQ(ierr);
5903f1db9ecSBarry Smith   } else if (PetscTypeCompare(vtype,DRAW_VIEWER)) {
5913a40ed3dSBarry Smith     ierr = MatView_SeqBAIJ_Draw(A,viewer);CHKERRQ(ierr);
5925cd90555SBarry Smith   } else {
5935cd90555SBarry Smith     SETERRQ(1,1,"Viewer type not supported by PETSc object");
5942593348eSBarry Smith   }
5953a40ed3dSBarry Smith   PetscFunctionReturn(0);
5962593348eSBarry Smith }
597b6490206SBarry Smith 
598cd0e1443SSatish Balay 
5995615d1e5SSatish Balay #undef __FUNC__
6002d61bbb3SSatish Balay #define __FUNC__ "MatGetValues_SeqBAIJ"
6012d61bbb3SSatish Balay int MatGetValues_SeqBAIJ(Mat A,int m,int *im,int n,int *in,Scalar *v)
602cd0e1443SSatish Balay {
603cd0e1443SSatish Balay   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
6042d61bbb3SSatish Balay   int        *rp, k, low, high, t, row, nrow, i, col, l, *aj = a->j;
6052d61bbb3SSatish Balay   int        *ai = a->i, *ailen = a->ilen;
6062d61bbb3SSatish Balay   int        brow,bcol,ridx,cidx,bs=a->bs,bs2=a->bs2;
6073f1db9ecSBarry Smith   MatScalar  *ap, *aa = a->a, zero = 0.0;
608cd0e1443SSatish Balay 
6093a40ed3dSBarry Smith   PetscFunctionBegin;
6102d61bbb3SSatish Balay   for ( k=0; k<m; k++ ) { /* loop over rows */
611cd0e1443SSatish Balay     row  = im[k]; brow = row/bs;
612a8c6a408SBarry Smith     if (row < 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Negative row");
613a8c6a408SBarry Smith     if (row >= a->m) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Row too large");
6142d61bbb3SSatish Balay     rp   = aj + ai[brow] ; ap = aa + bs2*ai[brow] ;
6152c3acbe9SBarry Smith     nrow = ailen[brow];
6162d61bbb3SSatish Balay     for ( l=0; l<n; l++ ) { /* loop over columns */
617a8c6a408SBarry Smith       if (in[l] < 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Negative column");
618a8c6a408SBarry Smith       if (in[l] >= a->n) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Column too large");
6192d61bbb3SSatish Balay       col  = in[l] ;
6202d61bbb3SSatish Balay       bcol = col/bs;
6212d61bbb3SSatish Balay       cidx = col%bs;
6222d61bbb3SSatish Balay       ridx = row%bs;
6232d61bbb3SSatish Balay       high = nrow;
6242d61bbb3SSatish Balay       low  = 0; /* assume unsorted */
6252d61bbb3SSatish Balay       while (high-low > 5) {
626cd0e1443SSatish Balay         t = (low+high)/2;
627cd0e1443SSatish Balay         if (rp[t] > bcol) high = t;
628cd0e1443SSatish Balay         else             low  = t;
629cd0e1443SSatish Balay       }
630cd0e1443SSatish Balay       for ( i=low; i<high; i++ ) {
631cd0e1443SSatish Balay         if (rp[i] > bcol) break;
632cd0e1443SSatish Balay         if (rp[i] == bcol) {
6332d61bbb3SSatish Balay           *v++ = ap[bs2*i+bs*cidx+ridx];
6342d61bbb3SSatish Balay           goto finished;
635cd0e1443SSatish Balay         }
636cd0e1443SSatish Balay       }
6372d61bbb3SSatish Balay       *v++ = zero;
6382d61bbb3SSatish Balay       finished:;
639cd0e1443SSatish Balay     }
640cd0e1443SSatish Balay   }
6413a40ed3dSBarry Smith   PetscFunctionReturn(0);
642cd0e1443SSatish Balay }
643cd0e1443SSatish Balay 
6442d61bbb3SSatish Balay 
6455615d1e5SSatish Balay #undef __FUNC__
64605a5f48eSSatish Balay #define __FUNC__ "MatSetValuesBlocked_SeqBAIJ"
64792c4ed94SBarry Smith int MatSetValuesBlocked_SeqBAIJ(Mat A,int m,int *im,int n,int *in,Scalar *v,InsertMode is)
64892c4ed94SBarry Smith {
64992c4ed94SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
6508a84c255SSatish Balay   int         *rp,k,low,high,t,ii,jj,row,nrow,i,col,l,rmax,N,sorted=a->sorted;
651dd9472c6SBarry Smith   int         *imax=a->imax,*ai=a->i,*ailen=a->ilen, roworiented=a->roworiented;
652dd9472c6SBarry Smith   int         *aj=a->j,nonew=a->nonew,bs2=a->bs2,bs=a->bs,stepval;
6533f1db9ecSBarry Smith   Scalar      *value = v;
6543f1db9ecSBarry Smith   MatScalar   *ap,*aa=a->a,*bap;
65592c4ed94SBarry Smith 
6563a40ed3dSBarry Smith   PetscFunctionBegin;
6570e324ae4SSatish Balay   if (roworiented) {
6580e324ae4SSatish Balay     stepval = (n-1)*bs;
6590e324ae4SSatish Balay   } else {
6600e324ae4SSatish Balay     stepval = (m-1)*bs;
6610e324ae4SSatish Balay   }
66292c4ed94SBarry Smith   for ( k=0; k<m; k++ ) { /* loop over added rows */
66392c4ed94SBarry Smith     row  = im[k];
664*5ef9f2a5SBarry Smith     if (row < 0) continue;
6653a40ed3dSBarry Smith #if defined(USE_PETSC_BOPT_g)
666a8c6a408SBarry Smith     if (row >= a->mbs) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Row too large");
66792c4ed94SBarry Smith #endif
66892c4ed94SBarry Smith     rp   = aj + ai[row];
66992c4ed94SBarry Smith     ap   = aa + bs2*ai[row];
67092c4ed94SBarry Smith     rmax = imax[row];
67192c4ed94SBarry Smith     nrow = ailen[row];
67292c4ed94SBarry Smith     low  = 0;
67392c4ed94SBarry Smith     for ( l=0; l<n; l++ ) { /* loop over added columns */
674*5ef9f2a5SBarry Smith       if (in[l] < 0) continue;
6753a40ed3dSBarry Smith #if defined(USE_PETSC_BOPT_g)
676a8c6a408SBarry Smith       if (in[l] >= a->nbs) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Column too large");
67792c4ed94SBarry Smith #endif
67892c4ed94SBarry Smith       col = in[l];
67992c4ed94SBarry Smith       if (roworiented) {
6800e324ae4SSatish Balay         value = v + k*(stepval+bs)*bs + l*bs;
6810e324ae4SSatish Balay       } else {
6820e324ae4SSatish Balay         value = v + l*(stepval+bs)*bs + k*bs;
68392c4ed94SBarry Smith       }
68492c4ed94SBarry Smith       if (!sorted) low = 0; high = nrow;
68592c4ed94SBarry Smith       while (high-low > 7) {
68692c4ed94SBarry Smith         t = (low+high)/2;
68792c4ed94SBarry Smith         if (rp[t] > col) high = t;
68892c4ed94SBarry Smith         else             low  = t;
68992c4ed94SBarry Smith       }
69092c4ed94SBarry Smith       for ( i=low; i<high; i++ ) {
69192c4ed94SBarry Smith         if (rp[i] > col) break;
69292c4ed94SBarry Smith         if (rp[i] == col) {
6938a84c255SSatish Balay           bap  = ap +  bs2*i;
6940e324ae4SSatish Balay           if (roworiented) {
6958a84c255SSatish Balay             if (is == ADD_VALUES) {
696dd9472c6SBarry Smith               for ( ii=0; ii<bs; ii++,value+=stepval ) {
697dd9472c6SBarry Smith                 for (jj=ii; jj<bs2; jj+=bs ) {
6988a84c255SSatish Balay                   bap[jj] += *value++;
699dd9472c6SBarry Smith                 }
700dd9472c6SBarry Smith               }
7010e324ae4SSatish Balay             } else {
702dd9472c6SBarry Smith               for ( ii=0; ii<bs; ii++,value+=stepval ) {
703dd9472c6SBarry Smith                 for (jj=ii; jj<bs2; jj+=bs ) {
7040e324ae4SSatish Balay                   bap[jj] = *value++;
7058a84c255SSatish Balay                 }
706dd9472c6SBarry Smith               }
707dd9472c6SBarry Smith             }
7080e324ae4SSatish Balay           } else {
7090e324ae4SSatish Balay             if (is == ADD_VALUES) {
710dd9472c6SBarry Smith               for ( ii=0; ii<bs; ii++,value+=stepval ) {
711dd9472c6SBarry Smith                 for (jj=0; jj<bs; jj++ ) {
7120e324ae4SSatish Balay                   *bap++ += *value++;
713dd9472c6SBarry Smith                 }
714dd9472c6SBarry Smith               }
7150e324ae4SSatish Balay             } else {
716dd9472c6SBarry Smith               for ( ii=0; ii<bs; ii++,value+=stepval ) {
717dd9472c6SBarry Smith                 for (jj=0; jj<bs; jj++ ) {
7180e324ae4SSatish Balay                   *bap++  = *value++;
7190e324ae4SSatish Balay                 }
7208a84c255SSatish Balay               }
721dd9472c6SBarry Smith             }
722dd9472c6SBarry Smith           }
723f1241b54SBarry Smith           goto noinsert2;
72492c4ed94SBarry Smith         }
72592c4ed94SBarry Smith       }
72689280ab3SLois Curfman McInnes       if (nonew == 1) goto noinsert2;
727a8c6a408SBarry Smith       else if (nonew == -1) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Inserting a new nonzero in the matrix");
72892c4ed94SBarry Smith       if (nrow >= rmax) {
72992c4ed94SBarry Smith         /* there is no extra room in row, therefore enlarge */
73092c4ed94SBarry Smith         int       new_nz = ai[a->mbs] + CHUNKSIZE,len,*new_i,*new_j;
7313f1db9ecSBarry Smith         MatScalar *new_a;
73292c4ed94SBarry Smith 
733a8c6a408SBarry Smith         if (nonew == -2) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Inserting a new nonzero in the matrix");
73489280ab3SLois Curfman McInnes 
73592c4ed94SBarry Smith         /* malloc new storage space */
7363f1db9ecSBarry Smith         len     = new_nz*(sizeof(int)+bs2*sizeof(MatScalar))+(a->mbs+1)*sizeof(int);
7373f1db9ecSBarry Smith         new_a   = (MatScalar *) PetscMalloc( len ); CHKPTRQ(new_a);
73892c4ed94SBarry Smith         new_j   = (int *) (new_a + bs2*new_nz);
73992c4ed94SBarry Smith         new_i   = new_j + new_nz;
74092c4ed94SBarry Smith 
74192c4ed94SBarry Smith         /* copy over old data into new slots */
74292c4ed94SBarry Smith         for ( ii=0; ii<row+1; ii++ ) {new_i[ii] = ai[ii];}
74392c4ed94SBarry Smith         for ( ii=row+1; ii<a->mbs+1; ii++ ) {new_i[ii] = ai[ii]+CHUNKSIZE;}
74492c4ed94SBarry Smith         PetscMemcpy(new_j,aj,(ai[row]+nrow)*sizeof(int));
74592c4ed94SBarry Smith         len = (new_nz - CHUNKSIZE - ai[row] - nrow);
746dd9472c6SBarry Smith         PetscMemcpy(new_j+ai[row]+nrow+CHUNKSIZE,aj+ai[row]+nrow,len*sizeof(int));
7473f1db9ecSBarry Smith         PetscMemcpy(new_a,aa,(ai[row]+nrow)*bs2*sizeof(MatScalar));
7483f1db9ecSBarry Smith         PetscMemzero(new_a+bs2*(ai[row]+nrow),bs2*CHUNKSIZE*sizeof(MatScalar));
7493f1db9ecSBarry Smith         PetscMemcpy(new_a+bs2*(ai[row]+nrow+CHUNKSIZE),aa+bs2*(ai[row]+nrow),bs2*len*sizeof(MatScalar));
75092c4ed94SBarry Smith         /* free up old matrix storage */
75192c4ed94SBarry Smith         PetscFree(a->a);
75292c4ed94SBarry Smith         if (!a->singlemalloc) {PetscFree(a->i);PetscFree(a->j);}
75392c4ed94SBarry Smith         aa = a->a = new_a; ai = a->i = new_i; aj = a->j = new_j;
75492c4ed94SBarry Smith         a->singlemalloc = 1;
75592c4ed94SBarry Smith 
75692c4ed94SBarry Smith         rp   = aj + ai[row]; ap = aa + bs2*ai[row];
75792c4ed94SBarry Smith         rmax = imax[row] = imax[row] + CHUNKSIZE;
7583f1db9ecSBarry Smith         PLogObjectMemory(A,CHUNKSIZE*(sizeof(int) + bs2*sizeof(MatScalar)));
75992c4ed94SBarry Smith         a->maxnz += bs2*CHUNKSIZE;
76092c4ed94SBarry Smith         a->reallocs++;
76192c4ed94SBarry Smith         a->nz++;
76292c4ed94SBarry Smith       }
76392c4ed94SBarry Smith       N = nrow++ - 1;
76492c4ed94SBarry Smith       /* shift up all the later entries in this row */
76592c4ed94SBarry Smith       for ( ii=N; ii>=i; ii-- ) {
76692c4ed94SBarry Smith         rp[ii+1] = rp[ii];
7673f1db9ecSBarry Smith         PetscMemcpy(ap+bs2*(ii+1),ap+bs2*(ii),bs2*sizeof(MatScalar));
76892c4ed94SBarry Smith       }
7693f1db9ecSBarry Smith       if (N >= i) PetscMemzero(ap+bs2*i,bs2*sizeof(MatScalar));
77092c4ed94SBarry Smith       rp[i] = col;
7718a84c255SSatish Balay       bap   = ap +  bs2*i;
7720e324ae4SSatish Balay       if (roworiented) {
773dd9472c6SBarry Smith         for ( ii=0; ii<bs; ii++,value+=stepval) {
774dd9472c6SBarry Smith           for (jj=ii; jj<bs2; jj+=bs ) {
7750e324ae4SSatish Balay             bap[jj] = *value++;
776dd9472c6SBarry Smith           }
777dd9472c6SBarry Smith         }
7780e324ae4SSatish Balay       } else {
779dd9472c6SBarry Smith         for ( ii=0; ii<bs; ii++,value+=stepval ) {
780dd9472c6SBarry Smith           for (jj=0; jj<bs; jj++ ) {
7810e324ae4SSatish Balay             *bap++  = *value++;
7820e324ae4SSatish Balay           }
783dd9472c6SBarry Smith         }
784dd9472c6SBarry Smith       }
785f1241b54SBarry Smith       noinsert2:;
78692c4ed94SBarry Smith       low = i;
78792c4ed94SBarry Smith     }
78892c4ed94SBarry Smith     ailen[row] = nrow;
78992c4ed94SBarry Smith   }
7903a40ed3dSBarry Smith   PetscFunctionReturn(0);
79192c4ed94SBarry Smith }
79292c4ed94SBarry Smith 
793f2501298SSatish Balay 
7945615d1e5SSatish Balay #undef __FUNC__
7955615d1e5SSatish Balay #define __FUNC__ "MatAssemblyEnd_SeqBAIJ"
7968f6be9afSLois Curfman McInnes int MatAssemblyEnd_SeqBAIJ(Mat A,MatAssemblyType mode)
797584200bdSSatish Balay {
798584200bdSSatish Balay   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
799584200bdSSatish Balay   int        fshift = 0,i,j,*ai = a->i, *aj = a->j, *imax = a->imax;
800a7c10996SSatish Balay   int        m = a->m,*ip, N, *ailen = a->ilen;
80143ee02c3SBarry Smith   int        mbs = a->mbs, bs2 = a->bs2,rmax = 0;
8023f1db9ecSBarry Smith   MatScalar  *aa = a->a, *ap;
803584200bdSSatish Balay 
8043a40ed3dSBarry Smith   PetscFunctionBegin;
8053a40ed3dSBarry Smith   if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0);
806584200bdSSatish Balay 
80743ee02c3SBarry Smith   if (m) rmax = ailen[0];
808584200bdSSatish Balay   for ( i=1; i<mbs; i++ ) {
809584200bdSSatish Balay     /* move each row back by the amount of empty slots (fshift) before it*/
810584200bdSSatish Balay     fshift += imax[i-1] - ailen[i-1];
811d402145bSBarry Smith     rmax   = PetscMax(rmax,ailen[i]);
812584200bdSSatish Balay     if (fshift) {
813a7c10996SSatish Balay       ip = aj + ai[i]; ap = aa + bs2*ai[i];
814584200bdSSatish Balay       N = ailen[i];
815584200bdSSatish Balay       for ( j=0; j<N; j++ ) {
816584200bdSSatish Balay         ip[j-fshift] = ip[j];
8173f1db9ecSBarry Smith         PetscMemcpy(ap+(j-fshift)*bs2,ap+j*bs2,bs2*sizeof(MatScalar));
818584200bdSSatish Balay       }
819584200bdSSatish Balay     }
820584200bdSSatish Balay     ai[i] = ai[i-1] + ailen[i-1];
821584200bdSSatish Balay   }
822584200bdSSatish Balay   if (mbs) {
823584200bdSSatish Balay     fshift += imax[mbs-1] - ailen[mbs-1];
824584200bdSSatish Balay     ai[mbs] = ai[mbs-1] + ailen[mbs-1];
825584200bdSSatish Balay   }
826584200bdSSatish Balay   /* reset ilen and imax for each row */
827584200bdSSatish Balay   for ( i=0; i<mbs; i++ ) {
828584200bdSSatish Balay     ailen[i] = imax[i] = ai[i+1] - ai[i];
829584200bdSSatish Balay   }
830a7c10996SSatish Balay   a->nz = ai[mbs];
831584200bdSSatish Balay 
832584200bdSSatish Balay   /* diagonals may have moved, so kill the diagonal pointers */
833584200bdSSatish Balay   if (fshift && a->diag) {
834584200bdSSatish Balay     PetscFree(a->diag);
835584200bdSSatish Balay     PLogObjectMemory(A,-(m+1)*sizeof(int));
836584200bdSSatish Balay     a->diag = 0;
837584200bdSSatish Balay   }
8383d2013a6SLois Curfman McInnes   PLogInfo(A,"MatAssemblyEnd_SeqBAIJ:Matrix size: %d X %d, block size %d; storage space: %d unneeded, %d used\n",
839219d9a1aSLois Curfman McInnes            m,a->n,a->bs,fshift*bs2,a->nz*bs2);
8403d2013a6SLois Curfman McInnes   PLogInfo(A,"MatAssemblyEnd_SeqBAIJ:Number of mallocs during MatSetValues is %d\n",
841584200bdSSatish Balay            a->reallocs);
842d402145bSBarry Smith   PLogInfo(A,"MatAssemblyEnd_SeqBAIJ:Most nonzeros blocks in any row is %d\n",rmax);
843e2f3b5e9SSatish Balay   a->reallocs          = 0;
8444e220ebcSLois Curfman McInnes   A->info.nz_unneeded  = (double)fshift*bs2;
8454e220ebcSLois Curfman McInnes 
8463a40ed3dSBarry Smith   PetscFunctionReturn(0);
847584200bdSSatish Balay }
848584200bdSSatish Balay 
8495a838052SSatish Balay 
850d9b7c43dSSatish Balay /* idx should be of length atlease bs */
8515615d1e5SSatish Balay #undef __FUNC__
8525615d1e5SSatish Balay #define __FUNC__ "MatZeroRows_SeqBAIJ_Check_Block"
853d9b7c43dSSatish Balay static int MatZeroRows_SeqBAIJ_Check_Block(int *idx, int bs, PetscTruth *flg)
854d9b7c43dSSatish Balay {
855d9b7c43dSSatish Balay   int i,row;
8563a40ed3dSBarry Smith 
8573a40ed3dSBarry Smith   PetscFunctionBegin;
858d9b7c43dSSatish Balay   row = idx[0];
8593a40ed3dSBarry Smith   if (row%bs!=0) { *flg = PETSC_FALSE; PetscFunctionReturn(0); }
860d9b7c43dSSatish Balay 
861d9b7c43dSSatish Balay   for ( i=1; i<bs; i++ ) {
8623a40ed3dSBarry Smith     if (row+i != idx[i]) { *flg = PETSC_FALSE; PetscFunctionReturn(0); }
863d9b7c43dSSatish Balay   }
864d9b7c43dSSatish Balay   *flg = PETSC_TRUE;
8653a40ed3dSBarry Smith   PetscFunctionReturn(0);
866d9b7c43dSSatish Balay }
867d9b7c43dSSatish Balay 
8685615d1e5SSatish Balay #undef __FUNC__
8695615d1e5SSatish Balay #define __FUNC__ "MatZeroRows_SeqBAIJ"
8708f6be9afSLois Curfman McInnes int MatZeroRows_SeqBAIJ(Mat A,IS is, Scalar *diag)
871d9b7c43dSSatish Balay {
872d9b7c43dSSatish Balay   Mat_SeqBAIJ *baij=(Mat_SeqBAIJ*)A->data;
873d9b7c43dSSatish Balay   IS          is_local;
874d9b7c43dSSatish Balay   int         ierr,i,j,count,m=baij->m,is_n,*is_idx,*rows,bs=baij->bs,bs2=baij->bs2;
875d9b7c43dSSatish Balay   PetscTruth  flg;
8763f1db9ecSBarry Smith   Scalar      zero = 0.0;
8773f1db9ecSBarry Smith   MatScalar   *aa;
878d9b7c43dSSatish Balay 
8793a40ed3dSBarry Smith   PetscFunctionBegin;
880d9b7c43dSSatish Balay   /* Make a copy of the IS and  sort it */
881d9b7c43dSSatish Balay   ierr = ISGetSize(is,&is_n);CHKERRQ(ierr);
882d9b7c43dSSatish Balay   ierr = ISGetIndices(is,&is_idx);CHKERRQ(ierr);
883537820f0SBarry Smith   ierr = ISCreateGeneral(A->comm,is_n,is_idx,&is_local); CHKERRQ(ierr);
884d9b7c43dSSatish Balay   ierr = ISSort(is_local); CHKERRQ(ierr);
885d9b7c43dSSatish Balay   ierr = ISGetIndices(is_local,&rows); CHKERRQ(ierr);
886d9b7c43dSSatish Balay 
887d9b7c43dSSatish Balay   i = 0;
888d9b7c43dSSatish Balay   while (i < is_n) {
889a8c6a408SBarry Smith     if (rows[i]<0 || rows[i]>m) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"row out of range");
890d9b7c43dSSatish Balay     flg = PETSC_FALSE;
891d9b7c43dSSatish Balay     if (i+bs <= is_n) {ierr = MatZeroRows_SeqBAIJ_Check_Block(rows+i,bs,&flg); CHKERRQ(ierr); }
892d9b7c43dSSatish Balay     count = (baij->i[rows[i]/bs +1] - baij->i[rows[i]/bs])*bs;
893d9b7c43dSSatish Balay     aa    = baij->a + baij->i[rows[i]/bs]*bs2 + (rows[i]%bs);
8942d61bbb3SSatish Balay     if (flg) { /* There exists a block of rows to be Zerowed */
895a07cd24cSSatish Balay       if (baij->ilen[rows[i]/bs] > 0) {
8963f1db9ecSBarry Smith         PetscMemzero(aa,count*bs*sizeof(MatScalar));
8972d61bbb3SSatish Balay         baij->ilen[rows[i]/bs] = 1;
8982d61bbb3SSatish Balay         baij->j[baij->i[rows[i]/bs]] = rows[i]/bs;
899a07cd24cSSatish Balay       }
9002d61bbb3SSatish Balay       i += bs;
9012d61bbb3SSatish Balay     } else { /* Zero out only the requested row */
902d9b7c43dSSatish Balay       for ( j=0; j<count; j++ ) {
903d9b7c43dSSatish Balay         aa[0] = zero;
904d9b7c43dSSatish Balay         aa+=bs;
905d9b7c43dSSatish Balay       }
906d9b7c43dSSatish Balay       i++;
907d9b7c43dSSatish Balay     }
908d9b7c43dSSatish Balay   }
909d9b7c43dSSatish Balay   if (diag) {
910d9b7c43dSSatish Balay     for ( j=0; j<is_n; j++ ) {
911f830108cSBarry Smith       ierr = (*A->ops->setvalues)(A,1,rows+j,1,rows+j,diag,INSERT_VALUES);CHKERRQ(ierr);
912d9b7c43dSSatish Balay     }
913d9b7c43dSSatish Balay   }
914d9b7c43dSSatish Balay   ierr = ISRestoreIndices(is,&is_idx); CHKERRQ(ierr);
915d9b7c43dSSatish Balay   ierr = ISRestoreIndices(is_local,&rows); CHKERRQ(ierr);
916d9b7c43dSSatish Balay   ierr = ISDestroy(is_local); CHKERRQ(ierr);
9179a8dea36SBarry Smith   ierr = MatAssemblyEnd_SeqBAIJ(A,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
9183a40ed3dSBarry Smith   PetscFunctionReturn(0);
919d9b7c43dSSatish Balay }
9201c351548SSatish Balay 
9215615d1e5SSatish Balay #undef __FUNC__
9222d61bbb3SSatish Balay #define __FUNC__ "MatSetValues_SeqBAIJ"
9232d61bbb3SSatish Balay int MatSetValues_SeqBAIJ(Mat A,int m,int *im,int n,int *in,Scalar *v,InsertMode is)
9242d61bbb3SSatish Balay {
9252d61bbb3SSatish Balay   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
9262d61bbb3SSatish Balay   int         *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N,sorted=a->sorted;
9272d61bbb3SSatish Balay   int         *imax=a->imax,*ai=a->i,*ailen=a->ilen,roworiented=a->roworiented;
9282d61bbb3SSatish Balay   int         *aj=a->j,nonew=a->nonew,bs=a->bs,brow,bcol;
9292d61bbb3SSatish Balay   int         ridx,cidx,bs2=a->bs2;
9303f1db9ecSBarry Smith   MatScalar   *ap,value,*aa=a->a,*bap;
9312d61bbb3SSatish Balay 
9322d61bbb3SSatish Balay   PetscFunctionBegin;
9332d61bbb3SSatish Balay   for ( k=0; k<m; k++ ) { /* loop over added rows */
9342d61bbb3SSatish Balay     row  = im[k]; brow = row/bs;
935*5ef9f2a5SBarry Smith     if (row < 0) continue;
9362d61bbb3SSatish Balay #if defined(USE_PETSC_BOPT_g)
9372d61bbb3SSatish Balay     if (row >= a->m) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Row too large");
9382d61bbb3SSatish Balay #endif
9392d61bbb3SSatish Balay     rp   = aj + ai[brow];
9402d61bbb3SSatish Balay     ap   = aa + bs2*ai[brow];
9412d61bbb3SSatish Balay     rmax = imax[brow];
9422d61bbb3SSatish Balay     nrow = ailen[brow];
9432d61bbb3SSatish Balay     low  = 0;
9442d61bbb3SSatish Balay     for ( l=0; l<n; l++ ) { /* loop over added columns */
945*5ef9f2a5SBarry Smith       if (in[l] < 0) continue;
9462d61bbb3SSatish Balay #if defined(USE_PETSC_BOPT_g)
9472d61bbb3SSatish Balay       if (in[l] >= a->n) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Column too large");
9482d61bbb3SSatish Balay #endif
9492d61bbb3SSatish Balay       col = in[l]; bcol = col/bs;
9502d61bbb3SSatish Balay       ridx = row % bs; cidx = col % bs;
9512d61bbb3SSatish Balay       if (roworiented) {
952*5ef9f2a5SBarry Smith         value = v[l + k*n];
9532d61bbb3SSatish Balay       } else {
9542d61bbb3SSatish Balay         value = v[k + l*m];
9552d61bbb3SSatish Balay       }
9562d61bbb3SSatish Balay       if (!sorted) low = 0; high = nrow;
9572d61bbb3SSatish Balay       while (high-low > 7) {
9582d61bbb3SSatish Balay         t = (low+high)/2;
9592d61bbb3SSatish Balay         if (rp[t] > bcol) high = t;
9602d61bbb3SSatish Balay         else              low  = t;
9612d61bbb3SSatish Balay       }
9622d61bbb3SSatish Balay       for ( i=low; i<high; i++ ) {
9632d61bbb3SSatish Balay         if (rp[i] > bcol) break;
9642d61bbb3SSatish Balay         if (rp[i] == bcol) {
9652d61bbb3SSatish Balay           bap  = ap +  bs2*i + bs*cidx + ridx;
9662d61bbb3SSatish Balay           if (is == ADD_VALUES) *bap += value;
9672d61bbb3SSatish Balay           else                  *bap  = value;
9682d61bbb3SSatish Balay           goto noinsert1;
9692d61bbb3SSatish Balay         }
9702d61bbb3SSatish Balay       }
9712d61bbb3SSatish Balay       if (nonew == 1) goto noinsert1;
9722d61bbb3SSatish Balay       else if (nonew == -1) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Inserting a new nonzero in the matrix");
9732d61bbb3SSatish Balay       if (nrow >= rmax) {
9742d61bbb3SSatish Balay         /* there is no extra room in row, therefore enlarge */
9752d61bbb3SSatish Balay         int       new_nz = ai[a->mbs] + CHUNKSIZE,len,*new_i,*new_j;
9763f1db9ecSBarry Smith         MatScalar *new_a;
9772d61bbb3SSatish Balay 
9782d61bbb3SSatish Balay         if (nonew == -2) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Inserting a new nonzero in the matrix");
9792d61bbb3SSatish Balay 
9802d61bbb3SSatish Balay         /* Malloc new storage space */
9813f1db9ecSBarry Smith         len     = new_nz*(sizeof(int)+bs2*sizeof(MatScalar))+(a->mbs+1)*sizeof(int);
9823f1db9ecSBarry Smith         new_a   = (MatScalar *) PetscMalloc( len ); CHKPTRQ(new_a);
9832d61bbb3SSatish Balay         new_j   = (int *) (new_a + bs2*new_nz);
9842d61bbb3SSatish Balay         new_i   = new_j + new_nz;
9852d61bbb3SSatish Balay 
9862d61bbb3SSatish Balay         /* copy over old data into new slots */
9872d61bbb3SSatish Balay         for ( ii=0; ii<brow+1; ii++ ) {new_i[ii] = ai[ii];}
9882d61bbb3SSatish Balay         for ( ii=brow+1; ii<a->mbs+1; ii++ ) {new_i[ii] = ai[ii]+CHUNKSIZE;}
9892d61bbb3SSatish Balay         PetscMemcpy(new_j,aj,(ai[brow]+nrow)*sizeof(int));
9902d61bbb3SSatish Balay         len = (new_nz - CHUNKSIZE - ai[brow] - nrow);
9912d61bbb3SSatish Balay         PetscMemcpy(new_j+ai[brow]+nrow+CHUNKSIZE,aj+ai[brow]+nrow,
9922d61bbb3SSatish Balay                                                            len*sizeof(int));
9933f1db9ecSBarry Smith         PetscMemcpy(new_a,aa,(ai[brow]+nrow)*bs2*sizeof(MatScalar));
9943f1db9ecSBarry Smith         PetscMemzero(new_a+bs2*(ai[brow]+nrow),bs2*CHUNKSIZE*sizeof(MatScalar));
9952d61bbb3SSatish Balay         PetscMemcpy(new_a+bs2*(ai[brow]+nrow+CHUNKSIZE),
9963f1db9ecSBarry Smith                     aa+bs2*(ai[brow]+nrow),bs2*len*sizeof(MatScalar));
9972d61bbb3SSatish Balay         /* free up old matrix storage */
9982d61bbb3SSatish Balay         PetscFree(a->a);
9992d61bbb3SSatish Balay         if (!a->singlemalloc) {PetscFree(a->i);PetscFree(a->j);}
10002d61bbb3SSatish Balay         aa = a->a = new_a; ai = a->i = new_i; aj = a->j = new_j;
10012d61bbb3SSatish Balay         a->singlemalloc = 1;
10022d61bbb3SSatish Balay 
10032d61bbb3SSatish Balay         rp   = aj + ai[brow]; ap = aa + bs2*ai[brow];
10042d61bbb3SSatish Balay         rmax = imax[brow] = imax[brow] + CHUNKSIZE;
10053f1db9ecSBarry Smith         PLogObjectMemory(A,CHUNKSIZE*(sizeof(int) + bs2*sizeof(MatScalar)));
10062d61bbb3SSatish Balay         a->maxnz += bs2*CHUNKSIZE;
10072d61bbb3SSatish Balay         a->reallocs++;
10082d61bbb3SSatish Balay         a->nz++;
10092d61bbb3SSatish Balay       }
10102d61bbb3SSatish Balay       N = nrow++ - 1;
10112d61bbb3SSatish Balay       /* shift up all the later entries in this row */
10122d61bbb3SSatish Balay       for ( ii=N; ii>=i; ii-- ) {
10132d61bbb3SSatish Balay         rp[ii+1] = rp[ii];
10143f1db9ecSBarry Smith         PetscMemcpy(ap+bs2*(ii+1),ap+bs2*(ii),bs2*sizeof(MatScalar));
10152d61bbb3SSatish Balay       }
10163f1db9ecSBarry Smith       if (N>=i) PetscMemzero(ap+bs2*i,bs2*sizeof(MatScalar));
10172d61bbb3SSatish Balay       rp[i]                      = bcol;
10182d61bbb3SSatish Balay       ap[bs2*i + bs*cidx + ridx] = value;
10192d61bbb3SSatish Balay       noinsert1:;
10202d61bbb3SSatish Balay       low = i;
10212d61bbb3SSatish Balay     }
10222d61bbb3SSatish Balay     ailen[brow] = nrow;
10232d61bbb3SSatish Balay   }
10242d61bbb3SSatish Balay   PetscFunctionReturn(0);
10252d61bbb3SSatish Balay }
10262d61bbb3SSatish Balay 
10272d61bbb3SSatish Balay extern int MatLUFactorSymbolic_SeqBAIJ(Mat,IS,IS,double,Mat*);
10282d61bbb3SSatish Balay extern int MatLUFactor_SeqBAIJ(Mat,IS,IS,double);
10292d61bbb3SSatish Balay extern int MatIncreaseOverlap_SeqBAIJ(Mat,int,IS*,int);
10307b2a1423SBarry Smith extern int MatGetSubMatrix_SeqBAIJ(Mat,IS,IS,int,MatReuse,Mat*);
10317b2a1423SBarry Smith extern int MatGetSubMatrices_SeqBAIJ(Mat,int,IS*,IS*,MatReuse,Mat**);
10322d61bbb3SSatish Balay extern int MatMultTrans_SeqBAIJ(Mat,Vec,Vec);
10332d61bbb3SSatish Balay extern int MatMultTransAdd_SeqBAIJ(Mat,Vec,Vec,Vec);
10342d61bbb3SSatish Balay extern int MatScale_SeqBAIJ(Scalar*,Mat);
10352d61bbb3SSatish Balay extern int MatNorm_SeqBAIJ(Mat,NormType,double *);
10362d61bbb3SSatish Balay extern int MatEqual_SeqBAIJ(Mat,Mat, PetscTruth*);
10372d61bbb3SSatish Balay extern int MatGetDiagonal_SeqBAIJ(Mat,Vec);
10382d61bbb3SSatish Balay extern int MatDiagonalScale_SeqBAIJ(Mat,Vec,Vec);
10392d61bbb3SSatish Balay extern int MatGetInfo_SeqBAIJ(Mat,MatInfoType,MatInfo *);
10402d61bbb3SSatish Balay extern int MatZeroEntries_SeqBAIJ(Mat);
10412d61bbb3SSatish Balay 
10422d61bbb3SSatish Balay extern int MatSolve_SeqBAIJ_N(Mat,Vec,Vec);
10432d61bbb3SSatish Balay extern int MatSolve_SeqBAIJ_1(Mat,Vec,Vec);
10442d61bbb3SSatish Balay extern int MatSolve_SeqBAIJ_2(Mat,Vec,Vec);
10452d61bbb3SSatish Balay extern int MatSolve_SeqBAIJ_3(Mat,Vec,Vec);
10462d61bbb3SSatish Balay extern int MatSolve_SeqBAIJ_4(Mat,Vec,Vec);
10472d61bbb3SSatish Balay extern int MatSolve_SeqBAIJ_5(Mat,Vec,Vec);
10482d61bbb3SSatish Balay extern int MatSolve_SeqBAIJ_7(Mat,Vec,Vec);
10492d61bbb3SSatish Balay 
10502d61bbb3SSatish Balay extern int MatLUFactorNumeric_SeqBAIJ_N(Mat,Mat*);
10512d61bbb3SSatish Balay extern int MatLUFactorNumeric_SeqBAIJ_1(Mat,Mat*);
10522d61bbb3SSatish Balay extern int MatLUFactorNumeric_SeqBAIJ_2(Mat,Mat*);
10532d61bbb3SSatish Balay extern int MatLUFactorNumeric_SeqBAIJ_3(Mat,Mat*);
10542d61bbb3SSatish Balay extern int MatLUFactorNumeric_SeqBAIJ_4(Mat,Mat*);
10552d61bbb3SSatish Balay extern int MatLUFactorNumeric_SeqBAIJ_5(Mat,Mat*);
10562d61bbb3SSatish Balay 
10572d61bbb3SSatish Balay extern int MatMult_SeqBAIJ_1(Mat,Vec,Vec);
10582d61bbb3SSatish Balay extern int MatMult_SeqBAIJ_2(Mat,Vec,Vec);
10592d61bbb3SSatish Balay extern int MatMult_SeqBAIJ_3(Mat,Vec,Vec);
10602d61bbb3SSatish Balay extern int MatMult_SeqBAIJ_4(Mat,Vec,Vec);
10612d61bbb3SSatish Balay extern int MatMult_SeqBAIJ_5(Mat,Vec,Vec);
10622d61bbb3SSatish Balay extern int MatMult_SeqBAIJ_7(Mat,Vec,Vec);
10632d61bbb3SSatish Balay extern int MatMult_SeqBAIJ_N(Mat,Vec,Vec);
10642d61bbb3SSatish Balay 
10652d61bbb3SSatish Balay extern int MatMultAdd_SeqBAIJ_1(Mat,Vec,Vec,Vec);
10662d61bbb3SSatish Balay extern int MatMultAdd_SeqBAIJ_2(Mat,Vec,Vec,Vec);
10672d61bbb3SSatish Balay extern int MatMultAdd_SeqBAIJ_3(Mat,Vec,Vec,Vec);
10682d61bbb3SSatish Balay extern int MatMultAdd_SeqBAIJ_4(Mat,Vec,Vec,Vec);
10692d61bbb3SSatish Balay extern int MatMultAdd_SeqBAIJ_5(Mat,Vec,Vec,Vec);
10702d61bbb3SSatish Balay extern int MatMultAdd_SeqBAIJ_7(Mat,Vec,Vec,Vec);
10712d61bbb3SSatish Balay extern int MatMultAdd_SeqBAIJ_N(Mat,Vec,Vec,Vec);
10722d61bbb3SSatish Balay 
10732d61bbb3SSatish Balay #undef __FUNC__
10742d61bbb3SSatish Balay #define __FUNC__ "MatILUFactor_SeqBAIJ"
1075*5ef9f2a5SBarry Smith int MatILUFactor_SeqBAIJ(Mat inA,IS row,IS col,MatILUInfo *info)
10762d61bbb3SSatish Balay {
10772d61bbb3SSatish Balay   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) inA->data;
10782d61bbb3SSatish Balay   Mat         outA;
10792d61bbb3SSatish Balay   int         ierr;
1080667159a5SBarry Smith   PetscTruth  row_identity, col_identity;
10812d61bbb3SSatish Balay 
10822d61bbb3SSatish Balay   PetscFunctionBegin;
1083*5ef9f2a5SBarry Smith   if (info && info->fill != 0) SETERRQ(PETSC_ERR_SUP,0,"Only fill=0 supported");
1084667159a5SBarry Smith   ierr = ISIdentity(row,&row_identity); CHKERRQ(ierr);
1085667159a5SBarry Smith   ierr = ISIdentity(col,&col_identity); CHKERRQ(ierr);
1086667159a5SBarry Smith   if (!row_identity || !col_identity) {
1087667159a5SBarry Smith     SETERRQ(1,1,"Row and column permutations must be identity");
1088667159a5SBarry Smith   }
10892d61bbb3SSatish Balay 
10902d61bbb3SSatish Balay   outA          = inA;
10912d61bbb3SSatish Balay   inA->factor   = FACTOR_LU;
10922d61bbb3SSatish Balay   a->row        = row;
10932d61bbb3SSatish Balay   a->col        = col;
10942d61bbb3SSatish Balay 
1095e51c0b9cSSatish Balay   /* Create the invert permutation so that it can be used in MatLUFactorNumeric() */
1096e51c0b9cSSatish Balay   ierr = ISInvertPermutation(col,&(a->icol)); CHKERRQ(ierr);
10971e4dd532SSatish Balay   PLogObjectParent(inA,a->icol);
1098e51c0b9cSSatish Balay 
10992d61bbb3SSatish Balay   if (!a->solve_work) {
11002d61bbb3SSatish Balay     a->solve_work = (Scalar *) PetscMalloc((a->m+a->bs)*sizeof(Scalar));CHKPTRQ(a->solve_work);
11012d61bbb3SSatish Balay     PLogObjectMemory(inA,(a->m+a->bs)*sizeof(Scalar));
11022d61bbb3SSatish Balay   }
11032d61bbb3SSatish Balay 
11042d61bbb3SSatish Balay   if (!a->diag) {
11052d61bbb3SSatish Balay     ierr = MatMarkDiag_SeqBAIJ(inA); CHKERRQ(ierr);
11062d61bbb3SSatish Balay   }
11072d61bbb3SSatish Balay   /*
1108667159a5SBarry Smith       Blocksize 4 and 5 have a special faster factorization/solver for ILU(0) factorization
11092d61bbb3SSatish Balay     with natural ordering
11102d61bbb3SSatish Balay   */
11112d61bbb3SSatish Balay   if (a->bs == 4) {
1112667159a5SBarry Smith     inA->ops->lufactornumeric = MatLUFactorNumeric_SeqBAIJ_4_NaturalOrdering;
1113f830108cSBarry Smith     inA->ops->solve           = MatSolve_SeqBAIJ_4_NaturalOrdering;
1114667159a5SBarry Smith     PLogInfo(inA,"Using special in-place natural ordering factor and solve BS=4\n");
1115667159a5SBarry Smith   } else if (a->bs == 5) {
1116667159a5SBarry Smith     inA->ops->lufactornumeric = MatLUFactorNumeric_SeqBAIJ_5_NaturalOrdering;
1117667159a5SBarry Smith     inA->ops->solve           = MatSolve_SeqBAIJ_5_NaturalOrdering;
1118667159a5SBarry Smith     PLogInfo(inA,"Using special in-place natural ordering factor and solve BS=5\n");
11192d61bbb3SSatish Balay   }
11202d61bbb3SSatish Balay 
1121667159a5SBarry Smith   ierr = MatLUFactorNumeric(inA,&outA); CHKERRQ(ierr);
1122667159a5SBarry Smith 
1123667159a5SBarry Smith 
11242d61bbb3SSatish Balay   PetscFunctionReturn(0);
11252d61bbb3SSatish Balay }
11262d61bbb3SSatish Balay #undef __FUNC__
1127d4bb536fSBarry Smith #define __FUNC__ "MatPrintHelp_SeqBAIJ"
1128ba4ca20aSSatish Balay int MatPrintHelp_SeqBAIJ(Mat A)
1129ba4ca20aSSatish Balay {
1130ba4ca20aSSatish Balay   static int called = 0;
1131ba4ca20aSSatish Balay   MPI_Comm   comm = A->comm;
1132ba4ca20aSSatish Balay 
11333a40ed3dSBarry Smith   PetscFunctionBegin;
11343a40ed3dSBarry Smith   if (called) {PetscFunctionReturn(0);} else called = 1;
113576be9ce4SBarry Smith   (*PetscHelpPrintf)(comm," Options for MATSEQBAIJ and MATMPIBAIJ matrix formats (the defaults):\n");
113676be9ce4SBarry Smith   (*PetscHelpPrintf)(comm,"  -mat_block_size <block_size>\n");
11373a40ed3dSBarry Smith   PetscFunctionReturn(0);
1138ba4ca20aSSatish Balay }
1139d9b7c43dSSatish Balay 
1140fb2e594dSBarry Smith EXTERN_C_BEGIN
114127a8da17SBarry Smith #undef __FUNC__
114227a8da17SBarry Smith #define __FUNC__ "MatSeqBAIJSetColumnIndices_SeqBAIJ"
114327a8da17SBarry Smith int MatSeqBAIJSetColumnIndices_SeqBAIJ(Mat mat,int *indices)
114427a8da17SBarry Smith {
114527a8da17SBarry Smith   Mat_SeqBAIJ *baij = (Mat_SeqBAIJ *)mat->data;
114627a8da17SBarry Smith   int         i,nz,n;
114727a8da17SBarry Smith 
114827a8da17SBarry Smith   PetscFunctionBegin;
114927a8da17SBarry Smith   nz = baij->maxnz;
115027a8da17SBarry Smith   n  = baij->n;
115127a8da17SBarry Smith   for (i=0; i<nz; i++) {
115227a8da17SBarry Smith     baij->j[i] = indices[i];
115327a8da17SBarry Smith   }
115427a8da17SBarry Smith   baij->nz = nz;
115527a8da17SBarry Smith   for ( i=0; i<n; i++ ) {
115627a8da17SBarry Smith     baij->ilen[i] = baij->imax[i];
115727a8da17SBarry Smith   }
115827a8da17SBarry Smith 
115927a8da17SBarry Smith   PetscFunctionReturn(0);
116027a8da17SBarry Smith }
1161fb2e594dSBarry Smith EXTERN_C_END
116227a8da17SBarry Smith 
116327a8da17SBarry Smith #undef __FUNC__
116427a8da17SBarry Smith #define __FUNC__ "MatSeqBAIJSetColumnIndices"
116527a8da17SBarry Smith /*@
116627a8da17SBarry Smith     MatSeqBAIJSetColumnIndices - Set the column indices for all the rows
116727a8da17SBarry Smith        in the matrix.
116827a8da17SBarry Smith 
116927a8da17SBarry Smith   Input Parameters:
117027a8da17SBarry Smith +  mat - the SeqBAIJ matrix
117127a8da17SBarry Smith -  indices - the column indices
117227a8da17SBarry Smith 
117327a8da17SBarry Smith   Notes:
117427a8da17SBarry Smith     This can be called if you have precomputed the nonzero structure of the
117527a8da17SBarry Smith   matrix and want to provide it to the matrix object to improve the performance
117627a8da17SBarry Smith   of the MatSetValues() operation.
117727a8da17SBarry Smith 
117827a8da17SBarry Smith     You MUST have set the correct numbers of nonzeros per row in the call to
117927a8da17SBarry Smith   MatCreateSeqBAIJ().
118027a8da17SBarry Smith 
118127a8da17SBarry Smith     MUST be called before any calls to MatSetValues();
118227a8da17SBarry Smith 
118327a8da17SBarry Smith @*/
118427a8da17SBarry Smith int MatSeqBAIJSetColumnIndices(Mat mat,int *indices)
118527a8da17SBarry Smith {
118627a8da17SBarry Smith   int ierr,(*f)(Mat,int *);
118727a8da17SBarry Smith 
118827a8da17SBarry Smith   PetscFunctionBegin;
118927a8da17SBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE);
119027a8da17SBarry Smith   ierr = PetscObjectQueryFunction((PetscObject)mat,"MatSeqBAIJSetColumnIndices_C",(void **)&f);
119127a8da17SBarry Smith          CHKERRQ(ierr);
119227a8da17SBarry Smith   if (f) {
119327a8da17SBarry Smith     ierr = (*f)(mat,indices);CHKERRQ(ierr);
119427a8da17SBarry Smith   } else {
119527a8da17SBarry Smith     SETERRQ(1,1,"Wrong type of matrix to set column indices");
119627a8da17SBarry Smith   }
119727a8da17SBarry Smith   PetscFunctionReturn(0);
119827a8da17SBarry Smith }
119927a8da17SBarry Smith 
12002593348eSBarry Smith /* -------------------------------------------------------------------*/
1201cc2dc46cSBarry Smith static struct _MatOps MatOps_Values = {MatSetValues_SeqBAIJ,
1202cc2dc46cSBarry Smith        MatGetRow_SeqBAIJ,
1203cc2dc46cSBarry Smith        MatRestoreRow_SeqBAIJ,
1204cc2dc46cSBarry Smith        MatMult_SeqBAIJ_N,
1205cc2dc46cSBarry Smith        MatMultAdd_SeqBAIJ_N,
1206cc2dc46cSBarry Smith        MatMultTrans_SeqBAIJ,
1207cc2dc46cSBarry Smith        MatMultTransAdd_SeqBAIJ,
1208cc2dc46cSBarry Smith        MatSolve_SeqBAIJ_N,
1209cc2dc46cSBarry Smith        0,
1210cc2dc46cSBarry Smith        0,
1211cc2dc46cSBarry Smith        0,
1212cc2dc46cSBarry Smith        MatLUFactor_SeqBAIJ,
1213cc2dc46cSBarry Smith        0,
1214b6490206SBarry Smith        0,
1215f2501298SSatish Balay        MatTranspose_SeqBAIJ,
1216cc2dc46cSBarry Smith        MatGetInfo_SeqBAIJ,
1217cc2dc46cSBarry Smith        MatEqual_SeqBAIJ,
1218cc2dc46cSBarry Smith        MatGetDiagonal_SeqBAIJ,
1219cc2dc46cSBarry Smith        MatDiagonalScale_SeqBAIJ,
1220cc2dc46cSBarry Smith        MatNorm_SeqBAIJ,
1221b6490206SBarry Smith        0,
1222cc2dc46cSBarry Smith        MatAssemblyEnd_SeqBAIJ,
1223cc2dc46cSBarry Smith        0,
1224cc2dc46cSBarry Smith        MatSetOption_SeqBAIJ,
1225cc2dc46cSBarry Smith        MatZeroEntries_SeqBAIJ,
1226cc2dc46cSBarry Smith        MatZeroRows_SeqBAIJ,
1227cc2dc46cSBarry Smith        MatLUFactorSymbolic_SeqBAIJ,
1228cc2dc46cSBarry Smith        MatLUFactorNumeric_SeqBAIJ_N,
1229cc2dc46cSBarry Smith        0,
1230cc2dc46cSBarry Smith        0,
1231cc2dc46cSBarry Smith        MatGetSize_SeqBAIJ,
1232cc2dc46cSBarry Smith        MatGetSize_SeqBAIJ,
1233cc2dc46cSBarry Smith        MatGetOwnershipRange_SeqBAIJ,
1234cc2dc46cSBarry Smith        MatILUFactorSymbolic_SeqBAIJ,
1235cc2dc46cSBarry Smith        0,
1236cc2dc46cSBarry Smith        0,
1237cc2dc46cSBarry Smith        0,
12382e8a6d31SBarry Smith        MatDuplicate_SeqBAIJ,
1239cc2dc46cSBarry Smith        0,
1240cc2dc46cSBarry Smith        0,
1241cc2dc46cSBarry Smith        MatILUFactor_SeqBAIJ,
1242cc2dc46cSBarry Smith        0,
1243cc2dc46cSBarry Smith        0,
1244cc2dc46cSBarry Smith        MatGetSubMatrices_SeqBAIJ,
1245cc2dc46cSBarry Smith        MatIncreaseOverlap_SeqBAIJ,
1246cc2dc46cSBarry Smith        MatGetValues_SeqBAIJ,
1247cc2dc46cSBarry Smith        0,
1248cc2dc46cSBarry Smith        MatPrintHelp_SeqBAIJ,
1249cc2dc46cSBarry Smith        MatScale_SeqBAIJ,
1250cc2dc46cSBarry Smith        0,
1251cc2dc46cSBarry Smith        0,
1252cc2dc46cSBarry Smith        0,
1253cc2dc46cSBarry Smith        MatGetBlockSize_SeqBAIJ,
12543b2fbd54SBarry Smith        MatGetRowIJ_SeqBAIJ,
125592c4ed94SBarry Smith        MatRestoreRowIJ_SeqBAIJ,
1256cc2dc46cSBarry Smith        0,
1257cc2dc46cSBarry Smith        0,
1258cc2dc46cSBarry Smith        0,
1259cc2dc46cSBarry Smith        0,
1260cc2dc46cSBarry Smith        0,
1261cc2dc46cSBarry Smith        0,
1262d3825aa8SBarry Smith        MatSetValuesBlocked_SeqBAIJ,
1263cc2dc46cSBarry Smith        MatGetSubMatrix_SeqBAIJ,
1264cc2dc46cSBarry Smith        0,
1265cc2dc46cSBarry Smith        0,
1266cc2dc46cSBarry Smith        MatGetMaps_Petsc};
12672593348eSBarry Smith 
12685615d1e5SSatish Balay #undef __FUNC__
12695615d1e5SSatish Balay #define __FUNC__ "MatCreateSeqBAIJ"
12702593348eSBarry Smith /*@C
127144cd7ae7SLois Curfman McInnes    MatCreateSeqBAIJ - Creates a sparse matrix in block AIJ (block
127244cd7ae7SLois Curfman McInnes    compressed row) format.  For good matrix assembly performance the
127344cd7ae7SLois Curfman McInnes    user should preallocate the matrix storage by setting the parameter nz
12742bd5e0b2SLois Curfman McInnes    (or the array nzz).  By setting these parameters accurately, performance
12752bd5e0b2SLois Curfman McInnes    during matrix assembly can be increased by more than a factor of 50.
12762593348eSBarry Smith 
1277db81eaa0SLois Curfman McInnes    Collective on MPI_Comm
1278db81eaa0SLois Curfman McInnes 
12792593348eSBarry Smith    Input Parameters:
1280db81eaa0SLois Curfman McInnes +  comm - MPI communicator, set to PETSC_COMM_SELF
1281b6490206SBarry Smith .  bs - size of block
12822593348eSBarry Smith .  m - number of rows
12832593348eSBarry Smith .  n - number of columns
1284b6490206SBarry Smith .  nz - number of block nonzeros per block row (same for all rows)
1285db81eaa0SLois Curfman McInnes -  nzz - array containing the number of block nonzeros in the various block rows
12862bd5e0b2SLois Curfman McInnes          (possibly different for each block row) or PETSC_NULL
12872593348eSBarry Smith 
12882593348eSBarry Smith    Output Parameter:
12892593348eSBarry Smith .  A - the matrix
12902593348eSBarry Smith 
12910513a670SBarry Smith    Options Database Keys:
1292db81eaa0SLois Curfman McInnes .   -mat_no_unroll - uses code that does not unroll the loops in the
1293db81eaa0SLois Curfman McInnes                      block calculations (much slower)
1294db81eaa0SLois Curfman McInnes .    -mat_block_size - size of the blocks to use
12950513a670SBarry Smith 
12962593348eSBarry Smith    Notes:
129744cd7ae7SLois Curfman McInnes    The block AIJ format is fully compatible with standard Fortran 77
12982593348eSBarry Smith    storage.  That is, the stored row and column indices can begin at
129944cd7ae7SLois Curfman McInnes    either one (as in Fortran) or zero.  See the users' manual for details.
13002593348eSBarry Smith 
13012593348eSBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
13022593348eSBarry Smith    Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory
13032593348eSBarry Smith    allocation.  For additional details, see the users manual chapter on
13046da5968aSLois Curfman McInnes    matrices.
13052593348eSBarry Smith 
1306db81eaa0SLois Curfman McInnes .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatCreateMPIBAIJ()
13072593348eSBarry Smith @*/
1308b6490206SBarry Smith int MatCreateSeqBAIJ(MPI_Comm comm,int bs,int m,int n,int nz,int *nnz, Mat *A)
13092593348eSBarry Smith {
13102593348eSBarry Smith   Mat         B;
1311b6490206SBarry Smith   Mat_SeqBAIJ *b;
13123b2fbd54SBarry Smith   int         i,len,ierr,flg,mbs=m/bs,nbs=n/bs,bs2=bs*bs,size;
13133b2fbd54SBarry Smith 
13143a40ed3dSBarry Smith   PetscFunctionBegin;
13153b2fbd54SBarry Smith   MPI_Comm_size(comm,&size);
1316a8c6a408SBarry Smith   if (size > 1) SETERRQ(PETSC_ERR_ARG_WRONG,0,"Comm must be of size 1");
1317b6490206SBarry Smith 
13180513a670SBarry Smith   ierr = OptionsGetInt(PETSC_NULL,"-mat_block_size",&bs,&flg);CHKERRQ(ierr);
13190513a670SBarry Smith 
13203a40ed3dSBarry Smith   if (mbs*bs!=m || nbs*bs!=n) {
1321a8c6a408SBarry Smith     SETERRQ(PETSC_ERR_ARG_SIZ,0,"Number rows, cols must be divisible by blocksize");
13223a40ed3dSBarry Smith   }
13232593348eSBarry Smith 
13242593348eSBarry Smith   *A = 0;
13253f1db9ecSBarry Smith   PetscHeaderCreate(B,_p_Mat,struct _MatOps,MAT_COOKIE,MATSEQBAIJ,"Mat",comm,MatDestroy,MatView);
13262593348eSBarry Smith   PLogObjectCreate(B);
1327b6490206SBarry Smith   B->data = (void *) (b = PetscNew(Mat_SeqBAIJ)); CHKPTRQ(b);
132844cd7ae7SLois Curfman McInnes   PetscMemzero(b,sizeof(Mat_SeqBAIJ));
1329cc2dc46cSBarry Smith   PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));
13301a6a6d98SBarry Smith   ierr = OptionsHasName(PETSC_NULL,"-mat_no_unroll",&flg); CHKERRQ(ierr);
13311a6a6d98SBarry Smith   if (!flg) {
13327fc0212eSBarry Smith     switch (bs) {
13337fc0212eSBarry Smith     case 1:
1334f830108cSBarry Smith       B->ops->lufactornumeric = MatLUFactorNumeric_SeqBAIJ_1;
1335f830108cSBarry Smith       B->ops->solve           = MatSolve_SeqBAIJ_1;
1336f830108cSBarry Smith       B->ops->mult            = MatMult_SeqBAIJ_1;
1337f830108cSBarry Smith       B->ops->multadd         = MatMultAdd_SeqBAIJ_1;
13387fc0212eSBarry Smith       break;
13394eeb42bcSBarry Smith     case 2:
1340f830108cSBarry Smith       B->ops->lufactornumeric = MatLUFactorNumeric_SeqBAIJ_2;
1341f830108cSBarry Smith       B->ops->solve           = MatSolve_SeqBAIJ_2;
1342f830108cSBarry Smith       B->ops->mult            = MatMult_SeqBAIJ_2;
1343f830108cSBarry Smith       B->ops->multadd         = MatMultAdd_SeqBAIJ_2;
13446d84be18SBarry Smith       break;
1345f327dd97SBarry Smith     case 3:
1346f830108cSBarry Smith       B->ops->lufactornumeric = MatLUFactorNumeric_SeqBAIJ_3;
1347f830108cSBarry Smith       B->ops->solve           = MatSolve_SeqBAIJ_3;
1348f830108cSBarry Smith       B->ops->mult            = MatMult_SeqBAIJ_3;
1349f830108cSBarry Smith       B->ops->multadd         = MatMultAdd_SeqBAIJ_3;
13504eeb42bcSBarry Smith       break;
13516d84be18SBarry Smith     case 4:
1352f830108cSBarry Smith       B->ops->lufactornumeric = MatLUFactorNumeric_SeqBAIJ_4;
1353f830108cSBarry Smith       B->ops->solve           = MatSolve_SeqBAIJ_4;
1354f830108cSBarry Smith       B->ops->mult            = MatMult_SeqBAIJ_4;
1355f830108cSBarry Smith       B->ops->multadd         = MatMultAdd_SeqBAIJ_4;
13566d84be18SBarry Smith       break;
13576d84be18SBarry Smith     case 5:
1358f830108cSBarry Smith       B->ops->lufactornumeric = MatLUFactorNumeric_SeqBAIJ_5;
1359f830108cSBarry Smith       B->ops->solve           = MatSolve_SeqBAIJ_5;
1360f830108cSBarry Smith       B->ops->mult            = MatMult_SeqBAIJ_5;
1361f830108cSBarry Smith       B->ops->multadd         = MatMultAdd_SeqBAIJ_5;
13626d84be18SBarry Smith       break;
136348e9ddb2SSatish Balay     case 7:
1364f830108cSBarry Smith       B->ops->mult            = MatMult_SeqBAIJ_7;
1365f830108cSBarry Smith       B->ops->solve           = MatSolve_SeqBAIJ_7;
1366f830108cSBarry Smith       B->ops->multadd         = MatMultAdd_SeqBAIJ_7;
136748e9ddb2SSatish Balay       break;
13687fc0212eSBarry Smith     }
13691a6a6d98SBarry Smith   }
1370e1311b90SBarry Smith   B->ops->destroy     = MatDestroy_SeqBAIJ;
1371e1311b90SBarry Smith   B->ops->view        = MatView_SeqBAIJ;
13722593348eSBarry Smith   B->factor           = 0;
13732593348eSBarry Smith   B->lupivotthreshold = 1.0;
137490f02eecSBarry Smith   B->mapping          = 0;
13752593348eSBarry Smith   b->row              = 0;
13762593348eSBarry Smith   b->col              = 0;
1377e51c0b9cSSatish Balay   b->icol             = 0;
13782593348eSBarry Smith   b->reallocs         = 0;
13792593348eSBarry Smith 
138044cd7ae7SLois Curfman McInnes   b->m       = m; B->m = m; B->M = m;
138144cd7ae7SLois Curfman McInnes   b->n       = n; B->n = n; B->N = n;
1382a5ae1ecdSBarry Smith 
13837413bad6SBarry Smith   ierr = MapCreateMPI(comm,m,m,&B->rmap);CHKERRQ(ierr);
13847413bad6SBarry Smith   ierr = MapCreateMPI(comm,n,n,&B->cmap);CHKERRQ(ierr);
1385a5ae1ecdSBarry Smith 
1386b6490206SBarry Smith   b->mbs     = mbs;
1387f2501298SSatish Balay   b->nbs     = nbs;
1388b6490206SBarry Smith   b->imax    = (int *) PetscMalloc( (mbs+1)*sizeof(int) ); CHKPTRQ(b->imax);
13892593348eSBarry Smith   if (nnz == PETSC_NULL) {
1390119a934aSSatish Balay     if (nz == PETSC_DEFAULT) nz = 5;
13912593348eSBarry Smith     else if (nz <= 0)        nz = 1;
1392b6490206SBarry Smith     for ( i=0; i<mbs; i++ ) b->imax[i] = nz;
1393b6490206SBarry Smith     nz = nz*mbs;
13943a40ed3dSBarry Smith   } else {
13952593348eSBarry Smith     nz = 0;
1396b6490206SBarry Smith     for ( i=0; i<mbs; i++ ) {b->imax[i] = nnz[i]; nz += nnz[i];}
13972593348eSBarry Smith   }
13982593348eSBarry Smith 
13992593348eSBarry Smith   /* allocate the matrix space */
14003f1db9ecSBarry Smith   len   = nz*sizeof(int) + nz*bs2*sizeof(MatScalar) + (b->m+1)*sizeof(int);
14013f1db9ecSBarry Smith   b->a  = (MatScalar *) PetscMalloc( len ); CHKPTRQ(b->a);
14023f1db9ecSBarry Smith   PetscMemzero(b->a,nz*bs2*sizeof(MatScalar));
14037e67e3f9SSatish Balay   b->j  = (int *) (b->a + nz*bs2);
14042593348eSBarry Smith   PetscMemzero(b->j,nz*sizeof(int));
14052593348eSBarry Smith   b->i  = b->j + nz;
14062593348eSBarry Smith   b->singlemalloc = 1;
14072593348eSBarry Smith 
1408de6a44a3SBarry Smith   b->i[0] = 0;
1409b6490206SBarry Smith   for (i=1; i<mbs+1; i++) {
14102593348eSBarry Smith     b->i[i] = b->i[i-1] + b->imax[i-1];
14112593348eSBarry Smith   }
14122593348eSBarry Smith 
1413b6490206SBarry Smith   /* b->ilen will count nonzeros in each block row so far. */
1414b6490206SBarry Smith   b->ilen = (int *) PetscMalloc((mbs+1)*sizeof(int));
1415f09e8eb9SSatish Balay   PLogObjectMemory(B,len+2*(mbs+1)*sizeof(int)+sizeof(struct _p_Mat)+sizeof(Mat_SeqBAIJ));
1416b6490206SBarry Smith   for ( i=0; i<mbs; i++ ) { b->ilen[i] = 0;}
14172593348eSBarry Smith 
1418b6490206SBarry Smith   b->bs               = bs;
14199df24120SSatish Balay   b->bs2              = bs2;
1420b6490206SBarry Smith   b->mbs              = mbs;
14212593348eSBarry Smith   b->nz               = 0;
142218e7b8e4SLois Curfman McInnes   b->maxnz            = nz*bs2;
14232593348eSBarry Smith   b->sorted           = 0;
14242593348eSBarry Smith   b->roworiented      = 1;
14252593348eSBarry Smith   b->nonew            = 0;
14262593348eSBarry Smith   b->diag             = 0;
14272593348eSBarry Smith   b->solve_work       = 0;
1428de6a44a3SBarry Smith   b->mult_work        = 0;
14292593348eSBarry Smith   b->spptr            = 0;
14304e220ebcSLois Curfman McInnes   B->info.nz_unneeded = (double)b->maxnz;
14314e220ebcSLois Curfman McInnes 
14322593348eSBarry Smith   *A = B;
14332593348eSBarry Smith   ierr = OptionsHasName(PETSC_NULL,"-help", &flg); CHKERRQ(ierr);
14342593348eSBarry Smith   if (flg) {ierr = MatPrintHelp(B); CHKERRQ(ierr); }
143527a8da17SBarry Smith 
143627a8da17SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqBAIJSetColumnIndices_C",
143727a8da17SBarry Smith                                      "MatSeqBAIJSetColumnIndices_SeqBAIJ",
143827a8da17SBarry Smith                                      (void*)MatSeqBAIJSetColumnIndices_SeqBAIJ);CHKERRQ(ierr);
14393a40ed3dSBarry Smith   PetscFunctionReturn(0);
14402593348eSBarry Smith }
14412593348eSBarry Smith 
14425615d1e5SSatish Balay #undef __FUNC__
14432e8a6d31SBarry Smith #define __FUNC__ "MatDuplicate_SeqBAIJ"
14442e8a6d31SBarry Smith int MatDuplicate_SeqBAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B)
14452593348eSBarry Smith {
14462593348eSBarry Smith   Mat         C;
1447b6490206SBarry Smith   Mat_SeqBAIJ *c,*a = (Mat_SeqBAIJ *) A->data;
144827a8da17SBarry Smith   int         i,len, mbs = a->mbs,nz = a->nz,bs2 =a->bs2,ierr;
1449de6a44a3SBarry Smith 
14503a40ed3dSBarry Smith   PetscFunctionBegin;
1451a8c6a408SBarry Smith   if (a->i[mbs] != nz) SETERRQ(PETSC_ERR_PLIB,0,"Corrupt matrix");
14522593348eSBarry Smith 
14532593348eSBarry Smith   *B = 0;
14543f1db9ecSBarry Smith   PetscHeaderCreate(C,_p_Mat,struct _MatOps,MAT_COOKIE,MATSEQBAIJ,"Mat",A->comm,MatDestroy,MatView);
14552593348eSBarry Smith   PLogObjectCreate(C);
1456b6490206SBarry Smith   C->data       = (void *) (c = PetscNew(Mat_SeqBAIJ)); CHKPTRQ(c);
1457c3c66ee5SSatish Balay   PetscMemcpy(C->ops,A->ops,sizeof(struct _MatOps));
1458e1311b90SBarry Smith   C->ops->destroy    = MatDestroy_SeqBAIJ;
1459e1311b90SBarry Smith   C->ops->view       = MatView_SeqBAIJ;
14602593348eSBarry Smith   C->factor          = A->factor;
14612593348eSBarry Smith   c->row             = 0;
14622593348eSBarry Smith   c->col             = 0;
14632593348eSBarry Smith   C->assembled       = PETSC_TRUE;
14642593348eSBarry Smith 
146544cd7ae7SLois Curfman McInnes   c->m = C->m   = a->m;
146644cd7ae7SLois Curfman McInnes   c->n = C->n   = a->n;
146744cd7ae7SLois Curfman McInnes   C->M          = a->m;
146844cd7ae7SLois Curfman McInnes   C->N          = a->n;
146944cd7ae7SLois Curfman McInnes 
1470b6490206SBarry Smith   c->bs         = a->bs;
14719df24120SSatish Balay   c->bs2        = a->bs2;
1472b6490206SBarry Smith   c->mbs        = a->mbs;
1473b6490206SBarry Smith   c->nbs        = a->nbs;
14742593348eSBarry Smith 
1475b6490206SBarry Smith   c->imax       = (int *) PetscMalloc((mbs+1)*sizeof(int)); CHKPTRQ(c->imax);
1476b6490206SBarry Smith   c->ilen       = (int *) PetscMalloc((mbs+1)*sizeof(int)); CHKPTRQ(c->ilen);
1477b6490206SBarry Smith   for ( i=0; i<mbs; i++ ) {
14782593348eSBarry Smith     c->imax[i] = a->imax[i];
14792593348eSBarry Smith     c->ilen[i] = a->ilen[i];
14802593348eSBarry Smith   }
14812593348eSBarry Smith 
14822593348eSBarry Smith   /* allocate the matrix space */
14832593348eSBarry Smith   c->singlemalloc = 1;
14843f1db9ecSBarry Smith   len   = (mbs+1)*sizeof(int) + nz*(bs2*sizeof(MatScalar) + sizeof(int));
14853f1db9ecSBarry Smith   c->a  = (MatScalar *) PetscMalloc( len ); CHKPTRQ(c->a);
14867e67e3f9SSatish Balay   c->j  = (int *) (c->a + nz*bs2);
1487de6a44a3SBarry Smith   c->i  = c->j + nz;
1488b6490206SBarry Smith   PetscMemcpy(c->i,a->i,(mbs+1)*sizeof(int));
1489b6490206SBarry Smith   if (mbs > 0) {
1490de6a44a3SBarry Smith     PetscMemcpy(c->j,a->j,nz*sizeof(int));
14912e8a6d31SBarry Smith     if (cpvalues == MAT_COPY_VALUES) {
14923f1db9ecSBarry Smith       PetscMemcpy(c->a,a->a,bs2*nz*sizeof(MatScalar));
14932e8a6d31SBarry Smith     } else {
14943f1db9ecSBarry Smith       PetscMemzero(c->a,bs2*nz*sizeof(MatScalar));
14952593348eSBarry Smith     }
14962593348eSBarry Smith   }
14972593348eSBarry Smith 
1498f09e8eb9SSatish Balay   PLogObjectMemory(C,len+2*(mbs+1)*sizeof(int)+sizeof(struct _p_Mat)+sizeof(Mat_SeqBAIJ));
14992593348eSBarry Smith   c->sorted      = a->sorted;
15002593348eSBarry Smith   c->roworiented = a->roworiented;
15012593348eSBarry Smith   c->nonew       = a->nonew;
15022593348eSBarry Smith 
15032593348eSBarry Smith   if (a->diag) {
1504b6490206SBarry Smith     c->diag = (int *) PetscMalloc( (mbs+1)*sizeof(int) ); CHKPTRQ(c->diag);
1505b6490206SBarry Smith     PLogObjectMemory(C,(mbs+1)*sizeof(int));
1506b6490206SBarry Smith     for ( i=0; i<mbs; i++ ) {
15072593348eSBarry Smith       c->diag[i] = a->diag[i];
15082593348eSBarry Smith     }
15092593348eSBarry Smith   }
15102593348eSBarry Smith   else c->diag          = 0;
15112593348eSBarry Smith   c->nz                 = a->nz;
15122593348eSBarry Smith   c->maxnz              = a->maxnz;
15132593348eSBarry Smith   c->solve_work         = 0;
15142593348eSBarry Smith   c->spptr              = 0;      /* Dangerous -I'm throwing away a->spptr */
15157fc0212eSBarry Smith   c->mult_work          = 0;
15162593348eSBarry Smith   *B = C;
15177b2a1423SBarry Smith   ierr = FListDuplicate(A->qlist,&C->qlist);CHKERRQ(ierr);
15183a40ed3dSBarry Smith   PetscFunctionReturn(0);
15192593348eSBarry Smith }
15202593348eSBarry Smith 
15215615d1e5SSatish Balay #undef __FUNC__
15225615d1e5SSatish Balay #define __FUNC__ "MatLoad_SeqBAIJ"
152319bcc07fSBarry Smith int MatLoad_SeqBAIJ(Viewer viewer,MatType type,Mat *A)
15242593348eSBarry Smith {
1525b6490206SBarry Smith   Mat_SeqBAIJ  *a;
15262593348eSBarry Smith   Mat          B;
1527de6a44a3SBarry Smith   int          i,nz,ierr,fd,header[4],size,*rowlengths=0,M,N,bs=1,flg;
1528b6490206SBarry Smith   int          *mask,mbs,*jj,j,rowcount,nzcount,k,*browlengths,maskcount;
152935aab85fSBarry Smith   int          kmax,jcount,block,idx,point,nzcountb,extra_rows;
1530a7c10996SSatish Balay   int          *masked, nmask,tmp,bs2,ishift;
1531b6490206SBarry Smith   Scalar       *aa;
153219bcc07fSBarry Smith   MPI_Comm     comm = ((PetscObject) viewer)->comm;
15332593348eSBarry Smith 
15343a40ed3dSBarry Smith   PetscFunctionBegin;
15351a6a6d98SBarry Smith   ierr = OptionsGetInt(PETSC_NULL,"-matload_block_size",&bs,&flg);CHKERRQ(ierr);
1536de6a44a3SBarry Smith   bs2  = bs*bs;
1537b6490206SBarry Smith 
15382593348eSBarry Smith   MPI_Comm_size(comm,&size);
1539cc0fae11SBarry Smith   if (size > 1) SETERRQ(PETSC_ERR_ARG_WRONG,0,"view must have one processor");
154090ace30eSBarry Smith   ierr = ViewerBinaryGetDescriptor(viewer,&fd); CHKERRQ(ierr);
15410752156aSBarry Smith   ierr = PetscBinaryRead(fd,header,4,PETSC_INT); CHKERRQ(ierr);
1542a8c6a408SBarry Smith   if (header[0] != MAT_COOKIE) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,0,"not Mat object");
15432593348eSBarry Smith   M = header[1]; N = header[2]; nz = header[3];
15442593348eSBarry Smith 
1545d64ed03dSBarry Smith   if (header[3] < 0) {
1546a8c6a408SBarry Smith     SETERRQ(PETSC_ERR_FILE_UNEXPECTED,1,"Matrix stored in special format, cannot load as SeqBAIJ");
1547d64ed03dSBarry Smith   }
1548d64ed03dSBarry Smith 
1549a8c6a408SBarry Smith   if (M != N) SETERRQ(PETSC_ERR_SUP,0,"Can only do square matrices");
155035aab85fSBarry Smith 
155135aab85fSBarry Smith   /*
155235aab85fSBarry Smith      This code adds extra rows to make sure the number of rows is
155335aab85fSBarry Smith     divisible by the blocksize
155435aab85fSBarry Smith   */
1555b6490206SBarry Smith   mbs        = M/bs;
155635aab85fSBarry Smith   extra_rows = bs - M + bs*(mbs);
155735aab85fSBarry Smith   if (extra_rows == bs) extra_rows = 0;
155835aab85fSBarry Smith   else                  mbs++;
155935aab85fSBarry Smith   if (extra_rows) {
1560537820f0SBarry Smith     PLogInfo(0,"MatLoad_SeqBAIJ:Padding loaded matrix to match blocksize\n");
156135aab85fSBarry Smith   }
1562b6490206SBarry Smith 
15632593348eSBarry Smith   /* read in row lengths */
156435aab85fSBarry Smith   rowlengths = (int*) PetscMalloc((M+extra_rows)*sizeof(int));CHKPTRQ(rowlengths);
15650752156aSBarry Smith   ierr = PetscBinaryRead(fd,rowlengths,M,PETSC_INT); CHKERRQ(ierr);
156635aab85fSBarry Smith   for ( i=0; i<extra_rows; i++ ) rowlengths[M+i] = 1;
15672593348eSBarry Smith 
1568b6490206SBarry Smith   /* read in column indices */
156935aab85fSBarry Smith   jj = (int*) PetscMalloc( (nz+extra_rows)*sizeof(int) ); CHKPTRQ(jj);
15700752156aSBarry Smith   ierr = PetscBinaryRead(fd,jj,nz,PETSC_INT); CHKERRQ(ierr);
157135aab85fSBarry Smith   for ( i=0; i<extra_rows; i++ ) jj[nz+i] = M+i;
1572b6490206SBarry Smith 
1573b6490206SBarry Smith   /* loop over row lengths determining block row lengths */
1574b6490206SBarry Smith   browlengths = (int *) PetscMalloc(mbs*sizeof(int));CHKPTRQ(browlengths);
1575b6490206SBarry Smith   PetscMemzero(browlengths,mbs*sizeof(int));
157635aab85fSBarry Smith   mask   = (int *) PetscMalloc( 2*mbs*sizeof(int) ); CHKPTRQ(mask);
157735aab85fSBarry Smith   PetscMemzero(mask,mbs*sizeof(int));
157835aab85fSBarry Smith   masked = mask + mbs;
1579b6490206SBarry Smith   rowcount = 0; nzcount = 0;
1580b6490206SBarry Smith   for ( i=0; i<mbs; i++ ) {
158135aab85fSBarry Smith     nmask = 0;
1582b6490206SBarry Smith     for ( j=0; j<bs; j++ ) {
1583b6490206SBarry Smith       kmax = rowlengths[rowcount];
1584b6490206SBarry Smith       for ( k=0; k<kmax; k++ ) {
158535aab85fSBarry Smith         tmp = jj[nzcount++]/bs;
158635aab85fSBarry Smith         if (!mask[tmp]) {masked[nmask++] = tmp; mask[tmp] = 1;}
1587b6490206SBarry Smith       }
1588b6490206SBarry Smith       rowcount++;
1589b6490206SBarry Smith     }
159035aab85fSBarry Smith     browlengths[i] += nmask;
159135aab85fSBarry Smith     /* zero out the mask elements we set */
159235aab85fSBarry Smith     for ( j=0; j<nmask; j++ ) mask[masked[j]] = 0;
1593b6490206SBarry Smith   }
1594b6490206SBarry Smith 
15952593348eSBarry Smith   /* create our matrix */
15963eee16b0SBarry Smith   ierr = MatCreateSeqBAIJ(comm,bs,M+extra_rows,N+extra_rows,0,browlengths,A);CHKERRQ(ierr);
15972593348eSBarry Smith   B = *A;
1598b6490206SBarry Smith   a = (Mat_SeqBAIJ *) B->data;
15992593348eSBarry Smith 
16002593348eSBarry Smith   /* set matrix "i" values */
1601de6a44a3SBarry Smith   a->i[0] = 0;
1602b6490206SBarry Smith   for ( i=1; i<= mbs; i++ ) {
1603b6490206SBarry Smith     a->i[i]      = a->i[i-1] + browlengths[i-1];
1604b6490206SBarry Smith     a->ilen[i-1] = browlengths[i-1];
16052593348eSBarry Smith   }
1606b6490206SBarry Smith   a->nz         = 0;
1607b6490206SBarry Smith   for ( i=0; i<mbs; i++ ) a->nz += browlengths[i];
16082593348eSBarry Smith 
1609b6490206SBarry Smith   /* read in nonzero values */
161035aab85fSBarry Smith   aa = (Scalar *) PetscMalloc((nz+extra_rows)*sizeof(Scalar));CHKPTRQ(aa);
16110752156aSBarry Smith   ierr = PetscBinaryRead(fd,aa,nz,PETSC_SCALAR); CHKERRQ(ierr);
161235aab85fSBarry Smith   for ( i=0; i<extra_rows; i++ ) aa[nz+i] = 1.0;
1613b6490206SBarry Smith 
1614b6490206SBarry Smith   /* set "a" and "j" values into matrix */
1615b6490206SBarry Smith   nzcount = 0; jcount = 0;
1616b6490206SBarry Smith   for ( i=0; i<mbs; i++ ) {
1617b6490206SBarry Smith     nzcountb = nzcount;
161835aab85fSBarry Smith     nmask    = 0;
1619b6490206SBarry Smith     for ( j=0; j<bs; j++ ) {
1620b6490206SBarry Smith       kmax = rowlengths[i*bs+j];
1621b6490206SBarry Smith       for ( k=0; k<kmax; k++ ) {
162235aab85fSBarry Smith         tmp = jj[nzcount++]/bs;
162335aab85fSBarry Smith 	if (!mask[tmp]) { masked[nmask++] = tmp; mask[tmp] = 1;}
1624b6490206SBarry Smith       }
1625b6490206SBarry Smith       rowcount++;
1626b6490206SBarry Smith     }
1627de6a44a3SBarry Smith     /* sort the masked values */
162877c4ece6SBarry Smith     PetscSortInt(nmask,masked);
1629de6a44a3SBarry Smith 
1630b6490206SBarry Smith     /* set "j" values into matrix */
1631b6490206SBarry Smith     maskcount = 1;
163235aab85fSBarry Smith     for ( j=0; j<nmask; j++ ) {
163335aab85fSBarry Smith       a->j[jcount++]  = masked[j];
1634de6a44a3SBarry Smith       mask[masked[j]] = maskcount++;
1635b6490206SBarry Smith     }
1636b6490206SBarry Smith     /* set "a" values into matrix */
1637de6a44a3SBarry Smith     ishift = bs2*a->i[i];
1638b6490206SBarry Smith     for ( j=0; j<bs; j++ ) {
1639b6490206SBarry Smith       kmax = rowlengths[i*bs+j];
1640b6490206SBarry Smith       for ( k=0; k<kmax; k++ ) {
1641de6a44a3SBarry Smith         tmp       = jj[nzcountb]/bs ;
1642de6a44a3SBarry Smith         block     = mask[tmp] - 1;
1643de6a44a3SBarry Smith         point     = jj[nzcountb] - bs*tmp;
1644de6a44a3SBarry Smith         idx       = ishift + bs2*block + j + bs*point;
1645b6490206SBarry Smith         a->a[idx] = aa[nzcountb++];
1646b6490206SBarry Smith       }
1647b6490206SBarry Smith     }
164835aab85fSBarry Smith     /* zero out the mask elements we set */
164935aab85fSBarry Smith     for ( j=0; j<nmask; j++ ) mask[masked[j]] = 0;
1650b6490206SBarry Smith   }
1651a8c6a408SBarry Smith   if (jcount != a->nz) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,0,"Bad binary matrix");
1652b6490206SBarry Smith 
1653b6490206SBarry Smith   PetscFree(rowlengths);
1654b6490206SBarry Smith   PetscFree(browlengths);
1655b6490206SBarry Smith   PetscFree(aa);
1656b6490206SBarry Smith   PetscFree(jj);
1657b6490206SBarry Smith   PetscFree(mask);
1658b6490206SBarry Smith 
1659b6490206SBarry Smith   B->assembled = PETSC_TRUE;
1660de6a44a3SBarry Smith 
16619c01be13SBarry Smith   ierr = MatView_Private(B); CHKERRQ(ierr);
16623a40ed3dSBarry Smith   PetscFunctionReturn(0);
16632593348eSBarry Smith }
16642593348eSBarry Smith 
16652593348eSBarry Smith 
16662593348eSBarry Smith 
1667