1*0e6d2581SBarry Smith /*$Id: baij.c,v 1.194 1999/11/24 21:53:59 bsmith Exp bsmith $*/ 22593348eSBarry Smith 32593348eSBarry Smith /* 4b6490206SBarry Smith Defines the basic matrix operations for the BAIJ (compressed row) 52593348eSBarry Smith matrix storage format. 62593348eSBarry Smith */ 73369ce9aSBarry Smith #include "sys.h" 870f55243SBarry Smith #include "src/mat/impls/baij/seq/baij.h" 91a6a6d98SBarry Smith #include "src/vec/vecimpl.h" 101a6a6d98SBarry Smith #include "src/inline/spops.h" 113b547af2SSatish Balay 122d61bbb3SSatish Balay #define CHUNKSIZE 10 13de6a44a3SBarry Smith 14be5855fcSBarry Smith /* 15be5855fcSBarry Smith Checks for missing diagonals 16be5855fcSBarry Smith */ 17be5855fcSBarry Smith #undef __FUNC__ 18c4992f7dSBarry Smith #define __FUNC__ "MatMissingDiagonal_SeqBAIJ" 19c4992f7dSBarry Smith int MatMissingDiagonal_SeqBAIJ(Mat A) 20be5855fcSBarry Smith { 21be5855fcSBarry Smith Mat_SeqBAIJ *a = (Mat_SeqBAIJ*)A->data; 22883fce79SBarry Smith int *diag,*jj = a->j,i,ierr; 23be5855fcSBarry Smith 24be5855fcSBarry Smith PetscFunctionBegin; 25c4992f7dSBarry Smith ierr = MatMarkDiagonal_SeqBAIJ(A);CHKERRQ(ierr); 26883fce79SBarry Smith diag = a->diag; 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__ 36c4992f7dSBarry Smith #define __FUNC__ "MatMarkDiagonal_SeqBAIJ" 37c4992f7dSBarry Smith int MatMarkDiagonal_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; 43883fce79SBarry Smith if (a->diag) PetscFunctionReturn(0); 44883fce79SBarry Smith 45de6a44a3SBarry Smith diag = (int*)PetscMalloc((m+1)*sizeof(int));CHKPTRQ(diag); 46de6a44a3SBarry Smith PLogObjectMemory(A,(m+1)*sizeof(int)); 477fc0212eSBarry Smith for (i=0; i<m; i++) { 48ecc615b2SBarry Smith diag[i] = a->i[i+1]; 49de6a44a3SBarry Smith for (j=a->i[i]; j<a->i[i+1]; j++) { 50de6a44a3SBarry Smith if (a->j[j] == i) { 51de6a44a3SBarry Smith diag[i] = j; 52de6a44a3SBarry Smith break; 53de6a44a3SBarry Smith } 54de6a44a3SBarry Smith } 55de6a44a3SBarry Smith } 56de6a44a3SBarry Smith a->diag = diag; 573a40ed3dSBarry Smith PetscFunctionReturn(0); 58de6a44a3SBarry Smith } 592593348eSBarry Smith 602593348eSBarry Smith 613b2fbd54SBarry Smith extern int MatToSymmetricIJ_SeqAIJ(int,int*,int*,int,int,int**,int**); 623b2fbd54SBarry Smith 635615d1e5SSatish Balay #undef __FUNC__ 645615d1e5SSatish Balay #define __FUNC__ "MatGetRowIJ_SeqBAIJ" 65*0e6d2581SBarry Smith static int MatGetRowIJ_SeqBAIJ(Mat A,int oshift,PetscTruth symmetric,int *nn,int **ia,int **ja,PetscTruth *done) 663b2fbd54SBarry Smith { 673b2fbd54SBarry Smith Mat_SeqBAIJ *a = (Mat_SeqBAIJ*)A->data; 683b2fbd54SBarry Smith int ierr,n = a->mbs,i; 693b2fbd54SBarry Smith 703a40ed3dSBarry Smith PetscFunctionBegin; 713b2fbd54SBarry Smith *nn = n; 723a40ed3dSBarry Smith if (!ia) PetscFunctionReturn(0); 733b2fbd54SBarry Smith if (symmetric) { 743b2fbd54SBarry Smith ierr = MatToSymmetricIJ_SeqAIJ(n,a->i,a->j,0,oshift,ia,ja);CHKERRQ(ierr); 753b2fbd54SBarry Smith } else if (oshift == 1) { 763b2fbd54SBarry Smith /* temporarily add 1 to i and j indices */ 773b2fbd54SBarry Smith int nz = a->i[n] + 1; 783b2fbd54SBarry Smith for (i=0; i<nz; i++) a->j[i]++; 793b2fbd54SBarry Smith for (i=0; i<n+1; i++) a->i[i]++; 803b2fbd54SBarry Smith *ia = a->i; *ja = a->j; 813b2fbd54SBarry Smith } else { 823b2fbd54SBarry Smith *ia = a->i; *ja = a->j; 833b2fbd54SBarry Smith } 843b2fbd54SBarry Smith 853a40ed3dSBarry Smith PetscFunctionReturn(0); 863b2fbd54SBarry Smith } 873b2fbd54SBarry Smith 885615d1e5SSatish Balay #undef __FUNC__ 89d4bb536fSBarry Smith #define __FUNC__ "MatRestoreRowIJ_SeqBAIJ" 903b2fbd54SBarry Smith static int MatRestoreRowIJ_SeqBAIJ(Mat A,int oshift,PetscTruth symmetric,int *nn,int **ia,int **ja, 913b2fbd54SBarry Smith PetscTruth *done) 923b2fbd54SBarry Smith { 933b2fbd54SBarry Smith Mat_SeqBAIJ *a = (Mat_SeqBAIJ*)A->data; 94606d414cSSatish Balay int i,n = a->mbs,ierr; 953b2fbd54SBarry Smith 963a40ed3dSBarry Smith PetscFunctionBegin; 973a40ed3dSBarry Smith if (!ia) PetscFunctionReturn(0); 983b2fbd54SBarry Smith if (symmetric) { 99606d414cSSatish Balay ierr = PetscFree(*ia);CHKERRQ(ierr); 100606d414cSSatish Balay ierr = PetscFree(*ja);CHKERRQ(ierr); 101af5da2bfSBarry Smith } else if (oshift == 1) { 1023b2fbd54SBarry Smith int nz = a->i[n]; 1033b2fbd54SBarry Smith for (i=0; i<nz; i++) a->j[i]--; 1043b2fbd54SBarry Smith for (i=0; i<n+1; i++) a->i[i]--; 1053b2fbd54SBarry Smith } 1063a40ed3dSBarry Smith PetscFunctionReturn(0); 1073b2fbd54SBarry Smith } 1083b2fbd54SBarry Smith 1092d61bbb3SSatish Balay #undef __FUNC__ 1102d61bbb3SSatish Balay #define __FUNC__ "MatGetBlockSize_SeqBAIJ" 1112d61bbb3SSatish Balay int MatGetBlockSize_SeqBAIJ(Mat mat,int *bs) 1122d61bbb3SSatish Balay { 1132d61bbb3SSatish Balay Mat_SeqBAIJ *baij = (Mat_SeqBAIJ*)mat->data; 1142d61bbb3SSatish Balay 1152d61bbb3SSatish Balay PetscFunctionBegin; 1162d61bbb3SSatish Balay *bs = baij->bs; 1172d61bbb3SSatish Balay PetscFunctionReturn(0); 1182d61bbb3SSatish Balay } 1192d61bbb3SSatish Balay 1202d61bbb3SSatish Balay 1212d61bbb3SSatish Balay #undef __FUNC__ 1222d61bbb3SSatish Balay #define __FUNC__ "MatDestroy_SeqBAIJ" 123e1311b90SBarry Smith int MatDestroy_SeqBAIJ(Mat A) 1242d61bbb3SSatish Balay { 1252d61bbb3SSatish Balay Mat_SeqBAIJ *a = (Mat_SeqBAIJ*)A->data; 126e51c0b9cSSatish Balay int ierr; 1272d61bbb3SSatish Balay 128433994e6SBarry Smith PetscFunctionBegin; 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 } 141aa482453SBarry Smith #if defined(PETSC_USE_LOG) 142e1311b90SBarry Smith PLogObjectState((PetscObject)A,"Rows=%d, Cols=%d, NZ=%d",a->m,a->n,a->nz); 1432d61bbb3SSatish Balay #endif 144606d414cSSatish Balay ierr = PetscFree(a->a);CHKERRQ(ierr); 145606d414cSSatish Balay if (!a->singlemalloc) { 146606d414cSSatish Balay ierr = PetscFree(a->i);CHKERRQ(ierr); 147606d414cSSatish Balay ierr = PetscFree(a->j);CHKERRQ(ierr); 148606d414cSSatish Balay } 149c38d4ed2SBarry Smith if (a->row) { 150c38d4ed2SBarry Smith ierr = ISDestroy(a->row);CHKERRQ(ierr); 151c38d4ed2SBarry Smith } 152c38d4ed2SBarry Smith if (a->col) { 153c38d4ed2SBarry Smith ierr = ISDestroy(a->col);CHKERRQ(ierr); 154c38d4ed2SBarry Smith } 155606d414cSSatish Balay if (a->diag) {ierr = PetscFree(a->diag);CHKERRQ(ierr);} 156606d414cSSatish Balay if (a->ilen) {ierr = PetscFree(a->ilen);CHKERRQ(ierr);} 157606d414cSSatish Balay if (a->imax) {ierr = PetscFree(a->imax);CHKERRQ(ierr);} 158606d414cSSatish Balay if (a->solve_work) {ierr = PetscFree(a->solve_work);CHKERRQ(ierr);} 159606d414cSSatish Balay if (a->mult_work) {ierr = PetscFree(a->mult_work);CHKERRQ(ierr);} 160e51c0b9cSSatish Balay if (a->icol) {ierr = ISDestroy(a->icol);CHKERRQ(ierr);} 161606d414cSSatish Balay if (a->saved_values) {ierr = PetscFree(a->saved_values);CHKERRQ(ierr);} 162606d414cSSatish Balay ierr = PetscFree(a);CHKERRQ(ierr); 1632d61bbb3SSatish Balay PLogObjectDestroy(A); 1642d61bbb3SSatish Balay PetscHeaderDestroy(A); 1652d61bbb3SSatish Balay PetscFunctionReturn(0); 1662d61bbb3SSatish Balay } 1672d61bbb3SSatish Balay 1682d61bbb3SSatish Balay #undef __FUNC__ 1692d61bbb3SSatish Balay #define __FUNC__ "MatSetOption_SeqBAIJ" 1702d61bbb3SSatish Balay int MatSetOption_SeqBAIJ(Mat A,MatOption op) 1712d61bbb3SSatish Balay { 1722d61bbb3SSatish Balay Mat_SeqBAIJ *a = (Mat_SeqBAIJ*)A->data; 1732d61bbb3SSatish Balay 1742d61bbb3SSatish Balay PetscFunctionBegin; 175c4992f7dSBarry Smith if (op == MAT_ROW_ORIENTED) a->roworiented = PETSC_TRUE; 176c4992f7dSBarry Smith else if (op == MAT_COLUMN_ORIENTED) a->roworiented = PETSC_FALSE; 177c4992f7dSBarry Smith else if (op == MAT_COLUMNS_SORTED) a->sorted = PETSC_TRUE; 178c4992f7dSBarry Smith else if (op == MAT_COLUMNS_UNSORTED) a->sorted = PETSC_FALSE; 179c4992f7dSBarry Smith else if (op == MAT_KEEP_ZEROED_ROWS) a->keepzeroedrows = PETSC_TRUE; 1802d61bbb3SSatish Balay else if (op == MAT_NO_NEW_NONZERO_LOCATIONS) a->nonew = 1; 1814787f768SSatish Balay else if (op == MAT_NEW_NONZERO_LOCATION_ERR) a->nonew = -1; 1824787f768SSatish Balay else if (op == MAT_NEW_NONZERO_ALLOCATION_ERR) a->nonew = -2; 1832d61bbb3SSatish Balay else if (op == MAT_YES_NEW_NONZERO_LOCATIONS) a->nonew = 0; 1842d61bbb3SSatish Balay else if (op == MAT_ROWS_SORTED || 1852d61bbb3SSatish Balay op == MAT_ROWS_UNSORTED || 1862d61bbb3SSatish Balay op == MAT_SYMMETRIC || 1872d61bbb3SSatish Balay op == MAT_STRUCTURALLY_SYMMETRIC || 1882d61bbb3SSatish Balay op == MAT_YES_NEW_DIAGONALS || 189b51ba29fSSatish Balay op == MAT_IGNORE_OFF_PROC_ENTRIES || 190b51ba29fSSatish Balay op == MAT_USE_HASH_TABLE) { 191981c4779SBarry Smith PLogInfo(A,"MatSetOption_SeqBAIJ:Option ignored\n"); 1922d61bbb3SSatish Balay } else if (op == MAT_NO_NEW_DIAGONALS) { 1932d61bbb3SSatish Balay SETERRQ(PETSC_ERR_SUP,0,"MAT_NO_NEW_DIAGONALS"); 1942d61bbb3SSatish Balay } else { 1952d61bbb3SSatish Balay SETERRQ(PETSC_ERR_SUP,0,"unknown option"); 1962d61bbb3SSatish Balay } 1972d61bbb3SSatish Balay PetscFunctionReturn(0); 1982d61bbb3SSatish Balay } 1992d61bbb3SSatish Balay 2002d61bbb3SSatish Balay 2012d61bbb3SSatish Balay #undef __FUNC__ 2022d61bbb3SSatish Balay #define __FUNC__ "MatGetSize_SeqBAIJ" 2032d61bbb3SSatish Balay int MatGetSize_SeqBAIJ(Mat A,int *m,int *n) 2042d61bbb3SSatish Balay { 2052d61bbb3SSatish Balay Mat_SeqBAIJ *a = (Mat_SeqBAIJ*)A->data; 2062d61bbb3SSatish Balay 2072d61bbb3SSatish Balay PetscFunctionBegin; 2082d61bbb3SSatish Balay if (m) *m = a->m; 2092d61bbb3SSatish Balay if (n) *n = a->n; 2102d61bbb3SSatish Balay PetscFunctionReturn(0); 2112d61bbb3SSatish Balay } 2122d61bbb3SSatish Balay 2132d61bbb3SSatish Balay #undef __FUNC__ 2142d61bbb3SSatish Balay #define __FUNC__ "MatGetOwnershipRange_SeqBAIJ" 2152d61bbb3SSatish Balay int MatGetOwnershipRange_SeqBAIJ(Mat A,int *m,int *n) 2162d61bbb3SSatish Balay { 2172d61bbb3SSatish Balay Mat_SeqBAIJ *a = (Mat_SeqBAIJ*)A->data; 2182d61bbb3SSatish Balay 2192d61bbb3SSatish Balay PetscFunctionBegin; 2202d61bbb3SSatish Balay *m = 0; *n = a->m; 2212d61bbb3SSatish Balay PetscFunctionReturn(0); 2222d61bbb3SSatish Balay } 2232d61bbb3SSatish Balay 2242d61bbb3SSatish Balay #undef __FUNC__ 2252d61bbb3SSatish Balay #define __FUNC__ "MatGetRow_SeqBAIJ" 2262d61bbb3SSatish Balay int MatGetRow_SeqBAIJ(Mat A,int row,int *nz,int **idx,Scalar **v) 2272d61bbb3SSatish Balay { 2282d61bbb3SSatish Balay Mat_SeqBAIJ *a = (Mat_SeqBAIJ*)A->data; 2292d61bbb3SSatish Balay int itmp,i,j,k,M,*ai,*aj,bs,bn,bp,*idx_i,bs2; 2303f1db9ecSBarry Smith MatScalar *aa,*aa_i; 2313f1db9ecSBarry Smith Scalar *v_i; 2322d61bbb3SSatish Balay 2332d61bbb3SSatish Balay PetscFunctionBegin; 2342d61bbb3SSatish Balay bs = a->bs; 2352d61bbb3SSatish Balay ai = a->i; 2362d61bbb3SSatish Balay aj = a->j; 2372d61bbb3SSatish Balay aa = a->a; 2382d61bbb3SSatish Balay bs2 = a->bs2; 2392d61bbb3SSatish Balay 2402d61bbb3SSatish Balay if (row < 0 || row >= a->m) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Row out of range"); 2412d61bbb3SSatish Balay 2422d61bbb3SSatish Balay bn = row/bs; /* Block number */ 2432d61bbb3SSatish Balay bp = row % bs; /* Block Position */ 2442d61bbb3SSatish Balay M = ai[bn+1] - ai[bn]; 2452d61bbb3SSatish Balay *nz = bs*M; 2462d61bbb3SSatish Balay 2472d61bbb3SSatish Balay if (v) { 2482d61bbb3SSatish Balay *v = 0; 2492d61bbb3SSatish Balay if (*nz) { 2502d61bbb3SSatish Balay *v = (Scalar*)PetscMalloc((*nz)*sizeof(Scalar));CHKPTRQ(*v); 2512d61bbb3SSatish Balay for (i=0; i<M; i++) { /* for each block in the block row */ 2522d61bbb3SSatish Balay v_i = *v + i*bs; 2532d61bbb3SSatish Balay aa_i = aa + bs2*(ai[bn] + i); 2542d61bbb3SSatish Balay for (j=bp,k=0; j<bs2; j+=bs,k++) {v_i[k] = aa_i[j];} 2552d61bbb3SSatish Balay } 2562d61bbb3SSatish Balay } 2572d61bbb3SSatish Balay } 2582d61bbb3SSatish Balay 2592d61bbb3SSatish Balay if (idx) { 2602d61bbb3SSatish Balay *idx = 0; 2612d61bbb3SSatish Balay if (*nz) { 2622d61bbb3SSatish Balay *idx = (int*)PetscMalloc((*nz)*sizeof(int));CHKPTRQ(*idx); 2632d61bbb3SSatish Balay for (i=0; i<M; i++) { /* for each block in the block row */ 2642d61bbb3SSatish Balay idx_i = *idx + i*bs; 2652d61bbb3SSatish Balay itmp = bs*aj[ai[bn] + i]; 2662d61bbb3SSatish Balay for (j=0; j<bs; j++) {idx_i[j] = itmp++;} 2672d61bbb3SSatish Balay } 2682d61bbb3SSatish Balay } 2692d61bbb3SSatish Balay } 2702d61bbb3SSatish Balay PetscFunctionReturn(0); 2712d61bbb3SSatish Balay } 2722d61bbb3SSatish Balay 2732d61bbb3SSatish Balay #undef __FUNC__ 2742d61bbb3SSatish Balay #define __FUNC__ "MatRestoreRow_SeqBAIJ" 2752d61bbb3SSatish Balay int MatRestoreRow_SeqBAIJ(Mat A,int row,int *nz,int **idx,Scalar **v) 2762d61bbb3SSatish Balay { 277606d414cSSatish Balay int ierr; 278606d414cSSatish Balay 2792d61bbb3SSatish Balay PetscFunctionBegin; 280606d414cSSatish Balay if (idx) {if (*idx) {ierr = PetscFree(*idx);CHKERRQ(ierr);}} 281606d414cSSatish Balay if (v) {if (*v) {ierr = PetscFree(*v);CHKERRQ(ierr);}} 2822d61bbb3SSatish Balay PetscFunctionReturn(0); 2832d61bbb3SSatish Balay } 2842d61bbb3SSatish Balay 2852d61bbb3SSatish Balay #undef __FUNC__ 2862d61bbb3SSatish Balay #define __FUNC__ "MatTranspose_SeqBAIJ" 2872d61bbb3SSatish Balay int MatTranspose_SeqBAIJ(Mat A,Mat *B) 2882d61bbb3SSatish Balay { 2892d61bbb3SSatish Balay Mat_SeqBAIJ *a=(Mat_SeqBAIJ *)A->data; 2902d61bbb3SSatish Balay Mat C; 2912d61bbb3SSatish Balay int i,j,k,ierr,*aj=a->j,*ai=a->i,bs=a->bs,mbs=a->mbs,nbs=a->nbs,len,*col; 292*0e6d2581SBarry Smith int *rows,*cols,bs2=a->bs2,refct; 2933f1db9ecSBarry Smith MatScalar *array = a->a; 2942d61bbb3SSatish Balay 2952d61bbb3SSatish Balay PetscFunctionBegin; 296*0e6d2581SBarry Smith if (!B && mbs!=nbs) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Square matrix only for in-place"); 2972d61bbb3SSatish Balay col = (int*)PetscMalloc((1+nbs)*sizeof(int));CHKPTRQ(col); 298549d3d68SSatish Balay ierr = PetscMemzero(col,(1+nbs)*sizeof(int));CHKERRQ(ierr); 2992d61bbb3SSatish Balay 3002d61bbb3SSatish Balay for (i=0; i<ai[mbs]; i++) col[aj[i]] += 1; 3012d61bbb3SSatish Balay ierr = MatCreateSeqBAIJ(A->comm,bs,a->n,a->m,PETSC_NULL,col,&C);CHKERRQ(ierr); 302606d414cSSatish Balay ierr = PetscFree(col);CHKERRQ(ierr); 3032d61bbb3SSatish Balay rows = (int*)PetscMalloc(2*bs*sizeof(int));CHKPTRQ(rows); 3042d61bbb3SSatish Balay cols = rows + bs; 3052d61bbb3SSatish Balay for (i=0; i<mbs; i++) { 3062d61bbb3SSatish Balay cols[0] = i*bs; 3072d61bbb3SSatish Balay for (k=1; k<bs; k++) cols[k] = cols[k-1] + 1; 3082d61bbb3SSatish Balay len = ai[i+1] - ai[i]; 3092d61bbb3SSatish Balay for (j=0; j<len; j++) { 3102d61bbb3SSatish Balay rows[0] = (*aj++)*bs; 3112d61bbb3SSatish Balay for (k=1; k<bs; k++) rows[k] = rows[k-1] + 1; 3122d61bbb3SSatish Balay ierr = MatSetValues(C,bs,rows,bs,cols,array,INSERT_VALUES);CHKERRQ(ierr); 3132d61bbb3SSatish Balay array += bs2; 3142d61bbb3SSatish Balay } 3152d61bbb3SSatish Balay } 316606d414cSSatish Balay ierr = PetscFree(rows);CHKERRQ(ierr); 3172d61bbb3SSatish Balay 3182d61bbb3SSatish Balay ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3192d61bbb3SSatish Balay ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3202d61bbb3SSatish Balay 321c4992f7dSBarry Smith if (B) { 3222d61bbb3SSatish Balay *B = C; 3232d61bbb3SSatish Balay } else { 324f830108cSBarry Smith PetscOps *Abops; 325cc2dc46cSBarry Smith MatOps Aops; 326f830108cSBarry Smith 3272d61bbb3SSatish Balay /* This isn't really an in-place transpose */ 328606d414cSSatish Balay ierr = PetscFree(a->a);CHKERRQ(ierr); 329606d414cSSatish Balay if (!a->singlemalloc) { 330606d414cSSatish Balay ierr = PetscFree(a->i);CHKERRQ(ierr); 331606d414cSSatish Balay ierr = PetscFree(a->j);CHKERRQ(ierr); 332606d414cSSatish Balay } 333606d414cSSatish Balay if (a->diag) {ierr = PetscFree(a->diag);CHKERRQ(ierr);} 334606d414cSSatish Balay if (a->ilen) {ierr = PetscFree(a->ilen);CHKERRQ(ierr);} 335606d414cSSatish Balay if (a->imax) {ierr = PetscFree(a->imax);CHKERRQ(ierr);} 336606d414cSSatish Balay if (a->solve_work) {ierr = PetscFree(a->solve_work);CHKERRQ(ierr);} 337606d414cSSatish Balay ierr = PetscFree(a);CHKERRQ(ierr); 338f830108cSBarry Smith 3397413bad6SBarry Smith 3407413bad6SBarry Smith ierr = MapDestroy(A->rmap);CHKERRQ(ierr); 3417413bad6SBarry Smith ierr = MapDestroy(A->cmap);CHKERRQ(ierr); 3427413bad6SBarry Smith 343f830108cSBarry Smith /* 344f830108cSBarry Smith This is horrible, horrible code. We need to keep the 345f830108cSBarry Smith A pointers for the bops and ops but copy everything 346f830108cSBarry Smith else from C. 347f830108cSBarry Smith */ 348f830108cSBarry Smith Abops = A->bops; 349f830108cSBarry Smith Aops = A->ops; 350*0e6d2581SBarry Smith refct = A->refct; 351549d3d68SSatish Balay ierr = PetscMemcpy(A,C,sizeof(struct _p_Mat));CHKERRQ(ierr); 352f830108cSBarry Smith A->bops = Abops; 353f830108cSBarry Smith A->ops = Aops; 35427a8da17SBarry Smith A->qlist = 0; 355*0e6d2581SBarry Smith A->refct = refct; 356f830108cSBarry Smith 3572d61bbb3SSatish Balay PetscHeaderDestroy(C); 3582d61bbb3SSatish Balay } 3592d61bbb3SSatish Balay PetscFunctionReturn(0); 3602d61bbb3SSatish Balay } 3612d61bbb3SSatish Balay 3625615d1e5SSatish Balay #undef __FUNC__ 363d4bb536fSBarry Smith #define __FUNC__ "MatView_SeqBAIJ_Binary" 364b6490206SBarry Smith static int MatView_SeqBAIJ_Binary(Mat A,Viewer viewer) 3652593348eSBarry Smith { 366b6490206SBarry Smith Mat_SeqBAIJ *a = (Mat_SeqBAIJ*)A->data; 3679df24120SSatish Balay int i,fd,*col_lens,ierr,bs = a->bs,count,*jj,j,k,l,bs2=a->bs2; 368b6490206SBarry Smith Scalar *aa; 369ce6f0cecSBarry Smith FILE *file; 3702593348eSBarry Smith 3713a40ed3dSBarry Smith PetscFunctionBegin; 37290ace30eSBarry Smith ierr = ViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr); 3732593348eSBarry Smith col_lens = (int*)PetscMalloc((4+a->m)*sizeof(int));CHKPTRQ(col_lens); 3742593348eSBarry Smith col_lens[0] = MAT_COOKIE; 3753b2fbd54SBarry Smith 3762593348eSBarry Smith col_lens[1] = a->m; 3772593348eSBarry Smith col_lens[2] = a->n; 3787e67e3f9SSatish Balay col_lens[3] = a->nz*bs2; 3792593348eSBarry Smith 3802593348eSBarry Smith /* store lengths of each row and write (including header) to file */ 381b6490206SBarry Smith count = 0; 382b6490206SBarry Smith for (i=0; i<a->mbs; i++) { 383b6490206SBarry Smith for (j=0; j<bs; j++) { 384b6490206SBarry Smith col_lens[4+count++] = bs*(a->i[i+1] - a->i[i]); 385b6490206SBarry Smith } 3862593348eSBarry Smith } 3870752156aSBarry Smith ierr = PetscBinaryWrite(fd,col_lens,4+a->m,PETSC_INT,1);CHKERRQ(ierr); 388606d414cSSatish Balay ierr = PetscFree(col_lens);CHKERRQ(ierr); 3892593348eSBarry Smith 3902593348eSBarry Smith /* store column indices (zero start index) */ 39166963ce1SSatish Balay jj = (int*)PetscMalloc((a->nz+1)*bs2*sizeof(int));CHKPTRQ(jj); 392b6490206SBarry Smith count = 0; 393b6490206SBarry Smith for (i=0; i<a->mbs; i++) { 394b6490206SBarry Smith for (j=0; j<bs; j++) { 395b6490206SBarry Smith for (k=a->i[i]; k<a->i[i+1]; k++) { 396b6490206SBarry Smith for (l=0; l<bs; l++) { 397b6490206SBarry Smith jj[count++] = bs*a->j[k] + l; 3982593348eSBarry Smith } 3992593348eSBarry Smith } 400b6490206SBarry Smith } 401b6490206SBarry Smith } 4020752156aSBarry Smith ierr = PetscBinaryWrite(fd,jj,bs2*a->nz,PETSC_INT,0);CHKERRQ(ierr); 403606d414cSSatish Balay ierr = PetscFree(jj);CHKERRQ(ierr); 4042593348eSBarry Smith 4052593348eSBarry Smith /* store nonzero values */ 40666963ce1SSatish Balay aa = (Scalar*)PetscMalloc((a->nz+1)*bs2*sizeof(Scalar));CHKPTRQ(aa); 407b6490206SBarry Smith count = 0; 408b6490206SBarry Smith for (i=0; i<a->mbs; i++) { 409b6490206SBarry Smith for (j=0; j<bs; j++) { 410b6490206SBarry Smith for (k=a->i[i]; k<a->i[i+1]; k++) { 411b6490206SBarry Smith for (l=0; l<bs; l++) { 4127e67e3f9SSatish Balay aa[count++] = a->a[bs2*k + l*bs + j]; 413b6490206SBarry Smith } 414b6490206SBarry Smith } 415b6490206SBarry Smith } 416b6490206SBarry Smith } 4170752156aSBarry Smith ierr = PetscBinaryWrite(fd,aa,bs2*a->nz,PETSC_SCALAR,0);CHKERRQ(ierr); 418606d414cSSatish Balay ierr = PetscFree(aa);CHKERRQ(ierr); 419ce6f0cecSBarry Smith 420ce6f0cecSBarry Smith ierr = ViewerBinaryGetInfoPointer(viewer,&file);CHKERRQ(ierr); 421ce6f0cecSBarry Smith if (file) { 422ce6f0cecSBarry Smith fprintf(file,"-matload_block_size %d\n",a->bs); 423ce6f0cecSBarry Smith } 4243a40ed3dSBarry Smith PetscFunctionReturn(0); 4252593348eSBarry Smith } 4262593348eSBarry Smith 4275615d1e5SSatish Balay #undef __FUNC__ 428d4bb536fSBarry Smith #define __FUNC__ "MatView_SeqBAIJ_ASCII" 429b6490206SBarry Smith static int MatView_SeqBAIJ_ASCII(Mat A,Viewer viewer) 4302593348eSBarry Smith { 431b6490206SBarry Smith Mat_SeqBAIJ *a = (Mat_SeqBAIJ*)A->data; 4329df24120SSatish Balay int ierr,i,j,format,bs = a->bs,k,l,bs2=a->bs2; 4332593348eSBarry Smith char *outputname; 4342593348eSBarry Smith 4353a40ed3dSBarry Smith PetscFunctionBegin; 43677ed5343SBarry Smith ierr = ViewerGetOutputname(viewer,&outputname);CHKERRQ(ierr); 437888f2ed8SSatish Balay ierr = ViewerGetFormat(viewer,&format);CHKERRQ(ierr); 438639f9d9dSBarry Smith if (format == VIEWER_FORMAT_ASCII_INFO || format == VIEWER_FORMAT_ASCII_INFO_LONG) { 439d132466eSBarry Smith ierr = ViewerASCIIPrintf(viewer," block size is %d\n",bs);CHKERRQ(ierr); 4400ef38995SBarry Smith } else if (format == VIEWER_FORMAT_ASCII_MATLAB) { 4416831982aSBarry Smith SETERRQ(PETSC_ERR_SUP,0,"Matlab format not supported"); 4420ef38995SBarry Smith } else if (format == VIEWER_FORMAT_ASCII_COMMON) { 4436831982aSBarry Smith ierr = ViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr); 44444cd7ae7SLois Curfman McInnes for (i=0; i<a->mbs; i++) { 44544cd7ae7SLois Curfman McInnes for (j=0; j<bs; j++) { 4466831982aSBarry Smith ierr = ViewerASCIIPrintf(viewer,"row %d:",i*bs+j);CHKERRQ(ierr); 44744cd7ae7SLois Curfman McInnes for (k=a->i[i]; k<a->i[i+1]; k++) { 44844cd7ae7SLois Curfman McInnes for (l=0; l<bs; l++) { 449aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX) 450*0e6d2581SBarry Smith if (PetscImaginaryPart(a->a[bs2*k + l*bs + j]) > 0.0 && PetscRealPart(a->a[bs2*k + l*bs + j]) != 0.0) { 4516831982aSBarry Smith ierr = ViewerASCIIPrintf(viewer," %d %g + %g i",bs*a->j[k]+l, 452*0e6d2581SBarry Smith PetscRealPart(a->a[bs2*k + l*bs + j]),PetscImaginaryPart(a->a[bs2*k + l*bs + j]));CHKERRQ(ierr); 453*0e6d2581SBarry Smith } else if (PetscImaginaryPart(a->a[bs2*k + l*bs + j]) < 0.0 && PetscRealPart(a->a[bs2*k + l*bs + j]) != 0.0) { 4546831982aSBarry Smith ierr = ViewerASCIIPrintf(viewer," %d %g - %g i",bs*a->j[k]+l, 455*0e6d2581SBarry Smith PetscRealPart(a->a[bs2*k + l*bs + j]),-PetscImaginaryPart(a->a[bs2*k + l*bs + j]));CHKERRQ(ierr); 456*0e6d2581SBarry Smith } else if (PetscRealPart(a->a[bs2*k + l*bs + j]) != 0.0) { 457*0e6d2581SBarry Smith ierr = ViewerASCIIPrintf(viewer," %d %g ",bs*a->j[k]+l,PetscRealPart(a->a[bs2*k + l*bs + j]));CHKERRQ(ierr); 4580ef38995SBarry Smith } 45944cd7ae7SLois Curfman McInnes #else 4600ef38995SBarry Smith if (a->a[bs2*k + l*bs + j] != 0.0) { 4616831982aSBarry Smith ierr = ViewerASCIIPrintf(viewer," %d %g ",bs*a->j[k]+l,a->a[bs2*k + l*bs + j]);CHKERRQ(ierr); 4620ef38995SBarry Smith } 46344cd7ae7SLois Curfman McInnes #endif 46444cd7ae7SLois Curfman McInnes } 46544cd7ae7SLois Curfman McInnes } 4666831982aSBarry Smith ierr = ViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 46744cd7ae7SLois Curfman McInnes } 46844cd7ae7SLois Curfman McInnes } 4696831982aSBarry Smith ierr = ViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr); 4700ef38995SBarry Smith } else { 4716831982aSBarry Smith ierr = ViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr); 472b6490206SBarry Smith for (i=0; i<a->mbs; i++) { 473b6490206SBarry Smith for (j=0; j<bs; j++) { 4746831982aSBarry Smith ierr = ViewerASCIIPrintf(viewer,"row %d:",i*bs+j);CHKERRQ(ierr); 475b6490206SBarry Smith for (k=a->i[i]; k<a->i[i+1]; k++) { 476b6490206SBarry Smith for (l=0; l<bs; l++) { 477aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX) 478*0e6d2581SBarry Smith if (PetscImaginaryPart(a->a[bs2*k + l*bs + j]) > 0.0) { 4796831982aSBarry Smith ierr = ViewerASCIIPrintf(viewer," %d %g + %g i",bs*a->j[k]+l, 480*0e6d2581SBarry Smith PetscRealPart(a->a[bs2*k + l*bs + j]),PetscImaginaryPart(a->a[bs2*k + l*bs + j]));CHKERRQ(ierr); 481*0e6d2581SBarry Smith } else if (PetscImaginaryPart(a->a[bs2*k + l*bs + j]) < 0.0) { 4826831982aSBarry Smith ierr = ViewerASCIIPrintf(viewer," %d %g - %g i",bs*a->j[k]+l, 483*0e6d2581SBarry Smith PetscRealPart(a->a[bs2*k + l*bs + j]),-PetscImaginaryPart(a->a[bs2*k + l*bs + j]));CHKERRQ(ierr); 4840ef38995SBarry Smith } else { 485*0e6d2581SBarry Smith ierr = ViewerASCIIPrintf(viewer," %d %g ",bs*a->j[k]+l,PetscRealPart(a->a[bs2*k + l*bs + j]));CHKERRQ(ierr); 48688685aaeSLois Curfman McInnes } 48788685aaeSLois Curfman McInnes #else 4886831982aSBarry Smith ierr = ViewerASCIIPrintf(viewer," %d %g ",bs*a->j[k]+l,a->a[bs2*k + l*bs + j]);CHKERRQ(ierr); 48988685aaeSLois Curfman McInnes #endif 4902593348eSBarry Smith } 4912593348eSBarry Smith } 4926831982aSBarry Smith ierr = ViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 4932593348eSBarry Smith } 4942593348eSBarry Smith } 4956831982aSBarry Smith ierr = ViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr); 496b6490206SBarry Smith } 4976831982aSBarry Smith ierr = ViewerFlush(viewer);CHKERRQ(ierr); 4983a40ed3dSBarry Smith PetscFunctionReturn(0); 4992593348eSBarry Smith } 5002593348eSBarry Smith 5015615d1e5SSatish Balay #undef __FUNC__ 50277ed5343SBarry Smith #define __FUNC__ "MatView_SeqBAIJ_Draw_Zoom" 50377ed5343SBarry Smith static int MatView_SeqBAIJ_Draw_Zoom(Draw draw,void *Aa) 5043270192aSSatish Balay { 50577ed5343SBarry Smith Mat A = (Mat) Aa; 5063270192aSSatish Balay Mat_SeqBAIJ *a=(Mat_SeqBAIJ*)A->data; 5077dce120fSSatish Balay int row,ierr,i,j,k,l,mbs=a->mbs,color,bs=a->bs,bs2=a->bs2,rank; 508*0e6d2581SBarry Smith PetscReal xl,yl,xr,yr,x_l,x_r,y_l,y_r; 5093f1db9ecSBarry Smith MatScalar *aa; 51077ed5343SBarry Smith MPI_Comm comm; 51177ed5343SBarry Smith Viewer viewer; 5123270192aSSatish Balay 5133a40ed3dSBarry Smith PetscFunctionBegin; 51477ed5343SBarry Smith /* 51577ed5343SBarry Smith This is nasty. If this is called from an originally parallel matrix 51677ed5343SBarry Smith then all processes call this,but only the first has the matrix so the 51777ed5343SBarry Smith rest should return immediately. 51877ed5343SBarry Smith */ 51977ed5343SBarry Smith ierr = PetscObjectGetComm((PetscObject)draw,&comm);CHKERRQ(ierr); 520d132466eSBarry Smith ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 52177ed5343SBarry Smith if (rank) PetscFunctionReturn(0); 5223270192aSSatish Balay 52377ed5343SBarry Smith ierr = PetscObjectQuery((PetscObject)A,"Zoomviewer",(PetscObject*)&viewer);CHKERRQ(ierr); 52477ed5343SBarry Smith 52577ed5343SBarry Smith ierr = DrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr); 52677ed5343SBarry Smith 5273270192aSSatish Balay /* loop over matrix elements drawing boxes */ 5283270192aSSatish Balay color = DRAW_BLUE; 5293270192aSSatish Balay for (i=0,row=0; i<mbs; i++,row+=bs) { 5303270192aSSatish Balay for (j=a->i[i]; j<a->i[i+1]; j++) { 5313270192aSSatish Balay y_l = a->m - row - 1.0; y_r = y_l + 1.0; 5323270192aSSatish Balay x_l = a->j[j]*bs; x_r = x_l + 1.0; 5333270192aSSatish Balay aa = a->a + j*bs2; 5343270192aSSatish Balay for (k=0; k<bs; k++) { 5353270192aSSatish Balay for (l=0; l<bs; l++) { 536*0e6d2581SBarry Smith if (PetscRealPart(*aa++) >= 0.) continue; 537433994e6SBarry Smith ierr = DrawRectangle(draw,x_l+k,y_l-l,x_r+k,y_r-l,color,color,color,color);CHKERRQ(ierr); 5383270192aSSatish Balay } 5393270192aSSatish Balay } 5403270192aSSatish Balay } 5413270192aSSatish Balay } 5423270192aSSatish Balay color = DRAW_CYAN; 5433270192aSSatish Balay for (i=0,row=0; i<mbs; i++,row+=bs) { 5443270192aSSatish Balay for (j=a->i[i]; j<a->i[i+1]; j++) { 5453270192aSSatish Balay y_l = a->m - row - 1.0; y_r = y_l + 1.0; 5463270192aSSatish Balay x_l = a->j[j]*bs; x_r = x_l + 1.0; 5473270192aSSatish Balay aa = a->a + j*bs2; 5483270192aSSatish Balay for (k=0; k<bs; k++) { 5493270192aSSatish Balay for (l=0; l<bs; l++) { 550*0e6d2581SBarry Smith if (PetscRealPart(*aa++) != 0.) continue; 551433994e6SBarry Smith ierr = DrawRectangle(draw,x_l+k,y_l-l,x_r+k,y_r-l,color,color,color,color);CHKERRQ(ierr); 5523270192aSSatish Balay } 5533270192aSSatish Balay } 5543270192aSSatish Balay } 5553270192aSSatish Balay } 5563270192aSSatish Balay 5573270192aSSatish Balay color = DRAW_RED; 5583270192aSSatish Balay for (i=0,row=0; i<mbs; i++,row+=bs) { 5593270192aSSatish Balay for (j=a->i[i]; j<a->i[i+1]; j++) { 5603270192aSSatish Balay y_l = a->m - row - 1.0; y_r = y_l + 1.0; 5613270192aSSatish Balay x_l = a->j[j]*bs; x_r = x_l + 1.0; 5623270192aSSatish Balay aa = a->a + j*bs2; 5633270192aSSatish Balay for (k=0; k<bs; k++) { 5643270192aSSatish Balay for (l=0; l<bs; l++) { 565*0e6d2581SBarry Smith if (PetscRealPart(*aa++) <= 0.) continue; 566433994e6SBarry Smith ierr = DrawRectangle(draw,x_l+k,y_l-l,x_r+k,y_r-l,color,color,color,color);CHKERRQ(ierr); 5673270192aSSatish Balay } 5683270192aSSatish Balay } 5693270192aSSatish Balay } 5703270192aSSatish Balay } 57177ed5343SBarry Smith PetscFunctionReturn(0); 57277ed5343SBarry Smith } 5733270192aSSatish Balay 57477ed5343SBarry Smith #undef __FUNC__ 57577ed5343SBarry Smith #define __FUNC__ "MatView_SeqBAIJ_Draw" 57677ed5343SBarry Smith static int MatView_SeqBAIJ_Draw(Mat A,Viewer viewer) 57777ed5343SBarry Smith { 57877ed5343SBarry Smith Mat_SeqBAIJ *a=(Mat_SeqBAIJ*)A->data; 5797dce120fSSatish Balay int ierr; 580*0e6d2581SBarry Smith PetscReal xl,yl,xr,yr,w,h; 58177ed5343SBarry Smith Draw draw; 58277ed5343SBarry Smith PetscTruth isnull; 5833270192aSSatish Balay 58477ed5343SBarry Smith PetscFunctionBegin; 58577ed5343SBarry Smith 58677ed5343SBarry Smith ierr = ViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr); 58777ed5343SBarry Smith ierr = DrawIsNull(draw,&isnull);CHKERRQ(ierr); if (isnull) PetscFunctionReturn(0); 58877ed5343SBarry Smith 58977ed5343SBarry Smith ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",(PetscObject)viewer);CHKERRQ(ierr); 59077ed5343SBarry Smith xr = a->n; yr = a->m; h = yr/10.0; w = xr/10.0; 59177ed5343SBarry Smith xr += w; yr += h; xl = -w; yl = -h; 5923270192aSSatish Balay ierr = DrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr); 59377ed5343SBarry Smith ierr = DrawZoom(draw,MatView_SeqBAIJ_Draw_Zoom,A);CHKERRQ(ierr); 59477ed5343SBarry Smith ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",PETSC_NULL);CHKERRQ(ierr); 5953a40ed3dSBarry Smith PetscFunctionReturn(0); 5963270192aSSatish Balay } 5973270192aSSatish Balay 5985615d1e5SSatish Balay #undef __FUNC__ 599d4bb536fSBarry Smith #define __FUNC__ "MatView_SeqBAIJ" 600e1311b90SBarry Smith int MatView_SeqBAIJ(Mat A,Viewer viewer) 6012593348eSBarry Smith { 60219bcc07fSBarry Smith int ierr; 6036831982aSBarry Smith PetscTruth issocket,isascii,isbinary,isdraw; 6042593348eSBarry Smith 6053a40ed3dSBarry Smith PetscFunctionBegin; 6066831982aSBarry Smith ierr = PetscTypeCompare((PetscObject)viewer,SOCKET_VIEWER,&issocket);CHKERRQ(ierr); 6076831982aSBarry Smith ierr = PetscTypeCompare((PetscObject)viewer,ASCII_VIEWER,&isascii);CHKERRQ(ierr); 6086831982aSBarry Smith ierr = PetscTypeCompare((PetscObject)viewer,BINARY_VIEWER,&isbinary);CHKERRQ(ierr); 6096831982aSBarry Smith ierr = PetscTypeCompare((PetscObject)viewer,DRAW_VIEWER,&isdraw);CHKERRQ(ierr); 6100f5bd95cSBarry Smith if (issocket) { 6117b2a1423SBarry Smith SETERRQ(PETSC_ERR_SUP,0,"Socket viewer not supported"); 6120f5bd95cSBarry Smith } else if (isascii){ 6133a40ed3dSBarry Smith ierr = MatView_SeqBAIJ_ASCII(A,viewer);CHKERRQ(ierr); 6140f5bd95cSBarry Smith } else if (isbinary) { 6153a40ed3dSBarry Smith ierr = MatView_SeqBAIJ_Binary(A,viewer);CHKERRQ(ierr); 6160f5bd95cSBarry Smith } else if (isdraw) { 6173a40ed3dSBarry Smith ierr = MatView_SeqBAIJ_Draw(A,viewer);CHKERRQ(ierr); 6185cd90555SBarry Smith } else { 6190f5bd95cSBarry Smith SETERRQ1(1,1,"Viewer type %s not supported by SeqBAIJ matrices",((PetscObject)viewer)->type_name); 6202593348eSBarry Smith } 6213a40ed3dSBarry Smith PetscFunctionReturn(0); 6222593348eSBarry Smith } 623b6490206SBarry Smith 624cd0e1443SSatish Balay 6255615d1e5SSatish Balay #undef __FUNC__ 6262d61bbb3SSatish Balay #define __FUNC__ "MatGetValues_SeqBAIJ" 6272d61bbb3SSatish Balay int MatGetValues_SeqBAIJ(Mat A,int m,int *im,int n,int *in,Scalar *v) 628cd0e1443SSatish Balay { 629cd0e1443SSatish Balay Mat_SeqBAIJ *a = (Mat_SeqBAIJ*)A->data; 6302d61bbb3SSatish Balay int *rp,k,low,high,t,row,nrow,i,col,l,*aj = a->j; 6312d61bbb3SSatish Balay int *ai = a->i,*ailen = a->ilen; 6322d61bbb3SSatish Balay int brow,bcol,ridx,cidx,bs=a->bs,bs2=a->bs2; 6333f1db9ecSBarry Smith MatScalar *ap,*aa = a->a,zero = 0.0; 634cd0e1443SSatish Balay 6353a40ed3dSBarry Smith PetscFunctionBegin; 6362d61bbb3SSatish Balay for (k=0; k<m; k++) { /* loop over rows */ 637cd0e1443SSatish Balay row = im[k]; brow = row/bs; 638a8c6a408SBarry Smith if (row < 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Negative row"); 639a8c6a408SBarry Smith if (row >= a->m) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Row too large"); 6402d61bbb3SSatish Balay rp = aj + ai[brow] ; ap = aa + bs2*ai[brow] ; 6412c3acbe9SBarry Smith nrow = ailen[brow]; 6422d61bbb3SSatish Balay for (l=0; l<n; l++) { /* loop over columns */ 643a8c6a408SBarry Smith if (in[l] < 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Negative column"); 644a8c6a408SBarry Smith if (in[l] >= a->n) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Column too large"); 6452d61bbb3SSatish Balay col = in[l] ; 6462d61bbb3SSatish Balay bcol = col/bs; 6472d61bbb3SSatish Balay cidx = col%bs; 6482d61bbb3SSatish Balay ridx = row%bs; 6492d61bbb3SSatish Balay high = nrow; 6502d61bbb3SSatish Balay low = 0; /* assume unsorted */ 6512d61bbb3SSatish Balay while (high-low > 5) { 652cd0e1443SSatish Balay t = (low+high)/2; 653cd0e1443SSatish Balay if (rp[t] > bcol) high = t; 654cd0e1443SSatish Balay else low = t; 655cd0e1443SSatish Balay } 656cd0e1443SSatish Balay for (i=low; i<high; i++) { 657cd0e1443SSatish Balay if (rp[i] > bcol) break; 658cd0e1443SSatish Balay if (rp[i] == bcol) { 6592d61bbb3SSatish Balay *v++ = ap[bs2*i+bs*cidx+ridx]; 6602d61bbb3SSatish Balay goto finished; 661cd0e1443SSatish Balay } 662cd0e1443SSatish Balay } 6632d61bbb3SSatish Balay *v++ = zero; 6642d61bbb3SSatish Balay finished:; 665cd0e1443SSatish Balay } 666cd0e1443SSatish Balay } 6673a40ed3dSBarry Smith PetscFunctionReturn(0); 668cd0e1443SSatish Balay } 669cd0e1443SSatish Balay 6702d61bbb3SSatish Balay 6715615d1e5SSatish Balay #undef __FUNC__ 67205a5f48eSSatish Balay #define __FUNC__ "MatSetValuesBlocked_SeqBAIJ" 67392c4ed94SBarry Smith int MatSetValuesBlocked_SeqBAIJ(Mat A,int m,int *im,int n,int *in,Scalar *v,InsertMode is) 67492c4ed94SBarry Smith { 67592c4ed94SBarry Smith Mat_SeqBAIJ *a = (Mat_SeqBAIJ*)A->data; 6768a84c255SSatish Balay int *rp,k,low,high,t,ii,jj,row,nrow,i,col,l,rmax,N,sorted=a->sorted; 677dd9472c6SBarry Smith int *imax=a->imax,*ai=a->i,*ailen=a->ilen,roworiented=a->roworiented; 678549d3d68SSatish Balay int *aj=a->j,nonew=a->nonew,bs2=a->bs2,bs=a->bs,stepval,ierr; 6793f1db9ecSBarry Smith Scalar *value = v; 6803f1db9ecSBarry Smith MatScalar *ap,*aa=a->a,*bap; 68192c4ed94SBarry Smith 6823a40ed3dSBarry Smith PetscFunctionBegin; 6830e324ae4SSatish Balay if (roworiented) { 6840e324ae4SSatish Balay stepval = (n-1)*bs; 6850e324ae4SSatish Balay } else { 6860e324ae4SSatish Balay stepval = (m-1)*bs; 6870e324ae4SSatish Balay } 68892c4ed94SBarry Smith for (k=0; k<m; k++) { /* loop over added rows */ 68992c4ed94SBarry Smith row = im[k]; 6905ef9f2a5SBarry Smith if (row < 0) continue; 691aa482453SBarry Smith #if defined(PETSC_USE_BOPT_g) 692a8c6a408SBarry Smith if (row >= a->mbs) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Row too large"); 69392c4ed94SBarry Smith #endif 69492c4ed94SBarry Smith rp = aj + ai[row]; 69592c4ed94SBarry Smith ap = aa + bs2*ai[row]; 69692c4ed94SBarry Smith rmax = imax[row]; 69792c4ed94SBarry Smith nrow = ailen[row]; 69892c4ed94SBarry Smith low = 0; 69992c4ed94SBarry Smith for (l=0; l<n; l++) { /* loop over added columns */ 7005ef9f2a5SBarry Smith if (in[l] < 0) continue; 701aa482453SBarry Smith #if defined(PETSC_USE_BOPT_g) 702a8c6a408SBarry Smith if (in[l] >= a->nbs) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Column too large"); 70392c4ed94SBarry Smith #endif 70492c4ed94SBarry Smith col = in[l]; 70592c4ed94SBarry Smith if (roworiented) { 7060e324ae4SSatish Balay value = v + k*(stepval+bs)*bs + l*bs; 7070e324ae4SSatish Balay } else { 7080e324ae4SSatish Balay value = v + l*(stepval+bs)*bs + k*bs; 70992c4ed94SBarry Smith } 71092c4ed94SBarry Smith if (!sorted) low = 0; high = nrow; 71192c4ed94SBarry Smith while (high-low > 7) { 71292c4ed94SBarry Smith t = (low+high)/2; 71392c4ed94SBarry Smith if (rp[t] > col) high = t; 71492c4ed94SBarry Smith else low = t; 71592c4ed94SBarry Smith } 71692c4ed94SBarry Smith for (i=low; i<high; i++) { 71792c4ed94SBarry Smith if (rp[i] > col) break; 71892c4ed94SBarry Smith if (rp[i] == col) { 7198a84c255SSatish Balay bap = ap + bs2*i; 7200e324ae4SSatish Balay if (roworiented) { 7218a84c255SSatish Balay if (is == ADD_VALUES) { 722dd9472c6SBarry Smith for (ii=0; ii<bs; ii++,value+=stepval) { 723dd9472c6SBarry Smith for (jj=ii; jj<bs2; jj+=bs) { 7248a84c255SSatish Balay bap[jj] += *value++; 725dd9472c6SBarry Smith } 726dd9472c6SBarry Smith } 7270e324ae4SSatish Balay } else { 728dd9472c6SBarry Smith for (ii=0; ii<bs; ii++,value+=stepval) { 729dd9472c6SBarry Smith for (jj=ii; jj<bs2; jj+=bs) { 7300e324ae4SSatish Balay bap[jj] = *value++; 7318a84c255SSatish Balay } 732dd9472c6SBarry Smith } 733dd9472c6SBarry Smith } 7340e324ae4SSatish Balay } else { 7350e324ae4SSatish Balay if (is == ADD_VALUES) { 736dd9472c6SBarry Smith for (ii=0; ii<bs; ii++,value+=stepval) { 737dd9472c6SBarry Smith for (jj=0; jj<bs; jj++) { 7380e324ae4SSatish Balay *bap++ += *value++; 739dd9472c6SBarry Smith } 740dd9472c6SBarry Smith } 7410e324ae4SSatish Balay } else { 742dd9472c6SBarry Smith for (ii=0; ii<bs; ii++,value+=stepval) { 743dd9472c6SBarry Smith for (jj=0; jj<bs; jj++) { 7440e324ae4SSatish Balay *bap++ = *value++; 7450e324ae4SSatish Balay } 7468a84c255SSatish Balay } 747dd9472c6SBarry Smith } 748dd9472c6SBarry Smith } 749f1241b54SBarry Smith goto noinsert2; 75092c4ed94SBarry Smith } 75192c4ed94SBarry Smith } 75289280ab3SLois Curfman McInnes if (nonew == 1) goto noinsert2; 753a8c6a408SBarry Smith else if (nonew == -1) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Inserting a new nonzero in the matrix"); 75492c4ed94SBarry Smith if (nrow >= rmax) { 75592c4ed94SBarry Smith /* there is no extra room in row, therefore enlarge */ 75692c4ed94SBarry Smith int new_nz = ai[a->mbs] + CHUNKSIZE,len,*new_i,*new_j; 7573f1db9ecSBarry Smith MatScalar *new_a; 75892c4ed94SBarry Smith 759a8c6a408SBarry Smith if (nonew == -2) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Inserting a new nonzero in the matrix"); 76089280ab3SLois Curfman McInnes 76192c4ed94SBarry Smith /* malloc new storage space */ 7623f1db9ecSBarry Smith len = new_nz*(sizeof(int)+bs2*sizeof(MatScalar))+(a->mbs+1)*sizeof(int); 7633f1db9ecSBarry Smith new_a = (MatScalar*)PetscMalloc(len);CHKPTRQ(new_a); 76492c4ed94SBarry Smith new_j = (int*)(new_a + bs2*new_nz); 76592c4ed94SBarry Smith new_i = new_j + new_nz; 76692c4ed94SBarry Smith 76792c4ed94SBarry Smith /* copy over old data into new slots */ 76892c4ed94SBarry Smith for (ii=0; ii<row+1; ii++) {new_i[ii] = ai[ii];} 76992c4ed94SBarry Smith for (ii=row+1; ii<a->mbs+1; ii++) {new_i[ii] = ai[ii]+CHUNKSIZE;} 770549d3d68SSatish Balay ierr = PetscMemcpy(new_j,aj,(ai[row]+nrow)*sizeof(int));CHKERRQ(ierr); 77192c4ed94SBarry Smith len = (new_nz - CHUNKSIZE - ai[row] - nrow); 772549d3d68SSatish Balay ierr = PetscMemcpy(new_j+ai[row]+nrow+CHUNKSIZE,aj+ai[row]+nrow,len*sizeof(int));CHKERRQ(ierr); 773549d3d68SSatish Balay ierr = PetscMemcpy(new_a,aa,(ai[row]+nrow)*bs2*sizeof(MatScalar));CHKERRQ(ierr); 774549d3d68SSatish Balay ierr = PetscMemzero(new_a+bs2*(ai[row]+nrow),bs2*CHUNKSIZE*sizeof(MatScalar));CHKERRQ(ierr); 775549d3d68SSatish Balay ierr = PetscMemcpy(new_a+bs2*(ai[row]+nrow+CHUNKSIZE),aa+bs2*(ai[row]+nrow),bs2*len*sizeof(MatScalar));CHKERRQ(ierr); 77692c4ed94SBarry Smith /* free up old matrix storage */ 777606d414cSSatish Balay ierr = PetscFree(a->a);CHKERRQ(ierr); 778606d414cSSatish Balay if (!a->singlemalloc) { 779606d414cSSatish Balay ierr = PetscFree(a->i);CHKERRQ(ierr); 780606d414cSSatish Balay ierr = PetscFree(a->j);CHKERRQ(ierr); 781606d414cSSatish Balay } 78292c4ed94SBarry Smith aa = a->a = new_a; ai = a->i = new_i; aj = a->j = new_j; 783c4992f7dSBarry Smith a->singlemalloc = PETSC_TRUE; 78492c4ed94SBarry Smith 78592c4ed94SBarry Smith rp = aj + ai[row]; ap = aa + bs2*ai[row]; 78692c4ed94SBarry Smith rmax = imax[row] = imax[row] + CHUNKSIZE; 7873f1db9ecSBarry Smith PLogObjectMemory(A,CHUNKSIZE*(sizeof(int) + bs2*sizeof(MatScalar))); 78892c4ed94SBarry Smith a->maxnz += bs2*CHUNKSIZE; 78992c4ed94SBarry Smith a->reallocs++; 79092c4ed94SBarry Smith a->nz++; 79192c4ed94SBarry Smith } 79292c4ed94SBarry Smith N = nrow++ - 1; 79392c4ed94SBarry Smith /* shift up all the later entries in this row */ 79492c4ed94SBarry Smith for (ii=N; ii>=i; ii--) { 79592c4ed94SBarry Smith rp[ii+1] = rp[ii]; 796549d3d68SSatish Balay ierr = PetscMemcpy(ap+bs2*(ii+1),ap+bs2*(ii),bs2*sizeof(MatScalar));CHKERRQ(ierr); 79792c4ed94SBarry Smith } 798549d3d68SSatish Balay if (N >= i) { 799549d3d68SSatish Balay ierr = PetscMemzero(ap+bs2*i,bs2*sizeof(MatScalar));CHKERRQ(ierr); 800549d3d68SSatish Balay } 80192c4ed94SBarry Smith rp[i] = col; 8028a84c255SSatish Balay bap = ap + bs2*i; 8030e324ae4SSatish Balay if (roworiented) { 804dd9472c6SBarry Smith for (ii=0; ii<bs; ii++,value+=stepval) { 805dd9472c6SBarry Smith for (jj=ii; jj<bs2; jj+=bs) { 8060e324ae4SSatish Balay bap[jj] = *value++; 807dd9472c6SBarry Smith } 808dd9472c6SBarry Smith } 8090e324ae4SSatish Balay } else { 810dd9472c6SBarry Smith for (ii=0; ii<bs; ii++,value+=stepval) { 811dd9472c6SBarry Smith for (jj=0; jj<bs; jj++) { 8120e324ae4SSatish Balay *bap++ = *value++; 8130e324ae4SSatish Balay } 814dd9472c6SBarry Smith } 815dd9472c6SBarry Smith } 816f1241b54SBarry Smith noinsert2:; 81792c4ed94SBarry Smith low = i; 81892c4ed94SBarry Smith } 81992c4ed94SBarry Smith ailen[row] = nrow; 82092c4ed94SBarry Smith } 8213a40ed3dSBarry Smith PetscFunctionReturn(0); 82292c4ed94SBarry Smith } 82392c4ed94SBarry Smith 824f2501298SSatish Balay 8255615d1e5SSatish Balay #undef __FUNC__ 8265615d1e5SSatish Balay #define __FUNC__ "MatAssemblyEnd_SeqBAIJ" 8278f6be9afSLois Curfman McInnes int MatAssemblyEnd_SeqBAIJ(Mat A,MatAssemblyType mode) 828584200bdSSatish Balay { 829584200bdSSatish Balay Mat_SeqBAIJ *a = (Mat_SeqBAIJ*)A->data; 830584200bdSSatish Balay int fshift = 0,i,j,*ai = a->i,*aj = a->j,*imax = a->imax; 831a7c10996SSatish Balay int m = a->m,*ip,N,*ailen = a->ilen; 832549d3d68SSatish Balay int mbs = a->mbs,bs2 = a->bs2,rmax = 0,ierr; 8333f1db9ecSBarry Smith MatScalar *aa = a->a,*ap; 834584200bdSSatish Balay 8353a40ed3dSBarry Smith PetscFunctionBegin; 8363a40ed3dSBarry Smith if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0); 837584200bdSSatish Balay 83843ee02c3SBarry Smith if (m) rmax = ailen[0]; 839584200bdSSatish Balay for (i=1; i<mbs; i++) { 840584200bdSSatish Balay /* move each row back by the amount of empty slots (fshift) before it*/ 841584200bdSSatish Balay fshift += imax[i-1] - ailen[i-1]; 842d402145bSBarry Smith rmax = PetscMax(rmax,ailen[i]); 843584200bdSSatish Balay if (fshift) { 844a7c10996SSatish Balay ip = aj + ai[i]; ap = aa + bs2*ai[i]; 845584200bdSSatish Balay N = ailen[i]; 846584200bdSSatish Balay for (j=0; j<N; j++) { 847584200bdSSatish Balay ip[j-fshift] = ip[j]; 848549d3d68SSatish Balay ierr = PetscMemcpy(ap+(j-fshift)*bs2,ap+j*bs2,bs2*sizeof(MatScalar));CHKERRQ(ierr); 849584200bdSSatish Balay } 850584200bdSSatish Balay } 851584200bdSSatish Balay ai[i] = ai[i-1] + ailen[i-1]; 852584200bdSSatish Balay } 853584200bdSSatish Balay if (mbs) { 854584200bdSSatish Balay fshift += imax[mbs-1] - ailen[mbs-1]; 855584200bdSSatish Balay ai[mbs] = ai[mbs-1] + ailen[mbs-1]; 856584200bdSSatish Balay } 857584200bdSSatish Balay /* reset ilen and imax for each row */ 858584200bdSSatish Balay for (i=0; i<mbs; i++) { 859584200bdSSatish Balay ailen[i] = imax[i] = ai[i+1] - ai[i]; 860584200bdSSatish Balay } 861a7c10996SSatish Balay a->nz = ai[mbs]; 862584200bdSSatish Balay 863584200bdSSatish Balay /* diagonals may have moved, so kill the diagonal pointers */ 864584200bdSSatish Balay if (fshift && a->diag) { 865606d414cSSatish Balay ierr = PetscFree(a->diag);CHKERRQ(ierr); 866584200bdSSatish Balay PLogObjectMemory(A,-(m+1)*sizeof(int)); 867584200bdSSatish Balay a->diag = 0; 868584200bdSSatish Balay } 8693d2013a6SLois Curfman McInnes PLogInfo(A,"MatAssemblyEnd_SeqBAIJ:Matrix size: %d X %d, block size %d; storage space: %d unneeded, %d used\n", 870219d9a1aSLois Curfman McInnes m,a->n,a->bs,fshift*bs2,a->nz*bs2); 8713d2013a6SLois Curfman McInnes PLogInfo(A,"MatAssemblyEnd_SeqBAIJ:Number of mallocs during MatSetValues is %d\n", 872584200bdSSatish Balay a->reallocs); 873d402145bSBarry Smith PLogInfo(A,"MatAssemblyEnd_SeqBAIJ:Most nonzeros blocks in any row is %d\n",rmax); 874e2f3b5e9SSatish Balay a->reallocs = 0; 875*0e6d2581SBarry Smith A->info.nz_unneeded = (PetscReal)fshift*bs2; 8764e220ebcSLois Curfman McInnes 8773a40ed3dSBarry Smith PetscFunctionReturn(0); 878584200bdSSatish Balay } 879584200bdSSatish Balay 8805a838052SSatish Balay 881bea157c4SSatish Balay 882bea157c4SSatish Balay /* 883bea157c4SSatish Balay This function returns an array of flags which indicate the locations of contiguous 884bea157c4SSatish Balay blocks that should be zeroed. for eg: if bs = 3 and is = [0,1,2,3,5,6,7,8,9] 885bea157c4SSatish Balay then the resulting sizes = [3,1,1,3,1] correspondig to sets [(0,1,2),(3),(5),(6,7,8),(9)] 886bea157c4SSatish Balay Assume: sizes should be long enough to hold all the values. 887bea157c4SSatish Balay */ 8885615d1e5SSatish Balay #undef __FUNC__ 889bea157c4SSatish Balay #define __FUNC__ "MatZeroRows_SeqBAIJ_Check_Blocks" 890bea157c4SSatish Balay static int MatZeroRows_SeqBAIJ_Check_Blocks(int idx[],int n,int bs,int sizes[], int *bs_max) 891d9b7c43dSSatish Balay { 892bea157c4SSatish Balay int i,j,k,row; 893bea157c4SSatish Balay PetscTruth flg; 8943a40ed3dSBarry Smith 895433994e6SBarry Smith PetscFunctionBegin; 896bea157c4SSatish Balay for (i=0,j=0; i<n; j++) { 897bea157c4SSatish Balay row = idx[i]; 898bea157c4SSatish Balay if (row%bs!=0) { /* Not the begining of a block */ 899bea157c4SSatish Balay sizes[j] = 1; 900bea157c4SSatish Balay i++; 901e4fda26cSSatish Balay } else if (i+bs > n) { /* complete block doesn't exist (at idx end) */ 902bea157c4SSatish Balay sizes[j] = 1; /* Also makes sure atleast 'bs' values exist for next else */ 903bea157c4SSatish Balay i++; 904bea157c4SSatish Balay } else { /* Begining of the block, so check if the complete block exists */ 905bea157c4SSatish Balay flg = PETSC_TRUE; 906bea157c4SSatish Balay for (k=1; k<bs; k++) { 907bea157c4SSatish Balay if (row+k != idx[i+k]) { /* break in the block */ 908bea157c4SSatish Balay flg = PETSC_FALSE; 909bea157c4SSatish Balay break; 910d9b7c43dSSatish Balay } 911bea157c4SSatish Balay } 912bea157c4SSatish Balay if (flg == PETSC_TRUE) { /* No break in the bs */ 913bea157c4SSatish Balay sizes[j] = bs; 914bea157c4SSatish Balay i+= bs; 915bea157c4SSatish Balay } else { 916bea157c4SSatish Balay sizes[j] = 1; 917bea157c4SSatish Balay i++; 918bea157c4SSatish Balay } 919bea157c4SSatish Balay } 920bea157c4SSatish Balay } 921bea157c4SSatish Balay *bs_max = j; 9223a40ed3dSBarry Smith PetscFunctionReturn(0); 923d9b7c43dSSatish Balay } 924d9b7c43dSSatish Balay 9255615d1e5SSatish Balay #undef __FUNC__ 9265615d1e5SSatish Balay #define __FUNC__ "MatZeroRows_SeqBAIJ" 9278f6be9afSLois Curfman McInnes int MatZeroRows_SeqBAIJ(Mat A,IS is,Scalar *diag) 928d9b7c43dSSatish Balay { 929d9b7c43dSSatish Balay Mat_SeqBAIJ *baij=(Mat_SeqBAIJ*)A->data; 930b6815fffSBarry Smith int ierr,i,j,k,count,is_n,*is_idx,*rows; 931bea157c4SSatish Balay int bs=baij->bs,bs2=baij->bs2,*sizes,row,bs_max; 9323f1db9ecSBarry Smith Scalar zero = 0.0; 9333f1db9ecSBarry Smith MatScalar *aa; 934d9b7c43dSSatish Balay 9353a40ed3dSBarry Smith PetscFunctionBegin; 936d9b7c43dSSatish Balay /* Make a copy of the IS and sort it */ 937d9b7c43dSSatish Balay ierr = ISGetSize(is,&is_n);CHKERRQ(ierr); 938d9b7c43dSSatish Balay ierr = ISGetIndices(is,&is_idx);CHKERRQ(ierr); 939d9b7c43dSSatish Balay 940bea157c4SSatish Balay /* allocate memory for rows,sizes */ 941bea157c4SSatish Balay rows = (int*)PetscMalloc((3*is_n+1)*sizeof(int));CHKPTRQ(rows); 942bea157c4SSatish Balay sizes = rows + is_n; 943bea157c4SSatish Balay 944bea157c4SSatish Balay /* initialize copy IS valurs to rows, and sort them */ 945bea157c4SSatish Balay for (i=0; i<is_n; i++) { rows[i] = is_idx[i]; } 946bea157c4SSatish Balay ierr = PetscSortInt(is_n,rows);CHKERRQ(ierr); 947dffd3267SBarry Smith if (baij->keepzeroedrows) { 948dffd3267SBarry Smith for (i=0; i<is_n; i++) { sizes[i] = 1; } 949dffd3267SBarry Smith bs_max = is_n; 950dffd3267SBarry Smith } else { 951bea157c4SSatish Balay ierr = MatZeroRows_SeqBAIJ_Check_Blocks(rows,is_n,bs,sizes,&bs_max);CHKERRQ(ierr); 952dffd3267SBarry Smith } 953b97a56abSSatish Balay ierr = ISRestoreIndices(is,&is_idx);CHKERRQ(ierr); 954bea157c4SSatish Balay 955bea157c4SSatish Balay for (i=0,j=0; i<bs_max; j+=sizes[i],i++) { 956bea157c4SSatish Balay row = rows[j]; 957b6815fffSBarry Smith if (row < 0 || row > baij->m) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,0,"row %d out of range",row); 958bea157c4SSatish Balay count = (baij->i[row/bs +1] - baij->i[row/bs])*bs; 959bea157c4SSatish Balay aa = baij->a + baij->i[row/bs]*bs2 + (row%bs); 960dffd3267SBarry Smith if (sizes[i] == bs && !baij->keepzeroedrows) { 961bea157c4SSatish Balay if (diag) { 962bea157c4SSatish Balay if (baij->ilen[row/bs] > 0) { 963bea157c4SSatish Balay baij->ilen[row/bs] = 1; 964bea157c4SSatish Balay baij->j[baij->i[row/bs]] = row/bs; 965bea157c4SSatish Balay ierr = PetscMemzero(aa,count*bs*sizeof(MatScalar));CHKERRQ(ierr); 966a07cd24cSSatish Balay } 967bea157c4SSatish Balay /* Now insert all the diagoanl values for this bs */ 968bea157c4SSatish Balay for (k=0; k<bs; k++) { 969bea157c4SSatish Balay ierr = (*A->ops->setvalues)(A,1,rows+j+k,1,rows+j+k,diag,INSERT_VALUES);CHKERRQ(ierr); 970bea157c4SSatish Balay } 971bea157c4SSatish Balay } else { /* (!diag) */ 972bea157c4SSatish Balay baij->ilen[row/bs] = 0; 973bea157c4SSatish Balay } /* end (!diag) */ 974bea157c4SSatish Balay } else { /* (sizes[i] != bs) */ 975aa482453SBarry Smith #if defined (PETSC_USE_DEBUG) 976bea157c4SSatish Balay if (sizes[i] != 1) SETERRQ(1,0,"Internal Error. Value should be 1"); 977bea157c4SSatish Balay #endif 978bea157c4SSatish Balay for (k=0; k<count; k++) { 979d9b7c43dSSatish Balay aa[0] = zero; 980d9b7c43dSSatish Balay aa+=bs; 981d9b7c43dSSatish Balay } 982d9b7c43dSSatish Balay if (diag) { 983f830108cSBarry Smith ierr = (*A->ops->setvalues)(A,1,rows+j,1,rows+j,diag,INSERT_VALUES);CHKERRQ(ierr); 984d9b7c43dSSatish Balay } 985d9b7c43dSSatish Balay } 986bea157c4SSatish Balay } 987bea157c4SSatish Balay 988606d414cSSatish Balay ierr = PetscFree(rows);CHKERRQ(ierr); 9899a8dea36SBarry Smith ierr = MatAssemblyEnd_SeqBAIJ(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 9903a40ed3dSBarry Smith PetscFunctionReturn(0); 991d9b7c43dSSatish Balay } 9921c351548SSatish Balay 9935615d1e5SSatish Balay #undef __FUNC__ 9942d61bbb3SSatish Balay #define __FUNC__ "MatSetValues_SeqBAIJ" 9952d61bbb3SSatish Balay int MatSetValues_SeqBAIJ(Mat A,int m,int *im,int n,int *in,Scalar *v,InsertMode is) 9962d61bbb3SSatish Balay { 9972d61bbb3SSatish Balay Mat_SeqBAIJ *a = (Mat_SeqBAIJ*)A->data; 9982d61bbb3SSatish Balay int *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N,sorted=a->sorted; 9992d61bbb3SSatish Balay int *imax=a->imax,*ai=a->i,*ailen=a->ilen,roworiented=a->roworiented; 10002d61bbb3SSatish Balay int *aj=a->j,nonew=a->nonew,bs=a->bs,brow,bcol; 1001549d3d68SSatish Balay int ridx,cidx,bs2=a->bs2,ierr; 10023f1db9ecSBarry Smith MatScalar *ap,value,*aa=a->a,*bap; 10032d61bbb3SSatish Balay 10042d61bbb3SSatish Balay PetscFunctionBegin; 10052d61bbb3SSatish Balay for (k=0; k<m; k++) { /* loop over added rows */ 10062d61bbb3SSatish Balay row = im[k]; brow = row/bs; 10075ef9f2a5SBarry Smith if (row < 0) continue; 1008aa482453SBarry Smith #if defined(PETSC_USE_BOPT_g) 100932e87ba3SBarry Smith if (row >= a->m) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,0,"Row too large: row %d max %d",row,a->m); 10102d61bbb3SSatish Balay #endif 10112d61bbb3SSatish Balay rp = aj + ai[brow]; 10122d61bbb3SSatish Balay ap = aa + bs2*ai[brow]; 10132d61bbb3SSatish Balay rmax = imax[brow]; 10142d61bbb3SSatish Balay nrow = ailen[brow]; 10152d61bbb3SSatish Balay low = 0; 10162d61bbb3SSatish Balay for (l=0; l<n; l++) { /* loop over added columns */ 10175ef9f2a5SBarry Smith if (in[l] < 0) continue; 1018aa482453SBarry Smith #if defined(PETSC_USE_BOPT_g) 101932e87ba3SBarry Smith if (in[l] >= a->n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,0,"Column too large: col %d max %d",in[l],a->n); 10202d61bbb3SSatish Balay #endif 10212d61bbb3SSatish Balay col = in[l]; bcol = col/bs; 10222d61bbb3SSatish Balay ridx = row % bs; cidx = col % bs; 10232d61bbb3SSatish Balay if (roworiented) { 10245ef9f2a5SBarry Smith value = v[l + k*n]; 10252d61bbb3SSatish Balay } else { 10262d61bbb3SSatish Balay value = v[k + l*m]; 10272d61bbb3SSatish Balay } 10282d61bbb3SSatish Balay if (!sorted) low = 0; high = nrow; 10292d61bbb3SSatish Balay while (high-low > 7) { 10302d61bbb3SSatish Balay t = (low+high)/2; 10312d61bbb3SSatish Balay if (rp[t] > bcol) high = t; 10322d61bbb3SSatish Balay else low = t; 10332d61bbb3SSatish Balay } 10342d61bbb3SSatish Balay for (i=low; i<high; i++) { 10352d61bbb3SSatish Balay if (rp[i] > bcol) break; 10362d61bbb3SSatish Balay if (rp[i] == bcol) { 10372d61bbb3SSatish Balay bap = ap + bs2*i + bs*cidx + ridx; 10382d61bbb3SSatish Balay if (is == ADD_VALUES) *bap += value; 10392d61bbb3SSatish Balay else *bap = value; 10402d61bbb3SSatish Balay goto noinsert1; 10412d61bbb3SSatish Balay } 10422d61bbb3SSatish Balay } 10432d61bbb3SSatish Balay if (nonew == 1) goto noinsert1; 10442d61bbb3SSatish Balay else if (nonew == -1) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Inserting a new nonzero in the matrix"); 10452d61bbb3SSatish Balay if (nrow >= rmax) { 10462d61bbb3SSatish Balay /* there is no extra room in row, therefore enlarge */ 10472d61bbb3SSatish Balay int new_nz = ai[a->mbs] + CHUNKSIZE,len,*new_i,*new_j; 10483f1db9ecSBarry Smith MatScalar *new_a; 10492d61bbb3SSatish Balay 10502d61bbb3SSatish Balay if (nonew == -2) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Inserting a new nonzero in the matrix"); 10512d61bbb3SSatish Balay 10522d61bbb3SSatish Balay /* Malloc new storage space */ 10533f1db9ecSBarry Smith len = new_nz*(sizeof(int)+bs2*sizeof(MatScalar))+(a->mbs+1)*sizeof(int); 10543f1db9ecSBarry Smith new_a = (MatScalar*)PetscMalloc(len);CHKPTRQ(new_a); 10552d61bbb3SSatish Balay new_j = (int*)(new_a + bs2*new_nz); 10562d61bbb3SSatish Balay new_i = new_j + new_nz; 10572d61bbb3SSatish Balay 10582d61bbb3SSatish Balay /* copy over old data into new slots */ 10592d61bbb3SSatish Balay for (ii=0; ii<brow+1; ii++) {new_i[ii] = ai[ii];} 10602d61bbb3SSatish Balay for (ii=brow+1; ii<a->mbs+1; ii++) {new_i[ii] = ai[ii]+CHUNKSIZE;} 1061549d3d68SSatish Balay ierr = PetscMemcpy(new_j,aj,(ai[brow]+nrow)*sizeof(int));CHKERRQ(ierr); 10622d61bbb3SSatish Balay len = (new_nz - CHUNKSIZE - ai[brow] - nrow); 1063549d3d68SSatish Balay ierr = PetscMemcpy(new_j+ai[brow]+nrow+CHUNKSIZE,aj+ai[brow]+nrow,len*sizeof(int));CHKERRQ(ierr); 1064549d3d68SSatish Balay ierr = PetscMemcpy(new_a,aa,(ai[brow]+nrow)*bs2*sizeof(MatScalar));CHKERRQ(ierr); 1065549d3d68SSatish Balay ierr = PetscMemzero(new_a+bs2*(ai[brow]+nrow),bs2*CHUNKSIZE*sizeof(MatScalar));CHKERRQ(ierr); 1066549d3d68SSatish Balay ierr = PetscMemcpy(new_a+bs2*(ai[brow]+nrow+CHUNKSIZE),aa+bs2*(ai[brow]+nrow),bs2*len*sizeof(MatScalar));CHKERRQ(ierr); 10672d61bbb3SSatish Balay /* free up old matrix storage */ 1068606d414cSSatish Balay ierr = PetscFree(a->a);CHKERRQ(ierr); 1069606d414cSSatish Balay if (!a->singlemalloc) { 1070606d414cSSatish Balay ierr = PetscFree(a->i);CHKERRQ(ierr); 1071606d414cSSatish Balay ierr = PetscFree(a->j);CHKERRQ(ierr); 1072606d414cSSatish Balay } 10732d61bbb3SSatish Balay aa = a->a = new_a; ai = a->i = new_i; aj = a->j = new_j; 1074c4992f7dSBarry Smith a->singlemalloc = PETSC_TRUE; 10752d61bbb3SSatish Balay 10762d61bbb3SSatish Balay rp = aj + ai[brow]; ap = aa + bs2*ai[brow]; 10772d61bbb3SSatish Balay rmax = imax[brow] = imax[brow] + CHUNKSIZE; 10783f1db9ecSBarry Smith PLogObjectMemory(A,CHUNKSIZE*(sizeof(int) + bs2*sizeof(MatScalar))); 10792d61bbb3SSatish Balay a->maxnz += bs2*CHUNKSIZE; 10802d61bbb3SSatish Balay a->reallocs++; 10812d61bbb3SSatish Balay a->nz++; 10822d61bbb3SSatish Balay } 10832d61bbb3SSatish Balay N = nrow++ - 1; 10842d61bbb3SSatish Balay /* shift up all the later entries in this row */ 10852d61bbb3SSatish Balay for (ii=N; ii>=i; ii--) { 10862d61bbb3SSatish Balay rp[ii+1] = rp[ii]; 1087549d3d68SSatish Balay ierr = PetscMemcpy(ap+bs2*(ii+1),ap+bs2*(ii),bs2*sizeof(MatScalar));CHKERRQ(ierr); 10882d61bbb3SSatish Balay } 1089549d3d68SSatish Balay if (N>=i) { 1090549d3d68SSatish Balay ierr = PetscMemzero(ap+bs2*i,bs2*sizeof(MatScalar));CHKERRQ(ierr); 1091549d3d68SSatish Balay } 10922d61bbb3SSatish Balay rp[i] = bcol; 10932d61bbb3SSatish Balay ap[bs2*i + bs*cidx + ridx] = value; 10942d61bbb3SSatish Balay noinsert1:; 10952d61bbb3SSatish Balay low = i; 10962d61bbb3SSatish Balay } 10972d61bbb3SSatish Balay ailen[brow] = nrow; 10982d61bbb3SSatish Balay } 10992d61bbb3SSatish Balay PetscFunctionReturn(0); 11002d61bbb3SSatish Balay } 11012d61bbb3SSatish Balay 1102*0e6d2581SBarry Smith extern int MatLUFactorSymbolic_SeqBAIJ(Mat,IS,IS,PetscReal,Mat*); 1103*0e6d2581SBarry Smith extern int MatLUFactor_SeqBAIJ(Mat,IS,IS,PetscReal); 11042d61bbb3SSatish Balay extern int MatIncreaseOverlap_SeqBAIJ(Mat,int,IS*,int); 11057b2a1423SBarry Smith extern int MatGetSubMatrix_SeqBAIJ(Mat,IS,IS,int,MatReuse,Mat*); 11067b2a1423SBarry Smith extern int MatGetSubMatrices_SeqBAIJ(Mat,int,IS*,IS*,MatReuse,Mat**); 11077c922b88SBarry Smith extern int MatMultTranspose_SeqBAIJ(Mat,Vec,Vec); 11087c922b88SBarry Smith extern int MatMultTransposeAdd_SeqBAIJ(Mat,Vec,Vec,Vec); 11092d61bbb3SSatish Balay extern int MatScale_SeqBAIJ(Scalar*,Mat); 1110*0e6d2581SBarry Smith extern int MatNorm_SeqBAIJ(Mat,NormType,PetscReal *); 11112d61bbb3SSatish Balay extern int MatEqual_SeqBAIJ(Mat,Mat,PetscTruth*); 11122d61bbb3SSatish Balay extern int MatGetDiagonal_SeqBAIJ(Mat,Vec); 11132d61bbb3SSatish Balay extern int MatDiagonalScale_SeqBAIJ(Mat,Vec,Vec); 11142d61bbb3SSatish Balay extern int MatGetInfo_SeqBAIJ(Mat,MatInfoType,MatInfo *); 11152d61bbb3SSatish Balay extern int MatZeroEntries_SeqBAIJ(Mat); 11162d61bbb3SSatish Balay 11172d61bbb3SSatish Balay extern int MatSolve_SeqBAIJ_N(Mat,Vec,Vec); 11182d61bbb3SSatish Balay extern int MatSolve_SeqBAIJ_1(Mat,Vec,Vec); 11192d61bbb3SSatish Balay extern int MatSolve_SeqBAIJ_2(Mat,Vec,Vec); 11202d61bbb3SSatish Balay extern int MatSolve_SeqBAIJ_3(Mat,Vec,Vec); 11212d61bbb3SSatish Balay extern int MatSolve_SeqBAIJ_4(Mat,Vec,Vec); 11222d61bbb3SSatish Balay extern int MatSolve_SeqBAIJ_5(Mat,Vec,Vec); 112315091d37SBarry Smith extern int MatSolve_SeqBAIJ_6(Mat,Vec,Vec); 11242d61bbb3SSatish Balay extern int MatSolve_SeqBAIJ_7(Mat,Vec,Vec); 11257c922b88SBarry Smith extern int MatSolveTranspose_SeqBAIJ_7(Mat,Vec,Vec); 11267c922b88SBarry Smith extern int MatSolveTranspose_SeqBAIJ_6(Mat,Vec,Vec); 11277c922b88SBarry Smith extern int MatSolveTranspose_SeqBAIJ_5(Mat,Vec,Vec); 11287c922b88SBarry Smith extern int MatSolveTranspose_SeqBAIJ_4(Mat,Vec,Vec); 11297c922b88SBarry Smith extern int MatSolveTranspose_SeqBAIJ_3(Mat,Vec,Vec); 11307c922b88SBarry Smith extern int MatSolveTranspose_SeqBAIJ_2(Mat,Vec,Vec); 11317c922b88SBarry Smith extern int MatSolveTranspose_SeqBAIJ_1(Mat,Vec,Vec); 11322d61bbb3SSatish Balay 11332d61bbb3SSatish Balay extern int MatLUFactorNumeric_SeqBAIJ_N(Mat,Mat*); 11342d61bbb3SSatish Balay extern int MatLUFactorNumeric_SeqBAIJ_1(Mat,Mat*); 11352d61bbb3SSatish Balay extern int MatLUFactorNumeric_SeqBAIJ_2(Mat,Mat*); 11362d61bbb3SSatish Balay extern int MatLUFactorNumeric_SeqBAIJ_3(Mat,Mat*); 11372d61bbb3SSatish Balay extern int MatLUFactorNumeric_SeqBAIJ_4(Mat,Mat*); 11382d61bbb3SSatish Balay extern int MatLUFactorNumeric_SeqBAIJ_5(Mat,Mat*); 113915091d37SBarry Smith extern int MatLUFactorNumeric_SeqBAIJ_6(Mat,Mat*); 11402d61bbb3SSatish Balay 11412d61bbb3SSatish Balay extern int MatMult_SeqBAIJ_1(Mat,Vec,Vec); 11422d61bbb3SSatish Balay extern int MatMult_SeqBAIJ_2(Mat,Vec,Vec); 11432d61bbb3SSatish Balay extern int MatMult_SeqBAIJ_3(Mat,Vec,Vec); 11442d61bbb3SSatish Balay extern int MatMult_SeqBAIJ_4(Mat,Vec,Vec); 11452d61bbb3SSatish Balay extern int MatMult_SeqBAIJ_5(Mat,Vec,Vec); 114615091d37SBarry Smith extern int MatMult_SeqBAIJ_6(Mat,Vec,Vec); 11472d61bbb3SSatish Balay extern int MatMult_SeqBAIJ_7(Mat,Vec,Vec); 11482d61bbb3SSatish Balay extern int MatMult_SeqBAIJ_N(Mat,Vec,Vec); 11492d61bbb3SSatish Balay 11502d61bbb3SSatish Balay extern int MatMultAdd_SeqBAIJ_1(Mat,Vec,Vec,Vec); 11512d61bbb3SSatish Balay extern int MatMultAdd_SeqBAIJ_2(Mat,Vec,Vec,Vec); 11522d61bbb3SSatish Balay extern int MatMultAdd_SeqBAIJ_3(Mat,Vec,Vec,Vec); 11532d61bbb3SSatish Balay extern int MatMultAdd_SeqBAIJ_4(Mat,Vec,Vec,Vec); 11542d61bbb3SSatish Balay extern int MatMultAdd_SeqBAIJ_5(Mat,Vec,Vec,Vec); 115515091d37SBarry Smith extern int MatMultAdd_SeqBAIJ_6(Mat,Vec,Vec,Vec); 11562d61bbb3SSatish Balay extern int MatMultAdd_SeqBAIJ_7(Mat,Vec,Vec,Vec); 11572d61bbb3SSatish Balay extern int MatMultAdd_SeqBAIJ_N(Mat,Vec,Vec,Vec); 11582d61bbb3SSatish Balay 11592d61bbb3SSatish Balay #undef __FUNC__ 11602d61bbb3SSatish Balay #define __FUNC__ "MatILUFactor_SeqBAIJ" 11615ef9f2a5SBarry Smith int MatILUFactor_SeqBAIJ(Mat inA,IS row,IS col,MatILUInfo *info) 11622d61bbb3SSatish Balay { 11632d61bbb3SSatish Balay Mat_SeqBAIJ *a = (Mat_SeqBAIJ*)inA->data; 11642d61bbb3SSatish Balay Mat outA; 11652d61bbb3SSatish Balay int ierr; 1166667159a5SBarry Smith PetscTruth row_identity,col_identity; 11672d61bbb3SSatish Balay 11682d61bbb3SSatish Balay PetscFunctionBegin; 1169b6d21a55SBarry Smith if (info && info->levels != 0) SETERRQ(PETSC_ERR_SUP,0,"Only levels = 0 supported for in-place ILU"); 1170667159a5SBarry Smith ierr = ISIdentity(row,&row_identity);CHKERRQ(ierr); 1171667159a5SBarry Smith ierr = ISIdentity(col,&col_identity);CHKERRQ(ierr); 1172667159a5SBarry Smith if (!row_identity || !col_identity) { 1173b008c796SBarry Smith SETERRQ(1,1,"Row and column permutations must be identity for in-place ILU"); 1174667159a5SBarry Smith } 11752d61bbb3SSatish Balay 11762d61bbb3SSatish Balay outA = inA; 11772d61bbb3SSatish Balay inA->factor = FACTOR_LU; 11782d61bbb3SSatish Balay 11792d61bbb3SSatish Balay if (!a->diag) { 1180c4992f7dSBarry Smith ierr = MatMarkDiagonal_SeqBAIJ(inA);CHKERRQ(ierr); 11812d61bbb3SSatish Balay } 11822d61bbb3SSatish Balay /* 118315091d37SBarry Smith Blocksize 2, 3, 4, 5, 6 and 7 have a special faster factorization/solver 118415091d37SBarry Smith for ILU(0) factorization with natural ordering 11852d61bbb3SSatish Balay */ 118615091d37SBarry Smith switch (a->bs) { 1187f1af5d2fSBarry Smith case 1: 11887c922b88SBarry Smith inA->ops->solvetranspose = MatSolveTranspose_SeqBAIJ_2_NaturalOrdering; 1189f1af5d2fSBarry Smith PLogInfo(inA,"MatILUFactor_SeqBAIJ:Using special in-place natural ordering solvetrans BS=1\n"); 119015091d37SBarry Smith case 2: 119115091d37SBarry Smith inA->ops->lufactornumeric = MatLUFactorNumeric_SeqBAIJ_2_NaturalOrdering; 119215091d37SBarry Smith inA->ops->solve = MatSolve_SeqBAIJ_2_NaturalOrdering; 11937c922b88SBarry Smith inA->ops->solvetranspose = MatSolveTranspose_SeqBAIJ_2_NaturalOrdering; 119415091d37SBarry Smith PLogInfo(inA,"MatILUFactor_SeqBAIJ:Using special in-place natural ordering factor and solve BS=2\n"); 119515091d37SBarry Smith break; 119615091d37SBarry Smith case 3: 119715091d37SBarry Smith inA->ops->lufactornumeric = MatLUFactorNumeric_SeqBAIJ_3_NaturalOrdering; 119815091d37SBarry Smith inA->ops->solve = MatSolve_SeqBAIJ_3_NaturalOrdering; 11997c922b88SBarry Smith inA->ops->solvetranspose = MatSolveTranspose_SeqBAIJ_3_NaturalOrdering; 120015091d37SBarry Smith PLogInfo(inA,"MatILUFactor_SeqBAIJ:Using special in-place natural ordering factor and solve BS=3\n"); 120115091d37SBarry Smith break; 120215091d37SBarry Smith case 4: 1203667159a5SBarry Smith inA->ops->lufactornumeric = MatLUFactorNumeric_SeqBAIJ_4_NaturalOrdering; 1204f830108cSBarry Smith inA->ops->solve = MatSolve_SeqBAIJ_4_NaturalOrdering; 12057c922b88SBarry Smith inA->ops->solvetranspose = MatSolveTranspose_SeqBAIJ_4_NaturalOrdering; 120615091d37SBarry Smith PLogInfo(inA,"MatILUFactor_SeqBAIJ:Using special in-place natural ordering factor and solve BS=4\n"); 120715091d37SBarry Smith break; 120815091d37SBarry Smith case 5: 1209667159a5SBarry Smith inA->ops->lufactornumeric = MatLUFactorNumeric_SeqBAIJ_5_NaturalOrdering; 1210667159a5SBarry Smith inA->ops->solve = MatSolve_SeqBAIJ_5_NaturalOrdering; 12117c922b88SBarry Smith inA->ops->solvetranspose = MatSolveTranspose_SeqBAIJ_5_NaturalOrdering; 121215091d37SBarry Smith PLogInfo(inA,"MatILUFactor_SeqBAIJ:Using special in-place natural ordering factor and solve BS=5\n"); 121315091d37SBarry Smith break; 121415091d37SBarry Smith case 6: 121515091d37SBarry Smith inA->ops->lufactornumeric = MatLUFactorNumeric_SeqBAIJ_6_NaturalOrdering; 121615091d37SBarry Smith inA->ops->solve = MatSolve_SeqBAIJ_6_NaturalOrdering; 12177c922b88SBarry Smith inA->ops->solvetranspose = MatSolveTranspose_SeqBAIJ_6_NaturalOrdering; 121815091d37SBarry Smith PLogInfo(inA,"MatILUFactor_SeqBAIJ:Using special in-place natural ordering factor and solve BS=6\n"); 121915091d37SBarry Smith break; 122015091d37SBarry Smith case 7: 122115091d37SBarry Smith inA->ops->lufactornumeric = MatLUFactorNumeric_SeqBAIJ_7_NaturalOrdering; 12227c922b88SBarry Smith inA->ops->solvetranspose = MatSolveTranspose_SeqBAIJ_7_NaturalOrdering; 122315091d37SBarry Smith inA->ops->solve = MatSolve_SeqBAIJ_7_NaturalOrdering; 122415091d37SBarry Smith PLogInfo(inA,"MatILUFactor_SeqBAIJ:Using special in-place natural ordering factor and solve BS=7\n"); 122515091d37SBarry Smith break; 1226c38d4ed2SBarry Smith default: 1227c38d4ed2SBarry Smith a->row = row; 1228c38d4ed2SBarry Smith a->col = col; 1229c38d4ed2SBarry Smith ierr = PetscObjectReference((PetscObject)row);CHKERRQ(ierr); 1230c38d4ed2SBarry Smith ierr = PetscObjectReference((PetscObject)col);CHKERRQ(ierr); 1231c38d4ed2SBarry Smith 1232c38d4ed2SBarry Smith /* Create the invert permutation so that it can be used in MatLUFactorNumeric() */ 1233c38d4ed2SBarry Smith ierr = ISInvertPermutation(col,&(a->icol));CHKERRQ(ierr); 1234c38d4ed2SBarry Smith PLogObjectParent(inA,a->icol); 1235c38d4ed2SBarry Smith 1236c38d4ed2SBarry Smith if (!a->solve_work) { 1237c38d4ed2SBarry Smith a->solve_work = (Scalar*)PetscMalloc((a->m+a->bs)*sizeof(Scalar));CHKPTRQ(a->solve_work); 1238c38d4ed2SBarry Smith PLogObjectMemory(inA,(a->m+a->bs)*sizeof(Scalar)); 1239c38d4ed2SBarry Smith } 12402d61bbb3SSatish Balay } 12412d61bbb3SSatish Balay 1242667159a5SBarry Smith ierr = MatLUFactorNumeric(inA,&outA);CHKERRQ(ierr); 1243667159a5SBarry Smith 12442d61bbb3SSatish Balay PetscFunctionReturn(0); 12452d61bbb3SSatish Balay } 12462d61bbb3SSatish Balay #undef __FUNC__ 1247d4bb536fSBarry Smith #define __FUNC__ "MatPrintHelp_SeqBAIJ" 1248ba4ca20aSSatish Balay int MatPrintHelp_SeqBAIJ(Mat A) 1249ba4ca20aSSatish Balay { 1250c38d4ed2SBarry Smith static PetscTruth called = PETSC_FALSE; 1251ba4ca20aSSatish Balay MPI_Comm comm = A->comm; 1252d132466eSBarry Smith int ierr; 1253ba4ca20aSSatish Balay 12543a40ed3dSBarry Smith PetscFunctionBegin; 1255c38d4ed2SBarry Smith if (called) {PetscFunctionReturn(0);} else called = PETSC_TRUE; 1256d132466eSBarry Smith ierr = (*PetscHelpPrintf)(comm," Options for MATSEQBAIJ and MATMPIBAIJ matrix formats (the defaults):\n");CHKERRQ(ierr); 1257d132466eSBarry Smith ierr = (*PetscHelpPrintf)(comm," -mat_block_size <block_size>\n");CHKERRQ(ierr); 12583a40ed3dSBarry Smith PetscFunctionReturn(0); 1259ba4ca20aSSatish Balay } 1260d9b7c43dSSatish Balay 1261fb2e594dSBarry Smith EXTERN_C_BEGIN 126227a8da17SBarry Smith #undef __FUNC__ 126327a8da17SBarry Smith #define __FUNC__ "MatSeqBAIJSetColumnIndices_SeqBAIJ" 126427a8da17SBarry Smith int MatSeqBAIJSetColumnIndices_SeqBAIJ(Mat mat,int *indices) 126527a8da17SBarry Smith { 126627a8da17SBarry Smith Mat_SeqBAIJ *baij = (Mat_SeqBAIJ *)mat->data; 126727a8da17SBarry Smith int i,nz,n; 126827a8da17SBarry Smith 126927a8da17SBarry Smith PetscFunctionBegin; 127027a8da17SBarry Smith nz = baij->maxnz; 127127a8da17SBarry Smith n = baij->n; 127227a8da17SBarry Smith for (i=0; i<nz; i++) { 127327a8da17SBarry Smith baij->j[i] = indices[i]; 127427a8da17SBarry Smith } 127527a8da17SBarry Smith baij->nz = nz; 127627a8da17SBarry Smith for (i=0; i<n; i++) { 127727a8da17SBarry Smith baij->ilen[i] = baij->imax[i]; 127827a8da17SBarry Smith } 127927a8da17SBarry Smith 128027a8da17SBarry Smith PetscFunctionReturn(0); 128127a8da17SBarry Smith } 1282fb2e594dSBarry Smith EXTERN_C_END 128327a8da17SBarry Smith 128427a8da17SBarry Smith #undef __FUNC__ 128527a8da17SBarry Smith #define __FUNC__ "MatSeqBAIJSetColumnIndices" 128627a8da17SBarry Smith /*@ 128727a8da17SBarry Smith MatSeqBAIJSetColumnIndices - Set the column indices for all the rows 128827a8da17SBarry Smith in the matrix. 128927a8da17SBarry Smith 129027a8da17SBarry Smith Input Parameters: 129127a8da17SBarry Smith + mat - the SeqBAIJ matrix 129227a8da17SBarry Smith - indices - the column indices 129327a8da17SBarry Smith 129415091d37SBarry Smith Level: advanced 129515091d37SBarry Smith 129627a8da17SBarry Smith Notes: 129727a8da17SBarry Smith This can be called if you have precomputed the nonzero structure of the 129827a8da17SBarry Smith matrix and want to provide it to the matrix object to improve the performance 129927a8da17SBarry Smith of the MatSetValues() operation. 130027a8da17SBarry Smith 130127a8da17SBarry Smith You MUST have set the correct numbers of nonzeros per row in the call to 130227a8da17SBarry Smith MatCreateSeqBAIJ(). 130327a8da17SBarry Smith 130427a8da17SBarry Smith MUST be called before any calls to MatSetValues(); 130527a8da17SBarry Smith 130627a8da17SBarry Smith @*/ 130727a8da17SBarry Smith int MatSeqBAIJSetColumnIndices(Mat mat,int *indices) 130827a8da17SBarry Smith { 130927a8da17SBarry Smith int ierr,(*f)(Mat,int *); 131027a8da17SBarry Smith 131127a8da17SBarry Smith PetscFunctionBegin; 131227a8da17SBarry Smith PetscValidHeaderSpecific(mat,MAT_COOKIE); 1313549d3d68SSatish Balay ierr = PetscObjectQueryFunction((PetscObject)mat,"MatSeqBAIJSetColumnIndices_C",(void **)&f);CHKERRQ(ierr); 131427a8da17SBarry Smith if (f) { 131527a8da17SBarry Smith ierr = (*f)(mat,indices);CHKERRQ(ierr); 131627a8da17SBarry Smith } else { 131727a8da17SBarry Smith SETERRQ(1,1,"Wrong type of matrix to set column indices"); 131827a8da17SBarry Smith } 131927a8da17SBarry Smith PetscFunctionReturn(0); 132027a8da17SBarry Smith } 132127a8da17SBarry Smith 13222593348eSBarry Smith /* -------------------------------------------------------------------*/ 1323cc2dc46cSBarry Smith static struct _MatOps MatOps_Values = {MatSetValues_SeqBAIJ, 1324cc2dc46cSBarry Smith MatGetRow_SeqBAIJ, 1325cc2dc46cSBarry Smith MatRestoreRow_SeqBAIJ, 1326cc2dc46cSBarry Smith MatMult_SeqBAIJ_N, 1327cc2dc46cSBarry Smith MatMultAdd_SeqBAIJ_N, 13287c922b88SBarry Smith MatMultTranspose_SeqBAIJ, 13297c922b88SBarry Smith MatMultTransposeAdd_SeqBAIJ, 1330cc2dc46cSBarry Smith MatSolve_SeqBAIJ_N, 1331cc2dc46cSBarry Smith 0, 1332cc2dc46cSBarry Smith 0, 1333cc2dc46cSBarry Smith 0, 1334cc2dc46cSBarry Smith MatLUFactor_SeqBAIJ, 1335cc2dc46cSBarry Smith 0, 1336b6490206SBarry Smith 0, 1337f2501298SSatish Balay MatTranspose_SeqBAIJ, 1338cc2dc46cSBarry Smith MatGetInfo_SeqBAIJ, 1339cc2dc46cSBarry Smith MatEqual_SeqBAIJ, 1340cc2dc46cSBarry Smith MatGetDiagonal_SeqBAIJ, 1341cc2dc46cSBarry Smith MatDiagonalScale_SeqBAIJ, 1342cc2dc46cSBarry Smith MatNorm_SeqBAIJ, 1343b6490206SBarry Smith 0, 1344cc2dc46cSBarry Smith MatAssemblyEnd_SeqBAIJ, 1345cc2dc46cSBarry Smith 0, 1346cc2dc46cSBarry Smith MatSetOption_SeqBAIJ, 1347cc2dc46cSBarry Smith MatZeroEntries_SeqBAIJ, 1348cc2dc46cSBarry Smith MatZeroRows_SeqBAIJ, 1349cc2dc46cSBarry Smith MatLUFactorSymbolic_SeqBAIJ, 1350cc2dc46cSBarry Smith MatLUFactorNumeric_SeqBAIJ_N, 1351cc2dc46cSBarry Smith 0, 1352cc2dc46cSBarry Smith 0, 1353cc2dc46cSBarry Smith MatGetSize_SeqBAIJ, 1354cc2dc46cSBarry Smith MatGetSize_SeqBAIJ, 1355cc2dc46cSBarry Smith MatGetOwnershipRange_SeqBAIJ, 1356cc2dc46cSBarry Smith MatILUFactorSymbolic_SeqBAIJ, 1357cc2dc46cSBarry Smith 0, 1358cc2dc46cSBarry Smith 0, 1359cc2dc46cSBarry Smith 0, 13602e8a6d31SBarry Smith MatDuplicate_SeqBAIJ, 1361cc2dc46cSBarry Smith 0, 1362cc2dc46cSBarry Smith 0, 1363cc2dc46cSBarry Smith MatILUFactor_SeqBAIJ, 1364cc2dc46cSBarry Smith 0, 1365cc2dc46cSBarry Smith 0, 1366cc2dc46cSBarry Smith MatGetSubMatrices_SeqBAIJ, 1367cc2dc46cSBarry Smith MatIncreaseOverlap_SeqBAIJ, 1368cc2dc46cSBarry Smith MatGetValues_SeqBAIJ, 1369cc2dc46cSBarry Smith 0, 1370cc2dc46cSBarry Smith MatPrintHelp_SeqBAIJ, 1371cc2dc46cSBarry Smith MatScale_SeqBAIJ, 1372cc2dc46cSBarry Smith 0, 1373cc2dc46cSBarry Smith 0, 1374cc2dc46cSBarry Smith 0, 1375cc2dc46cSBarry Smith MatGetBlockSize_SeqBAIJ, 13763b2fbd54SBarry Smith MatGetRowIJ_SeqBAIJ, 137792c4ed94SBarry Smith MatRestoreRowIJ_SeqBAIJ, 1378cc2dc46cSBarry Smith 0, 1379cc2dc46cSBarry Smith 0, 1380cc2dc46cSBarry Smith 0, 1381cc2dc46cSBarry Smith 0, 1382cc2dc46cSBarry Smith 0, 1383cc2dc46cSBarry Smith 0, 1384d3825aa8SBarry Smith MatSetValuesBlocked_SeqBAIJ, 1385cc2dc46cSBarry Smith MatGetSubMatrix_SeqBAIJ, 1386cc2dc46cSBarry Smith 0, 1387cc2dc46cSBarry Smith 0, 1388cc2dc46cSBarry Smith MatGetMaps_Petsc}; 13892593348eSBarry Smith 13903e90b805SBarry Smith EXTERN_C_BEGIN 13913e90b805SBarry Smith #undef __FUNC__ 13923e90b805SBarry Smith #define __FUNC__ "MatStoreValues_SeqBAIJ" 13933e90b805SBarry Smith int MatStoreValues_SeqBAIJ(Mat mat) 13943e90b805SBarry Smith { 13953e90b805SBarry Smith Mat_SeqBAIJ *aij = (Mat_SeqBAIJ *)mat->data; 13963e90b805SBarry Smith int nz = aij->i[aij->m]*aij->bs*aij->bs2; 1397d132466eSBarry Smith int ierr; 13983e90b805SBarry Smith 13993e90b805SBarry Smith PetscFunctionBegin; 14003e90b805SBarry Smith if (aij->nonew != 1) { 14013e90b805SBarry Smith SETERRQ(1,1,"Must call MatSetOption(A,MAT_NO_NEW_NONZERO_LOCATIONS);first"); 14023e90b805SBarry Smith } 14033e90b805SBarry Smith 14043e90b805SBarry Smith /* allocate space for values if not already there */ 14053e90b805SBarry Smith if (!aij->saved_values) { 14063e90b805SBarry Smith aij->saved_values = (Scalar*)PetscMalloc(nz*sizeof(Scalar));CHKPTRQ(aij->saved_values); 14073e90b805SBarry Smith } 14083e90b805SBarry Smith 14093e90b805SBarry Smith /* copy values over */ 1410d132466eSBarry Smith ierr = PetscMemcpy(aij->saved_values,aij->a,nz*sizeof(Scalar));CHKERRQ(ierr); 14113e90b805SBarry Smith PetscFunctionReturn(0); 14123e90b805SBarry Smith } 14133e90b805SBarry Smith EXTERN_C_END 14143e90b805SBarry Smith 14153e90b805SBarry Smith EXTERN_C_BEGIN 14163e90b805SBarry Smith #undef __FUNC__ 141732e87ba3SBarry Smith #define __FUNC__ "MatRetrieveValues_SeqBAIJ" 141832e87ba3SBarry Smith int MatRetrieveValues_SeqBAIJ(Mat mat) 14193e90b805SBarry Smith { 14203e90b805SBarry Smith Mat_SeqBAIJ *aij = (Mat_SeqBAIJ *)mat->data; 1421549d3d68SSatish Balay int nz = aij->i[aij->m]*aij->bs*aij->bs2,ierr; 14223e90b805SBarry Smith 14233e90b805SBarry Smith PetscFunctionBegin; 14243e90b805SBarry Smith if (aij->nonew != 1) { 14253e90b805SBarry Smith SETERRQ(1,1,"Must call MatSetOption(A,MAT_NO_NEW_NONZERO_LOCATIONS);first"); 14263e90b805SBarry Smith } 14273e90b805SBarry Smith if (!aij->saved_values) { 14283e90b805SBarry Smith SETERRQ(1,1,"Must call MatStoreValues(A);first"); 14293e90b805SBarry Smith } 14303e90b805SBarry Smith 14313e90b805SBarry Smith /* copy values over */ 1432549d3d68SSatish Balay ierr = PetscMemcpy(aij->a,aij->saved_values,nz*sizeof(Scalar));CHKERRQ(ierr); 14333e90b805SBarry Smith PetscFunctionReturn(0); 14343e90b805SBarry Smith } 14353e90b805SBarry Smith EXTERN_C_END 14363e90b805SBarry Smith 14375615d1e5SSatish Balay #undef __FUNC__ 14385615d1e5SSatish Balay #define __FUNC__ "MatCreateSeqBAIJ" 14392593348eSBarry Smith /*@C 144044cd7ae7SLois Curfman McInnes MatCreateSeqBAIJ - Creates a sparse matrix in block AIJ (block 144144cd7ae7SLois Curfman McInnes compressed row) format. For good matrix assembly performance the 144244cd7ae7SLois Curfman McInnes user should preallocate the matrix storage by setting the parameter nz 14437fc3c18eSBarry Smith (or the array nnz). By setting these parameters accurately, performance 14442bd5e0b2SLois Curfman McInnes during matrix assembly can be increased by more than a factor of 50. 14452593348eSBarry Smith 1446db81eaa0SLois Curfman McInnes Collective on MPI_Comm 1447db81eaa0SLois Curfman McInnes 14482593348eSBarry Smith Input Parameters: 1449db81eaa0SLois Curfman McInnes + comm - MPI communicator, set to PETSC_COMM_SELF 1450b6490206SBarry Smith . bs - size of block 14512593348eSBarry Smith . m - number of rows 14522593348eSBarry Smith . n - number of columns 1453b6490206SBarry Smith . nz - number of block nonzeros per block row (same for all rows) 14547fc3c18eSBarry Smith - nnz - array containing the number of block nonzeros in the various block rows 14552bd5e0b2SLois Curfman McInnes (possibly different for each block row) or PETSC_NULL 14562593348eSBarry Smith 14572593348eSBarry Smith Output Parameter: 14582593348eSBarry Smith . A - the matrix 14592593348eSBarry Smith 14600513a670SBarry Smith Options Database Keys: 1461db81eaa0SLois Curfman McInnes . -mat_no_unroll - uses code that does not unroll the loops in the 1462db81eaa0SLois Curfman McInnes block calculations (much slower) 1463db81eaa0SLois Curfman McInnes . -mat_block_size - size of the blocks to use 14640513a670SBarry Smith 146515091d37SBarry Smith Level: intermediate 146615091d37SBarry Smith 14672593348eSBarry Smith Notes: 146844cd7ae7SLois Curfman McInnes The block AIJ format is fully compatible with standard Fortran 77 14692593348eSBarry Smith storage. That is, the stored row and column indices can begin at 147044cd7ae7SLois Curfman McInnes either one (as in Fortran) or zero. See the users' manual for details. 14712593348eSBarry Smith 14722593348eSBarry Smith Specify the preallocated storage with either nz or nnz (not both). 14732593348eSBarry Smith Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory 14742593348eSBarry Smith allocation. For additional details, see the users manual chapter on 14756da5968aSLois Curfman McInnes matrices. 14762593348eSBarry Smith 1477db81eaa0SLois Curfman McInnes .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatCreateMPIBAIJ() 14782593348eSBarry Smith @*/ 1479b6490206SBarry Smith int MatCreateSeqBAIJ(MPI_Comm comm,int bs,int m,int n,int nz,int *nnz,Mat *A) 14802593348eSBarry Smith { 14812593348eSBarry Smith Mat B; 1482b6490206SBarry Smith Mat_SeqBAIJ *b; 1483f1af5d2fSBarry Smith int i,len,ierr,mbs,nbs,bs2,size; 1484f1af5d2fSBarry Smith PetscTruth flg; 14853b2fbd54SBarry Smith 14863a40ed3dSBarry Smith PetscFunctionBegin; 1487d132466eSBarry Smith ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 1488a8c6a408SBarry Smith if (size > 1) SETERRQ(PETSC_ERR_ARG_WRONG,0,"Comm must be of size 1"); 1489b6490206SBarry Smith 1490962fb4a0SBarry Smith ierr = OptionsGetInt(PETSC_NULL,"-mat_block_size",&bs,PETSC_NULL);CHKERRQ(ierr); 1491302e33e3SBarry Smith mbs = m/bs; 1492302e33e3SBarry Smith nbs = n/bs; 1493302e33e3SBarry Smith bs2 = bs*bs; 14940513a670SBarry Smith 14953a40ed3dSBarry Smith if (mbs*bs!=m || nbs*bs!=n) { 1496a8c6a408SBarry Smith SETERRQ(PETSC_ERR_ARG_SIZ,0,"Number rows, cols must be divisible by blocksize"); 14973a40ed3dSBarry Smith } 14982593348eSBarry Smith 1499b73539f3SBarry Smith if (nz < -2) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,0,"nz cannot be less than -2: value %d",nz); 1500b73539f3SBarry Smith if (nnz) { 1501faf3f1fcSBarry Smith for (i=0; i<mbs; i++) { 1502b73539f3SBarry Smith if (nnz[i] < 0) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,0,"nnz cannot be less than 0: local row %d value %d",i,nnz[i]); 1503b73539f3SBarry Smith } 1504b73539f3SBarry Smith } 1505b73539f3SBarry Smith 15062593348eSBarry Smith *A = 0; 15073f1db9ecSBarry Smith PetscHeaderCreate(B,_p_Mat,struct _MatOps,MAT_COOKIE,MATSEQBAIJ,"Mat",comm,MatDestroy,MatView); 15082593348eSBarry Smith PLogObjectCreate(B); 1509b6490206SBarry Smith B->data = (void*)(b = PetscNew(Mat_SeqBAIJ));CHKPTRQ(b); 1510549d3d68SSatish Balay ierr = PetscMemzero(b,sizeof(Mat_SeqBAIJ));CHKERRQ(ierr); 1511549d3d68SSatish Balay ierr = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr); 15121a6a6d98SBarry Smith ierr = OptionsHasName(PETSC_NULL,"-mat_no_unroll",&flg);CHKERRQ(ierr); 15131a6a6d98SBarry Smith if (!flg) { 15147fc0212eSBarry Smith switch (bs) { 15157fc0212eSBarry Smith case 1: 1516f830108cSBarry Smith B->ops->lufactornumeric = MatLUFactorNumeric_SeqBAIJ_1; 1517f830108cSBarry Smith B->ops->solve = MatSolve_SeqBAIJ_1; 15187c922b88SBarry Smith B->ops->solvetranspose = MatSolveTranspose_SeqBAIJ_1; 1519f830108cSBarry Smith B->ops->mult = MatMult_SeqBAIJ_1; 1520f830108cSBarry Smith B->ops->multadd = MatMultAdd_SeqBAIJ_1; 15217fc0212eSBarry Smith break; 15224eeb42bcSBarry Smith case 2: 1523f830108cSBarry Smith B->ops->lufactornumeric = MatLUFactorNumeric_SeqBAIJ_2; 1524f830108cSBarry Smith B->ops->solve = MatSolve_SeqBAIJ_2; 15257c922b88SBarry Smith B->ops->solvetranspose = MatSolveTranspose_SeqBAIJ_2; 1526f830108cSBarry Smith B->ops->mult = MatMult_SeqBAIJ_2; 1527f830108cSBarry Smith B->ops->multadd = MatMultAdd_SeqBAIJ_2; 15286d84be18SBarry Smith break; 1529f327dd97SBarry Smith case 3: 1530f830108cSBarry Smith B->ops->lufactornumeric = MatLUFactorNumeric_SeqBAIJ_3; 1531f830108cSBarry Smith B->ops->solve = MatSolve_SeqBAIJ_3; 15327c922b88SBarry Smith B->ops->solvetranspose = MatSolveTranspose_SeqBAIJ_3; 1533f830108cSBarry Smith B->ops->mult = MatMult_SeqBAIJ_3; 1534f830108cSBarry Smith B->ops->multadd = MatMultAdd_SeqBAIJ_3; 15354eeb42bcSBarry Smith break; 15366d84be18SBarry Smith case 4: 1537f830108cSBarry Smith B->ops->lufactornumeric = MatLUFactorNumeric_SeqBAIJ_4; 1538f830108cSBarry Smith B->ops->solve = MatSolve_SeqBAIJ_4; 15397c922b88SBarry Smith B->ops->solvetranspose = MatSolveTranspose_SeqBAIJ_4; 1540f830108cSBarry Smith B->ops->mult = MatMult_SeqBAIJ_4; 1541f830108cSBarry Smith B->ops->multadd = MatMultAdd_SeqBAIJ_4; 15426d84be18SBarry Smith break; 15436d84be18SBarry Smith case 5: 1544f830108cSBarry Smith B->ops->lufactornumeric = MatLUFactorNumeric_SeqBAIJ_5; 1545f830108cSBarry Smith B->ops->solve = MatSolve_SeqBAIJ_5; 15467c922b88SBarry Smith B->ops->solvetranspose = MatSolveTranspose_SeqBAIJ_5; 1547f830108cSBarry Smith B->ops->mult = MatMult_SeqBAIJ_5; 1548f830108cSBarry Smith B->ops->multadd = MatMultAdd_SeqBAIJ_5; 15496d84be18SBarry Smith break; 155015091d37SBarry Smith case 6: 155115091d37SBarry Smith B->ops->lufactornumeric = MatLUFactorNumeric_SeqBAIJ_6; 155215091d37SBarry Smith B->ops->solve = MatSolve_SeqBAIJ_6; 15537c922b88SBarry Smith B->ops->solvetranspose = MatSolveTranspose_SeqBAIJ_6; 155415091d37SBarry Smith B->ops->mult = MatMult_SeqBAIJ_6; 155515091d37SBarry Smith B->ops->multadd = MatMultAdd_SeqBAIJ_6; 155615091d37SBarry Smith break; 155748e9ddb2SSatish Balay case 7: 1558f830108cSBarry Smith B->ops->mult = MatMult_SeqBAIJ_7; 1559f830108cSBarry Smith B->ops->solve = MatSolve_SeqBAIJ_7; 15607c922b88SBarry Smith B->ops->solvetranspose = MatSolveTranspose_SeqBAIJ_7; 1561f830108cSBarry Smith B->ops->multadd = MatMultAdd_SeqBAIJ_7; 156248e9ddb2SSatish Balay break; 15637fc0212eSBarry Smith } 15641a6a6d98SBarry Smith } 1565e1311b90SBarry Smith B->ops->destroy = MatDestroy_SeqBAIJ; 1566e1311b90SBarry Smith B->ops->view = MatView_SeqBAIJ; 15672593348eSBarry Smith B->factor = 0; 15682593348eSBarry Smith B->lupivotthreshold = 1.0; 156990f02eecSBarry Smith B->mapping = 0; 15702593348eSBarry Smith b->row = 0; 15712593348eSBarry Smith b->col = 0; 1572e51c0b9cSSatish Balay b->icol = 0; 15732593348eSBarry Smith b->reallocs = 0; 15743e90b805SBarry Smith b->saved_values = 0; 15752593348eSBarry Smith 157644cd7ae7SLois Curfman McInnes b->m = m; B->m = m; B->M = m; 157744cd7ae7SLois Curfman McInnes b->n = n; B->n = n; B->N = n; 1578a5ae1ecdSBarry Smith 15797413bad6SBarry Smith ierr = MapCreateMPI(comm,m,m,&B->rmap);CHKERRQ(ierr); 15807413bad6SBarry Smith ierr = MapCreateMPI(comm,n,n,&B->cmap);CHKERRQ(ierr); 1581a5ae1ecdSBarry Smith 1582b6490206SBarry Smith b->mbs = mbs; 1583f2501298SSatish Balay b->nbs = nbs; 1584b6490206SBarry Smith b->imax = (int*)PetscMalloc((mbs+1)*sizeof(int));CHKPTRQ(b->imax); 1585c4992f7dSBarry Smith if (!nnz) { 1586119a934aSSatish Balay if (nz == PETSC_DEFAULT) nz = 5; 15872593348eSBarry Smith else if (nz <= 0) nz = 1; 1588b6490206SBarry Smith for (i=0; i<mbs; i++) b->imax[i] = nz; 1589b6490206SBarry Smith nz = nz*mbs; 15903a40ed3dSBarry Smith } else { 15912593348eSBarry Smith nz = 0; 1592b6490206SBarry Smith for (i=0; i<mbs; i++) {b->imax[i] = nnz[i]; nz += nnz[i];} 15932593348eSBarry Smith } 15942593348eSBarry Smith 15952593348eSBarry Smith /* allocate the matrix space */ 15963f1db9ecSBarry Smith len = nz*sizeof(int) + nz*bs2*sizeof(MatScalar) + (b->m+1)*sizeof(int); 15973f1db9ecSBarry Smith b->a = (MatScalar*)PetscMalloc(len);CHKPTRQ(b->a); 1598549d3d68SSatish Balay ierr = PetscMemzero(b->a,nz*bs2*sizeof(MatScalar));CHKERRQ(ierr); 15997e67e3f9SSatish Balay b->j = (int*)(b->a + nz*bs2); 1600549d3d68SSatish Balay ierr = PetscMemzero(b->j,nz*sizeof(int));CHKERRQ(ierr); 16012593348eSBarry Smith b->i = b->j + nz; 1602c4992f7dSBarry Smith b->singlemalloc = PETSC_TRUE; 16032593348eSBarry Smith 1604de6a44a3SBarry Smith b->i[0] = 0; 1605b6490206SBarry Smith for (i=1; i<mbs+1; i++) { 16062593348eSBarry Smith b->i[i] = b->i[i-1] + b->imax[i-1]; 16072593348eSBarry Smith } 16082593348eSBarry Smith 1609b6490206SBarry Smith /* b->ilen will count nonzeros in each block row so far. */ 1610b6490206SBarry Smith b->ilen = (int*)PetscMalloc((mbs+1)*sizeof(int)); 1611f09e8eb9SSatish Balay PLogObjectMemory(B,len+2*(mbs+1)*sizeof(int)+sizeof(struct _p_Mat)+sizeof(Mat_SeqBAIJ)); 1612b6490206SBarry Smith for (i=0; i<mbs; i++) { b->ilen[i] = 0;} 16132593348eSBarry Smith 1614b6490206SBarry Smith b->bs = bs; 16159df24120SSatish Balay b->bs2 = bs2; 1616b6490206SBarry Smith b->mbs = mbs; 16172593348eSBarry Smith b->nz = 0; 161818e7b8e4SLois Curfman McInnes b->maxnz = nz*bs2; 1619c4992f7dSBarry Smith b->sorted = PETSC_FALSE; 1620c4992f7dSBarry Smith b->roworiented = PETSC_TRUE; 16212593348eSBarry Smith b->nonew = 0; 16222593348eSBarry Smith b->diag = 0; 16232593348eSBarry Smith b->solve_work = 0; 1624de6a44a3SBarry Smith b->mult_work = 0; 16252593348eSBarry Smith b->spptr = 0; 1626*0e6d2581SBarry Smith B->info.nz_unneeded = (PetscReal)b->maxnz; 1627883fce79SBarry Smith b->keepzeroedrows = PETSC_FALSE; 16284e220ebcSLois Curfman McInnes 16292593348eSBarry Smith *A = B; 16302593348eSBarry Smith ierr = OptionsHasName(PETSC_NULL,"-help",&flg);CHKERRQ(ierr); 16312593348eSBarry Smith if (flg) {ierr = MatPrintHelp(B);CHKERRQ(ierr); } 163227a8da17SBarry Smith 1633f1af5d2fSBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatStoreValues_C", 16343e90b805SBarry Smith "MatStoreValues_SeqBAIJ", 16353e90b805SBarry Smith (void*)MatStoreValues_SeqBAIJ);CHKERRQ(ierr); 1636f1af5d2fSBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatRetrieveValues_C", 16373e90b805SBarry Smith "MatRetrieveValues_SeqBAIJ", 16383e90b805SBarry Smith (void*)MatRetrieveValues_SeqBAIJ);CHKERRQ(ierr); 1639f1af5d2fSBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqBAIJSetColumnIndices_C", 164027a8da17SBarry Smith "MatSeqBAIJSetColumnIndices_SeqBAIJ", 164127a8da17SBarry Smith (void*)MatSeqBAIJSetColumnIndices_SeqBAIJ);CHKERRQ(ierr); 16423a40ed3dSBarry Smith PetscFunctionReturn(0); 16432593348eSBarry Smith } 16442593348eSBarry Smith 16455615d1e5SSatish Balay #undef __FUNC__ 16462e8a6d31SBarry Smith #define __FUNC__ "MatDuplicate_SeqBAIJ" 16472e8a6d31SBarry Smith int MatDuplicate_SeqBAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B) 16482593348eSBarry Smith { 16492593348eSBarry Smith Mat C; 1650b6490206SBarry Smith Mat_SeqBAIJ *c,*a = (Mat_SeqBAIJ*)A->data; 165127a8da17SBarry Smith int i,len,mbs = a->mbs,nz = a->nz,bs2 =a->bs2,ierr; 1652de6a44a3SBarry Smith 16533a40ed3dSBarry Smith PetscFunctionBegin; 1654a8c6a408SBarry Smith if (a->i[mbs] != nz) SETERRQ(PETSC_ERR_PLIB,0,"Corrupt matrix"); 16552593348eSBarry Smith 16562593348eSBarry Smith *B = 0; 16573f1db9ecSBarry Smith PetscHeaderCreate(C,_p_Mat,struct _MatOps,MAT_COOKIE,MATSEQBAIJ,"Mat",A->comm,MatDestroy,MatView); 16582593348eSBarry Smith PLogObjectCreate(C); 1659b6490206SBarry Smith C->data = (void*)(c = PetscNew(Mat_SeqBAIJ));CHKPTRQ(c); 1660549d3d68SSatish Balay ierr = PetscMemcpy(C->ops,A->ops,sizeof(struct _MatOps));CHKERRQ(ierr); 1661e1311b90SBarry Smith C->ops->destroy = MatDestroy_SeqBAIJ; 1662e1311b90SBarry Smith C->ops->view = MatView_SeqBAIJ; 16632593348eSBarry Smith C->factor = A->factor; 16642593348eSBarry Smith c->row = 0; 16652593348eSBarry Smith c->col = 0; 1666cac97260SSatish Balay c->icol = 0; 166732e87ba3SBarry Smith c->saved_values = 0; 1668f1e2ffcdSBarry Smith c->keepzeroedrows = a->keepzeroedrows; 16692593348eSBarry Smith C->assembled = PETSC_TRUE; 16702593348eSBarry Smith 167144cd7ae7SLois Curfman McInnes c->m = C->m = a->m; 167244cd7ae7SLois Curfman McInnes c->n = C->n = a->n; 167344cd7ae7SLois Curfman McInnes C->M = a->m; 167444cd7ae7SLois Curfman McInnes C->N = a->n; 167544cd7ae7SLois Curfman McInnes 1676b6490206SBarry Smith c->bs = a->bs; 16779df24120SSatish Balay c->bs2 = a->bs2; 1678b6490206SBarry Smith c->mbs = a->mbs; 1679b6490206SBarry Smith c->nbs = a->nbs; 16802593348eSBarry Smith 1681b6490206SBarry Smith c->imax = (int*)PetscMalloc((mbs+1)*sizeof(int));CHKPTRQ(c->imax); 1682b6490206SBarry Smith c->ilen = (int*)PetscMalloc((mbs+1)*sizeof(int));CHKPTRQ(c->ilen); 1683b6490206SBarry Smith for (i=0; i<mbs; i++) { 16842593348eSBarry Smith c->imax[i] = a->imax[i]; 16852593348eSBarry Smith c->ilen[i] = a->ilen[i]; 16862593348eSBarry Smith } 16872593348eSBarry Smith 16882593348eSBarry Smith /* allocate the matrix space */ 1689c4992f7dSBarry Smith c->singlemalloc = PETSC_TRUE; 16903f1db9ecSBarry Smith len = (mbs+1)*sizeof(int) + nz*(bs2*sizeof(MatScalar) + sizeof(int)); 16913f1db9ecSBarry Smith c->a = (MatScalar*)PetscMalloc(len);CHKPTRQ(c->a); 16927e67e3f9SSatish Balay c->j = (int*)(c->a + nz*bs2); 1693de6a44a3SBarry Smith c->i = c->j + nz; 1694549d3d68SSatish Balay ierr = PetscMemcpy(c->i,a->i,(mbs+1)*sizeof(int));CHKERRQ(ierr); 1695b6490206SBarry Smith if (mbs > 0) { 1696549d3d68SSatish Balay ierr = PetscMemcpy(c->j,a->j,nz*sizeof(int));CHKERRQ(ierr); 16972e8a6d31SBarry Smith if (cpvalues == MAT_COPY_VALUES) { 1698549d3d68SSatish Balay ierr = PetscMemcpy(c->a,a->a,bs2*nz*sizeof(MatScalar));CHKERRQ(ierr); 16992e8a6d31SBarry Smith } else { 1700549d3d68SSatish Balay ierr = PetscMemzero(c->a,bs2*nz*sizeof(MatScalar));CHKERRQ(ierr); 17012593348eSBarry Smith } 17022593348eSBarry Smith } 17032593348eSBarry Smith 1704f09e8eb9SSatish Balay PLogObjectMemory(C,len+2*(mbs+1)*sizeof(int)+sizeof(struct _p_Mat)+sizeof(Mat_SeqBAIJ)); 17052593348eSBarry Smith c->sorted = a->sorted; 17062593348eSBarry Smith c->roworiented = a->roworiented; 17072593348eSBarry Smith c->nonew = a->nonew; 17082593348eSBarry Smith 17092593348eSBarry Smith if (a->diag) { 1710b6490206SBarry Smith c->diag = (int*)PetscMalloc((mbs+1)*sizeof(int));CHKPTRQ(c->diag); 1711b6490206SBarry Smith PLogObjectMemory(C,(mbs+1)*sizeof(int)); 1712b6490206SBarry Smith for (i=0; i<mbs; i++) { 17132593348eSBarry Smith c->diag[i] = a->diag[i]; 17142593348eSBarry Smith } 171598305bb5SBarry Smith } else c->diag = 0; 17162593348eSBarry Smith c->nz = a->nz; 17172593348eSBarry Smith c->maxnz = a->maxnz; 17182593348eSBarry Smith c->solve_work = 0; 17192593348eSBarry Smith c->spptr = 0; /* Dangerous -I'm throwing away a->spptr */ 17207fc0212eSBarry Smith c->mult_work = 0; 17212593348eSBarry Smith *B = C; 17227b2a1423SBarry Smith ierr = FListDuplicate(A->qlist,&C->qlist);CHKERRQ(ierr); 17233a40ed3dSBarry Smith PetscFunctionReturn(0); 17242593348eSBarry Smith } 17252593348eSBarry Smith 17265615d1e5SSatish Balay #undef __FUNC__ 17275615d1e5SSatish Balay #define __FUNC__ "MatLoad_SeqBAIJ" 172819bcc07fSBarry Smith int MatLoad_SeqBAIJ(Viewer viewer,MatType type,Mat *A) 17292593348eSBarry Smith { 1730b6490206SBarry Smith Mat_SeqBAIJ *a; 17312593348eSBarry Smith Mat B; 1732f1af5d2fSBarry Smith int i,nz,ierr,fd,header[4],size,*rowlengths=0,M,N,bs=1; 1733b6490206SBarry Smith int *mask,mbs,*jj,j,rowcount,nzcount,k,*browlengths,maskcount; 173435aab85fSBarry Smith int kmax,jcount,block,idx,point,nzcountb,extra_rows; 1735a7c10996SSatish Balay int *masked,nmask,tmp,bs2,ishift; 1736b6490206SBarry Smith Scalar *aa; 173719bcc07fSBarry Smith MPI_Comm comm = ((PetscObject)viewer)->comm; 17382593348eSBarry Smith 17393a40ed3dSBarry Smith PetscFunctionBegin; 1740f1af5d2fSBarry Smith ierr = OptionsGetInt(PETSC_NULL,"-matload_block_size",&bs,PETSC_NULL);CHKERRQ(ierr); 1741de6a44a3SBarry Smith bs2 = bs*bs; 1742b6490206SBarry Smith 1743d132466eSBarry Smith ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 1744cc0fae11SBarry Smith if (size > 1) SETERRQ(PETSC_ERR_ARG_WRONG,0,"view must have one processor"); 174590ace30eSBarry Smith ierr = ViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr); 17460752156aSBarry Smith ierr = PetscBinaryRead(fd,header,4,PETSC_INT);CHKERRQ(ierr); 1747a8c6a408SBarry Smith if (header[0] != MAT_COOKIE) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,0,"not Mat object"); 17482593348eSBarry Smith M = header[1]; N = header[2]; nz = header[3]; 17492593348eSBarry Smith 1750d64ed03dSBarry Smith if (header[3] < 0) { 1751a8c6a408SBarry Smith SETERRQ(PETSC_ERR_FILE_UNEXPECTED,1,"Matrix stored in special format, cannot load as SeqBAIJ"); 1752d64ed03dSBarry Smith } 1753d64ed03dSBarry Smith 1754a8c6a408SBarry Smith if (M != N) SETERRQ(PETSC_ERR_SUP,0,"Can only do square matrices"); 175535aab85fSBarry Smith 175635aab85fSBarry Smith /* 175735aab85fSBarry Smith This code adds extra rows to make sure the number of rows is 175835aab85fSBarry Smith divisible by the blocksize 175935aab85fSBarry Smith */ 1760b6490206SBarry Smith mbs = M/bs; 176135aab85fSBarry Smith extra_rows = bs - M + bs*(mbs); 176235aab85fSBarry Smith if (extra_rows == bs) extra_rows = 0; 176335aab85fSBarry Smith else mbs++; 176435aab85fSBarry Smith if (extra_rows) { 1765537820f0SBarry Smith PLogInfo(0,"MatLoad_SeqBAIJ:Padding loaded matrix to match blocksize\n"); 176635aab85fSBarry Smith } 1767b6490206SBarry Smith 17682593348eSBarry Smith /* read in row lengths */ 176935aab85fSBarry Smith rowlengths = (int*)PetscMalloc((M+extra_rows)*sizeof(int));CHKPTRQ(rowlengths); 17700752156aSBarry Smith ierr = PetscBinaryRead(fd,rowlengths,M,PETSC_INT);CHKERRQ(ierr); 177135aab85fSBarry Smith for (i=0; i<extra_rows; i++) rowlengths[M+i] = 1; 17722593348eSBarry Smith 1773b6490206SBarry Smith /* read in column indices */ 177435aab85fSBarry Smith jj = (int*)PetscMalloc((nz+extra_rows)*sizeof(int));CHKPTRQ(jj); 17750752156aSBarry Smith ierr = PetscBinaryRead(fd,jj,nz,PETSC_INT);CHKERRQ(ierr); 177635aab85fSBarry Smith for (i=0; i<extra_rows; i++) jj[nz+i] = M+i; 1777b6490206SBarry Smith 1778b6490206SBarry Smith /* loop over row lengths determining block row lengths */ 1779b6490206SBarry Smith browlengths = (int*)PetscMalloc(mbs*sizeof(int));CHKPTRQ(browlengths); 1780549d3d68SSatish Balay ierr = PetscMemzero(browlengths,mbs*sizeof(int));CHKERRQ(ierr); 178135aab85fSBarry Smith mask = (int*)PetscMalloc(2*mbs*sizeof(int));CHKPTRQ(mask); 1782549d3d68SSatish Balay ierr = PetscMemzero(mask,mbs*sizeof(int));CHKERRQ(ierr); 178335aab85fSBarry Smith masked = mask + mbs; 1784b6490206SBarry Smith rowcount = 0; nzcount = 0; 1785b6490206SBarry Smith for (i=0; i<mbs; i++) { 178635aab85fSBarry Smith nmask = 0; 1787b6490206SBarry Smith for (j=0; j<bs; j++) { 1788b6490206SBarry Smith kmax = rowlengths[rowcount]; 1789b6490206SBarry Smith for (k=0; k<kmax; k++) { 179035aab85fSBarry Smith tmp = jj[nzcount++]/bs; 179135aab85fSBarry Smith if (!mask[tmp]) {masked[nmask++] = tmp; mask[tmp] = 1;} 1792b6490206SBarry Smith } 1793b6490206SBarry Smith rowcount++; 1794b6490206SBarry Smith } 179535aab85fSBarry Smith browlengths[i] += nmask; 179635aab85fSBarry Smith /* zero out the mask elements we set */ 179735aab85fSBarry Smith for (j=0; j<nmask; j++) mask[masked[j]] = 0; 1798b6490206SBarry Smith } 1799b6490206SBarry Smith 18002593348eSBarry Smith /* create our matrix */ 18013eee16b0SBarry Smith ierr = MatCreateSeqBAIJ(comm,bs,M+extra_rows,N+extra_rows,0,browlengths,A);CHKERRQ(ierr); 18022593348eSBarry Smith B = *A; 1803b6490206SBarry Smith a = (Mat_SeqBAIJ*)B->data; 18042593348eSBarry Smith 18052593348eSBarry Smith /* set matrix "i" values */ 1806de6a44a3SBarry Smith a->i[0] = 0; 1807b6490206SBarry Smith for (i=1; i<= mbs; i++) { 1808b6490206SBarry Smith a->i[i] = a->i[i-1] + browlengths[i-1]; 1809b6490206SBarry Smith a->ilen[i-1] = browlengths[i-1]; 18102593348eSBarry Smith } 1811b6490206SBarry Smith a->nz = 0; 1812b6490206SBarry Smith for (i=0; i<mbs; i++) a->nz += browlengths[i]; 18132593348eSBarry Smith 1814b6490206SBarry Smith /* read in nonzero values */ 181535aab85fSBarry Smith aa = (Scalar*)PetscMalloc((nz+extra_rows)*sizeof(Scalar));CHKPTRQ(aa); 18160752156aSBarry Smith ierr = PetscBinaryRead(fd,aa,nz,PETSC_SCALAR);CHKERRQ(ierr); 181735aab85fSBarry Smith for (i=0; i<extra_rows; i++) aa[nz+i] = 1.0; 1818b6490206SBarry Smith 1819b6490206SBarry Smith /* set "a" and "j" values into matrix */ 1820b6490206SBarry Smith nzcount = 0; jcount = 0; 1821b6490206SBarry Smith for (i=0; i<mbs; i++) { 1822b6490206SBarry Smith nzcountb = nzcount; 182335aab85fSBarry Smith nmask = 0; 1824b6490206SBarry Smith for (j=0; j<bs; j++) { 1825b6490206SBarry Smith kmax = rowlengths[i*bs+j]; 1826b6490206SBarry Smith for (k=0; k<kmax; k++) { 182735aab85fSBarry Smith tmp = jj[nzcount++]/bs; 182835aab85fSBarry Smith if (!mask[tmp]) { masked[nmask++] = tmp; mask[tmp] = 1;} 1829b6490206SBarry Smith } 1830b6490206SBarry Smith rowcount++; 1831b6490206SBarry Smith } 1832de6a44a3SBarry Smith /* sort the masked values */ 1833433994e6SBarry Smith ierr = PetscSortInt(nmask,masked);CHKERRQ(ierr); 1834de6a44a3SBarry Smith 1835b6490206SBarry Smith /* set "j" values into matrix */ 1836b6490206SBarry Smith maskcount = 1; 183735aab85fSBarry Smith for (j=0; j<nmask; j++) { 183835aab85fSBarry Smith a->j[jcount++] = masked[j]; 1839de6a44a3SBarry Smith mask[masked[j]] = maskcount++; 1840b6490206SBarry Smith } 1841b6490206SBarry Smith /* set "a" values into matrix */ 1842de6a44a3SBarry Smith ishift = bs2*a->i[i]; 1843b6490206SBarry Smith for (j=0; j<bs; j++) { 1844b6490206SBarry Smith kmax = rowlengths[i*bs+j]; 1845b6490206SBarry Smith for (k=0; k<kmax; k++) { 1846de6a44a3SBarry Smith tmp = jj[nzcountb]/bs ; 1847de6a44a3SBarry Smith block = mask[tmp] - 1; 1848de6a44a3SBarry Smith point = jj[nzcountb] - bs*tmp; 1849de6a44a3SBarry Smith idx = ishift + bs2*block + j + bs*point; 1850b6490206SBarry Smith a->a[idx] = aa[nzcountb++]; 1851b6490206SBarry Smith } 1852b6490206SBarry Smith } 185335aab85fSBarry Smith /* zero out the mask elements we set */ 185435aab85fSBarry Smith for (j=0; j<nmask; j++) mask[masked[j]] = 0; 1855b6490206SBarry Smith } 1856a8c6a408SBarry Smith if (jcount != a->nz) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,0,"Bad binary matrix"); 1857b6490206SBarry Smith 1858606d414cSSatish Balay ierr = PetscFree(rowlengths);CHKERRQ(ierr); 1859606d414cSSatish Balay ierr = PetscFree(browlengths);CHKERRQ(ierr); 1860606d414cSSatish Balay ierr = PetscFree(aa);CHKERRQ(ierr); 1861606d414cSSatish Balay ierr = PetscFree(jj);CHKERRQ(ierr); 1862606d414cSSatish Balay ierr = PetscFree(mask);CHKERRQ(ierr); 1863b6490206SBarry Smith 1864b6490206SBarry Smith B->assembled = PETSC_TRUE; 1865de6a44a3SBarry Smith 18669c01be13SBarry Smith ierr = MatView_Private(B);CHKERRQ(ierr); 18673a40ed3dSBarry Smith PetscFunctionReturn(0); 18682593348eSBarry Smith } 18692593348eSBarry Smith 18702593348eSBarry Smith 18712593348eSBarry Smith 1872