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