10367cb8aSBarry Smith 2a5eb4965SSatish Balay #ifdef PETSC_RCS_HEADER 3*15091d37SBarry Smith static char vcid[] = "$Id: zerodiag.c,v 1.31 1999/03/11 16:20:20 bsmith Exp bsmith $"; 4ad608de0SBarry Smith #endif 5ad608de0SBarry Smith 6ad608de0SBarry Smith /* 7ad608de0SBarry Smith This file contains routines to reorder a matrix so that the diagonal 848b35521SBarry Smith elements are nonzero. 9ad608de0SBarry Smith */ 10ad608de0SBarry Smith 1170f55243SBarry Smith #include "src/mat/matimpl.h" /*I "mat.h" I*/ 12ad608de0SBarry Smith 1348b35521SBarry Smith #define SWAP(a,b) {int _t; _t = a; a = b; b = _t; } 1448b35521SBarry Smith 155615d1e5SSatish Balay #undef __FUNC__ 165615d1e5SSatish Balay #define __FUNC__ "MatReorderForNonzeroDiagonal" 17ad608de0SBarry Smith /*@ 1848b35521SBarry Smith MatReorderForNonzeroDiagonal - Changes matrix ordering to remove 1948b35521SBarry Smith zeros from diagonal. This may help in the LU factorization to 2048b35521SBarry Smith prevent a zero pivot. 21ad608de0SBarry Smith 22fee21e36SBarry Smith Collective on Mat 23fee21e36SBarry Smith 2498a79cdbSBarry Smith Input Parameters: 2598a79cdbSBarry Smith + mat - matrix to reorder 2698a79cdbSBarry Smith - rmap,cmap - row and column permutations. Usually obtained from 2791e9ee9fSBarry Smith MatGetOrdering(). 2898a79cdbSBarry Smith 29*15091d37SBarry Smith Level: intermediate 30*15091d37SBarry Smith 31ad608de0SBarry Smith Notes: 32ad608de0SBarry Smith This is not intended as a replacement for pivoting for matrices that 33d252947aSBarry Smith have ``bad'' structure. It is only a stop-gap measure. Should be called 3491e9ee9fSBarry Smith after a call to MatGetOrdering(), this routine changes the column 35d252947aSBarry Smith ordering defined in cis. 36d252947aSBarry Smith 37b259b22eSLois Curfman McInnes Options Database Keys (When using SLES): 3898a79cdbSBarry Smith + -pc_ilu_nonzeros_along_diagonal 3998a79cdbSBarry Smith - -pc_lu_nonzeros_along_diagonal 40ad608de0SBarry Smith 4133f51a72SBarry Smith Algorithm Notes: 4233f51a72SBarry Smith Column pivoting is used. 4333f51a72SBarry Smith 4433f51a72SBarry Smith 1) Choice of column is made by looking at the 4533f51a72SBarry Smith non-zero elements in the troublesome row for columns that are not yet 4633f51a72SBarry Smith included (moving from left to right). 4733f51a72SBarry Smith 4833f51a72SBarry Smith 2) If (1) fails we check all the columns to the left of the current row 49814823dcSBarry Smith and see if one of them has could be swapped. It can be swapped if 50814823dcSBarry Smith its corresponding row has a non-zero in the column it is being 51814823dcSBarry Smith swapped with; to make sure the previous nonzero diagonal remains 52814823dcSBarry Smith nonzero 5333f51a72SBarry Smith 5498a79cdbSBarry Smith 55ad608de0SBarry Smith @*/ 5648b35521SBarry Smith int MatReorderForNonzeroDiagonal(Mat mat,double atol,IS ris,IS cis ) 57ad608de0SBarry Smith { 5872af6520SSatish Balay int ierr, prow, k, nz, n, repl, *j, *col, *row, m, *icol,nnz,*jj,kk; 59fd61f322SBarry Smith Scalar *v,*vv; 60d93a2b8dSBarry Smith double repla; 61fd61f322SBarry Smith IS icis; 62ad608de0SBarry Smith 633a40ed3dSBarry Smith PetscFunctionBegin; 6490f02eecSBarry Smith PetscValidHeaderSpecific(mat,MAT_COOKIE); 6590f02eecSBarry Smith PetscValidHeaderSpecific(ris,IS_COOKIE); 6690f02eecSBarry Smith PetscValidHeaderSpecific(cis,IS_COOKIE); 6790f02eecSBarry Smith 6848b35521SBarry Smith ierr = ISGetIndices(ris,&row); CHKERRQ(ierr); 6948b35521SBarry Smith ierr = ISGetIndices(cis,&col); CHKERRQ(ierr); 7033f51a72SBarry Smith ierr = ISInvertPermutation(cis,&icis);CHKERRQ(ierr); 7133f51a72SBarry Smith ierr = ISGetIndices(icis,&icol); CHKERRQ(ierr); 7248b35521SBarry Smith ierr = MatGetSize(mat,&m,&n); CHKERRQ(ierr); 73ad608de0SBarry Smith 74ad608de0SBarry Smith for (prow=0; prow<n; prow++) { 7590f02eecSBarry Smith ierr = MatGetRow( mat, row[prow], &nz, &j, &v ); CHKERRQ(ierr); 7633f51a72SBarry Smith for (k=0; k<nz; k++) {if (icol[j[k]] == prow) break;} 77cddf8d76SBarry Smith if (k >= nz || PetscAbsScalar(v[k]) <= atol) { 78ad608de0SBarry Smith /* Element too small or zero; find the best candidate */ 79ad608de0SBarry Smith repl = prow; 80cddf8d76SBarry Smith repla = (k >= nz) ? 0.0 : PetscAbsScalar(v[k]); 81d4bb536fSBarry Smith /* 82fd61f322SBarry Smith Look for a later column we can swap with this one 83d4bb536fSBarry Smith */ 8448b35521SBarry Smith for (k=0; k<nz; k++) { 8533f51a72SBarry Smith if (icol[j[k]] > prow && PetscAbsScalar(v[k]) > repla) { 86fd61f322SBarry Smith /* found a suitable later column */ 8733f51a72SBarry Smith repl = icol[j[k]]; 88cddf8d76SBarry Smith repla = PetscAbsScalar(v[k]); 8933f51a72SBarry Smith SWAP(icol[col[prow]],icol[col[repl]]); 90ad608de0SBarry Smith SWAP(col[prow],col[repl]); 91fd61f322SBarry Smith goto found; 92fd61f322SBarry Smith } 93fd61f322SBarry Smith } 94fd61f322SBarry Smith /* 95fd61f322SBarry Smith Did not find a suitable later column so look for an earlier column 96fd61f322SBarry Smith We need to be sure that we don't introduce a zero in a previous 97fd61f322SBarry Smith diagonal 98fd61f322SBarry Smith */ 99fd61f322SBarry Smith for (k=0; k<nz; k++) { 100fd61f322SBarry Smith if (icol[j[k]] < prow && PetscAbsScalar(v[k]) > repla) { 101fd61f322SBarry Smith /* See if this one will work */ 102fd61f322SBarry Smith repl = icol[j[k]]; 103fd61f322SBarry Smith ierr = MatGetRow( mat, row[repl], &nnz, &jj, &vv ); CHKERRQ(ierr); 104fd61f322SBarry Smith for (kk=0; kk<nnz; kk++) { 105fd61f322SBarry Smith if (icol[jj[kk]] == prow && PetscAbsScalar(vv[kk]) > atol) { 106fd61f322SBarry Smith repla = PetscAbsScalar(v[k]); 107fd61f322SBarry Smith ierr = MatRestoreRow( mat, row[repl], &nnz, &jj, &vv ); CHKERRQ(ierr); 108fd61f322SBarry Smith SWAP(icol[col[prow]],icol[col[repl]]); 109fd61f322SBarry Smith SWAP(col[prow],col[repl]); 110fd61f322SBarry Smith goto found; 111fd61f322SBarry Smith } 112fd61f322SBarry Smith } 113fd61f322SBarry Smith ierr = MatRestoreRow( mat, row[repl], &nnz, &jj, &vv ); CHKERRQ(ierr); 114fd61f322SBarry Smith } 115fd61f322SBarry Smith } 116fd61f322SBarry Smith /* 117fd61f322SBarry Smith No column suitable; instead check all future rows 118fd61f322SBarry Smith Note: this will be very slow 119fd61f322SBarry Smith */ 120fd61f322SBarry Smith for (k=prow+1; k<n; k++) { 121fd61f322SBarry Smith ierr = MatGetRow( mat, row[k], &nnz, &jj, &vv ); CHKERRQ(ierr); 122fd61f322SBarry Smith for (kk=0; kk<nnz; kk++) { 123fd61f322SBarry Smith if (icol[jj[kk]] == prow && PetscAbsScalar(vv[kk]) > atol) { 124fd61f322SBarry Smith /* found a row */ 125fd61f322SBarry Smith SWAP(row[prow],row[k]); 126fd61f322SBarry Smith goto found; 127fd61f322SBarry Smith } 128fd61f322SBarry Smith } 129fd61f322SBarry Smith ierr = MatRestoreRow( mat, row[k], &nnz, &jj, &vv ); CHKERRQ(ierr); 130fd61f322SBarry Smith } 131fd61f322SBarry Smith 132fd61f322SBarry Smith found:; 133ad608de0SBarry Smith } 13490f02eecSBarry Smith ierr = MatRestoreRow( mat, row[prow], &nz, &j, &v ); CHKERRQ(ierr); 135ad608de0SBarry Smith } 13648b35521SBarry Smith ierr = ISRestoreIndices(ris,&row); CHKERRQ(ierr); 13748b35521SBarry Smith ierr = ISRestoreIndices(cis,&col); CHKERRQ(ierr); 13833f51a72SBarry Smith ierr = ISRestoreIndices(icis,&icol); CHKERRQ(ierr); 13933f51a72SBarry Smith ierr = ISDestroy(icis); CHKERRQ(ierr); 1403a40ed3dSBarry Smith PetscFunctionReturn(0); 141ad608de0SBarry Smith } 14248b35521SBarry Smith 14348b35521SBarry Smith 14448b35521SBarry Smith 145