1c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/aij.h> 2c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/bas/spbas.h> 3b2f1ab58SBarry Smith 4845006b9SBarry Smith /*MC 52692d6eeSBarry Smith MATSOLVERBAS - Provides ICC(k) with drop tolerance 6845006b9SBarry Smith 7845006b9SBarry Smith Works with MATAIJ matrices 8845006b9SBarry Smith 9845006b9SBarry Smith Options Database Keys: 100053dfc8SBarry Smith + -pc_factor_levels <l> - number of levels of fill 110053dfc8SBarry Smith - -pc_factor_drop_tolerance - is not currently hooked up to do anything 12845006b9SBarry Smith 130053dfc8SBarry Smith Level: intermediate 14845006b9SBarry Smith 15845006b9SBarry Smith Contributed by: Bas van 't Hof 16845006b9SBarry Smith 170053dfc8SBarry Smith Notes: Since this currently hooked up to use drop tolerance it should produce the same factors and hence convergence as the PETSc ICC, for higher 180053dfc8SBarry Smith levels of fill it does not. This needs to be investigated. Unless you are interested in drop tolerance ICC and willing to work through the code 190053dfc8SBarry Smith we recommend not using this functionality. 200053dfc8SBarry Smith 21b7c853c4SBarry Smith .seealso: PCFactorSetMatSolverPackage(), MatSolverPackage, PCFactorSetLevels(), PCFactorSetDropTolerance() 22845006b9SBarry Smith 23845006b9SBarry Smith M*/ 249ccc4a9bSBarry Smith 25b2f1ab58SBarry Smith /* 26b2f1ab58SBarry Smith spbas_memory_requirement: 27b2f1ab58SBarry Smith Calculate the number of bytes needed to store tha matrix 28b2f1ab58SBarry Smith */ 293dfa2556SBarry Smith size_t spbas_memory_requirement(spbas_matrix matrix) 30b2f1ab58SBarry Smith { 313dfa2556SBarry Smith size_t memreq = 6 * sizeof(PetscInt) + /* nrows, ncols, nnz, n_alloc_icol, n_alloc_val, col_idx_type */ 32ace3abfcSBarry Smith sizeof(PetscBool) + /* block_data */ 33c328eeadSBarry Smith sizeof(PetscScalar**) + /* values */ 34c328eeadSBarry Smith sizeof(PetscScalar*) + /* alloc_val */ 353dfa2556SBarry Smith 2 * sizeof(PetscInt**) + /* icols, icols0 */ 36c328eeadSBarry Smith 2 * sizeof(PetscInt*) + /* row_nnz, alloc_icol */ 37c328eeadSBarry Smith matrix.nrows * sizeof(PetscInt) + /* row_nnz[*] */ 38c328eeadSBarry Smith matrix.nrows * sizeof(PetscInt*); /* icols[*] */ 39b2f1ab58SBarry Smith 40c328eeadSBarry Smith /* icol0[*] */ 412205254eSKarl Rupp if (matrix.col_idx_type == SPBAS_OFFSET_ARRAY) memreq += matrix.nrows * sizeof(PetscInt); 42b2f1ab58SBarry Smith 43c328eeadSBarry Smith /* icols[*][*] */ 442205254eSKarl Rupp if (matrix.block_data) memreq += matrix.n_alloc_icol * sizeof(PetscInt); 452205254eSKarl Rupp else memreq += matrix.nnz * sizeof(PetscInt); 46b2f1ab58SBarry Smith 474e1ff37aSBarry Smith if (matrix.values) { 48c328eeadSBarry Smith memreq += matrix.nrows * sizeof(PetscScalar*); /* values[*] */ 49c328eeadSBarry Smith /* values[*][*] */ 502205254eSKarl Rupp if (matrix.block_data) memreq += matrix.n_alloc_val * sizeof(PetscScalar); 512205254eSKarl Rupp else memreq += matrix.nnz * sizeof(PetscScalar); 52b2f1ab58SBarry Smith } 53b2f1ab58SBarry Smith return memreq; 54b2f1ab58SBarry Smith } 55b2f1ab58SBarry Smith 56b2f1ab58SBarry Smith /* 57b2f1ab58SBarry Smith spbas_allocate_pattern: 58b2f1ab58SBarry Smith allocate the pattern arrays row_nnz, icols and optionally values 59b2f1ab58SBarry Smith */ 60ace3abfcSBarry Smith PetscErrorCode spbas_allocate_pattern(spbas_matrix * result, PetscBool do_values) 61b2f1ab58SBarry Smith { 62b2f1ab58SBarry Smith PetscErrorCode ierr; 63b2f1ab58SBarry Smith PetscInt nrows = result->nrows; 64b2f1ab58SBarry Smith PetscInt col_idx_type = result->col_idx_type; 65b2f1ab58SBarry Smith 66b2f1ab58SBarry Smith PetscFunctionBegin; 67c328eeadSBarry Smith /* Allocate sparseness pattern */ 68785e854fSJed Brown ierr = PetscMalloc1(nrows,&result->row_nnz);CHKERRQ(ierr); 69785e854fSJed Brown ierr = PetscMalloc1(nrows,&result->icols);CHKERRQ(ierr); 70b2f1ab58SBarry Smith 71c328eeadSBarry Smith /* If offsets are given wrt an array, create array */ 724e1ff37aSBarry Smith if (col_idx_type == SPBAS_OFFSET_ARRAY) { 73785e854fSJed Brown ierr = PetscMalloc1(nrows,&result->icol0);CHKERRQ(ierr); 744e1ff37aSBarry Smith } else { 750298fd71SBarry Smith result->icol0 = NULL; 76b2f1ab58SBarry Smith } 77b2f1ab58SBarry Smith 78c328eeadSBarry Smith /* If values are given, allocate values array */ 794e1ff37aSBarry Smith if (do_values) { 80785e854fSJed Brown ierr = PetscMalloc1(nrows,&result->values);CHKERRQ(ierr); 814e1ff37aSBarry Smith } else { 820298fd71SBarry Smith result->values = NULL; 83b2f1ab58SBarry Smith } 84b2f1ab58SBarry Smith PetscFunctionReturn(0); 85b2f1ab58SBarry Smith } 86b2f1ab58SBarry Smith 87b2f1ab58SBarry Smith /* 88b2f1ab58SBarry Smith spbas_allocate_data: 89b2f1ab58SBarry Smith in case of block_data: 90b2f1ab58SBarry Smith Allocate the data arrays alloc_icol and optionally alloc_val, 91b2f1ab58SBarry Smith set appropriate pointers from icols and values; 92b2f1ab58SBarry Smith in case of !block_data: 93b2f1ab58SBarry Smith Allocate the arrays icols[i] and optionally values[i] 94b2f1ab58SBarry Smith */ 95b2f1ab58SBarry Smith PetscErrorCode spbas_allocate_data(spbas_matrix * result) 96b2f1ab58SBarry Smith { 97b2f1ab58SBarry Smith PetscInt i; 98b2f1ab58SBarry Smith PetscInt nnz = result->nnz; 99b2f1ab58SBarry Smith PetscInt nrows = result->nrows; 100b2f1ab58SBarry Smith PetscInt r_nnz; 101b2f1ab58SBarry Smith PetscErrorCode ierr; 1026c4ed002SBarry Smith PetscBool do_values = (result->values) ? PETSC_TRUE : PETSC_FALSE; 103ace3abfcSBarry Smith PetscBool block_data = result->block_data; 104b2f1ab58SBarry Smith 105b2f1ab58SBarry Smith PetscFunctionBegin; 1064e1ff37aSBarry Smith if (block_data) { 107c328eeadSBarry Smith /* Allocate the column number array and point to it */ 108b2f1ab58SBarry Smith result->n_alloc_icol = nnz; 1092205254eSKarl Rupp 110785e854fSJed Brown ierr = PetscMalloc1(nnz, &result->alloc_icol);CHKERRQ(ierr); 1112205254eSKarl Rupp 112b2f1ab58SBarry Smith result->icols[0] = result->alloc_icol; 1134e1ff37aSBarry Smith for (i=1; i<nrows; i++) { 114b2f1ab58SBarry Smith result->icols[i] = result->icols[i-1] + result->row_nnz[i-1]; 115b2f1ab58SBarry Smith } 116b2f1ab58SBarry Smith 117c328eeadSBarry Smith /* Allocate the value array and point to it */ 1184e1ff37aSBarry Smith if (do_values) { 119b2f1ab58SBarry Smith result->n_alloc_val = nnz; 1202205254eSKarl Rupp 121785e854fSJed Brown ierr = PetscMalloc1(nnz, &result->alloc_val);CHKERRQ(ierr); 1222205254eSKarl Rupp 123b2f1ab58SBarry Smith result->values[0] = result->alloc_val; 1244e1ff37aSBarry Smith for (i=1; i<nrows; i++) { 125b2f1ab58SBarry Smith result->values[i] = result->values[i-1] + result->row_nnz[i-1]; 126b2f1ab58SBarry Smith } 127b2f1ab58SBarry Smith } 1284e1ff37aSBarry Smith } else { 1294e1ff37aSBarry Smith for (i=0; i<nrows; i++) { 130b2f1ab58SBarry Smith r_nnz = result->row_nnz[i]; 131785e854fSJed Brown ierr = PetscMalloc1(r_nnz, &result->icols[i]);CHKERRQ(ierr); 132b2f1ab58SBarry Smith } 1334e1ff37aSBarry Smith if (do_values) { 1344e1ff37aSBarry Smith for (i=0; i<nrows; i++) { 135b2f1ab58SBarry Smith r_nnz = result->row_nnz[i]; 136785e854fSJed Brown ierr = PetscMalloc1(r_nnz, &result->values[i]);CHKERRQ(ierr); 137b2f1ab58SBarry Smith } 138b2f1ab58SBarry Smith } 139b2f1ab58SBarry Smith } 140b2f1ab58SBarry Smith PetscFunctionReturn(0); 141b2f1ab58SBarry Smith } 142b2f1ab58SBarry Smith 143b2f1ab58SBarry Smith /* 144b2f1ab58SBarry Smith spbas_row_order_icol 145b2f1ab58SBarry Smith determine if row i1 should come 146b2f1ab58SBarry Smith + before row i2 in the sorted rows (return -1), 147b2f1ab58SBarry Smith + after (return 1) 148b2f1ab58SBarry Smith + is identical (return 0). 149b2f1ab58SBarry Smith */ 150b2f1ab58SBarry Smith int spbas_row_order_icol(PetscInt i1, PetscInt i2, PetscInt *irow_in, PetscInt *icol_in,PetscInt col_idx_type) 151b2f1ab58SBarry Smith { 152b2f1ab58SBarry Smith PetscInt j; 153b2f1ab58SBarry Smith PetscInt nnz1 = irow_in[i1+1] - irow_in[i1]; 154b2f1ab58SBarry Smith PetscInt nnz2 = irow_in[i2+1] - irow_in[i2]; 155b2f1ab58SBarry Smith PetscInt * icol1 = &icol_in[irow_in[i1]]; 156b2f1ab58SBarry Smith PetscInt * icol2 = &icol_in[irow_in[i2]]; 157b2f1ab58SBarry Smith 1582205254eSKarl Rupp if (nnz1<nnz2) return -1; 1592205254eSKarl Rupp if (nnz1>nnz2) return 1; 160b2f1ab58SBarry Smith 1614e1ff37aSBarry Smith if (col_idx_type == SPBAS_COLUMN_NUMBERS) { 1624e1ff37aSBarry Smith for (j=0; j<nnz1; j++) { 1632205254eSKarl Rupp if (icol1[j]< icol2[j]) return -1; 1642205254eSKarl Rupp if (icol1[j]> icol2[j]) return 1; 165b2f1ab58SBarry Smith } 1664e1ff37aSBarry Smith } else if (col_idx_type == SPBAS_DIAGONAL_OFFSETS) { 1674e1ff37aSBarry Smith for (j=0; j<nnz1; j++) { 1682205254eSKarl Rupp if (icol1[j]-i1< icol2[j]-i2) return -1; 1692205254eSKarl Rupp if (icol1[j]-i1> icol2[j]-i2) return 1; 170b2f1ab58SBarry Smith } 1714e1ff37aSBarry Smith } else if (col_idx_type == SPBAS_OFFSET_ARRAY) { 1724e1ff37aSBarry Smith for (j=1; j<nnz1; j++) { 1732205254eSKarl Rupp if (icol1[j]-icol1[0] < icol2[j]-icol2[0]) return -1; 1742205254eSKarl Rupp if (icol1[j]-icol1[0] > icol2[j]-icol2[0]) return 1; 175b2f1ab58SBarry Smith } 176b2f1ab58SBarry Smith } 177b2f1ab58SBarry Smith return 0; 178b2f1ab58SBarry Smith } 179b2f1ab58SBarry Smith 180b2f1ab58SBarry Smith /* 181b2f1ab58SBarry Smith spbas_mergesort_icols: 182b2f1ab58SBarry Smith return a sorting of the rows in which identical sparseness patterns are 183b2f1ab58SBarry Smith next to each other 184b2f1ab58SBarry Smith */ 185b2f1ab58SBarry Smith PetscErrorCode spbas_mergesort_icols(PetscInt nrows, PetscInt * irow_in, PetscInt * icol_in,PetscInt col_idx_type, PetscInt *isort) 186b2f1ab58SBarry Smith { 187b2f1ab58SBarry Smith PetscErrorCode ierr; 188c328eeadSBarry Smith PetscInt istep; /* Chunk-sizes of already sorted parts of arrays */ 189c328eeadSBarry Smith PetscInt i, i1, i2; /* Loop counters for (partly) sorted arrays */ 190c328eeadSBarry Smith PetscInt istart, i1end, i2end; /* start of newly sorted array part, end of both parts */ 191c328eeadSBarry Smith PetscInt *ialloc; /* Allocated arrays */ 192c328eeadSBarry Smith PetscInt *iswap; /* auxiliary pointers for swapping */ 193c328eeadSBarry Smith PetscInt *ihlp1; /* Pointers to new version of arrays, */ 194c328eeadSBarry Smith PetscInt *ihlp2; /* Pointers to previous version of arrays, */ 195b2f1ab58SBarry Smith 196b2f1ab58SBarry Smith PetscFunctionBegin; 197785e854fSJed Brown ierr = PetscMalloc1(nrows,&ialloc);CHKERRQ(ierr); 198b2f1ab58SBarry Smith 199b2f1ab58SBarry Smith ihlp1 = ialloc; 200b2f1ab58SBarry Smith ihlp2 = isort; 201b2f1ab58SBarry Smith 202c328eeadSBarry Smith /* Sorted array chunks are first 1 long, and increase until they are the complete array */ 2034e1ff37aSBarry Smith for (istep=1; istep<nrows; istep*=2) { 204c328eeadSBarry Smith /* 205c328eeadSBarry Smith Combine sorted parts 206c328eeadSBarry Smith istart:istart+istep-1 and istart+istep-1:istart+2*istep-1 207c328eeadSBarry Smith of ihlp2 and vhlp2 208c328eeadSBarry Smith 209c328eeadSBarry Smith into one sorted part 210c328eeadSBarry Smith istart:istart+2*istep-1 211c328eeadSBarry Smith of ihlp1 and vhlp1 212c328eeadSBarry Smith */ 2134e1ff37aSBarry Smith for (istart=0; istart<nrows; istart+=2*istep) { 214c328eeadSBarry Smith /* Set counters and bound array part endings */ 2152205254eSKarl Rupp i1=istart; i1end = i1+istep; if (i1end>nrows) i1end=nrows; 2162205254eSKarl Rupp i2=istart+istep; i2end = i2+istep; if (i2end>nrows) i2end=nrows; 217b2f1ab58SBarry Smith 218c328eeadSBarry Smith /* Merge the two array parts */ 2194e1ff37aSBarry Smith for (i=istart; i<i2end; i++) { 2204e1ff37aSBarry Smith if (i1<i1end && i2<i2end && spbas_row_order_icol(ihlp2[i1], ihlp2[i2], irow_in, icol_in, col_idx_type) < 0) { 221b2f1ab58SBarry Smith ihlp1[i] = ihlp2[i1]; 222b2f1ab58SBarry Smith i1++; 2234e1ff37aSBarry Smith } else if (i2<i2end) { 224b2f1ab58SBarry Smith ihlp1[i] = ihlp2[i2]; 225b2f1ab58SBarry Smith i2++; 2264e1ff37aSBarry Smith } else { 227b2f1ab58SBarry Smith ihlp1[i] = ihlp2[i1]; 228b2f1ab58SBarry Smith i1++; 229b2f1ab58SBarry Smith } 230b2f1ab58SBarry Smith } 231b2f1ab58SBarry Smith } 232b2f1ab58SBarry Smith 233c328eeadSBarry Smith /* Swap the two array sets */ 234b2f1ab58SBarry Smith iswap = ihlp2; ihlp2 = ihlp1; ihlp1 = iswap; 235b2f1ab58SBarry Smith } 236b2f1ab58SBarry Smith 237c328eeadSBarry Smith /* Copy one more time in case the sorted arrays are the temporary ones */ 2384e1ff37aSBarry Smith if (ihlp2 != isort) { 2392205254eSKarl Rupp for (i=0; i<nrows; i++) isort[i] = ihlp2[i]; 240b2f1ab58SBarry Smith } 241b2f1ab58SBarry Smith ierr = PetscFree(ialloc);CHKERRQ(ierr); 242b2f1ab58SBarry Smith PetscFunctionReturn(0); 243b2f1ab58SBarry Smith } 244b2f1ab58SBarry Smith 245b2f1ab58SBarry Smith 246b2f1ab58SBarry Smith 247b2f1ab58SBarry Smith /* 248b2f1ab58SBarry Smith spbas_compress_pattern: 249b2f1ab58SBarry Smith calculate a compressed sparseness pattern for a sparseness pattern 250b2f1ab58SBarry Smith given in compressed row storage. The compressed sparseness pattern may 251b2f1ab58SBarry Smith require (much) less memory. 252b2f1ab58SBarry Smith */ 2534e1ff37aSBarry Smith PetscErrorCode spbas_compress_pattern(PetscInt *irow_in, PetscInt *icol_in, PetscInt nrows, PetscInt ncols, PetscInt col_idx_type, spbas_matrix *B,PetscReal *mem_reduction) 254b2f1ab58SBarry Smith { 255b2f1ab58SBarry Smith PetscInt nnz = irow_in[nrows]; 2563dfa2556SBarry Smith size_t mem_orig = (nrows + nnz) * sizeof(PetscInt); 2573dfa2556SBarry Smith size_t mem_compressed; 258b2f1ab58SBarry Smith PetscErrorCode ierr; 259b2f1ab58SBarry Smith PetscInt *isort; 260b2f1ab58SBarry Smith PetscInt *icols; 261b2f1ab58SBarry Smith PetscInt row_nnz; 262b2f1ab58SBarry Smith PetscInt *ipoint; 263ace3abfcSBarry Smith PetscBool *used; 264b2f1ab58SBarry Smith PetscInt ptr; 265b2f1ab58SBarry Smith PetscInt i,j; 266ace3abfcSBarry Smith const PetscBool no_values = PETSC_FALSE; 267b2f1ab58SBarry Smith 268b2f1ab58SBarry Smith PetscFunctionBegin; 269c328eeadSBarry Smith /* Allocate the structure of the new matrix */ 270b2f1ab58SBarry Smith B->nrows = nrows; 271b2f1ab58SBarry Smith B->ncols = ncols; 272b2f1ab58SBarry Smith B->nnz = nnz; 273b2f1ab58SBarry Smith B->col_idx_type = col_idx_type; 274b2f1ab58SBarry Smith B->block_data = PETSC_TRUE; 2752205254eSKarl Rupp 276b2f1ab58SBarry Smith ierr = spbas_allocate_pattern(B, no_values);CHKERRQ(ierr); 277b2f1ab58SBarry Smith 278c328eeadSBarry Smith /* When using an offset array, set it */ 2794e1ff37aSBarry Smith if (col_idx_type==SPBAS_OFFSET_ARRAY) { 2802205254eSKarl Rupp for (i=0; i<nrows; i++) B->icol0[i] = icol_in[irow_in[i]]; 281b2f1ab58SBarry Smith } 282b2f1ab58SBarry Smith 283c328eeadSBarry Smith /* Allocate the ordering for the rows */ 284785e854fSJed Brown ierr = PetscMalloc1(nrows,&isort);CHKERRQ(ierr); 285785e854fSJed Brown ierr = PetscMalloc1(nrows,&ipoint);CHKERRQ(ierr); 286785e854fSJed Brown ierr = PetscMalloc1(nrows,&used);CHKERRQ(ierr); 287b2f1ab58SBarry Smith 288c328eeadSBarry Smith /* Initialize the sorting */ 289ace3abfcSBarry Smith ierr = PetscMemzero((void*) used, nrows*sizeof(PetscBool));CHKERRQ(ierr); 2904e1ff37aSBarry Smith for (i = 0; i<nrows; i++) { 291b2f1ab58SBarry Smith B->row_nnz[i] = irow_in[i+1]-irow_in[i]; 292b2f1ab58SBarry Smith isort[i] = i; 293b2f1ab58SBarry Smith ipoint[i] = i; 294b2f1ab58SBarry Smith } 295b2f1ab58SBarry Smith 296c328eeadSBarry Smith /* Sort the rows so that identical columns will be next to each other */ 297b2f1ab58SBarry Smith ierr = spbas_mergesort_icols(nrows, irow_in, icol_in, col_idx_type, isort);CHKERRQ(ierr); 2980298fd71SBarry Smith ierr = PetscInfo(NULL,"Rows have been sorted for patterns\n");CHKERRQ(ierr); 299b2f1ab58SBarry Smith 300c328eeadSBarry Smith /* Replace identical rows with the first one in the list */ 3014e1ff37aSBarry Smith for (i=1; i<nrows; i++) { 3024e1ff37aSBarry Smith if (spbas_row_order_icol(isort[i-1], isort[i], irow_in, icol_in, col_idx_type) == 0) { 303b2f1ab58SBarry Smith ipoint[isort[i]] = ipoint[isort[i-1]]; 304b2f1ab58SBarry Smith } 305b2f1ab58SBarry Smith } 306b2f1ab58SBarry Smith 307c328eeadSBarry Smith /* Collect the rows which are used*/ 3082205254eSKarl Rupp for (i=0; i<nrows; i++) used[ipoint[i]] = PETSC_TRUE; 309b2f1ab58SBarry Smith 310c328eeadSBarry Smith /* Calculate needed memory */ 311b2f1ab58SBarry Smith B->n_alloc_icol = 0; 3124e1ff37aSBarry Smith for (i=0; i<nrows; i++) { 3132205254eSKarl Rupp if (used[i]) B->n_alloc_icol += B->row_nnz[i]; 314b2f1ab58SBarry Smith } 315785e854fSJed Brown ierr = PetscMalloc1(B->n_alloc_icol,&B->alloc_icol);CHKERRQ(ierr); 316b2f1ab58SBarry Smith 317c328eeadSBarry Smith /* Fill in the diagonal offsets for the rows which store their own data */ 318b2f1ab58SBarry Smith ptr = 0; 3194e1ff37aSBarry Smith for (i=0; i<B->nrows; i++) { 3204e1ff37aSBarry Smith if (used[i]) { 321b2f1ab58SBarry Smith B->icols[i] = &B->alloc_icol[ptr]; 322b2f1ab58SBarry Smith icols = &icol_in[irow_in[i]]; 323b2f1ab58SBarry Smith row_nnz = B->row_nnz[i]; 3244e1ff37aSBarry Smith if (col_idx_type == SPBAS_COLUMN_NUMBERS) { 3254e1ff37aSBarry Smith for (j=0; j<row_nnz; j++) { 326b2f1ab58SBarry Smith B->icols[i][j] = icols[j]; 327b2f1ab58SBarry Smith } 3284e1ff37aSBarry Smith } else if (col_idx_type == SPBAS_DIAGONAL_OFFSETS) { 3294e1ff37aSBarry Smith for (j=0; j<row_nnz; j++) { 330b2f1ab58SBarry Smith B->icols[i][j] = icols[j]-i; 331b2f1ab58SBarry Smith } 3324e1ff37aSBarry Smith } else if (col_idx_type == SPBAS_OFFSET_ARRAY) { 3334e1ff37aSBarry Smith for (j=0; j<row_nnz; j++) { 334b2f1ab58SBarry Smith B->icols[i][j] = icols[j]-icols[0]; 335b2f1ab58SBarry Smith } 336b2f1ab58SBarry Smith } 337b2f1ab58SBarry Smith ptr += B->row_nnz[i]; 338b2f1ab58SBarry Smith } 339b2f1ab58SBarry Smith } 340b2f1ab58SBarry Smith 341c328eeadSBarry Smith /* Point to the right places for all data */ 3424e1ff37aSBarry Smith for (i=0; i<nrows; i++) { 343b2f1ab58SBarry Smith B->icols[i] = B->icols[ipoint[i]]; 344b2f1ab58SBarry Smith } 3450298fd71SBarry Smith ierr = PetscInfo(NULL,"Row patterns have been compressed\n");CHKERRQ(ierr); 34657622a8eSBarry Smith ierr = PetscInfo1(NULL," (%g nonzeros per row)\n", (double) ((PetscReal) nnz / (PetscReal) nrows));CHKERRQ(ierr); 347b2f1ab58SBarry Smith 348b2f1ab58SBarry Smith ierr=PetscFree(isort);CHKERRQ(ierr); 349b2f1ab58SBarry Smith ierr=PetscFree(used);CHKERRQ(ierr); 350b2f1ab58SBarry Smith ierr=PetscFree(ipoint);CHKERRQ(ierr); 351b2f1ab58SBarry Smith 352b2f1ab58SBarry Smith mem_compressed = spbas_memory_requirement(*B); 3534e1ff37aSBarry Smith *mem_reduction = 100.0 * (PetscReal)(mem_orig-mem_compressed)/ (PetscReal) mem_orig; 354b2f1ab58SBarry Smith PetscFunctionReturn(0); 355b2f1ab58SBarry Smith } 356b2f1ab58SBarry Smith 357b2f1ab58SBarry Smith /* 358b2f1ab58SBarry Smith spbas_incomplete_cholesky 359b2f1ab58SBarry Smith Incomplete Cholesky decomposition 360b2f1ab58SBarry Smith */ 361c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/bas/spbas_cholesky.h> 362b2f1ab58SBarry Smith 363b2f1ab58SBarry Smith /* 364b2f1ab58SBarry Smith spbas_delete : de-allocate the arrays owned by this matrix 365b2f1ab58SBarry Smith */ 366b2f1ab58SBarry Smith PetscErrorCode spbas_delete(spbas_matrix matrix) 367b2f1ab58SBarry Smith { 368b2f1ab58SBarry Smith PetscInt i; 369b2f1ab58SBarry Smith PetscErrorCode ierr; 3709ccc4a9bSBarry Smith 371b2f1ab58SBarry Smith PetscFunctionBegin; 3729ccc4a9bSBarry Smith if (matrix.block_data) { 373cb9801acSJed Brown ierr=PetscFree(matrix.alloc_icol);CHKERRQ(ierr); 374b2f1ab58SBarry Smith if (matrix.values) {ierr=PetscFree(matrix.alloc_val);CHKERRQ(ierr);} 3759ccc4a9bSBarry Smith } else { 3769ccc4a9bSBarry Smith for (i=0; i<matrix.nrows; i++) { ierr=PetscFree(matrix.icols[i]);CHKERRQ(ierr);} 377b2f1ab58SBarry Smith ierr = PetscFree(matrix.icols);CHKERRQ(ierr); 3789ccc4a9bSBarry Smith if (matrix.values) { 3799ccc4a9bSBarry Smith for (i=0; i<matrix.nrows; i++) { ierr=PetscFree(matrix.values[i]);CHKERRQ(ierr);} 380b2f1ab58SBarry Smith } 381b2f1ab58SBarry Smith } 382b2f1ab58SBarry Smith 383b2f1ab58SBarry Smith ierr=PetscFree(matrix.row_nnz);CHKERRQ(ierr); 384b2f1ab58SBarry Smith ierr=PetscFree(matrix.icols);CHKERRQ(ierr); 3859ccc4a9bSBarry Smith if (matrix.col_idx_type == SPBAS_OFFSET_ARRAY) {ierr=PetscFree(matrix.icol0);CHKERRQ(ierr);} 386c31cb41cSBarry Smith ierr=PetscFree(matrix.values);CHKERRQ(ierr); 387b2f1ab58SBarry Smith PetscFunctionReturn(0); 388b2f1ab58SBarry Smith } 389b2f1ab58SBarry Smith 390b2f1ab58SBarry Smith /* 391b2f1ab58SBarry Smith spbas_matrix_to_crs: 392b2f1ab58SBarry Smith Convert an spbas_matrix to compessed row storage 393b2f1ab58SBarry Smith */ 394b2f1ab58SBarry Smith PetscErrorCode spbas_matrix_to_crs(spbas_matrix matrix_A,MatScalar **val_out, PetscInt **irow_out, PetscInt **icol_out) 395b2f1ab58SBarry Smith { 396b2f1ab58SBarry Smith PetscInt nrows = matrix_A.nrows; 397b2f1ab58SBarry Smith PetscInt nnz = matrix_A.nnz; 398b2f1ab58SBarry Smith PetscInt i,j,r_nnz,i0; 399b2f1ab58SBarry Smith PetscInt *irow; 400b2f1ab58SBarry Smith PetscInt *icol; 401b2f1ab58SBarry Smith PetscInt *icol_A; 402b2f1ab58SBarry Smith MatScalar *val; 403b2f1ab58SBarry Smith PetscScalar *val_A; 404b2f1ab58SBarry Smith PetscInt col_idx_type = matrix_A.col_idx_type; 405ace3abfcSBarry Smith PetscBool do_values = matrix_A.values ? PETSC_TRUE : PETSC_FALSE; 406b2f1ab58SBarry Smith PetscErrorCode ierr; 407b2f1ab58SBarry Smith 408b2f1ab58SBarry Smith PetscFunctionBegin; 409854ce69bSBarry Smith ierr = PetscMalloc1(nrows+1, &irow);CHKERRQ(ierr); 410854ce69bSBarry Smith ierr = PetscMalloc1(nnz, &icol);CHKERRQ(ierr); 4119ccc4a9bSBarry Smith *icol_out = icol; 4129ccc4a9bSBarry Smith *irow_out = irow; 4139ccc4a9bSBarry Smith if (do_values) { 414854ce69bSBarry Smith ierr = PetscMalloc1(nnz, &val);CHKERRQ(ierr); 415b2f1ab58SBarry Smith *val_out = val; *icol_out = icol; *irow_out=irow; 416b2f1ab58SBarry Smith } 417b2f1ab58SBarry Smith 418b2f1ab58SBarry Smith irow[0]=0; 4199ccc4a9bSBarry Smith for (i=0; i<nrows; i++) { 420b2f1ab58SBarry Smith r_nnz = matrix_A.row_nnz[i]; 421b2f1ab58SBarry Smith i0 = irow[i]; 422b2f1ab58SBarry Smith irow[i+1] = i0 + r_nnz; 423b2f1ab58SBarry Smith icol_A = matrix_A.icols[i]; 424b2f1ab58SBarry Smith 4259ccc4a9bSBarry Smith if (do_values) { 426b2f1ab58SBarry Smith val_A = matrix_A.values[i]; 4279ccc4a9bSBarry Smith for (j=0; j<r_nnz; j++) { 428b2f1ab58SBarry Smith icol[i0+j] = icol_A[j]; 429b2f1ab58SBarry Smith val[i0+j] = val_A[j]; 430b2f1ab58SBarry Smith } 4319ccc4a9bSBarry Smith } else { 4322205254eSKarl Rupp for (j=0; j<r_nnz; j++) icol[i0+j] = icol_A[j]; 433b2f1ab58SBarry Smith } 434b2f1ab58SBarry Smith 4359ccc4a9bSBarry Smith if (col_idx_type == SPBAS_DIAGONAL_OFFSETS) { 4362205254eSKarl Rupp for (j=0; j<r_nnz; j++) icol[i0+j] += i; 4372205254eSKarl Rupp } else if (col_idx_type == SPBAS_OFFSET_ARRAY) { 438b2f1ab58SBarry Smith i0 = matrix_A.icol0[i]; 4392205254eSKarl Rupp for (j=0; j<r_nnz; j++) icol[i0+j] += i0; 440b2f1ab58SBarry Smith } 441b2f1ab58SBarry Smith } 442b2f1ab58SBarry Smith PetscFunctionReturn(0); 443b2f1ab58SBarry Smith } 444b2f1ab58SBarry Smith 445b2f1ab58SBarry Smith 446b2f1ab58SBarry Smith /* 447b2f1ab58SBarry Smith spbas_transpose 448b2f1ab58SBarry Smith return the transpose of a matrix 449b2f1ab58SBarry Smith */ 450b2f1ab58SBarry Smith PetscErrorCode spbas_transpose(spbas_matrix in_matrix, spbas_matrix * result) 451b2f1ab58SBarry Smith { 452b2f1ab58SBarry Smith PetscInt col_idx_type = in_matrix.col_idx_type; 453b2f1ab58SBarry Smith PetscInt nnz = in_matrix.nnz; 454b2f1ab58SBarry Smith PetscInt ncols = in_matrix.nrows; 455b2f1ab58SBarry Smith PetscInt nrows = in_matrix.ncols; 456b2f1ab58SBarry Smith PetscInt i,j,k; 457b2f1ab58SBarry Smith PetscInt r_nnz; 458b2f1ab58SBarry Smith PetscInt *irow; 4594efc9174SBarry Smith PetscInt icol0 = 0; 460b2f1ab58SBarry Smith PetscScalar * val; 461b2f1ab58SBarry Smith PetscErrorCode ierr; 4624e1ff37aSBarry Smith 463b2f1ab58SBarry Smith PetscFunctionBegin; 464c328eeadSBarry Smith /* Copy input values */ 465b2f1ab58SBarry Smith result->nrows = nrows; 466b2f1ab58SBarry Smith result->ncols = ncols; 467b2f1ab58SBarry Smith result->nnz = nnz; 468b2f1ab58SBarry Smith result->col_idx_type = SPBAS_COLUMN_NUMBERS; 469b2f1ab58SBarry Smith result->block_data = PETSC_TRUE; 470b2f1ab58SBarry Smith 471c328eeadSBarry Smith /* Allocate sparseness pattern */ 47271d55d18SBarry Smith ierr = spbas_allocate_pattern(result, in_matrix.values ? PETSC_TRUE : PETSC_FALSE);CHKERRQ(ierr); 473b2f1ab58SBarry Smith 474c328eeadSBarry Smith /* Count the number of nonzeros in each row */ 4752205254eSKarl Rupp for (i = 0; i<nrows; i++) result->row_nnz[i] = 0; 476b2f1ab58SBarry Smith 4779ccc4a9bSBarry Smith for (i=0; i<ncols; i++) { 478b2f1ab58SBarry Smith r_nnz = in_matrix.row_nnz[i]; 479b2f1ab58SBarry Smith irow = in_matrix.icols[i]; 4809ccc4a9bSBarry Smith if (col_idx_type == SPBAS_COLUMN_NUMBERS) { 4812205254eSKarl Rupp for (j=0; j<r_nnz; j++) result->row_nnz[irow[j]]++; 4829ccc4a9bSBarry Smith } else if (col_idx_type == SPBAS_DIAGONAL_OFFSETS) { 4832205254eSKarl Rupp for (j=0; j<r_nnz; j++) result->row_nnz[i+irow[j]]++; 4849ccc4a9bSBarry Smith } else if (col_idx_type == SPBAS_OFFSET_ARRAY) { 485b2f1ab58SBarry Smith icol0=in_matrix.icol0[i]; 4862205254eSKarl Rupp for (j=0; j<r_nnz; j++) result->row_nnz[icol0+irow[j]]++; 487b2f1ab58SBarry Smith } 488b2f1ab58SBarry Smith } 489b2f1ab58SBarry Smith 490c328eeadSBarry Smith /* Set the pointers to the data */ 491b2f1ab58SBarry Smith ierr = spbas_allocate_data(result);CHKERRQ(ierr); 492b2f1ab58SBarry Smith 493c328eeadSBarry Smith /* Reset the number of nonzeros in each row */ 4942205254eSKarl Rupp for (i = 0; i<nrows; i++) result->row_nnz[i] = 0; 495b2f1ab58SBarry Smith 496c328eeadSBarry Smith /* Fill the data arrays */ 4979ccc4a9bSBarry Smith if (in_matrix.values) { 4989ccc4a9bSBarry Smith for (i=0; i<ncols; i++) { 499b2f1ab58SBarry Smith r_nnz = in_matrix.row_nnz[i]; 500b2f1ab58SBarry Smith irow = in_matrix.icols[i]; 501b2f1ab58SBarry Smith val = in_matrix.values[i]; 502b2f1ab58SBarry Smith 5032205254eSKarl Rupp if (col_idx_type == SPBAS_COLUMN_NUMBERS) icol0 = 0; 5042205254eSKarl Rupp else if (col_idx_type == SPBAS_DIAGONAL_OFFSETS) icol0 = i; 5052205254eSKarl Rupp else if (col_idx_type == SPBAS_OFFSET_ARRAY) icol0 = in_matrix.icol0[i]; 5069ccc4a9bSBarry Smith for (j=0; j<r_nnz; j++) { 507b2f1ab58SBarry Smith k = icol0 + irow[j]; 508b2f1ab58SBarry Smith result->icols[k][result->row_nnz[k]] = i; 509b2f1ab58SBarry Smith result->values[k][result->row_nnz[k]] = val[j]; 510b2f1ab58SBarry Smith result->row_nnz[k]++; 511b2f1ab58SBarry Smith } 512b2f1ab58SBarry Smith } 5139ccc4a9bSBarry Smith } else { 5149ccc4a9bSBarry Smith for (i=0; i<ncols; i++) { 515b2f1ab58SBarry Smith r_nnz = in_matrix.row_nnz[i]; 516b2f1ab58SBarry Smith irow = in_matrix.icols[i]; 517b2f1ab58SBarry Smith 5182205254eSKarl Rupp if (col_idx_type == SPBAS_COLUMN_NUMBERS) icol0=0; 5192205254eSKarl Rupp else if (col_idx_type == SPBAS_DIAGONAL_OFFSETS) icol0=i; 5202205254eSKarl Rupp else if (col_idx_type == SPBAS_OFFSET_ARRAY) icol0=in_matrix.icol0[i]; 521b2f1ab58SBarry Smith 5229ccc4a9bSBarry Smith for (j=0; j<r_nnz; j++) { 523b2f1ab58SBarry Smith k = icol0 + irow[j]; 524b2f1ab58SBarry Smith result->icols[k][result->row_nnz[k]] = i; 525b2f1ab58SBarry Smith result->row_nnz[k]++; 526b2f1ab58SBarry Smith } 527b2f1ab58SBarry Smith } 528b2f1ab58SBarry Smith } 529b2f1ab58SBarry Smith PetscFunctionReturn(0); 530b2f1ab58SBarry Smith } 531b2f1ab58SBarry Smith 532b2f1ab58SBarry Smith /* 533b2f1ab58SBarry Smith spbas_mergesort 534b2f1ab58SBarry Smith 535*bb42e86aSJed Brown mergesort for an array of integers and an array of associated 536b2f1ab58SBarry Smith reals 537b2f1ab58SBarry Smith 538b2f1ab58SBarry Smith on output, icol[0..nnz-1] is increasing; 539b2f1ab58SBarry Smith val[0..nnz-1] has undergone the same permutation as icol 540b2f1ab58SBarry Smith 5410298fd71SBarry Smith NB: val may be NULL: in that case, only the integers are sorted 542b2f1ab58SBarry Smith 543b2f1ab58SBarry Smith */ 544b2f1ab58SBarry Smith PetscErrorCode spbas_mergesort(PetscInt nnz, PetscInt *icol, PetscScalar *val) 545b2f1ab58SBarry Smith { 546c328eeadSBarry Smith PetscInt istep; /* Chunk-sizes of already sorted parts of arrays */ 547c328eeadSBarry Smith PetscInt i, i1, i2; /* Loop counters for (partly) sorted arrays */ 548c328eeadSBarry Smith PetscInt istart, i1end, i2end; /* start of newly sorted array part, end of both parts */ 549c328eeadSBarry Smith PetscInt *ialloc; /* Allocated arrays */ 5500298fd71SBarry Smith PetscScalar *valloc=NULL; 551c328eeadSBarry Smith PetscInt *iswap; /* auxiliary pointers for swapping */ 552b2f1ab58SBarry Smith PetscScalar *vswap; 553c328eeadSBarry Smith PetscInt *ihlp1; /* Pointers to new version of arrays, */ 5540298fd71SBarry Smith PetscScalar *vhlp1=NULL; /* (arrays under construction) */ 555c328eeadSBarry Smith PetscInt *ihlp2; /* Pointers to previous version of arrays, */ 5560298fd71SBarry Smith PetscScalar *vhlp2=NULL; 557b2f1ab58SBarry Smith PetscErrorCode ierr; 558b2f1ab58SBarry Smith 559785e854fSJed Brown ierr = PetscMalloc1(nnz,&ialloc);CHKERRQ(ierr); 560b2f1ab58SBarry Smith ihlp1 = ialloc; 561b2f1ab58SBarry Smith ihlp2 = icol; 562b2f1ab58SBarry Smith 5639ccc4a9bSBarry Smith if (val) { 564785e854fSJed Brown ierr = PetscMalloc1(nnz,&valloc);CHKERRQ(ierr); 565b2f1ab58SBarry Smith vhlp1 = valloc; 566b2f1ab58SBarry Smith vhlp2 = val; 567b2f1ab58SBarry Smith } 568b2f1ab58SBarry Smith 569b2f1ab58SBarry Smith 570c328eeadSBarry Smith /* Sorted array chunks are first 1 long, and increase until they are the complete array */ 5719ccc4a9bSBarry Smith for (istep=1; istep<nnz; istep*=2) { 572c328eeadSBarry Smith /* 573c328eeadSBarry Smith Combine sorted parts 574c328eeadSBarry Smith istart:istart+istep-1 and istart+istep-1:istart+2*istep-1 575c328eeadSBarry Smith of ihlp2 and vhlp2 576c328eeadSBarry Smith 577c328eeadSBarry Smith into one sorted part 578c328eeadSBarry Smith istart:istart+2*istep-1 579c328eeadSBarry Smith of ihlp1 and vhlp1 580c328eeadSBarry Smith */ 5819ccc4a9bSBarry Smith for (istart=0; istart<nnz; istart+=2*istep) { 582c328eeadSBarry Smith /* Set counters and bound array part endings */ 5832205254eSKarl Rupp i1=istart; i1end = i1+istep; if (i1end>nnz) i1end=nnz; 5842205254eSKarl Rupp i2=istart+istep; i2end = i2+istep; if (i2end>nnz) i2end=nnz; 585b2f1ab58SBarry Smith 586c328eeadSBarry Smith /* Merge the two array parts */ 5879ccc4a9bSBarry Smith if (val) { 5889ccc4a9bSBarry Smith for (i=istart; i<i2end; i++) { 5899ccc4a9bSBarry Smith if (i1<i1end && i2<i2end && ihlp2[i1] < ihlp2[i2]) { 590b2f1ab58SBarry Smith ihlp1[i] = ihlp2[i1]; 591b2f1ab58SBarry Smith vhlp1[i] = vhlp2[i1]; 592b2f1ab58SBarry Smith i1++; 5939ccc4a9bSBarry Smith } else if (i2<i2end) { 594b2f1ab58SBarry Smith ihlp1[i] = ihlp2[i2]; 595b2f1ab58SBarry Smith vhlp1[i] = vhlp2[i2]; 596b2f1ab58SBarry Smith i2++; 5979ccc4a9bSBarry Smith } else { 598b2f1ab58SBarry Smith ihlp1[i] = ihlp2[i1]; 599b2f1ab58SBarry Smith vhlp1[i] = vhlp2[i1]; 600b2f1ab58SBarry Smith i1++; 601b2f1ab58SBarry Smith } 602b2f1ab58SBarry Smith } 6039ccc4a9bSBarry Smith } else { 6046322f4bdSBarry Smith for (i=istart; i<i2end; i++) { 6056322f4bdSBarry Smith if (i1<i1end && i2<i2end && ihlp2[i1] < ihlp2[i2]) { 606b2f1ab58SBarry Smith ihlp1[i] = ihlp2[i1]; 607b2f1ab58SBarry Smith i1++; 6086322f4bdSBarry Smith } else if (i2<i2end) { 609b2f1ab58SBarry Smith ihlp1[i] = ihlp2[i2]; 610b2f1ab58SBarry Smith i2++; 6116322f4bdSBarry Smith } else { 612b2f1ab58SBarry Smith ihlp1[i] = ihlp2[i1]; 613b2f1ab58SBarry Smith i1++; 614b2f1ab58SBarry Smith } 615b2f1ab58SBarry Smith } 616b2f1ab58SBarry Smith } 617b2f1ab58SBarry Smith } 618b2f1ab58SBarry Smith 619c328eeadSBarry Smith /* Swap the two array sets */ 620b2f1ab58SBarry Smith iswap = ihlp2; ihlp2 = ihlp1; ihlp1 = iswap; 621b2f1ab58SBarry Smith vswap = vhlp2; vhlp2 = vhlp1; vhlp1 = vswap; 622b2f1ab58SBarry Smith } 623b2f1ab58SBarry Smith 624c328eeadSBarry Smith /* Copy one more time in case the sorted arrays are the temporary ones */ 6256322f4bdSBarry Smith if (ihlp2 != icol) { 6262205254eSKarl Rupp for (i=0; i<nnz; i++) icol[i] = ihlp2[i]; 6276322f4bdSBarry Smith if (val) { 6282205254eSKarl Rupp for (i=0; i<nnz; i++) val[i] = vhlp2[i]; 629b2f1ab58SBarry Smith } 630b2f1ab58SBarry Smith } 631b2f1ab58SBarry Smith 632b2f1ab58SBarry Smith ierr = PetscFree(ialloc);CHKERRQ(ierr); 633b2f1ab58SBarry Smith if (val) {ierr = PetscFree(valloc);CHKERRQ(ierr);} 634b2f1ab58SBarry Smith PetscFunctionReturn(0); 635b2f1ab58SBarry Smith } 636b2f1ab58SBarry Smith 637b2f1ab58SBarry Smith /* 638b2f1ab58SBarry Smith spbas_apply_reordering_rows: 639b2f1ab58SBarry Smith apply the given reordering to the rows: matrix_A = matrix_A(perm,:); 640b2f1ab58SBarry Smith */ 641b2f1ab58SBarry Smith PetscErrorCode spbas_apply_reordering_rows(spbas_matrix *matrix_A, const PetscInt *permutation) 642b2f1ab58SBarry Smith { 643b2f1ab58SBarry Smith PetscInt i,j,ip; 644b2f1ab58SBarry Smith PetscInt nrows=matrix_A->nrows; 645b2f1ab58SBarry Smith PetscInt * row_nnz; 646b2f1ab58SBarry Smith PetscInt **icols; 647ace3abfcSBarry Smith PetscBool do_values = matrix_A->values ? PETSC_TRUE : PETSC_FALSE; 6480298fd71SBarry Smith PetscScalar **vals = NULL; 649b2f1ab58SBarry Smith PetscErrorCode ierr; 650b2f1ab58SBarry Smith 651b2f1ab58SBarry Smith PetscFunctionBegin; 652e32f2f54SBarry Smith if (matrix_A->col_idx_type != SPBAS_DIAGONAL_OFFSETS) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS,"must have diagonal offsets in pattern\n"); 653b2f1ab58SBarry Smith 6546322f4bdSBarry Smith if (do_values) { 655854ce69bSBarry Smith ierr = PetscMalloc1(nrows, &vals);CHKERRQ(ierr); 656b2f1ab58SBarry Smith } 657854ce69bSBarry Smith ierr = PetscMalloc1(nrows, &row_nnz);CHKERRQ(ierr); 658854ce69bSBarry Smith ierr = PetscMalloc1(nrows, &icols);CHKERRQ(ierr); 659b2f1ab58SBarry Smith 6606322f4bdSBarry Smith for (i=0; i<nrows; i++) { 661b2f1ab58SBarry Smith ip = permutation[i]; 6622205254eSKarl Rupp if (do_values) vals[i] = matrix_A->values[ip]; 663b2f1ab58SBarry Smith icols[i] = matrix_A->icols[ip]; 664b2f1ab58SBarry Smith row_nnz[i] = matrix_A->row_nnz[ip]; 6652205254eSKarl Rupp for (j=0; j<row_nnz[i]; j++) icols[i][j] += ip-i; 666b2f1ab58SBarry Smith } 667b2f1ab58SBarry Smith 668b2f1ab58SBarry Smith if (do_values) { ierr = PetscFree(matrix_A->values);CHKERRQ(ierr);} 669b2f1ab58SBarry Smith ierr = PetscFree(matrix_A->icols);CHKERRQ(ierr); 670b2f1ab58SBarry Smith ierr = PetscFree(matrix_A->row_nnz);CHKERRQ(ierr); 671b2f1ab58SBarry Smith 6722205254eSKarl Rupp if (do_values) matrix_A->values = vals; 673b2f1ab58SBarry Smith matrix_A->icols = icols; 674b2f1ab58SBarry Smith matrix_A->row_nnz = row_nnz; 675b2f1ab58SBarry Smith PetscFunctionReturn(0); 676b2f1ab58SBarry Smith } 677b2f1ab58SBarry Smith 678b2f1ab58SBarry Smith 679b2f1ab58SBarry Smith /* 680b2f1ab58SBarry Smith spbas_apply_reordering_cols: 681b2f1ab58SBarry Smith apply the given reordering to the columns: matrix_A(:,perm) = matrix_A; 682b2f1ab58SBarry Smith */ 683b2f1ab58SBarry Smith PetscErrorCode spbas_apply_reordering_cols(spbas_matrix *matrix_A,const PetscInt *permutation) 684b2f1ab58SBarry Smith { 685b2f1ab58SBarry Smith PetscInt i,j; 686b2f1ab58SBarry Smith PetscInt nrows=matrix_A->nrows; 687b2f1ab58SBarry Smith PetscInt row_nnz; 688b2f1ab58SBarry Smith PetscInt *icols; 689ace3abfcSBarry Smith PetscBool do_values = matrix_A->values ? PETSC_TRUE : PETSC_FALSE; 6900298fd71SBarry Smith PetscScalar *vals = NULL; 691b2f1ab58SBarry Smith PetscErrorCode ierr; 692b2f1ab58SBarry Smith 693b2f1ab58SBarry Smith PetscFunctionBegin; 694e32f2f54SBarry Smith if (matrix_A->col_idx_type != SPBAS_DIAGONAL_OFFSETS) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "must have diagonal offsets in pattern\n"); 695b2f1ab58SBarry Smith 6966322f4bdSBarry Smith for (i=0; i<nrows; i++) { 697b2f1ab58SBarry Smith icols = matrix_A->icols[i]; 698b2f1ab58SBarry Smith row_nnz = matrix_A->row_nnz[i]; 6992205254eSKarl Rupp if (do_values) vals = matrix_A->values[i]; 700b2f1ab58SBarry Smith 7016322f4bdSBarry Smith for (j=0; j<row_nnz; j++) { 702b2f1ab58SBarry Smith icols[j] = permutation[i+icols[j]]-i; 703b2f1ab58SBarry Smith } 704b2f1ab58SBarry Smith ierr = spbas_mergesort(row_nnz, icols, vals);CHKERRQ(ierr); 705b2f1ab58SBarry Smith } 706b2f1ab58SBarry Smith PetscFunctionReturn(0); 707b2f1ab58SBarry Smith } 708b2f1ab58SBarry Smith 709b2f1ab58SBarry Smith /* 710b2f1ab58SBarry Smith spbas_apply_reordering: 711b2f1ab58SBarry Smith apply the given reordering: matrix_A(perm,perm) = matrix_A; 712b2f1ab58SBarry Smith */ 713b2f1ab58SBarry Smith PetscErrorCode spbas_apply_reordering(spbas_matrix *matrix_A, const PetscInt *permutation, const PetscInt * inv_perm) 714b2f1ab58SBarry Smith { 715b2f1ab58SBarry Smith PetscErrorCode ierr; 7165fd66863SKarl Rupp 717b2f1ab58SBarry Smith PetscFunctionBegin; 718b2f1ab58SBarry Smith ierr = spbas_apply_reordering_rows(matrix_A, inv_perm);CHKERRQ(ierr); 719b2f1ab58SBarry Smith ierr = spbas_apply_reordering_cols(matrix_A, permutation);CHKERRQ(ierr); 720b2f1ab58SBarry Smith PetscFunctionReturn(0); 721b2f1ab58SBarry Smith } 722b2f1ab58SBarry Smith 723b2f1ab58SBarry Smith PetscErrorCode spbas_pattern_only(PetscInt nrows, PetscInt ncols, PetscInt *ai, PetscInt *aj, spbas_matrix * result) 724b2f1ab58SBarry Smith { 725b2f1ab58SBarry Smith spbas_matrix retval; 726b2f1ab58SBarry Smith PetscInt i, j, i0, r_nnz; 727b2f1ab58SBarry Smith PetscErrorCode ierr; 728b2f1ab58SBarry Smith 729b2f1ab58SBarry Smith PetscFunctionBegin; 730c328eeadSBarry Smith /* Copy input values */ 731b2f1ab58SBarry Smith retval.nrows = nrows; 732b2f1ab58SBarry Smith retval.ncols = ncols; 733b2f1ab58SBarry Smith retval.nnz = ai[nrows]; 734b2f1ab58SBarry Smith 735b2f1ab58SBarry Smith retval.block_data = PETSC_TRUE; 736b2f1ab58SBarry Smith retval.col_idx_type = SPBAS_DIAGONAL_OFFSETS; 737b2f1ab58SBarry Smith 738c328eeadSBarry Smith /* Allocate output matrix */ 739b2f1ab58SBarry Smith ierr = spbas_allocate_pattern(&retval, PETSC_FALSE);CHKERRQ(ierr); 7402205254eSKarl Rupp for (i=0; i<nrows; i++) retval.row_nnz[i] = ai[i+1]-ai[i]; 741b2f1ab58SBarry Smith ierr = spbas_allocate_data(&retval);CHKERRQ(ierr); 742c328eeadSBarry Smith /* Copy the structure */ 7436322f4bdSBarry Smith for (i = 0; i<retval.nrows; i++) { 744b2f1ab58SBarry Smith i0 = ai[i]; 745b2f1ab58SBarry Smith r_nnz = ai[i+1]-i0; 746b2f1ab58SBarry Smith 7476322f4bdSBarry Smith for (j=0; j<r_nnz; j++) { 748b2f1ab58SBarry Smith retval.icols[i][j] = aj[i0+j]-i; 749b2f1ab58SBarry Smith } 750b2f1ab58SBarry Smith } 751b2f1ab58SBarry Smith *result = retval; 752b2f1ab58SBarry Smith PetscFunctionReturn(0); 753b2f1ab58SBarry Smith } 754b2f1ab58SBarry Smith 755b2f1ab58SBarry Smith 756b2f1ab58SBarry Smith /* 757b2f1ab58SBarry Smith spbas_mark_row_power: 758b2f1ab58SBarry Smith Mark the columns in row 'row' which are nonzero in 759b2f1ab58SBarry Smith matrix^2log(marker). 760b2f1ab58SBarry Smith */ 761be332245SKarl Rupp PetscErrorCode spbas_mark_row_power(PetscInt *iwork, /* marker-vector */ 762c328eeadSBarry Smith PetscInt row, /* row for which the columns are marked */ 763c328eeadSBarry Smith spbas_matrix * in_matrix, /* matrix for which the power is being calculated */ 764c328eeadSBarry Smith PetscInt marker, /* marker-value: 2^power */ 765c328eeadSBarry Smith PetscInt minmrk, /* lower bound for marked points */ 766c328eeadSBarry Smith PetscInt maxmrk) /* upper bound for marked points */ 767b2f1ab58SBarry Smith { 768b2f1ab58SBarry Smith PetscErrorCode ierr; 769b2f1ab58SBarry Smith PetscInt i,j, nnz; 770b2f1ab58SBarry Smith 771b2f1ab58SBarry Smith PetscFunctionBegin; 772b2f1ab58SBarry Smith nnz = in_matrix->row_nnz[row]; 773b2f1ab58SBarry Smith 774c328eeadSBarry Smith /* For higher powers, call this function recursively */ 7756322f4bdSBarry Smith if (marker>1) { 7766322f4bdSBarry Smith for (i=0; i<nnz; i++) { 777b2f1ab58SBarry Smith j = row + in_matrix->icols[row][i]; 7786322f4bdSBarry Smith if (minmrk<=j && j<maxmrk && iwork[j] < marker) { 77971d55d18SBarry Smith ierr = spbas_mark_row_power(iwork, row + in_matrix->icols[row][i],in_matrix, marker/2,minmrk,maxmrk);CHKERRQ(ierr); 780b2f1ab58SBarry Smith iwork[j] |= marker; 781b2f1ab58SBarry Smith } 782b2f1ab58SBarry Smith } 7836322f4bdSBarry Smith } else { 784c328eeadSBarry Smith /* Mark the columns reached */ 7856322f4bdSBarry Smith for (i=0; i<nnz; i++) { 786b2f1ab58SBarry Smith j = row + in_matrix->icols[row][i]; 7872205254eSKarl Rupp if (minmrk<=j && j<maxmrk) iwork[j] |= 1; 788b2f1ab58SBarry Smith } 789b2f1ab58SBarry Smith } 790b2f1ab58SBarry Smith PetscFunctionReturn(0); 791b2f1ab58SBarry Smith } 792b2f1ab58SBarry Smith 793b2f1ab58SBarry Smith 794b2f1ab58SBarry Smith /* 795b2f1ab58SBarry Smith spbas_power 796b2f1ab58SBarry Smith Calculate sparseness patterns for incomplete Cholesky decompositions 797b2f1ab58SBarry Smith of a given order: (almost) all nonzeros of the matrix^(order+1) which 798b2f1ab58SBarry Smith are inside the band width are found and stored in the output sparseness 799b2f1ab58SBarry Smith pattern. 800b2f1ab58SBarry Smith */ 801b2f1ab58SBarry Smith PetscErrorCode spbas_power(spbas_matrix in_matrix,PetscInt power, spbas_matrix * result) 802b2f1ab58SBarry Smith { 803b2f1ab58SBarry Smith spbas_matrix retval; 804b2f1ab58SBarry Smith PetscInt nrows = in_matrix.nrows; 805b2f1ab58SBarry Smith PetscInt ncols = in_matrix.ncols; 806b2f1ab58SBarry Smith PetscInt i, j, kend; 807b2f1ab58SBarry Smith PetscInt nnz, inz; 808b2f1ab58SBarry Smith PetscInt *iwork; 809b2f1ab58SBarry Smith PetscInt marker; 810b2f1ab58SBarry Smith PetscInt maxmrk=0; 811b2f1ab58SBarry Smith PetscErrorCode ierr; 812b2f1ab58SBarry Smith 813b2f1ab58SBarry Smith PetscFunctionBegin; 814e32f2f54SBarry Smith if (in_matrix.col_idx_type != SPBAS_DIAGONAL_OFFSETS) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS,"must have diagonal offsets in pattern\n"); 815e32f2f54SBarry Smith if (ncols != nrows) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Dimension error\n"); 816e32f2f54SBarry Smith if (in_matrix.values) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Input array must be sparseness pattern (no values)"); 817e32f2f54SBarry Smith if (power<=0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Power must be 1 or up"); 818b2f1ab58SBarry Smith 819c328eeadSBarry Smith /* Copy input values*/ 820b2f1ab58SBarry Smith retval.nrows = ncols; 821b2f1ab58SBarry Smith retval.ncols = nrows; 822b2f1ab58SBarry Smith retval.nnz = 0; 823b2f1ab58SBarry Smith retval.col_idx_type = SPBAS_DIAGONAL_OFFSETS; 824b2f1ab58SBarry Smith retval.block_data = PETSC_FALSE; 825b2f1ab58SBarry Smith 826c328eeadSBarry Smith /* Allocate sparseness pattern */ 82771d55d18SBarry Smith ierr = spbas_allocate_pattern(&retval, in_matrix.values ? PETSC_TRUE : PETSC_FALSE);CHKERRQ(ierr); 828b2f1ab58SBarry Smith 829c328eeadSBarry Smith /* Allocate marker array */ 830785e854fSJed Brown ierr = PetscMalloc1(nrows, &iwork);CHKERRQ(ierr); 831b2f1ab58SBarry Smith 832c328eeadSBarry Smith /* Erase the pattern for this row */ 8334e1ff37aSBarry Smith ierr = PetscMemzero((void*) iwork, retval.nrows*sizeof(PetscInt));CHKERRQ(ierr); 834b2f1ab58SBarry Smith 835c328eeadSBarry Smith /* Calculate marker values */ 8362205254eSKarl Rupp marker = 1; for (i=1; i<power; i++) marker*=2; 837b2f1ab58SBarry Smith 8386322f4bdSBarry Smith for (i=0; i<nrows; i++) { 839c328eeadSBarry Smith /* Calculate the pattern for each row */ 840b2f1ab58SBarry Smith 841b2f1ab58SBarry Smith nnz = in_matrix.row_nnz[i]; 842b2f1ab58SBarry Smith kend = i+in_matrix.icols[i][nnz-1]; 8432205254eSKarl Rupp if (maxmrk<=kend) maxmrk=kend+1; 84471d55d18SBarry Smith ierr = spbas_mark_row_power(iwork, i, &in_matrix, marker, i, maxmrk);CHKERRQ(ierr); 845b2f1ab58SBarry Smith 846c328eeadSBarry Smith /* Count the columns*/ 847b2f1ab58SBarry Smith nnz = 0; 8482205254eSKarl Rupp for (j=i; j<maxmrk; j++) nnz+= (iwork[j]!=0); 849b2f1ab58SBarry Smith 850c328eeadSBarry Smith /* Allocate the column indices */ 851b2f1ab58SBarry Smith retval.row_nnz[i] = nnz; 852785e854fSJed Brown ierr = PetscMalloc1(nnz,&retval.icols[i]);CHKERRQ(ierr); 853b2f1ab58SBarry Smith 854c328eeadSBarry Smith /* Administrate the column indices */ 855b2f1ab58SBarry Smith inz = 0; 8566322f4bdSBarry Smith for (j=i; j<maxmrk; j++) { 8576322f4bdSBarry Smith if (iwork[j]) { 858b2f1ab58SBarry Smith retval.icols[i][inz] = j-i; 859b2f1ab58SBarry Smith inz++; 860b2f1ab58SBarry Smith iwork[j]=0; 861b2f1ab58SBarry Smith } 862b2f1ab58SBarry Smith } 863b2f1ab58SBarry Smith retval.nnz += nnz; 864b2f1ab58SBarry Smith }; 865b2f1ab58SBarry Smith ierr = PetscFree(iwork);CHKERRQ(ierr); 866b2f1ab58SBarry Smith *result = retval; 867b2f1ab58SBarry Smith PetscFunctionReturn(0); 868b2f1ab58SBarry Smith } 869b2f1ab58SBarry Smith 870b2f1ab58SBarry Smith 871b2f1ab58SBarry Smith 872b2f1ab58SBarry Smith /* 873b2f1ab58SBarry Smith spbas_keep_upper: 874b2f1ab58SBarry Smith remove the lower part of the matrix: keep the upper part 875b2f1ab58SBarry Smith */ 876b2f1ab58SBarry Smith PetscErrorCode spbas_keep_upper(spbas_matrix * inout_matrix) 877b2f1ab58SBarry Smith { 878b2f1ab58SBarry Smith PetscInt i, j; 879b2f1ab58SBarry Smith PetscInt jstart; 880b2f1ab58SBarry Smith 881b2f1ab58SBarry Smith PetscFunctionBegin; 882e32f2f54SBarry Smith if (inout_matrix->block_data) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Not yet for block data matrices\n"); 8836322f4bdSBarry Smith for (i=0; i<inout_matrix->nrows; i++) { 8846322f4bdSBarry Smith for (jstart=0; (jstart<inout_matrix->row_nnz[i]) && (inout_matrix->icols[i][jstart]<0); jstart++) {} 8856322f4bdSBarry Smith if (jstart>0) { 8866322f4bdSBarry Smith for (j=0; j<inout_matrix->row_nnz[i]-jstart; j++) { 8876322f4bdSBarry Smith inout_matrix->icols[i][j] = inout_matrix->icols[i][j+jstart]; 888b2f1ab58SBarry Smith } 889b2f1ab58SBarry Smith 8906322f4bdSBarry Smith if (inout_matrix->values) { 8916322f4bdSBarry Smith for (j=0; j<inout_matrix->row_nnz[i]-jstart; j++) { 8926322f4bdSBarry Smith inout_matrix->values[i][j] = inout_matrix->values[i][j+jstart]; 893b2f1ab58SBarry Smith } 894b2f1ab58SBarry Smith } 895b2f1ab58SBarry Smith 896b2f1ab58SBarry Smith inout_matrix->row_nnz[i] -= jstart; 897b2f1ab58SBarry Smith 8986322f4bdSBarry Smith inout_matrix->icols[i] = (PetscInt*) realloc((void*) inout_matrix->icols[i], inout_matrix->row_nnz[i]*sizeof(PetscInt)); 899b2f1ab58SBarry Smith 9006322f4bdSBarry Smith if (inout_matrix->values) { 9016322f4bdSBarry Smith inout_matrix->values[i] = (PetscScalar*) realloc((void*) inout_matrix->values[i], inout_matrix->row_nnz[i]*sizeof(PetscScalar)); 902b2f1ab58SBarry Smith } 903b2f1ab58SBarry Smith inout_matrix->nnz -= jstart; 904b2f1ab58SBarry Smith } 905b2f1ab58SBarry Smith } 906b2f1ab58SBarry Smith PetscFunctionReturn(0); 907b2f1ab58SBarry Smith } 908b2f1ab58SBarry Smith 909