Actual source code: baijfact3.c
1: /*$Id: baijfact3.c,v 1.6 2001/08/06 21:15:36 bsmith Exp $*/
2: /*
3: Factorization code for BAIJ format.
4: */
5: #include src/mat/impls/baij/seq/baij.h
6: #include src/vec/vecimpl.h
7: #include src/inline/ilu.h
9: /*
10: The symbolic factorization code is identical to that for AIJ format,
11: except for very small changes since this is now a SeqBAIJ datastructure.
12: NOT good code reuse.
13: */
14: int MatLUFactorSymbolic_SeqBAIJ(Mat A,IS isrow,IS iscol,MatLUInfo *info,Mat *B)
15: {
16: Mat_SeqBAIJ *a = (Mat_SeqBAIJ*)A->data,*b;
17: IS isicol;
18: int *r,*ic,ierr,i,n = a->mbs,*ai = a->i,*aj = a->j;
19: int *ainew,*ajnew,jmax,*fill,*ajtmp,nz,bs = a->bs,bs2=a->bs2;
20: int *idnew,idx,row,m,fm,nnz,nzi,realloc = 0,nzbd,*im;
21: PetscReal f = 1.0;
24: if (A->M != A->N) SETERRQ(PETSC_ERR_ARG_WRONG,"matrix must be square");
25: ISInvertPermutation(iscol,PETSC_DECIDE,&isicol);
26: ISGetIndices(isrow,&r);
27: ISGetIndices(isicol,&ic);
29: if (info) f = info->fill;
30: /* get new row pointers */
31: ierr = PetscMalloc((n+1)*sizeof(int),&ainew);
32: ainew[0] = 0;
33: /* don't know how many column pointers are needed so estimate */
34: jmax = (int)(f*ai[n] + 1);
35: ierr = PetscMalloc((jmax)*sizeof(int),&ajnew);
36: /* fill is a linked list of nonzeros in active row */
37: ierr = PetscMalloc((2*n+1)*sizeof(int),&fill);
38: im = fill + n + 1;
39: /* idnew is location of diagonal in factor */
40: ierr = PetscMalloc((n+1)*sizeof(int),&idnew);
41: idnew[0] = 0;
43: for (i=0; i<n; i++) {
44: /* first copy previous fill into linked list */
45: nnz = nz = ai[r[i]+1] - ai[r[i]];
46: if (!nz) SETERRQ(PETSC_ERR_MAT_LU_ZRPVT,"Empty row in matrix");
47: ajtmp = aj + ai[r[i]];
48: fill[n] = n;
49: while (nz--) {
50: fm = n;
51: idx = ic[*ajtmp++];
52: do {
53: m = fm;
54: fm = fill[m];
55: } while (fm < idx);
56: fill[m] = idx;
57: fill[idx] = fm;
58: }
59: row = fill[n];
60: while (row < i) {
61: ajtmp = ajnew + idnew[row] + 1;
62: nzbd = 1 + idnew[row] - ainew[row];
63: nz = im[row] - nzbd;
64: fm = row;
65: while (nz-- > 0) {
66: idx = *ajtmp++;
67: nzbd++;
68: if (idx == i) im[row] = nzbd;
69: do {
70: m = fm;
71: fm = fill[m];
72: } while (fm < idx);
73: if (fm != idx) {
74: fill[m] = idx;
75: fill[idx] = fm;
76: fm = idx;
77: nnz++;
78: }
79: }
80: row = fill[row];
81: }
82: /* copy new filled row into permanent storage */
83: ainew[i+1] = ainew[i] + nnz;
84: if (ainew[i+1] > jmax) {
86: /* estimate how much additional space we will need */
87: /* use the strategy suggested by David Hysom <hysom@perch-t.icase.edu> */
88: /* just double the memory each time */
89: int maxadd = jmax;
90: /* maxadd = (int)((f*(ai[n]+1)*(n-i+5))/n); */
91: if (maxadd < nnz) maxadd = (n-i)*(nnz+1);
92: jmax += maxadd;
94: /* allocate a longer ajnew */
95: ierr = PetscMalloc(jmax*sizeof(int),&ajtmp);
96: ierr = PetscMemcpy(ajtmp,ajnew,ainew[i]*sizeof(int));
97: ierr = PetscFree(ajnew);
98: ajnew = ajtmp;
99: realloc++; /* count how many times we realloc */
100: }
101: ajtmp = ajnew + ainew[i];
102: fm = fill[n];
103: nzi = 0;
104: im[i] = nnz;
105: while (nnz--) {
106: if (fm < i) nzi++;
107: *ajtmp++ = fm;
108: fm = fill[fm];
109: }
110: idnew[i] = ainew[i] + nzi;
111: }
113: if (ai[n] != 0) {
114: PetscReal af = ((PetscReal)ainew[n])/((PetscReal)ai[n]);
115: PetscLogInfo(A,"MatLUFactorSymbolic_SeqBAIJ:Reallocs %d Fill ratio:given %g needed %gn",realloc,f,af);
116: PetscLogInfo(A,"MatLUFactorSymbolic_SeqBAIJ:Run with -pc_lu_fill %g or use n",af);
117: PetscLogInfo(A,"MatLUFactorSymbolic_SeqBAIJ:PCLUSetFill(pc,%g);n",af);
118: PetscLogInfo(A,"MatLUFactorSymbolic_SeqBAIJ:for best performance.n");
119: } else {
120: PetscLogInfo(A,"MatLUFactorSymbolic_SeqBAIJ:Empty matrix.n");
121: }
123: ISRestoreIndices(isrow,&r);
124: ISRestoreIndices(isicol,&ic);
126: PetscFree(fill);
128: /* put together the new matrix */
129: MatCreateSeqBAIJ(A->comm,bs,bs*n,bs*n,0,PETSC_NULL,B);
130: PetscLogObjectParent(*B,isicol);
131: b = (Mat_SeqBAIJ*)(*B)->data;
132: PetscFree(b->imax);
133: b->singlemalloc = PETSC_FALSE;
134: /* the next line frees the default space generated by the Create() */
135: PetscFree(b->a);
136: PetscFree(b->ilen);
137: ierr = PetscMalloc((ainew[n]+1)*sizeof(MatScalar)*bs2,&b->a);
138: b->j = ajnew;
139: b->i = ainew;
140: b->diag = idnew;
141: b->ilen = 0;
142: b->imax = 0;
143: b->row = isrow;
144: b->col = iscol;
145: if (info) b->pivotinblocks = (info->pivotinblocks) ? PETSC_TRUE : PETSC_FALSE;
146: else b->pivotinblocks = PETSC_TRUE;
147: ierr = PetscObjectReference((PetscObject)isrow);
148: ierr = PetscObjectReference((PetscObject)iscol);
149: b->icol = isicol;
150: PetscMalloc((bs*n+bs)*sizeof(PetscScalar),&b->solve_work);
151: /* In b structure: Free imax, ilen, old a, old j.
152: Allocate idnew, solve_work, new a, new j */
153: PetscLogObjectMemory(*B,(ainew[n]-n)*(sizeof(int)+sizeof(MatScalar)));
154: b->maxnz = b->nz = ainew[n];
155:
156: (*B)->factor = FACTOR_LU;
157: (*B)->info.factor_mallocs = realloc;
158: (*B)->info.fill_ratio_given = f;
159: if (ai[n] != 0) {
160: (*B)->info.fill_ratio_needed = ((PetscReal)ainew[n])/((PetscReal)ai[n]);
161: } else {
162: (*B)->info.fill_ratio_needed = 0.0;
163: }
164: return(0);
165: }