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 */ 29b2f1ab58SBarry Smith #undef __FUNCT__ 30b2f1ab58SBarry Smith #define __FUNCT__ "spbas_memory_requirement" 31*3dfa2556SBarry Smith size_t spbas_memory_requirement(spbas_matrix matrix) 32b2f1ab58SBarry Smith { 33*3dfa2556SBarry Smith size_t memreq = 6 * sizeof(PetscInt) + /* nrows, ncols, nnz, n_alloc_icol, n_alloc_val, col_idx_type */ 34ace3abfcSBarry Smith sizeof(PetscBool) + /* block_data */ 35c328eeadSBarry Smith sizeof(PetscScalar**) + /* values */ 36c328eeadSBarry Smith sizeof(PetscScalar*) + /* alloc_val */ 37*3dfa2556SBarry Smith 2 * sizeof(PetscInt**) + /* icols, icols0 */ 38c328eeadSBarry Smith 2 * sizeof(PetscInt*) + /* row_nnz, alloc_icol */ 39c328eeadSBarry Smith matrix.nrows * sizeof(PetscInt) + /* row_nnz[*] */ 40c328eeadSBarry Smith matrix.nrows * sizeof(PetscInt*); /* icols[*] */ 41b2f1ab58SBarry Smith 42c328eeadSBarry Smith /* icol0[*] */ 432205254eSKarl Rupp if (matrix.col_idx_type == SPBAS_OFFSET_ARRAY) memreq += matrix.nrows * sizeof(PetscInt); 44b2f1ab58SBarry Smith 45c328eeadSBarry Smith /* icols[*][*] */ 462205254eSKarl Rupp if (matrix.block_data) memreq += matrix.n_alloc_icol * sizeof(PetscInt); 472205254eSKarl Rupp else memreq += matrix.nnz * sizeof(PetscInt); 48b2f1ab58SBarry Smith 494e1ff37aSBarry Smith if (matrix.values) { 50c328eeadSBarry Smith memreq += matrix.nrows * sizeof(PetscScalar*); /* values[*] */ 51c328eeadSBarry Smith /* values[*][*] */ 522205254eSKarl Rupp if (matrix.block_data) memreq += matrix.n_alloc_val * sizeof(PetscScalar); 532205254eSKarl Rupp else memreq += matrix.nnz * sizeof(PetscScalar); 54b2f1ab58SBarry Smith } 55b2f1ab58SBarry Smith return memreq; 56b2f1ab58SBarry Smith } 57b2f1ab58SBarry Smith 58b2f1ab58SBarry Smith /* 59b2f1ab58SBarry Smith spbas_allocate_pattern: 60b2f1ab58SBarry Smith allocate the pattern arrays row_nnz, icols and optionally values 61b2f1ab58SBarry Smith */ 62b2f1ab58SBarry Smith #undef __FUNCT__ 63b2f1ab58SBarry Smith #define __FUNCT__ "spbas_allocate_pattern" 64ace3abfcSBarry Smith PetscErrorCode spbas_allocate_pattern(spbas_matrix * result, PetscBool do_values) 65b2f1ab58SBarry Smith { 66b2f1ab58SBarry Smith PetscErrorCode ierr; 67b2f1ab58SBarry Smith PetscInt nrows = result->nrows; 68b2f1ab58SBarry Smith PetscInt col_idx_type = result->col_idx_type; 69b2f1ab58SBarry Smith 70b2f1ab58SBarry Smith PetscFunctionBegin; 71c328eeadSBarry Smith /* Allocate sparseness pattern */ 72785e854fSJed Brown ierr = PetscMalloc1(nrows,&result->row_nnz);CHKERRQ(ierr); 73785e854fSJed Brown ierr = PetscMalloc1(nrows,&result->icols);CHKERRQ(ierr); 74b2f1ab58SBarry Smith 75c328eeadSBarry Smith /* If offsets are given wrt an array, create array */ 764e1ff37aSBarry Smith if (col_idx_type == SPBAS_OFFSET_ARRAY) { 77785e854fSJed Brown ierr = PetscMalloc1(nrows,&result->icol0);CHKERRQ(ierr); 784e1ff37aSBarry Smith } else { 790298fd71SBarry Smith result->icol0 = NULL; 80b2f1ab58SBarry Smith } 81b2f1ab58SBarry Smith 82c328eeadSBarry Smith /* If values are given, allocate values array */ 834e1ff37aSBarry Smith if (do_values) { 84785e854fSJed Brown ierr = PetscMalloc1(nrows,&result->values);CHKERRQ(ierr); 854e1ff37aSBarry Smith } else { 860298fd71SBarry Smith result->values = NULL; 87b2f1ab58SBarry Smith } 88b2f1ab58SBarry Smith PetscFunctionReturn(0); 89b2f1ab58SBarry Smith } 90b2f1ab58SBarry Smith 91b2f1ab58SBarry Smith /* 92b2f1ab58SBarry Smith spbas_allocate_data: 93b2f1ab58SBarry Smith in case of block_data: 94b2f1ab58SBarry Smith Allocate the data arrays alloc_icol and optionally alloc_val, 95b2f1ab58SBarry Smith set appropriate pointers from icols and values; 96b2f1ab58SBarry Smith in case of !block_data: 97b2f1ab58SBarry Smith Allocate the arrays icols[i] and optionally values[i] 98b2f1ab58SBarry Smith */ 99b2f1ab58SBarry Smith #undef __FUNCT__ 100b2f1ab58SBarry Smith #define __FUNCT__ "spbas_allocate_data" 101b2f1ab58SBarry Smith PetscErrorCode spbas_allocate_data(spbas_matrix * result) 102b2f1ab58SBarry Smith { 103b2f1ab58SBarry Smith PetscInt i; 104b2f1ab58SBarry Smith PetscInt nnz = result->nnz; 105b2f1ab58SBarry Smith PetscInt nrows = result->nrows; 106b2f1ab58SBarry Smith PetscInt r_nnz; 107b2f1ab58SBarry Smith PetscErrorCode ierr; 1086c4ed002SBarry Smith PetscBool do_values = (result->values) ? PETSC_TRUE : PETSC_FALSE; 109ace3abfcSBarry Smith PetscBool block_data = result->block_data; 110b2f1ab58SBarry Smith 111b2f1ab58SBarry Smith PetscFunctionBegin; 1124e1ff37aSBarry Smith if (block_data) { 113c328eeadSBarry Smith /* Allocate the column number array and point to it */ 114b2f1ab58SBarry Smith result->n_alloc_icol = nnz; 1152205254eSKarl Rupp 116785e854fSJed Brown ierr = PetscMalloc1(nnz, &result->alloc_icol);CHKERRQ(ierr); 1172205254eSKarl Rupp 118b2f1ab58SBarry Smith result->icols[0] = result->alloc_icol; 1194e1ff37aSBarry Smith for (i=1; i<nrows; i++) { 120b2f1ab58SBarry Smith result->icols[i] = result->icols[i-1] + result->row_nnz[i-1]; 121b2f1ab58SBarry Smith } 122b2f1ab58SBarry Smith 123c328eeadSBarry Smith /* Allocate the value array and point to it */ 1244e1ff37aSBarry Smith if (do_values) { 125b2f1ab58SBarry Smith result->n_alloc_val = nnz; 1262205254eSKarl Rupp 127785e854fSJed Brown ierr = PetscMalloc1(nnz, &result->alloc_val);CHKERRQ(ierr); 1282205254eSKarl Rupp 129b2f1ab58SBarry Smith result->values[0] = result->alloc_val; 1304e1ff37aSBarry Smith for (i=1; i<nrows; i++) { 131b2f1ab58SBarry Smith result->values[i] = result->values[i-1] + result->row_nnz[i-1]; 132b2f1ab58SBarry Smith } 133b2f1ab58SBarry Smith } 1344e1ff37aSBarry Smith } else { 1354e1ff37aSBarry Smith for (i=0; i<nrows; i++) { 136b2f1ab58SBarry Smith r_nnz = result->row_nnz[i]; 137785e854fSJed Brown ierr = PetscMalloc1(r_nnz, &result->icols[i]);CHKERRQ(ierr); 138b2f1ab58SBarry Smith } 1394e1ff37aSBarry Smith if (do_values) { 1404e1ff37aSBarry Smith for (i=0; i<nrows; i++) { 141b2f1ab58SBarry Smith r_nnz = result->row_nnz[i]; 142785e854fSJed Brown ierr = PetscMalloc1(r_nnz, &result->values[i]);CHKERRQ(ierr); 143b2f1ab58SBarry Smith } 144b2f1ab58SBarry Smith } 145b2f1ab58SBarry Smith } 146b2f1ab58SBarry Smith PetscFunctionReturn(0); 147b2f1ab58SBarry Smith } 148b2f1ab58SBarry Smith 149b2f1ab58SBarry Smith /* 150b2f1ab58SBarry Smith spbas_row_order_icol 151b2f1ab58SBarry Smith determine if row i1 should come 152b2f1ab58SBarry Smith + before row i2 in the sorted rows (return -1), 153b2f1ab58SBarry Smith + after (return 1) 154b2f1ab58SBarry Smith + is identical (return 0). 155b2f1ab58SBarry Smith */ 156b2f1ab58SBarry Smith #undef __FUNCT__ 157b2f1ab58SBarry Smith #define __FUNCT__ "spbas_row_order_icol" 158b2f1ab58SBarry Smith int spbas_row_order_icol(PetscInt i1, PetscInt i2, PetscInt *irow_in, PetscInt *icol_in,PetscInt col_idx_type) 159b2f1ab58SBarry Smith { 160b2f1ab58SBarry Smith PetscInt j; 161b2f1ab58SBarry Smith PetscInt nnz1 = irow_in[i1+1] - irow_in[i1]; 162b2f1ab58SBarry Smith PetscInt nnz2 = irow_in[i2+1] - irow_in[i2]; 163b2f1ab58SBarry Smith PetscInt * icol1 = &icol_in[irow_in[i1]]; 164b2f1ab58SBarry Smith PetscInt * icol2 = &icol_in[irow_in[i2]]; 165b2f1ab58SBarry Smith 1662205254eSKarl Rupp if (nnz1<nnz2) return -1; 1672205254eSKarl Rupp if (nnz1>nnz2) return 1; 168b2f1ab58SBarry Smith 1694e1ff37aSBarry Smith if (col_idx_type == SPBAS_COLUMN_NUMBERS) { 1704e1ff37aSBarry Smith for (j=0; j<nnz1; j++) { 1712205254eSKarl Rupp if (icol1[j]< icol2[j]) return -1; 1722205254eSKarl Rupp if (icol1[j]> icol2[j]) return 1; 173b2f1ab58SBarry Smith } 1744e1ff37aSBarry Smith } else if (col_idx_type == SPBAS_DIAGONAL_OFFSETS) { 1754e1ff37aSBarry Smith for (j=0; j<nnz1; j++) { 1762205254eSKarl Rupp if (icol1[j]-i1< icol2[j]-i2) return -1; 1772205254eSKarl Rupp if (icol1[j]-i1> icol2[j]-i2) return 1; 178b2f1ab58SBarry Smith } 1794e1ff37aSBarry Smith } else if (col_idx_type == SPBAS_OFFSET_ARRAY) { 1804e1ff37aSBarry Smith for (j=1; j<nnz1; j++) { 1812205254eSKarl Rupp if (icol1[j]-icol1[0] < icol2[j]-icol2[0]) return -1; 1822205254eSKarl Rupp if (icol1[j]-icol1[0] > icol2[j]-icol2[0]) return 1; 183b2f1ab58SBarry Smith } 184b2f1ab58SBarry Smith } 185b2f1ab58SBarry Smith return 0; 186b2f1ab58SBarry Smith } 187b2f1ab58SBarry Smith 188b2f1ab58SBarry Smith /* 189b2f1ab58SBarry Smith spbas_mergesort_icols: 190b2f1ab58SBarry Smith return a sorting of the rows in which identical sparseness patterns are 191b2f1ab58SBarry Smith next to each other 192b2f1ab58SBarry Smith */ 193b2f1ab58SBarry Smith #undef __FUNCT__ 194b2f1ab58SBarry Smith #define __FUNCT__ "spbas_mergesort_icols" 195b2f1ab58SBarry Smith PetscErrorCode spbas_mergesort_icols(PetscInt nrows, PetscInt * irow_in, PetscInt * icol_in,PetscInt col_idx_type, PetscInt *isort) 196b2f1ab58SBarry Smith { 197b2f1ab58SBarry Smith PetscErrorCode ierr; 198c328eeadSBarry Smith PetscInt istep; /* Chunk-sizes of already sorted parts of arrays */ 199c328eeadSBarry Smith PetscInt i, i1, i2; /* Loop counters for (partly) sorted arrays */ 200c328eeadSBarry Smith PetscInt istart, i1end, i2end; /* start of newly sorted array part, end of both parts */ 201c328eeadSBarry Smith PetscInt *ialloc; /* Allocated arrays */ 202c328eeadSBarry Smith PetscInt *iswap; /* auxiliary pointers for swapping */ 203c328eeadSBarry Smith PetscInt *ihlp1; /* Pointers to new version of arrays, */ 204c328eeadSBarry Smith PetscInt *ihlp2; /* Pointers to previous version of arrays, */ 205b2f1ab58SBarry Smith 206b2f1ab58SBarry Smith PetscFunctionBegin; 207785e854fSJed Brown ierr = PetscMalloc1(nrows,&ialloc);CHKERRQ(ierr); 208b2f1ab58SBarry Smith 209b2f1ab58SBarry Smith ihlp1 = ialloc; 210b2f1ab58SBarry Smith ihlp2 = isort; 211b2f1ab58SBarry Smith 212c328eeadSBarry Smith /* Sorted array chunks are first 1 long, and increase until they are the complete array */ 2134e1ff37aSBarry Smith for (istep=1; istep<nrows; istep*=2) { 214c328eeadSBarry Smith /* 215c328eeadSBarry Smith Combine sorted parts 216c328eeadSBarry Smith istart:istart+istep-1 and istart+istep-1:istart+2*istep-1 217c328eeadSBarry Smith of ihlp2 and vhlp2 218c328eeadSBarry Smith 219c328eeadSBarry Smith into one sorted part 220c328eeadSBarry Smith istart:istart+2*istep-1 221c328eeadSBarry Smith of ihlp1 and vhlp1 222c328eeadSBarry Smith */ 2234e1ff37aSBarry Smith for (istart=0; istart<nrows; istart+=2*istep) { 224c328eeadSBarry Smith /* Set counters and bound array part endings */ 2252205254eSKarl Rupp i1=istart; i1end = i1+istep; if (i1end>nrows) i1end=nrows; 2262205254eSKarl Rupp i2=istart+istep; i2end = i2+istep; if (i2end>nrows) i2end=nrows; 227b2f1ab58SBarry Smith 228c328eeadSBarry Smith /* Merge the two array parts */ 2294e1ff37aSBarry Smith for (i=istart; i<i2end; i++) { 2304e1ff37aSBarry Smith if (i1<i1end && i2<i2end && spbas_row_order_icol(ihlp2[i1], ihlp2[i2], irow_in, icol_in, col_idx_type) < 0) { 231b2f1ab58SBarry Smith ihlp1[i] = ihlp2[i1]; 232b2f1ab58SBarry Smith i1++; 2334e1ff37aSBarry Smith } else if (i2<i2end) { 234b2f1ab58SBarry Smith ihlp1[i] = ihlp2[i2]; 235b2f1ab58SBarry Smith i2++; 2364e1ff37aSBarry Smith } else { 237b2f1ab58SBarry Smith ihlp1[i] = ihlp2[i1]; 238b2f1ab58SBarry Smith i1++; 239b2f1ab58SBarry Smith } 240b2f1ab58SBarry Smith } 241b2f1ab58SBarry Smith } 242b2f1ab58SBarry Smith 243c328eeadSBarry Smith /* Swap the two array sets */ 244b2f1ab58SBarry Smith iswap = ihlp2; ihlp2 = ihlp1; ihlp1 = iswap; 245b2f1ab58SBarry Smith } 246b2f1ab58SBarry Smith 247c328eeadSBarry Smith /* Copy one more time in case the sorted arrays are the temporary ones */ 2484e1ff37aSBarry Smith if (ihlp2 != isort) { 2492205254eSKarl Rupp for (i=0; i<nrows; i++) isort[i] = ihlp2[i]; 250b2f1ab58SBarry Smith } 251b2f1ab58SBarry Smith ierr = PetscFree(ialloc);CHKERRQ(ierr); 252b2f1ab58SBarry Smith PetscFunctionReturn(0); 253b2f1ab58SBarry Smith } 254b2f1ab58SBarry Smith 255b2f1ab58SBarry Smith 256b2f1ab58SBarry Smith 257b2f1ab58SBarry Smith /* 258b2f1ab58SBarry Smith spbas_compress_pattern: 259b2f1ab58SBarry Smith calculate a compressed sparseness pattern for a sparseness pattern 260b2f1ab58SBarry Smith given in compressed row storage. The compressed sparseness pattern may 261b2f1ab58SBarry Smith require (much) less memory. 262b2f1ab58SBarry Smith */ 263b2f1ab58SBarry Smith #undef __FUNCT__ 264b2f1ab58SBarry Smith #define __FUNCT__ "spbas_compress_pattern" 2654e1ff37aSBarry 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) 266b2f1ab58SBarry Smith { 267b2f1ab58SBarry Smith PetscInt nnz = irow_in[nrows]; 268*3dfa2556SBarry Smith size_t mem_orig = (nrows + nnz) * sizeof(PetscInt); 269*3dfa2556SBarry Smith size_t mem_compressed; 270b2f1ab58SBarry Smith PetscErrorCode ierr; 271b2f1ab58SBarry Smith PetscInt *isort; 272b2f1ab58SBarry Smith PetscInt *icols; 273b2f1ab58SBarry Smith PetscInt row_nnz; 274b2f1ab58SBarry Smith PetscInt *ipoint; 275ace3abfcSBarry Smith PetscBool *used; 276b2f1ab58SBarry Smith PetscInt ptr; 277b2f1ab58SBarry Smith PetscInt i,j; 278ace3abfcSBarry Smith const PetscBool no_values = PETSC_FALSE; 279b2f1ab58SBarry Smith 280b2f1ab58SBarry Smith PetscFunctionBegin; 281c328eeadSBarry Smith /* Allocate the structure of the new matrix */ 282b2f1ab58SBarry Smith B->nrows = nrows; 283b2f1ab58SBarry Smith B->ncols = ncols; 284b2f1ab58SBarry Smith B->nnz = nnz; 285b2f1ab58SBarry Smith B->col_idx_type = col_idx_type; 286b2f1ab58SBarry Smith B->block_data = PETSC_TRUE; 2872205254eSKarl Rupp 288b2f1ab58SBarry Smith ierr = spbas_allocate_pattern(B, no_values);CHKERRQ(ierr); 289b2f1ab58SBarry Smith 290c328eeadSBarry Smith /* When using an offset array, set it */ 2914e1ff37aSBarry Smith if (col_idx_type==SPBAS_OFFSET_ARRAY) { 2922205254eSKarl Rupp for (i=0; i<nrows; i++) B->icol0[i] = icol_in[irow_in[i]]; 293b2f1ab58SBarry Smith } 294b2f1ab58SBarry Smith 295c328eeadSBarry Smith /* Allocate the ordering for the rows */ 296785e854fSJed Brown ierr = PetscMalloc1(nrows,&isort);CHKERRQ(ierr); 297785e854fSJed Brown ierr = PetscMalloc1(nrows,&ipoint);CHKERRQ(ierr); 298785e854fSJed Brown ierr = PetscMalloc1(nrows,&used);CHKERRQ(ierr); 299b2f1ab58SBarry Smith 300c328eeadSBarry Smith /* Initialize the sorting */ 301ace3abfcSBarry Smith ierr = PetscMemzero((void*) used, nrows*sizeof(PetscBool));CHKERRQ(ierr); 3024e1ff37aSBarry Smith for (i = 0; i<nrows; i++) { 303b2f1ab58SBarry Smith B->row_nnz[i] = irow_in[i+1]-irow_in[i]; 304b2f1ab58SBarry Smith isort[i] = i; 305b2f1ab58SBarry Smith ipoint[i] = i; 306b2f1ab58SBarry Smith } 307b2f1ab58SBarry Smith 308c328eeadSBarry Smith /* Sort the rows so that identical columns will be next to each other */ 309b2f1ab58SBarry Smith ierr = spbas_mergesort_icols(nrows, irow_in, icol_in, col_idx_type, isort);CHKERRQ(ierr); 3100298fd71SBarry Smith ierr = PetscInfo(NULL,"Rows have been sorted for patterns\n");CHKERRQ(ierr); 311b2f1ab58SBarry Smith 312c328eeadSBarry Smith /* Replace identical rows with the first one in the list */ 3134e1ff37aSBarry Smith for (i=1; i<nrows; i++) { 3144e1ff37aSBarry Smith if (spbas_row_order_icol(isort[i-1], isort[i], irow_in, icol_in, col_idx_type) == 0) { 315b2f1ab58SBarry Smith ipoint[isort[i]] = ipoint[isort[i-1]]; 316b2f1ab58SBarry Smith } 317b2f1ab58SBarry Smith } 318b2f1ab58SBarry Smith 319c328eeadSBarry Smith /* Collect the rows which are used*/ 3202205254eSKarl Rupp for (i=0; i<nrows; i++) used[ipoint[i]] = PETSC_TRUE; 321b2f1ab58SBarry Smith 322c328eeadSBarry Smith /* Calculate needed memory */ 323b2f1ab58SBarry Smith B->n_alloc_icol = 0; 3244e1ff37aSBarry Smith for (i=0; i<nrows; i++) { 3252205254eSKarl Rupp if (used[i]) B->n_alloc_icol += B->row_nnz[i]; 326b2f1ab58SBarry Smith } 327785e854fSJed Brown ierr = PetscMalloc1(B->n_alloc_icol,&B->alloc_icol);CHKERRQ(ierr); 328b2f1ab58SBarry Smith 329c328eeadSBarry Smith /* Fill in the diagonal offsets for the rows which store their own data */ 330b2f1ab58SBarry Smith ptr = 0; 3314e1ff37aSBarry Smith for (i=0; i<B->nrows; i++) { 3324e1ff37aSBarry Smith if (used[i]) { 333b2f1ab58SBarry Smith B->icols[i] = &B->alloc_icol[ptr]; 334b2f1ab58SBarry Smith icols = &icol_in[irow_in[i]]; 335b2f1ab58SBarry Smith row_nnz = B->row_nnz[i]; 3364e1ff37aSBarry Smith if (col_idx_type == SPBAS_COLUMN_NUMBERS) { 3374e1ff37aSBarry Smith for (j=0; j<row_nnz; j++) { 338b2f1ab58SBarry Smith B->icols[i][j] = icols[j]; 339b2f1ab58SBarry Smith } 3404e1ff37aSBarry Smith } else if (col_idx_type == SPBAS_DIAGONAL_OFFSETS) { 3414e1ff37aSBarry Smith for (j=0; j<row_nnz; j++) { 342b2f1ab58SBarry Smith B->icols[i][j] = icols[j]-i; 343b2f1ab58SBarry Smith } 3444e1ff37aSBarry Smith } else if (col_idx_type == SPBAS_OFFSET_ARRAY) { 3454e1ff37aSBarry Smith for (j=0; j<row_nnz; j++) { 346b2f1ab58SBarry Smith B->icols[i][j] = icols[j]-icols[0]; 347b2f1ab58SBarry Smith } 348b2f1ab58SBarry Smith } 349b2f1ab58SBarry Smith ptr += B->row_nnz[i]; 350b2f1ab58SBarry Smith } 351b2f1ab58SBarry Smith } 352b2f1ab58SBarry Smith 353c328eeadSBarry Smith /* Point to the right places for all data */ 3544e1ff37aSBarry Smith for (i=0; i<nrows; i++) { 355b2f1ab58SBarry Smith B->icols[i] = B->icols[ipoint[i]]; 356b2f1ab58SBarry Smith } 3570298fd71SBarry Smith ierr = PetscInfo(NULL,"Row patterns have been compressed\n");CHKERRQ(ierr); 35857622a8eSBarry Smith ierr = PetscInfo1(NULL," (%g nonzeros per row)\n", (double) ((PetscReal) nnz / (PetscReal) nrows));CHKERRQ(ierr); 359b2f1ab58SBarry Smith 360b2f1ab58SBarry Smith ierr=PetscFree(isort);CHKERRQ(ierr); 361b2f1ab58SBarry Smith ierr=PetscFree(used);CHKERRQ(ierr); 362b2f1ab58SBarry Smith ierr=PetscFree(ipoint);CHKERRQ(ierr); 363b2f1ab58SBarry Smith 364b2f1ab58SBarry Smith mem_compressed = spbas_memory_requirement(*B); 3654e1ff37aSBarry Smith *mem_reduction = 100.0 * (PetscReal)(mem_orig-mem_compressed)/ (PetscReal) mem_orig; 366b2f1ab58SBarry Smith PetscFunctionReturn(0); 367b2f1ab58SBarry Smith } 368b2f1ab58SBarry Smith 369b2f1ab58SBarry Smith /* 370b2f1ab58SBarry Smith spbas_incomplete_cholesky 371b2f1ab58SBarry Smith Incomplete Cholesky decomposition 372b2f1ab58SBarry Smith */ 373c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/bas/spbas_cholesky.h> 374b2f1ab58SBarry Smith 375b2f1ab58SBarry Smith /* 376b2f1ab58SBarry Smith spbas_delete : de-allocate the arrays owned by this matrix 377b2f1ab58SBarry Smith */ 378b2f1ab58SBarry Smith #undef __FUNCT__ 379b2f1ab58SBarry Smith #define __FUNCT__ "spbas_delete" 380b2f1ab58SBarry Smith PetscErrorCode spbas_delete(spbas_matrix matrix) 381b2f1ab58SBarry Smith { 382b2f1ab58SBarry Smith PetscInt i; 383b2f1ab58SBarry Smith PetscErrorCode ierr; 3849ccc4a9bSBarry Smith 385b2f1ab58SBarry Smith PetscFunctionBegin; 3869ccc4a9bSBarry Smith if (matrix.block_data) { 387cb9801acSJed Brown ierr=PetscFree(matrix.alloc_icol);CHKERRQ(ierr); 388b2f1ab58SBarry Smith if (matrix.values) {ierr=PetscFree(matrix.alloc_val);CHKERRQ(ierr);} 3899ccc4a9bSBarry Smith } else { 3909ccc4a9bSBarry Smith for (i=0; i<matrix.nrows; i++) { ierr=PetscFree(matrix.icols[i]);CHKERRQ(ierr);} 391b2f1ab58SBarry Smith ierr = PetscFree(matrix.icols);CHKERRQ(ierr); 3929ccc4a9bSBarry Smith if (matrix.values) { 3939ccc4a9bSBarry Smith for (i=0; i<matrix.nrows; i++) { ierr=PetscFree(matrix.values[i]);CHKERRQ(ierr);} 394b2f1ab58SBarry Smith } 395b2f1ab58SBarry Smith } 396b2f1ab58SBarry Smith 397b2f1ab58SBarry Smith ierr=PetscFree(matrix.row_nnz);CHKERRQ(ierr); 398b2f1ab58SBarry Smith ierr=PetscFree(matrix.icols);CHKERRQ(ierr); 3999ccc4a9bSBarry Smith if (matrix.col_idx_type == SPBAS_OFFSET_ARRAY) {ierr=PetscFree(matrix.icol0);CHKERRQ(ierr);} 400c31cb41cSBarry Smith ierr=PetscFree(matrix.values);CHKERRQ(ierr); 401b2f1ab58SBarry Smith PetscFunctionReturn(0); 402b2f1ab58SBarry Smith } 403b2f1ab58SBarry Smith 404b2f1ab58SBarry Smith /* 405b2f1ab58SBarry Smith spbas_matrix_to_crs: 406b2f1ab58SBarry Smith Convert an spbas_matrix to compessed row storage 407b2f1ab58SBarry Smith */ 408b2f1ab58SBarry Smith #undef __FUNCT__ 409b2f1ab58SBarry Smith #define __FUNCT__ "spbas_matrix_to_crs" 410b2f1ab58SBarry Smith PetscErrorCode spbas_matrix_to_crs(spbas_matrix matrix_A,MatScalar **val_out, PetscInt **irow_out, PetscInt **icol_out) 411b2f1ab58SBarry Smith { 412b2f1ab58SBarry Smith PetscInt nrows = matrix_A.nrows; 413b2f1ab58SBarry Smith PetscInt nnz = matrix_A.nnz; 414b2f1ab58SBarry Smith PetscInt i,j,r_nnz,i0; 415b2f1ab58SBarry Smith PetscInt *irow; 416b2f1ab58SBarry Smith PetscInt *icol; 417b2f1ab58SBarry Smith PetscInt *icol_A; 418b2f1ab58SBarry Smith MatScalar *val; 419b2f1ab58SBarry Smith PetscScalar *val_A; 420b2f1ab58SBarry Smith PetscInt col_idx_type = matrix_A.col_idx_type; 421ace3abfcSBarry Smith PetscBool do_values = matrix_A.values ? PETSC_TRUE : PETSC_FALSE; 422b2f1ab58SBarry Smith PetscErrorCode ierr; 423b2f1ab58SBarry Smith 424b2f1ab58SBarry Smith PetscFunctionBegin; 425854ce69bSBarry Smith ierr = PetscMalloc1(nrows+1, &irow);CHKERRQ(ierr); 426854ce69bSBarry Smith ierr = PetscMalloc1(nnz, &icol);CHKERRQ(ierr); 4279ccc4a9bSBarry Smith *icol_out = icol; 4289ccc4a9bSBarry Smith *irow_out = irow; 4299ccc4a9bSBarry Smith if (do_values) { 430854ce69bSBarry Smith ierr = PetscMalloc1(nnz, &val);CHKERRQ(ierr); 431b2f1ab58SBarry Smith *val_out = val; *icol_out = icol; *irow_out=irow; 432b2f1ab58SBarry Smith } 433b2f1ab58SBarry Smith 434b2f1ab58SBarry Smith irow[0]=0; 4359ccc4a9bSBarry Smith for (i=0; i<nrows; i++) { 436b2f1ab58SBarry Smith r_nnz = matrix_A.row_nnz[i]; 437b2f1ab58SBarry Smith i0 = irow[i]; 438b2f1ab58SBarry Smith irow[i+1] = i0 + r_nnz; 439b2f1ab58SBarry Smith icol_A = matrix_A.icols[i]; 440b2f1ab58SBarry Smith 4419ccc4a9bSBarry Smith if (do_values) { 442b2f1ab58SBarry Smith val_A = matrix_A.values[i]; 4439ccc4a9bSBarry Smith for (j=0; j<r_nnz; j++) { 444b2f1ab58SBarry Smith icol[i0+j] = icol_A[j]; 445b2f1ab58SBarry Smith val[i0+j] = val_A[j]; 446b2f1ab58SBarry Smith } 4479ccc4a9bSBarry Smith } else { 4482205254eSKarl Rupp for (j=0; j<r_nnz; j++) icol[i0+j] = icol_A[j]; 449b2f1ab58SBarry Smith } 450b2f1ab58SBarry Smith 4519ccc4a9bSBarry Smith if (col_idx_type == SPBAS_DIAGONAL_OFFSETS) { 4522205254eSKarl Rupp for (j=0; j<r_nnz; j++) icol[i0+j] += i; 4532205254eSKarl Rupp } else if (col_idx_type == SPBAS_OFFSET_ARRAY) { 454b2f1ab58SBarry Smith i0 = matrix_A.icol0[i]; 4552205254eSKarl Rupp for (j=0; j<r_nnz; j++) icol[i0+j] += i0; 456b2f1ab58SBarry Smith } 457b2f1ab58SBarry Smith } 458b2f1ab58SBarry Smith PetscFunctionReturn(0); 459b2f1ab58SBarry Smith } 460b2f1ab58SBarry Smith 461b2f1ab58SBarry Smith 462b2f1ab58SBarry Smith /* 463b2f1ab58SBarry Smith spbas_transpose 464b2f1ab58SBarry Smith return the transpose of a matrix 465b2f1ab58SBarry Smith */ 466b2f1ab58SBarry Smith #undef __FUNCT__ 467b2f1ab58SBarry Smith #define __FUNCT__ "spbas_transpose" 468b2f1ab58SBarry Smith PetscErrorCode spbas_transpose(spbas_matrix in_matrix, spbas_matrix * result) 469b2f1ab58SBarry Smith { 470b2f1ab58SBarry Smith PetscInt col_idx_type = in_matrix.col_idx_type; 471b2f1ab58SBarry Smith PetscInt nnz = in_matrix.nnz; 472b2f1ab58SBarry Smith PetscInt ncols = in_matrix.nrows; 473b2f1ab58SBarry Smith PetscInt nrows = in_matrix.ncols; 474b2f1ab58SBarry Smith PetscInt i,j,k; 475b2f1ab58SBarry Smith PetscInt r_nnz; 476b2f1ab58SBarry Smith PetscInt *irow; 4774efc9174SBarry Smith PetscInt icol0 = 0; 478b2f1ab58SBarry Smith PetscScalar * val; 479b2f1ab58SBarry Smith PetscErrorCode ierr; 4804e1ff37aSBarry Smith 481b2f1ab58SBarry Smith PetscFunctionBegin; 482c328eeadSBarry Smith /* Copy input values */ 483b2f1ab58SBarry Smith result->nrows = nrows; 484b2f1ab58SBarry Smith result->ncols = ncols; 485b2f1ab58SBarry Smith result->nnz = nnz; 486b2f1ab58SBarry Smith result->col_idx_type = SPBAS_COLUMN_NUMBERS; 487b2f1ab58SBarry Smith result->block_data = PETSC_TRUE; 488b2f1ab58SBarry Smith 489c328eeadSBarry Smith /* Allocate sparseness pattern */ 49071d55d18SBarry Smith ierr = spbas_allocate_pattern(result, in_matrix.values ? PETSC_TRUE : PETSC_FALSE);CHKERRQ(ierr); 491b2f1ab58SBarry Smith 492c328eeadSBarry Smith /* Count the number of nonzeros in each row */ 4932205254eSKarl Rupp for (i = 0; i<nrows; i++) result->row_nnz[i] = 0; 494b2f1ab58SBarry Smith 4959ccc4a9bSBarry Smith for (i=0; i<ncols; i++) { 496b2f1ab58SBarry Smith r_nnz = in_matrix.row_nnz[i]; 497b2f1ab58SBarry Smith irow = in_matrix.icols[i]; 4989ccc4a9bSBarry Smith if (col_idx_type == SPBAS_COLUMN_NUMBERS) { 4992205254eSKarl Rupp for (j=0; j<r_nnz; j++) result->row_nnz[irow[j]]++; 5009ccc4a9bSBarry Smith } else if (col_idx_type == SPBAS_DIAGONAL_OFFSETS) { 5012205254eSKarl Rupp for (j=0; j<r_nnz; j++) result->row_nnz[i+irow[j]]++; 5029ccc4a9bSBarry Smith } else if (col_idx_type == SPBAS_OFFSET_ARRAY) { 503b2f1ab58SBarry Smith icol0=in_matrix.icol0[i]; 5042205254eSKarl Rupp for (j=0; j<r_nnz; j++) result->row_nnz[icol0+irow[j]]++; 505b2f1ab58SBarry Smith } 506b2f1ab58SBarry Smith } 507b2f1ab58SBarry Smith 508c328eeadSBarry Smith /* Set the pointers to the data */ 509b2f1ab58SBarry Smith ierr = spbas_allocate_data(result);CHKERRQ(ierr); 510b2f1ab58SBarry Smith 511c328eeadSBarry Smith /* Reset the number of nonzeros in each row */ 5122205254eSKarl Rupp for (i = 0; i<nrows; i++) result->row_nnz[i] = 0; 513b2f1ab58SBarry Smith 514c328eeadSBarry Smith /* Fill the data arrays */ 5159ccc4a9bSBarry Smith if (in_matrix.values) { 5169ccc4a9bSBarry Smith for (i=0; i<ncols; i++) { 517b2f1ab58SBarry Smith r_nnz = in_matrix.row_nnz[i]; 518b2f1ab58SBarry Smith irow = in_matrix.icols[i]; 519b2f1ab58SBarry Smith val = in_matrix.values[i]; 520b2f1ab58SBarry Smith 5212205254eSKarl Rupp if (col_idx_type == SPBAS_COLUMN_NUMBERS) icol0 = 0; 5222205254eSKarl Rupp else if (col_idx_type == SPBAS_DIAGONAL_OFFSETS) icol0 = i; 5232205254eSKarl Rupp else if (col_idx_type == SPBAS_OFFSET_ARRAY) icol0 = in_matrix.icol0[i]; 5249ccc4a9bSBarry Smith for (j=0; j<r_nnz; j++) { 525b2f1ab58SBarry Smith k = icol0 + irow[j]; 526b2f1ab58SBarry Smith result->icols[k][result->row_nnz[k]] = i; 527b2f1ab58SBarry Smith result->values[k][result->row_nnz[k]] = val[j]; 528b2f1ab58SBarry Smith result->row_nnz[k]++; 529b2f1ab58SBarry Smith } 530b2f1ab58SBarry Smith } 5319ccc4a9bSBarry Smith } else { 5329ccc4a9bSBarry Smith for (i=0; i<ncols; i++) { 533b2f1ab58SBarry Smith r_nnz = in_matrix.row_nnz[i]; 534b2f1ab58SBarry Smith irow = in_matrix.icols[i]; 535b2f1ab58SBarry Smith 5362205254eSKarl Rupp if (col_idx_type == SPBAS_COLUMN_NUMBERS) icol0=0; 5372205254eSKarl Rupp else if (col_idx_type == SPBAS_DIAGONAL_OFFSETS) icol0=i; 5382205254eSKarl Rupp else if (col_idx_type == SPBAS_OFFSET_ARRAY) icol0=in_matrix.icol0[i]; 539b2f1ab58SBarry Smith 5409ccc4a9bSBarry Smith for (j=0; j<r_nnz; j++) { 541b2f1ab58SBarry Smith k = icol0 + irow[j]; 542b2f1ab58SBarry Smith result->icols[k][result->row_nnz[k]] = i; 543b2f1ab58SBarry Smith result->row_nnz[k]++; 544b2f1ab58SBarry Smith } 545b2f1ab58SBarry Smith } 546b2f1ab58SBarry Smith } 547b2f1ab58SBarry Smith PetscFunctionReturn(0); 548b2f1ab58SBarry Smith } 549b2f1ab58SBarry Smith 550b2f1ab58SBarry Smith /* 551b2f1ab58SBarry Smith spbas_mergesort 552b2f1ab58SBarry Smith 553b2f1ab58SBarry Smith mergesort for an array of intergers and an array of associated 554b2f1ab58SBarry Smith reals 555b2f1ab58SBarry Smith 556b2f1ab58SBarry Smith on output, icol[0..nnz-1] is increasing; 557b2f1ab58SBarry Smith val[0..nnz-1] has undergone the same permutation as icol 558b2f1ab58SBarry Smith 5590298fd71SBarry Smith NB: val may be NULL: in that case, only the integers are sorted 560b2f1ab58SBarry Smith 561b2f1ab58SBarry Smith */ 562b2f1ab58SBarry Smith #undef __FUNCT__ 563b2f1ab58SBarry Smith #define __FUNCT__ "spbas_mergesort" 564b2f1ab58SBarry Smith PetscErrorCode spbas_mergesort(PetscInt nnz, PetscInt *icol, PetscScalar *val) 565b2f1ab58SBarry Smith { 566c328eeadSBarry Smith PetscInt istep; /* Chunk-sizes of already sorted parts of arrays */ 567c328eeadSBarry Smith PetscInt i, i1, i2; /* Loop counters for (partly) sorted arrays */ 568c328eeadSBarry Smith PetscInt istart, i1end, i2end; /* start of newly sorted array part, end of both parts */ 569c328eeadSBarry Smith PetscInt *ialloc; /* Allocated arrays */ 5700298fd71SBarry Smith PetscScalar *valloc=NULL; 571c328eeadSBarry Smith PetscInt *iswap; /* auxiliary pointers for swapping */ 572b2f1ab58SBarry Smith PetscScalar *vswap; 573c328eeadSBarry Smith PetscInt *ihlp1; /* Pointers to new version of arrays, */ 5740298fd71SBarry Smith PetscScalar *vhlp1=NULL; /* (arrays under construction) */ 575c328eeadSBarry Smith PetscInt *ihlp2; /* Pointers to previous version of arrays, */ 5760298fd71SBarry Smith PetscScalar *vhlp2=NULL; 577b2f1ab58SBarry Smith PetscErrorCode ierr; 578b2f1ab58SBarry Smith 579785e854fSJed Brown ierr = PetscMalloc1(nnz,&ialloc);CHKERRQ(ierr); 580b2f1ab58SBarry Smith ihlp1 = ialloc; 581b2f1ab58SBarry Smith ihlp2 = icol; 582b2f1ab58SBarry Smith 5839ccc4a9bSBarry Smith if (val) { 584785e854fSJed Brown ierr = PetscMalloc1(nnz,&valloc);CHKERRQ(ierr); 585b2f1ab58SBarry Smith vhlp1 = valloc; 586b2f1ab58SBarry Smith vhlp2 = val; 587b2f1ab58SBarry Smith } 588b2f1ab58SBarry Smith 589b2f1ab58SBarry Smith 590c328eeadSBarry Smith /* Sorted array chunks are first 1 long, and increase until they are the complete array */ 5919ccc4a9bSBarry Smith for (istep=1; istep<nnz; istep*=2) { 592c328eeadSBarry Smith /* 593c328eeadSBarry Smith Combine sorted parts 594c328eeadSBarry Smith istart:istart+istep-1 and istart+istep-1:istart+2*istep-1 595c328eeadSBarry Smith of ihlp2 and vhlp2 596c328eeadSBarry Smith 597c328eeadSBarry Smith into one sorted part 598c328eeadSBarry Smith istart:istart+2*istep-1 599c328eeadSBarry Smith of ihlp1 and vhlp1 600c328eeadSBarry Smith */ 6019ccc4a9bSBarry Smith for (istart=0; istart<nnz; istart+=2*istep) { 602c328eeadSBarry Smith /* Set counters and bound array part endings */ 6032205254eSKarl Rupp i1=istart; i1end = i1+istep; if (i1end>nnz) i1end=nnz; 6042205254eSKarl Rupp i2=istart+istep; i2end = i2+istep; if (i2end>nnz) i2end=nnz; 605b2f1ab58SBarry Smith 606c328eeadSBarry Smith /* Merge the two array parts */ 6079ccc4a9bSBarry Smith if (val) { 6089ccc4a9bSBarry Smith for (i=istart; i<i2end; i++) { 6099ccc4a9bSBarry Smith if (i1<i1end && i2<i2end && ihlp2[i1] < ihlp2[i2]) { 610b2f1ab58SBarry Smith ihlp1[i] = ihlp2[i1]; 611b2f1ab58SBarry Smith vhlp1[i] = vhlp2[i1]; 612b2f1ab58SBarry Smith i1++; 6139ccc4a9bSBarry Smith } else if (i2<i2end) { 614b2f1ab58SBarry Smith ihlp1[i] = ihlp2[i2]; 615b2f1ab58SBarry Smith vhlp1[i] = vhlp2[i2]; 616b2f1ab58SBarry Smith i2++; 6179ccc4a9bSBarry Smith } else { 618b2f1ab58SBarry Smith ihlp1[i] = ihlp2[i1]; 619b2f1ab58SBarry Smith vhlp1[i] = vhlp2[i1]; 620b2f1ab58SBarry Smith i1++; 621b2f1ab58SBarry Smith } 622b2f1ab58SBarry Smith } 6239ccc4a9bSBarry Smith } else { 6246322f4bdSBarry Smith for (i=istart; i<i2end; i++) { 6256322f4bdSBarry Smith if (i1<i1end && i2<i2end && ihlp2[i1] < ihlp2[i2]) { 626b2f1ab58SBarry Smith ihlp1[i] = ihlp2[i1]; 627b2f1ab58SBarry Smith i1++; 6286322f4bdSBarry Smith } else if (i2<i2end) { 629b2f1ab58SBarry Smith ihlp1[i] = ihlp2[i2]; 630b2f1ab58SBarry Smith i2++; 6316322f4bdSBarry Smith } else { 632b2f1ab58SBarry Smith ihlp1[i] = ihlp2[i1]; 633b2f1ab58SBarry Smith i1++; 634b2f1ab58SBarry Smith } 635b2f1ab58SBarry Smith } 636b2f1ab58SBarry Smith } 637b2f1ab58SBarry Smith } 638b2f1ab58SBarry Smith 639c328eeadSBarry Smith /* Swap the two array sets */ 640b2f1ab58SBarry Smith iswap = ihlp2; ihlp2 = ihlp1; ihlp1 = iswap; 641b2f1ab58SBarry Smith vswap = vhlp2; vhlp2 = vhlp1; vhlp1 = vswap; 642b2f1ab58SBarry Smith } 643b2f1ab58SBarry Smith 644c328eeadSBarry Smith /* Copy one more time in case the sorted arrays are the temporary ones */ 6456322f4bdSBarry Smith if (ihlp2 != icol) { 6462205254eSKarl Rupp for (i=0; i<nnz; i++) icol[i] = ihlp2[i]; 6476322f4bdSBarry Smith if (val) { 6482205254eSKarl Rupp for (i=0; i<nnz; i++) val[i] = vhlp2[i]; 649b2f1ab58SBarry Smith } 650b2f1ab58SBarry Smith } 651b2f1ab58SBarry Smith 652b2f1ab58SBarry Smith ierr = PetscFree(ialloc);CHKERRQ(ierr); 653b2f1ab58SBarry Smith if (val) {ierr = PetscFree(valloc);CHKERRQ(ierr);} 654b2f1ab58SBarry Smith PetscFunctionReturn(0); 655b2f1ab58SBarry Smith } 656b2f1ab58SBarry Smith 657b2f1ab58SBarry Smith /* 658b2f1ab58SBarry Smith spbas_apply_reordering_rows: 659b2f1ab58SBarry Smith apply the given reordering to the rows: matrix_A = matrix_A(perm,:); 660b2f1ab58SBarry Smith */ 661b2f1ab58SBarry Smith #undef __FUNCT__ 662b2f1ab58SBarry Smith #define __FUNCT__ "spbas_apply_reordering_rows" 663b2f1ab58SBarry Smith PetscErrorCode spbas_apply_reordering_rows(spbas_matrix *matrix_A, const PetscInt *permutation) 664b2f1ab58SBarry Smith { 665b2f1ab58SBarry Smith PetscInt i,j,ip; 666b2f1ab58SBarry Smith PetscInt nrows=matrix_A->nrows; 667b2f1ab58SBarry Smith PetscInt * row_nnz; 668b2f1ab58SBarry Smith PetscInt **icols; 669ace3abfcSBarry Smith PetscBool do_values = matrix_A->values ? PETSC_TRUE : PETSC_FALSE; 6700298fd71SBarry Smith PetscScalar **vals = NULL; 671b2f1ab58SBarry Smith PetscErrorCode ierr; 672b2f1ab58SBarry Smith 673b2f1ab58SBarry Smith PetscFunctionBegin; 674e32f2f54SBarry 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"); 675b2f1ab58SBarry Smith 6766322f4bdSBarry Smith if (do_values) { 677854ce69bSBarry Smith ierr = PetscMalloc1(nrows, &vals);CHKERRQ(ierr); 678b2f1ab58SBarry Smith } 679854ce69bSBarry Smith ierr = PetscMalloc1(nrows, &row_nnz);CHKERRQ(ierr); 680854ce69bSBarry Smith ierr = PetscMalloc1(nrows, &icols);CHKERRQ(ierr); 681b2f1ab58SBarry Smith 6826322f4bdSBarry Smith for (i=0; i<nrows; i++) { 683b2f1ab58SBarry Smith ip = permutation[i]; 6842205254eSKarl Rupp if (do_values) vals[i] = matrix_A->values[ip]; 685b2f1ab58SBarry Smith icols[i] = matrix_A->icols[ip]; 686b2f1ab58SBarry Smith row_nnz[i] = matrix_A->row_nnz[ip]; 6872205254eSKarl Rupp for (j=0; j<row_nnz[i]; j++) icols[i][j] += ip-i; 688b2f1ab58SBarry Smith } 689b2f1ab58SBarry Smith 690b2f1ab58SBarry Smith if (do_values) { ierr = PetscFree(matrix_A->values);CHKERRQ(ierr);} 691b2f1ab58SBarry Smith ierr = PetscFree(matrix_A->icols);CHKERRQ(ierr); 692b2f1ab58SBarry Smith ierr = PetscFree(matrix_A->row_nnz);CHKERRQ(ierr); 693b2f1ab58SBarry Smith 6942205254eSKarl Rupp if (do_values) matrix_A->values = vals; 695b2f1ab58SBarry Smith matrix_A->icols = icols; 696b2f1ab58SBarry Smith matrix_A->row_nnz = row_nnz; 697b2f1ab58SBarry Smith PetscFunctionReturn(0); 698b2f1ab58SBarry Smith } 699b2f1ab58SBarry Smith 700b2f1ab58SBarry Smith 701b2f1ab58SBarry Smith /* 702b2f1ab58SBarry Smith spbas_apply_reordering_cols: 703b2f1ab58SBarry Smith apply the given reordering to the columns: matrix_A(:,perm) = matrix_A; 704b2f1ab58SBarry Smith */ 705b2f1ab58SBarry Smith #undef __FUNCT__ 706b2f1ab58SBarry Smith #define __FUNCT__ "spbas_apply_reordering_cols" 707b2f1ab58SBarry Smith PetscErrorCode spbas_apply_reordering_cols(spbas_matrix *matrix_A,const PetscInt *permutation) 708b2f1ab58SBarry Smith { 709b2f1ab58SBarry Smith PetscInt i,j; 710b2f1ab58SBarry Smith PetscInt nrows=matrix_A->nrows; 711b2f1ab58SBarry Smith PetscInt row_nnz; 712b2f1ab58SBarry Smith PetscInt *icols; 713ace3abfcSBarry Smith PetscBool do_values = matrix_A->values ? PETSC_TRUE : PETSC_FALSE; 7140298fd71SBarry Smith PetscScalar *vals = NULL; 715b2f1ab58SBarry Smith PetscErrorCode ierr; 716b2f1ab58SBarry Smith 717b2f1ab58SBarry Smith PetscFunctionBegin; 718e32f2f54SBarry 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"); 719b2f1ab58SBarry Smith 7206322f4bdSBarry Smith for (i=0; i<nrows; i++) { 721b2f1ab58SBarry Smith icols = matrix_A->icols[i]; 722b2f1ab58SBarry Smith row_nnz = matrix_A->row_nnz[i]; 7232205254eSKarl Rupp if (do_values) vals = matrix_A->values[i]; 724b2f1ab58SBarry Smith 7256322f4bdSBarry Smith for (j=0; j<row_nnz; j++) { 726b2f1ab58SBarry Smith icols[j] = permutation[i+icols[j]]-i; 727b2f1ab58SBarry Smith } 728b2f1ab58SBarry Smith ierr = spbas_mergesort(row_nnz, icols, vals);CHKERRQ(ierr); 729b2f1ab58SBarry Smith } 730b2f1ab58SBarry Smith PetscFunctionReturn(0); 731b2f1ab58SBarry Smith } 732b2f1ab58SBarry Smith 733b2f1ab58SBarry Smith /* 734b2f1ab58SBarry Smith spbas_apply_reordering: 735b2f1ab58SBarry Smith apply the given reordering: matrix_A(perm,perm) = matrix_A; 736b2f1ab58SBarry Smith */ 737b2f1ab58SBarry Smith #undef __FUNCT__ 738b2f1ab58SBarry Smith #define __FUNCT__ "spbas_apply_reordering" 739b2f1ab58SBarry Smith PetscErrorCode spbas_apply_reordering(spbas_matrix *matrix_A, const PetscInt *permutation, const PetscInt * inv_perm) 740b2f1ab58SBarry Smith { 741b2f1ab58SBarry Smith PetscErrorCode ierr; 7425fd66863SKarl Rupp 743b2f1ab58SBarry Smith PetscFunctionBegin; 744b2f1ab58SBarry Smith ierr = spbas_apply_reordering_rows(matrix_A, inv_perm);CHKERRQ(ierr); 745b2f1ab58SBarry Smith ierr = spbas_apply_reordering_cols(matrix_A, permutation);CHKERRQ(ierr); 746b2f1ab58SBarry Smith PetscFunctionReturn(0); 747b2f1ab58SBarry Smith } 748b2f1ab58SBarry Smith 749b2f1ab58SBarry Smith #undef __FUNCT__ 750b2f1ab58SBarry Smith #define __FUNCT__ "spbas_pattern_only" 751b2f1ab58SBarry Smith PetscErrorCode spbas_pattern_only(PetscInt nrows, PetscInt ncols, PetscInt *ai, PetscInt *aj, spbas_matrix * result) 752b2f1ab58SBarry Smith { 753b2f1ab58SBarry Smith spbas_matrix retval; 754b2f1ab58SBarry Smith PetscInt i, j, i0, r_nnz; 755b2f1ab58SBarry Smith PetscErrorCode ierr; 756b2f1ab58SBarry Smith 757b2f1ab58SBarry Smith PetscFunctionBegin; 758c328eeadSBarry Smith /* Copy input values */ 759b2f1ab58SBarry Smith retval.nrows = nrows; 760b2f1ab58SBarry Smith retval.ncols = ncols; 761b2f1ab58SBarry Smith retval.nnz = ai[nrows]; 762b2f1ab58SBarry Smith 763b2f1ab58SBarry Smith retval.block_data = PETSC_TRUE; 764b2f1ab58SBarry Smith retval.col_idx_type = SPBAS_DIAGONAL_OFFSETS; 765b2f1ab58SBarry Smith 766c328eeadSBarry Smith /* Allocate output matrix */ 767b2f1ab58SBarry Smith ierr = spbas_allocate_pattern(&retval, PETSC_FALSE);CHKERRQ(ierr); 7682205254eSKarl Rupp for (i=0; i<nrows; i++) retval.row_nnz[i] = ai[i+1]-ai[i]; 769b2f1ab58SBarry Smith ierr = spbas_allocate_data(&retval);CHKERRQ(ierr); 770c328eeadSBarry Smith /* Copy the structure */ 7716322f4bdSBarry Smith for (i = 0; i<retval.nrows; i++) { 772b2f1ab58SBarry Smith i0 = ai[i]; 773b2f1ab58SBarry Smith r_nnz = ai[i+1]-i0; 774b2f1ab58SBarry Smith 7756322f4bdSBarry Smith for (j=0; j<r_nnz; j++) { 776b2f1ab58SBarry Smith retval.icols[i][j] = aj[i0+j]-i; 777b2f1ab58SBarry Smith } 778b2f1ab58SBarry Smith } 779b2f1ab58SBarry Smith *result = retval; 780b2f1ab58SBarry Smith PetscFunctionReturn(0); 781b2f1ab58SBarry Smith } 782b2f1ab58SBarry Smith 783b2f1ab58SBarry Smith 784b2f1ab58SBarry Smith /* 785b2f1ab58SBarry Smith spbas_mark_row_power: 786b2f1ab58SBarry Smith Mark the columns in row 'row' which are nonzero in 787b2f1ab58SBarry Smith matrix^2log(marker). 788b2f1ab58SBarry Smith */ 789b2f1ab58SBarry Smith #undef __FUNCT__ 790b2f1ab58SBarry Smith #define __FUNCT__ "spbas_mark_row_power" 791be332245SKarl Rupp PetscErrorCode spbas_mark_row_power(PetscInt *iwork, /* marker-vector */ 792c328eeadSBarry Smith PetscInt row, /* row for which the columns are marked */ 793c328eeadSBarry Smith spbas_matrix * in_matrix, /* matrix for which the power is being calculated */ 794c328eeadSBarry Smith PetscInt marker, /* marker-value: 2^power */ 795c328eeadSBarry Smith PetscInt minmrk, /* lower bound for marked points */ 796c328eeadSBarry Smith PetscInt maxmrk) /* upper bound for marked points */ 797b2f1ab58SBarry Smith { 798b2f1ab58SBarry Smith PetscErrorCode ierr; 799b2f1ab58SBarry Smith PetscInt i,j, nnz; 800b2f1ab58SBarry Smith 801b2f1ab58SBarry Smith PetscFunctionBegin; 802b2f1ab58SBarry Smith nnz = in_matrix->row_nnz[row]; 803b2f1ab58SBarry Smith 804c328eeadSBarry Smith /* For higher powers, call this function recursively */ 8056322f4bdSBarry Smith if (marker>1) { 8066322f4bdSBarry Smith for (i=0; i<nnz; i++) { 807b2f1ab58SBarry Smith j = row + in_matrix->icols[row][i]; 8086322f4bdSBarry Smith if (minmrk<=j && j<maxmrk && iwork[j] < marker) { 80971d55d18SBarry Smith ierr = spbas_mark_row_power(iwork, row + in_matrix->icols[row][i],in_matrix, marker/2,minmrk,maxmrk);CHKERRQ(ierr); 810b2f1ab58SBarry Smith iwork[j] |= marker; 811b2f1ab58SBarry Smith } 812b2f1ab58SBarry Smith } 8136322f4bdSBarry Smith } else { 814c328eeadSBarry Smith /* Mark the columns reached */ 8156322f4bdSBarry Smith for (i=0; i<nnz; i++) { 816b2f1ab58SBarry Smith j = row + in_matrix->icols[row][i]; 8172205254eSKarl Rupp if (minmrk<=j && j<maxmrk) iwork[j] |= 1; 818b2f1ab58SBarry Smith } 819b2f1ab58SBarry Smith } 820b2f1ab58SBarry Smith PetscFunctionReturn(0); 821b2f1ab58SBarry Smith } 822b2f1ab58SBarry Smith 823b2f1ab58SBarry Smith 824b2f1ab58SBarry Smith /* 825b2f1ab58SBarry Smith spbas_power 826b2f1ab58SBarry Smith Calculate sparseness patterns for incomplete Cholesky decompositions 827b2f1ab58SBarry Smith of a given order: (almost) all nonzeros of the matrix^(order+1) which 828b2f1ab58SBarry Smith are inside the band width are found and stored in the output sparseness 829b2f1ab58SBarry Smith pattern. 830b2f1ab58SBarry Smith */ 831b2f1ab58SBarry Smith #undef __FUNCT__ 832b2f1ab58SBarry Smith #define __FUNCT__ "spbas_power" 833b2f1ab58SBarry Smith PetscErrorCode spbas_power(spbas_matrix in_matrix,PetscInt power, spbas_matrix * result) 834b2f1ab58SBarry Smith { 835b2f1ab58SBarry Smith spbas_matrix retval; 836b2f1ab58SBarry Smith PetscInt nrows = in_matrix.nrows; 837b2f1ab58SBarry Smith PetscInt ncols = in_matrix.ncols; 838b2f1ab58SBarry Smith PetscInt i, j, kend; 839b2f1ab58SBarry Smith PetscInt nnz, inz; 840b2f1ab58SBarry Smith PetscInt *iwork; 841b2f1ab58SBarry Smith PetscInt marker; 842b2f1ab58SBarry Smith PetscInt maxmrk=0; 843b2f1ab58SBarry Smith PetscErrorCode ierr; 844b2f1ab58SBarry Smith 845b2f1ab58SBarry Smith PetscFunctionBegin; 846e32f2f54SBarry 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"); 847e32f2f54SBarry Smith if (ncols != nrows) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Dimension error\n"); 848e32f2f54SBarry Smith if (in_matrix.values) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Input array must be sparseness pattern (no values)"); 849e32f2f54SBarry Smith if (power<=0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Power must be 1 or up"); 850b2f1ab58SBarry Smith 851c328eeadSBarry Smith /* Copy input values*/ 852b2f1ab58SBarry Smith retval.nrows = ncols; 853b2f1ab58SBarry Smith retval.ncols = nrows; 854b2f1ab58SBarry Smith retval.nnz = 0; 855b2f1ab58SBarry Smith retval.col_idx_type = SPBAS_DIAGONAL_OFFSETS; 856b2f1ab58SBarry Smith retval.block_data = PETSC_FALSE; 857b2f1ab58SBarry Smith 858c328eeadSBarry Smith /* Allocate sparseness pattern */ 85971d55d18SBarry Smith ierr = spbas_allocate_pattern(&retval, in_matrix.values ? PETSC_TRUE : PETSC_FALSE);CHKERRQ(ierr); 860b2f1ab58SBarry Smith 861c328eeadSBarry Smith /* Allocate marker array */ 862785e854fSJed Brown ierr = PetscMalloc1(nrows, &iwork);CHKERRQ(ierr); 863b2f1ab58SBarry Smith 864c328eeadSBarry Smith /* Erase the pattern for this row */ 8654e1ff37aSBarry Smith ierr = PetscMemzero((void*) iwork, retval.nrows*sizeof(PetscInt));CHKERRQ(ierr); 866b2f1ab58SBarry Smith 867c328eeadSBarry Smith /* Calculate marker values */ 8682205254eSKarl Rupp marker = 1; for (i=1; i<power; i++) marker*=2; 869b2f1ab58SBarry Smith 8706322f4bdSBarry Smith for (i=0; i<nrows; i++) { 871c328eeadSBarry Smith /* Calculate the pattern for each row */ 872b2f1ab58SBarry Smith 873b2f1ab58SBarry Smith nnz = in_matrix.row_nnz[i]; 874b2f1ab58SBarry Smith kend = i+in_matrix.icols[i][nnz-1]; 8752205254eSKarl Rupp if (maxmrk<=kend) maxmrk=kend+1; 87671d55d18SBarry Smith ierr = spbas_mark_row_power(iwork, i, &in_matrix, marker, i, maxmrk);CHKERRQ(ierr); 877b2f1ab58SBarry Smith 878c328eeadSBarry Smith /* Count the columns*/ 879b2f1ab58SBarry Smith nnz = 0; 8802205254eSKarl Rupp for (j=i; j<maxmrk; j++) nnz+= (iwork[j]!=0); 881b2f1ab58SBarry Smith 882c328eeadSBarry Smith /* Allocate the column indices */ 883b2f1ab58SBarry Smith retval.row_nnz[i] = nnz; 884785e854fSJed Brown ierr = PetscMalloc1(nnz,&retval.icols[i]);CHKERRQ(ierr); 885b2f1ab58SBarry Smith 886c328eeadSBarry Smith /* Administrate the column indices */ 887b2f1ab58SBarry Smith inz = 0; 8886322f4bdSBarry Smith for (j=i; j<maxmrk; j++) { 8896322f4bdSBarry Smith if (iwork[j]) { 890b2f1ab58SBarry Smith retval.icols[i][inz] = j-i; 891b2f1ab58SBarry Smith inz++; 892b2f1ab58SBarry Smith iwork[j]=0; 893b2f1ab58SBarry Smith } 894b2f1ab58SBarry Smith } 895b2f1ab58SBarry Smith retval.nnz += nnz; 896b2f1ab58SBarry Smith }; 897b2f1ab58SBarry Smith ierr = PetscFree(iwork);CHKERRQ(ierr); 898b2f1ab58SBarry Smith *result = retval; 899b2f1ab58SBarry Smith PetscFunctionReturn(0); 900b2f1ab58SBarry Smith } 901b2f1ab58SBarry Smith 902b2f1ab58SBarry Smith 903b2f1ab58SBarry Smith 904b2f1ab58SBarry Smith /* 905b2f1ab58SBarry Smith spbas_keep_upper: 906b2f1ab58SBarry Smith remove the lower part of the matrix: keep the upper part 907b2f1ab58SBarry Smith */ 908b2f1ab58SBarry Smith #undef __FUNCT__ 909b2f1ab58SBarry Smith #define __FUNCT__ "spbas_keep_upper" 910b2f1ab58SBarry Smith PetscErrorCode spbas_keep_upper(spbas_matrix * inout_matrix) 911b2f1ab58SBarry Smith { 912b2f1ab58SBarry Smith PetscInt i, j; 913b2f1ab58SBarry Smith PetscInt jstart; 914b2f1ab58SBarry Smith 915b2f1ab58SBarry Smith PetscFunctionBegin; 916e32f2f54SBarry Smith if (inout_matrix->block_data) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Not yet for block data matrices\n"); 9176322f4bdSBarry Smith for (i=0; i<inout_matrix->nrows; i++) { 9186322f4bdSBarry Smith for (jstart=0; (jstart<inout_matrix->row_nnz[i]) && (inout_matrix->icols[i][jstart]<0); jstart++) {} 9196322f4bdSBarry Smith if (jstart>0) { 9206322f4bdSBarry Smith for (j=0; j<inout_matrix->row_nnz[i]-jstart; j++) { 9216322f4bdSBarry Smith inout_matrix->icols[i][j] = inout_matrix->icols[i][j+jstart]; 922b2f1ab58SBarry Smith } 923b2f1ab58SBarry Smith 9246322f4bdSBarry Smith if (inout_matrix->values) { 9256322f4bdSBarry Smith for (j=0; j<inout_matrix->row_nnz[i]-jstart; j++) { 9266322f4bdSBarry Smith inout_matrix->values[i][j] = inout_matrix->values[i][j+jstart]; 927b2f1ab58SBarry Smith } 928b2f1ab58SBarry Smith } 929b2f1ab58SBarry Smith 930b2f1ab58SBarry Smith inout_matrix->row_nnz[i] -= jstart; 931b2f1ab58SBarry Smith 9326322f4bdSBarry Smith inout_matrix->icols[i] = (PetscInt*) realloc((void*) inout_matrix->icols[i], inout_matrix->row_nnz[i]*sizeof(PetscInt)); 933b2f1ab58SBarry Smith 9346322f4bdSBarry Smith if (inout_matrix->values) { 9356322f4bdSBarry Smith inout_matrix->values[i] = (PetscScalar*) realloc((void*) inout_matrix->values[i], inout_matrix->row_nnz[i]*sizeof(PetscScalar)); 936b2f1ab58SBarry Smith } 937b2f1ab58SBarry Smith inout_matrix->nnz -= jstart; 938b2f1ab58SBarry Smith } 939b2f1ab58SBarry Smith } 940b2f1ab58SBarry Smith PetscFunctionReturn(0); 941b2f1ab58SBarry Smith } 942b2f1ab58SBarry Smith 943