1*49b5e25fSSatish Balay #include "petscsys.h" 2*49b5e25fSSatish Balay #include "src/mat/impls/baij/seq/baij.h" 3*49b5e25fSSatish Balay #include "src/vec/vecimpl.h" 4*49b5e25fSSatish Balay #include "src/inline/spops.h" 5*49b5e25fSSatish Balay #include "sbaij.h" 6*49b5e25fSSatish Balay 7*49b5e25fSSatish Balay /* 8*49b5e25fSSatish Balay Symmetric reordering the index of sparse symmetric matrix A 9*49b5e25fSSatish Balay so that P*A*P^T is also stored symmetrically. 10*49b5e25fSSatish Balay The permutation needs to be symmetric, i.e., P = P^T = inv(P). 11*49b5e25fSSatish Balay -- modified from sor.f of YSMP 12*49b5e25fSSatish Balay -- idea: reorder (ai, aj, a) (not A!) to ensure that all nonzero A_(p(i),isp(k)) 13*49b5e25fSSatish Balay are stored in the upper triangle of P*A*P^T 14*49b5e25fSSatish Balay */ 15*49b5e25fSSatish Balay #undef __FUNC__ 16*49b5e25fSSatish Balay #define __FUNC__ "MatReordering_SeqSBAIJ" 17*49b5e25fSSatish Balay int MatReordering_SeqSBAIJ(Mat A,IS isp) 18*49b5e25fSSatish Balay { 19*49b5e25fSSatish Balay Mat_SeqSBAIJ *a=(Mat_SeqSBAIJ *)A->data; 20*49b5e25fSSatish Balay int *r,ierr,i,mbs=a->mbs,*vi,*ai=a->i,*aj=a->j,*rip,*riip; 21*49b5e25fSSatish Balay MatScalar *aa=a->a,*v; 22*49b5e25fSSatish Balay Scalar ak; 23*49b5e25fSSatish Balay int *nzr,nz,jmin,jmax,j,k,ajk; 24*49b5e25fSSatish Balay IS isip; /* inverse of isp */ 25*49b5e25fSSatish Balay 26*49b5e25fSSatish Balay PetscFunctionBegin; 27*49b5e25fSSatish Balay if (!mbs) PetscFunctionReturn(0); 28*49b5e25fSSatish Balay 29*49b5e25fSSatish Balay ierr = ISGetIndices(isp,&rip);CHKERRQ(ierr); 30*49b5e25fSSatish Balay ierr = ISInvertPermutation(isp,PETSC_DECIDE,&isip);CHKERRQ(ierr); 31*49b5e25fSSatish Balay ierr = ISGetIndices(isip,&riip);CHKERRQ(ierr); 32*49b5e25fSSatish Balay 33*49b5e25fSSatish Balay for (i=0; i<mbs; i++) { 34*49b5e25fSSatish Balay if ( rip[i] - riip[i] != 0 ) { 35*49b5e25fSSatish Balay printf("Non-symm. permutation, use symm. permutation or general matrix format\n"); 36*49b5e25fSSatish Balay break; 37*49b5e25fSSatish Balay } 38*49b5e25fSSatish Balay } 39*49b5e25fSSatish Balay 40*49b5e25fSSatish Balay /* Phase 1: find row in which to store each nonzero (r) 41*49b5e25fSSatish Balay initialize count of nonzeros to be stored in each row (nzr) */ 42*49b5e25fSSatish Balay 43*49b5e25fSSatish Balay nzr = (int*)PetscMalloc(mbs*sizeof(int));CHKPTRQ(nzr); 44*49b5e25fSSatish Balay r = (int*)PetscMalloc(ai[mbs]*sizeof(int));CHKPTRQ(r); 45*49b5e25fSSatish Balay for (i=0; i<mbs; i++) nzr[i] = 0; 46*49b5e25fSSatish Balay for (i=0; i<ai[mbs]; i++) r[i] = 0; 47*49b5e25fSSatish Balay 48*49b5e25fSSatish Balay /* for each nonzero element */ 49*49b5e25fSSatish Balay for (i=0; i<mbs; i++){ 50*49b5e25fSSatish Balay nz = ai[i+1] - ai[i]; 51*49b5e25fSSatish Balay j = ai[i]; 52*49b5e25fSSatish Balay while (nz--){ 53*49b5e25fSSatish Balay /* --- find row (=r[j]) and column (=aj[j]) in which to store a[j] ...*/ 54*49b5e25fSSatish Balay k = aj[j]; 55*49b5e25fSSatish Balay if (rip[k] < rip[i]) aj[j] = i; 56*49b5e25fSSatish Balay else k = i; 57*49b5e25fSSatish Balay r[j] = k; j++; 58*49b5e25fSSatish Balay nzr[k] ++; /* increment count of nonzeros in that row */ 59*49b5e25fSSatish Balay } 60*49b5e25fSSatish Balay } 61*49b5e25fSSatish Balay 62*49b5e25fSSatish Balay /* Phase 2: find new ai and permutation to apply to (aj,a) 63*49b5e25fSSatish Balay determine pointers (r) to delimit rows in permuted (aj,a) */ 64*49b5e25fSSatish Balay for (i=0; i<mbs; i++){ 65*49b5e25fSSatish Balay ai[i+1] = ai[i] + nzr[i]; 66*49b5e25fSSatish Balay nzr[i] = ai[i+1]; 67*49b5e25fSSatish Balay } 68*49b5e25fSSatish Balay 69*49b5e25fSSatish Balay /* determine where each (aj[j], a[j]) is stored in permuted (aj,a) 70*49b5e25fSSatish Balay for each nonzero element (in reverse order) */ 71*49b5e25fSSatish Balay jmin = ai[0]; jmax = ai[mbs]; 72*49b5e25fSSatish Balay nz = jmax - jmin; 73*49b5e25fSSatish Balay j = jmax-1; 74*49b5e25fSSatish Balay while (nz--){ 75*49b5e25fSSatish Balay i = r[j]; /* row value */ 76*49b5e25fSSatish Balay if (aj[j] == i) r[j] = ai[i]; /* put diagonal nonzero at beginning of row */ 77*49b5e25fSSatish Balay else { /* put off-diagonal nonzero in last unused location in row */ 78*49b5e25fSSatish Balay nzr[i]--; r[j] = nzr[i]; 79*49b5e25fSSatish Balay } 80*49b5e25fSSatish Balay j--; 81*49b5e25fSSatish Balay } 82*49b5e25fSSatish Balay 83*49b5e25fSSatish Balay /* Phase 3: permute (aj,a) to upper triangular form (wrt new ordering) */ 84*49b5e25fSSatish Balay for (j=jmin; j<jmax; j++){ 85*49b5e25fSSatish Balay while (r[j] != j){ 86*49b5e25fSSatish Balay k = r[j]; r[j] = r[k]; r[k] = k; 87*49b5e25fSSatish Balay ajk = aj[k]; aj[k] = aj[j]; aj[j] = ajk; 88*49b5e25fSSatish Balay ak = aa[k]; aa[k] = aa[j]; aa[j] = ak; 89*49b5e25fSSatish Balay } 90*49b5e25fSSatish Balay } 91*49b5e25fSSatish Balay 92*49b5e25fSSatish Balay ierr = ISRestoreIndices(isp,&rip);CHKERRQ(ierr); 93*49b5e25fSSatish Balay 94*49b5e25fSSatish Balay a->row = isp; 95*49b5e25fSSatish Balay a->col = isp; 96*49b5e25fSSatish Balay a->icol = isp; 97*49b5e25fSSatish Balay ierr = PetscObjectReference((PetscObject)isp); CHKERRQ(ierr); 98*49b5e25fSSatish Balay PetscFunctionReturn(0); 99*49b5e25fSSatish Balay } 100*49b5e25fSSatish Balay 101