xref: /petsc/src/mat/utils/zerodiag.c (revision 15091d3721b14bd18f7efa625bb8738e103dca31)
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