xref: /petsc/src/mat/impls/sell/mpi/mmsell.c (revision a3ebf921741f253acd95844bdd6a9601d7f5a522)
1d4002b98SHong Zhang /*
2d4002b98SHong Zhang    Support for the parallel SELL matrix vector multiply
3d4002b98SHong Zhang */
4d4002b98SHong Zhang #include <../src/mat/impls/sell/mpi/mpisell.h>
5d4002b98SHong Zhang #include <petsc/private/isimpl.h>    /* needed because accesses data structure of ISLocalToGlobalMapping directly */
6d4002b98SHong Zhang 
7d4002b98SHong Zhang /*
8d4002b98SHong Zhang    Takes the local part of an already assembled MPISELL matrix
9d4002b98SHong Zhang    and disassembles it. This is to allow new nonzeros into the matrix
10d4002b98SHong Zhang    that require more communication in the matrix vector multiply.
11d4002b98SHong Zhang    Thus certain data-structures must be rebuilt.
12d4002b98SHong Zhang 
13d4002b98SHong Zhang    Kind of slow! But that's what application programmers get when
14d4002b98SHong Zhang    they are sloppy.
15d4002b98SHong Zhang */
16d4002b98SHong Zhang PetscErrorCode MatDisAssemble_MPISELL(Mat A)
17d4002b98SHong Zhang {
18d4002b98SHong Zhang   Mat_MPISELL    *sell=(Mat_MPISELL*)A->data;
19d4002b98SHong Zhang   Mat            B=sell->B,Bnew;
20d4002b98SHong Zhang   Mat_SeqSELL    *Bsell=(Mat_SeqSELL*)B->data;
21d4002b98SHong Zhang   PetscInt       i,j,totalslices,N=A->cmap->N,ec,row;
22d4002b98SHong Zhang   PetscBool      isnonzero;
23d4002b98SHong Zhang   PetscErrorCode ierr;
24d4002b98SHong Zhang 
25d4002b98SHong Zhang   PetscFunctionBegin;
26d4002b98SHong Zhang   /* free stuff related to matrix-vec multiply */
27d4002b98SHong Zhang   ierr = VecGetSize(sell->lvec,&ec);CHKERRQ(ierr); /* needed for PetscLogObjectMemory below */
28d4002b98SHong Zhang   ierr = VecDestroy(&sell->lvec);CHKERRQ(ierr);
29d4002b98SHong Zhang   ierr = VecScatterDestroy(&sell->Mvctx);CHKERRQ(ierr);
30d4002b98SHong Zhang   if (sell->colmap) {
31d4002b98SHong Zhang #if defined(PETSC_USE_CTABLE)
32d4002b98SHong Zhang     ierr = PetscTableDestroy(&sell->colmap);CHKERRQ(ierr);
33d4002b98SHong Zhang #else
34d4002b98SHong Zhang     ierr = PetscFree(sell->colmap);CHKERRQ(ierr);
35d4002b98SHong Zhang     ierr = PetscLogObjectMemory((PetscObject)A,-sell->B->cmap->n*sizeof(PetscInt));CHKERRQ(ierr);
36d4002b98SHong Zhang #endif
37d4002b98SHong Zhang   }
38d4002b98SHong Zhang 
39d4002b98SHong Zhang   /* make sure that B is assembled so we can access its values */
40d4002b98SHong Zhang   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
41d4002b98SHong Zhang   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
42d4002b98SHong Zhang 
43d4002b98SHong Zhang   /* invent new B and copy stuff over */
44d4002b98SHong Zhang   ierr = MatCreate(PETSC_COMM_SELF,&Bnew);CHKERRQ(ierr);
45d4002b98SHong Zhang   ierr = MatSetSizes(Bnew,B->rmap->n,N,B->rmap->n,N);CHKERRQ(ierr);
46d4002b98SHong Zhang   ierr = MatSetBlockSizesFromMats(Bnew,A,A);CHKERRQ(ierr);
47d4002b98SHong Zhang   ierr = MatSetType(Bnew,((PetscObject)B)->type_name);CHKERRQ(ierr);
48d4002b98SHong Zhang   ierr = MatSeqSELLSetPreallocation(Bnew,0,Bsell->rlen);CHKERRQ(ierr);
49b38c15b3SStefano Zampini   if (Bsell->nonew >= 0) { /* Inherit insertion error options (if positive). */
50b38c15b3SStefano Zampini     ((Mat_SeqSELL*)Bnew->data)->nonew = Bsell->nonew;
51b38c15b3SStefano Zampini   }
52d4002b98SHong Zhang 
53d4002b98SHong Zhang   /*
54d4002b98SHong Zhang    Ensure that B's nonzerostate is monotonically increasing.
55d4002b98SHong Zhang    Or should this follow the MatSetValues() loop to preserve B's nonzerstate across a MatDisAssemble() call?
56d4002b98SHong Zhang    */
57d4002b98SHong Zhang   Bnew->nonzerostate = B->nonzerostate;
58d4002b98SHong Zhang 
59d4002b98SHong Zhang   totalslices = B->rmap->n/8+((B->rmap->n & 0x07)?1:0); /* floor(n/8) */
60d4002b98SHong Zhang   for (i=0; i<totalslices; i++) { /* loop over slices */
61d4002b98SHong Zhang     for (j=Bsell->sliidx[i],row=0; j<Bsell->sliidx[i+1]; j++,row=((row+1)&0x07)) {
62d4002b98SHong Zhang       isnonzero = (PetscBool)((j-Bsell->sliidx[i])/8 < Bsell->rlen[8*i+row]);
63d4002b98SHong Zhang       if (isnonzero) {
64d4002b98SHong Zhang         ierr = MatSetValue(Bnew,8*i+row,sell->garray[Bsell->colidx[j]],Bsell->val[j],B->insertmode);CHKERRQ(ierr);
65d4002b98SHong Zhang       }
66d4002b98SHong Zhang     }
67d4002b98SHong Zhang   }
68d4002b98SHong Zhang 
69d4002b98SHong Zhang   ierr = PetscFree(sell->garray);CHKERRQ(ierr);
70d4002b98SHong Zhang   ierr = PetscLogObjectMemory((PetscObject)A,-ec*sizeof(PetscInt));CHKERRQ(ierr);
71d4002b98SHong Zhang   ierr = MatDestroy(&B);CHKERRQ(ierr);
72d4002b98SHong Zhang   ierr = PetscLogObjectParent((PetscObject)A,(PetscObject)Bnew);CHKERRQ(ierr);
73d4002b98SHong Zhang 
74d4002b98SHong Zhang   sell->B          = Bnew;
75d4002b98SHong Zhang   A->was_assembled = PETSC_FALSE;
76d4002b98SHong Zhang   A->assembled     = PETSC_FALSE;
77d4002b98SHong Zhang   PetscFunctionReturn(0);
78d4002b98SHong Zhang }
79d4002b98SHong Zhang 
80d4002b98SHong Zhang PetscErrorCode MatSetUpMultiply_MPISELL(Mat mat)
81d4002b98SHong Zhang {
82d4002b98SHong Zhang   Mat_MPISELL    *sell=(Mat_MPISELL*)mat->data;
83d4002b98SHong Zhang   Mat_SeqSELL    *B=(Mat_SeqSELL*)(sell->B->data);
84d4002b98SHong Zhang   PetscErrorCode ierr;
85d4002b98SHong Zhang   PetscInt       i,j,*bcolidx=B->colidx,ec=0,*garray,totalslices;
86d4002b98SHong Zhang   IS             from,to;
87d4002b98SHong Zhang   Vec            gvec;
88d4002b98SHong Zhang   PetscBool      isnonzero;
89d4002b98SHong Zhang #if defined(PETSC_USE_CTABLE)
90d4002b98SHong Zhang   PetscTable         gid1_lid1;
91d4002b98SHong Zhang   PetscTablePosition tpos;
92d4002b98SHong Zhang   PetscInt           gid,lid;
93d4002b98SHong Zhang #else
94d4002b98SHong Zhang   PetscInt N = mat->cmap->N,*indices;
95d4002b98SHong Zhang #endif
96d4002b98SHong Zhang 
97d4002b98SHong Zhang   PetscFunctionBegin;
98d4002b98SHong Zhang   totalslices = sell->B->rmap->n/8+((sell->B->rmap->n & 0x07)?1:0); /* floor(n/8) */
99d4002b98SHong Zhang 
100d4002b98SHong Zhang   /* ec counts the number of columns that contain nonzeros */
101d4002b98SHong Zhang #if defined(PETSC_USE_CTABLE)
102d4002b98SHong Zhang   /* use a table */
103d4002b98SHong Zhang   ierr = PetscTableCreate(sell->B->rmap->n,mat->cmap->N+1,&gid1_lid1);CHKERRQ(ierr);
104d4002b98SHong Zhang   for (i=0; i<totalslices; i++) { /* loop over slices */
105d4002b98SHong Zhang     for (j=B->sliidx[i]; j<B->sliidx[i+1]; j++) {
106d4002b98SHong Zhang       isnonzero = (PetscBool)((j-B->sliidx[i])/8 < B->rlen[(i<<3)+(j&0x07)]);
107d4002b98SHong Zhang       if (isnonzero) { /* check the mask bit */
108d4002b98SHong Zhang         PetscInt data,gid1 = bcolidx[j] + 1;
109d4002b98SHong Zhang         ierr = PetscTableFind(gid1_lid1,gid1,&data);CHKERRQ(ierr);
110d4002b98SHong Zhang         if (!data) {
111d4002b98SHong Zhang           /* one based table */
112d4002b98SHong Zhang           ierr = PetscTableAdd(gid1_lid1,gid1,++ec,INSERT_VALUES);CHKERRQ(ierr);
113d4002b98SHong Zhang         }
114d4002b98SHong Zhang       }
115d4002b98SHong Zhang     }
116d4002b98SHong Zhang   }
117d4002b98SHong Zhang 
118d4002b98SHong Zhang   /* form array of columns we need */
119d4002b98SHong Zhang   ierr = PetscMalloc1(ec+1,&garray);CHKERRQ(ierr);
120d4002b98SHong Zhang   ierr = PetscTableGetHeadPosition(gid1_lid1,&tpos);CHKERRQ(ierr);
121d4002b98SHong Zhang   while (tpos) {
122d4002b98SHong Zhang     ierr = PetscTableGetNext(gid1_lid1,&tpos,&gid,&lid);CHKERRQ(ierr);
123d4002b98SHong Zhang     gid--;
124d4002b98SHong Zhang     lid--;
125d4002b98SHong Zhang     garray[lid] = gid;
126d4002b98SHong Zhang   }
127d4002b98SHong Zhang   ierr = PetscSortInt(ec,garray);CHKERRQ(ierr); /* sort, and rebuild */
128d4002b98SHong Zhang   ierr = PetscTableRemoveAll(gid1_lid1);CHKERRQ(ierr);
129d4002b98SHong Zhang   for (i=0; i<ec; i++) {
130d4002b98SHong Zhang     ierr = PetscTableAdd(gid1_lid1,garray[i]+1,i+1,INSERT_VALUES);CHKERRQ(ierr);
131d4002b98SHong Zhang   }
132d4002b98SHong Zhang 
133d4002b98SHong Zhang   /* compact out the extra columns in B */
134d4002b98SHong Zhang   for (i=0; i<totalslices; i++) { /* loop over slices */
135d4002b98SHong Zhang     for (j=B->sliidx[i]; j<B->sliidx[i+1]; j++) {
136d4002b98SHong Zhang       isnonzero = (PetscBool)((j-B->sliidx[i])/8 < B->rlen[(i<<3)+(j&0x07)]);
137d4002b98SHong Zhang       if (isnonzero) {
138d4002b98SHong Zhang         PetscInt gid1 = bcolidx[j] + 1;
139d4002b98SHong Zhang         ierr = PetscTableFind(gid1_lid1,gid1,&lid);CHKERRQ(ierr);
140d4002b98SHong Zhang         lid--;
141d4002b98SHong Zhang         bcolidx[j] = lid;
142d4002b98SHong Zhang       }
143d4002b98SHong Zhang     }
144d4002b98SHong Zhang   }
145d4002b98SHong Zhang   sell->B->cmap->n = sell->B->cmap->N = ec;
146d4002b98SHong Zhang   sell->B->cmap->bs = 1;
147d4002b98SHong Zhang 
148d4002b98SHong Zhang   ierr = PetscLayoutSetUp((sell->B->cmap));CHKERRQ(ierr);
149d4002b98SHong Zhang   ierr = PetscTableDestroy(&gid1_lid1);CHKERRQ(ierr);
150d4002b98SHong Zhang #else
151d4002b98SHong Zhang   /* Make an array as long as the number of columns */
152d4002b98SHong Zhang   ierr = PetscCalloc1(N+1,&indices);CHKERRQ(ierr);
153d4002b98SHong Zhang   /* mark those columns that are in sell->B */
154d4002b98SHong Zhang   for (i=0; i<totalslices; i++) { /* loop over slices */
155d4002b98SHong Zhang     for (j=B->sliidx[i]; j<B->sliidx[i+1]; j++) {
156d4002b98SHong Zhang       isnonzero = (PetscBool)((j-B->sliidx[i])/8 < B->rlen[(i<<3)+(j&0x07)]);
157d4002b98SHong Zhang       if (isnonzero) {
158d4002b98SHong Zhang         if (!indices[bcolidx[j]]) ec++;
159d4002b98SHong Zhang         indices[bcolidx[j]] = 1;
160d4002b98SHong Zhang       }
161d4002b98SHong Zhang     }
162d4002b98SHong Zhang   }
163d4002b98SHong Zhang 
164d4002b98SHong Zhang   /* form array of columns we need */
165d4002b98SHong Zhang   ierr = PetscMalloc1(ec+1,&garray);CHKERRQ(ierr);
166d4002b98SHong Zhang   ec   = 0;
167d4002b98SHong Zhang   for (i=0; i<N; i++) {
168d4002b98SHong Zhang     if (indices[i]) garray[ec++] = i;
169d4002b98SHong Zhang   }
170d4002b98SHong Zhang 
171d4002b98SHong Zhang   /* make indices now point into garray */
172d4002b98SHong Zhang   for (i=0; i<ec; i++) {
173d4002b98SHong Zhang     indices[garray[i]] = i;
174d4002b98SHong Zhang   }
175d4002b98SHong Zhang 
176d4002b98SHong Zhang   /* compact out the extra columns in B */
177d4002b98SHong Zhang   for (i=0; i<totalslices; i++) { /* loop over slices */
178d4002b98SHong Zhang     for (j=B->sliidx[i]; j<B->sliidx[i+1]; j++) {
179d4002b98SHong Zhang       isnonzero = (PetscBool)((j-B->sliidx[i])/8 < B->rlen[(i<<3)+(j&0x07)]);
180d4002b98SHong Zhang       if (isnonzero) bcolidx[j] = indices[bcolidx[j]];
181d4002b98SHong Zhang     }
182d4002b98SHong Zhang   }
183d4002b98SHong Zhang   sell->B->cmap->n = sell->B->cmap->N = ec; /* number of columns that are not all zeros */
184d4002b98SHong Zhang   sell->B->cmap->bs = 1;
185d4002b98SHong Zhang 
186d4002b98SHong Zhang   ierr = PetscLayoutSetUp((sell->B->cmap));CHKERRQ(ierr);
187d4002b98SHong Zhang   ierr = PetscFree(indices);CHKERRQ(ierr);
188d4002b98SHong Zhang #endif
189d4002b98SHong Zhang   /* create local vector that is used to scatter into */
190d4002b98SHong Zhang   ierr = VecCreateSeq(PETSC_COMM_SELF,ec,&sell->lvec);CHKERRQ(ierr);
191d4002b98SHong Zhang   /* create two temporary Index sets for build scatter gather */
192*a3ebf921SJunchao Zhang   ierr = ISCreateGeneral(PETSC_COMM_SELF,ec,garray,PETSC_COPY_VALUES,&from);CHKERRQ(ierr);
193d4002b98SHong Zhang   ierr = ISCreateStride(PETSC_COMM_SELF,ec,0,1,&to);CHKERRQ(ierr);
194d4002b98SHong Zhang 
195d4002b98SHong Zhang   /* create temporary global vector to generate scatter context */
196d4002b98SHong Zhang   /* This does not allocate the array's memory so is efficient */
197d4002b98SHong Zhang   ierr = VecCreateMPIWithArray(PetscObjectComm((PetscObject)mat),1,mat->cmap->n,mat->cmap->N,NULL,&gvec);CHKERRQ(ierr);
198d4002b98SHong Zhang 
199d4002b98SHong Zhang   /* generate the scatter context */
2009448b7f1SJunchao Zhang   ierr = VecScatterCreate(gvec,from,sell->lvec,to,&sell->Mvctx);CHKERRQ(ierr);
201d4002b98SHong Zhang   ierr = PetscLogObjectParent((PetscObject)mat,(PetscObject)sell->Mvctx);CHKERRQ(ierr);
202d4002b98SHong Zhang   ierr = PetscLogObjectParent((PetscObject)mat,(PetscObject)sell->lvec);CHKERRQ(ierr);
203d4002b98SHong Zhang   ierr = PetscLogObjectParent((PetscObject)mat,(PetscObject)from);CHKERRQ(ierr);
204d4002b98SHong Zhang   ierr = PetscLogObjectParent((PetscObject)mat,(PetscObject)to);CHKERRQ(ierr);
205d4002b98SHong Zhang 
206d4002b98SHong Zhang   sell->garray = garray;
207d4002b98SHong Zhang 
208d4002b98SHong Zhang   ierr = PetscLogObjectMemory((PetscObject)mat,(ec+1)*sizeof(PetscInt));CHKERRQ(ierr);
209d4002b98SHong Zhang   ierr = ISDestroy(&from);CHKERRQ(ierr);
210d4002b98SHong Zhang   ierr = ISDestroy(&to);CHKERRQ(ierr);
211d4002b98SHong Zhang   ierr = VecDestroy(&gvec);CHKERRQ(ierr);
212d4002b98SHong Zhang   PetscFunctionReturn(0);
213d4002b98SHong Zhang }
214d4002b98SHong Zhang 
215d4002b98SHong Zhang /*      ugly stuff added for Glenn someday we should fix this up */
216d4002b98SHong Zhang static PetscInt *auglyrmapd = 0,*auglyrmapo = 0; /* mapping from the local ordering to the "diagonal" and "off-diagonal" parts of the local matrix */
217d4002b98SHong Zhang static Vec auglydd          = 0,auglyoo     = 0; /* work vectors used to scale the two parts of the local matrix */
218d4002b98SHong Zhang 
219d4002b98SHong Zhang PetscErrorCode MatMPISELLDiagonalScaleLocalSetUp(Mat inA,Vec scale)
220d4002b98SHong Zhang {
221d4002b98SHong Zhang   Mat_MPISELL    *ina=(Mat_MPISELL*)inA->data; /*access private part of matrix */
222d4002b98SHong Zhang   PetscErrorCode ierr;
223d4002b98SHong Zhang   PetscInt       i,n,nt,cstart,cend,no,*garray=ina->garray,*lindices;
224d4002b98SHong Zhang   PetscInt       *r_rmapd,*r_rmapo;
225d4002b98SHong Zhang 
226d4002b98SHong Zhang   PetscFunctionBegin;
227d4002b98SHong Zhang   ierr = MatGetOwnershipRange(inA,&cstart,&cend);CHKERRQ(ierr);
228d4002b98SHong Zhang   ierr = MatGetSize(ina->A,NULL,&n);CHKERRQ(ierr);
229d4002b98SHong Zhang   ierr = PetscCalloc1(inA->rmap->mapping->n+1,&r_rmapd);CHKERRQ(ierr);
230d4002b98SHong Zhang   nt   = 0;
231d4002b98SHong Zhang   for (i=0; i<inA->rmap->mapping->n; i++) {
232d4002b98SHong Zhang     if (inA->rmap->mapping->indices[i] >= cstart && inA->rmap->mapping->indices[i] < cend) {
233d4002b98SHong Zhang       nt++;
234d4002b98SHong Zhang       r_rmapd[i] = inA->rmap->mapping->indices[i] + 1;
235d4002b98SHong Zhang     }
236d4002b98SHong Zhang   }
237d4002b98SHong Zhang   if (nt != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Hmm nt %D n %D",nt,n);
238d4002b98SHong Zhang   ierr = PetscMalloc1(n+1,&auglyrmapd);CHKERRQ(ierr);
239d4002b98SHong Zhang   for (i=0; i<inA->rmap->mapping->n; i++) {
240d4002b98SHong Zhang     if (r_rmapd[i]) {
241d4002b98SHong Zhang       auglyrmapd[(r_rmapd[i]-1)-cstart] = i;
242d4002b98SHong Zhang     }
243d4002b98SHong Zhang   }
244d4002b98SHong Zhang   ierr = PetscFree(r_rmapd);CHKERRQ(ierr);
245d4002b98SHong Zhang   ierr = VecCreateSeq(PETSC_COMM_SELF,n,&auglydd);CHKERRQ(ierr);
246d4002b98SHong Zhang   ierr = PetscCalloc1(inA->cmap->N+1,&lindices);CHKERRQ(ierr);
247d4002b98SHong Zhang   for (i=0; i<ina->B->cmap->n; i++) {
248d4002b98SHong Zhang     lindices[garray[i]] = i+1;
249d4002b98SHong Zhang   }
250d4002b98SHong Zhang   no   = inA->rmap->mapping->n - nt;
251d4002b98SHong Zhang   ierr = PetscCalloc1(inA->rmap->mapping->n+1,&r_rmapo);CHKERRQ(ierr);
252d4002b98SHong Zhang   nt   = 0;
253d4002b98SHong Zhang   for (i=0; i<inA->rmap->mapping->n; i++) {
254d4002b98SHong Zhang     if (lindices[inA->rmap->mapping->indices[i]]) {
255d4002b98SHong Zhang       nt++;
256d4002b98SHong Zhang       r_rmapo[i] = lindices[inA->rmap->mapping->indices[i]];
257d4002b98SHong Zhang     }
258d4002b98SHong Zhang   }
259d4002b98SHong Zhang   if (nt > no) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Hmm nt %D no %D",nt,n);
260d4002b98SHong Zhang   ierr = PetscFree(lindices);CHKERRQ(ierr);
261d4002b98SHong Zhang   ierr = PetscMalloc1(nt+1,&auglyrmapo);CHKERRQ(ierr);
262d4002b98SHong Zhang   for (i=0; i<inA->rmap->mapping->n; i++) {
263d4002b98SHong Zhang     if (r_rmapo[i]) {
264d4002b98SHong Zhang       auglyrmapo[(r_rmapo[i]-1)] = i;
265d4002b98SHong Zhang     }
266d4002b98SHong Zhang   }
267d4002b98SHong Zhang   ierr = PetscFree(r_rmapo);CHKERRQ(ierr);
268d4002b98SHong Zhang   ierr = VecCreateSeq(PETSC_COMM_SELF,nt,&auglyoo);CHKERRQ(ierr);
269d4002b98SHong Zhang   PetscFunctionReturn(0);
270d4002b98SHong Zhang }
271d4002b98SHong Zhang 
272d4002b98SHong Zhang PetscErrorCode MatDiagonalScaleLocal_MPISELL(Mat A,Vec scale)
273d4002b98SHong Zhang {
274d4002b98SHong Zhang   Mat_MPISELL       *a=(Mat_MPISELL*)A->data; /*access private part of matrix */
275d4002b98SHong Zhang   PetscErrorCode    ierr;
276d4002b98SHong Zhang   PetscInt          n,i;
277d4002b98SHong Zhang   PetscScalar       *d,*o;
278d4002b98SHong Zhang   const PetscScalar *s;
279d4002b98SHong Zhang 
280d4002b98SHong Zhang   PetscFunctionBegin;
281d4002b98SHong Zhang   if (!auglyrmapd) {
282d4002b98SHong Zhang     ierr = MatMPISELLDiagonalScaleLocalSetUp(A,scale);CHKERRQ(ierr);
283d4002b98SHong Zhang   }
284d4002b98SHong Zhang   ierr = VecGetArrayRead(scale,&s);CHKERRQ(ierr);
285d4002b98SHong Zhang   ierr = VecGetLocalSize(auglydd,&n);CHKERRQ(ierr);
286d4002b98SHong Zhang   ierr = VecGetArray(auglydd,&d);CHKERRQ(ierr);
287d4002b98SHong Zhang   for (i=0; i<n; i++) {
288d4002b98SHong Zhang     d[i] = s[auglyrmapd[i]]; /* copy "diagonal" (true local) portion of scale into dd vector */
289d4002b98SHong Zhang   }
290d4002b98SHong Zhang   ierr = VecRestoreArray(auglydd,&d);CHKERRQ(ierr);
291d4002b98SHong Zhang   /* column scale "diagonal" portion of local matrix */
292d4002b98SHong Zhang   ierr = MatDiagonalScale(a->A,NULL,auglydd);CHKERRQ(ierr);
293d4002b98SHong Zhang   ierr = VecGetLocalSize(auglyoo,&n);CHKERRQ(ierr);
294d4002b98SHong Zhang   ierr = VecGetArray(auglyoo,&o);CHKERRQ(ierr);
295d4002b98SHong Zhang   for (i=0; i<n; i++) {
296d4002b98SHong Zhang     o[i] = s[auglyrmapo[i]]; /* copy "off-diagonal" portion of scale into oo vector */
297d4002b98SHong Zhang   }
298d4002b98SHong Zhang   ierr = VecRestoreArrayRead(scale,&s);CHKERRQ(ierr);
299d4002b98SHong Zhang   ierr = VecRestoreArray(auglyoo,&o);CHKERRQ(ierr);
300d4002b98SHong Zhang   /* column scale "off-diagonal" portion of local matrix */
301d4002b98SHong Zhang   ierr = MatDiagonalScale(a->B,NULL,auglyoo);CHKERRQ(ierr);
302d4002b98SHong Zhang   PetscFunctionReturn(0);
303d4002b98SHong Zhang }
304