xref: /petsc/src/mat/impls/sell/mpi/mpisell.c (revision d4002b989b2d6051384fadc0d4465c98dea57b78)
1*d4002b98SHong Zhang #include <../src/mat/impls/aij/mpi/mpiaij.h>   /*I "petscmat.h" I*/
2*d4002b98SHong Zhang #include <../src/mat/impls/sell/mpi/mpisell.h>   /*I "petscmat.h" I*/
3*d4002b98SHong Zhang #include <petsc/private/vecimpl.h>
4*d4002b98SHong Zhang #include <petsc/private/isimpl.h>
5*d4002b98SHong Zhang #include <petscblaslapack.h>
6*d4002b98SHong Zhang #include <petscsf.h>
7*d4002b98SHong Zhang 
8*d4002b98SHong Zhang /*MC
9*d4002b98SHong Zhang    MATSELL - MATSELL = "sell" - A matrix type to be used for sparse matrices.
10*d4002b98SHong Zhang 
11*d4002b98SHong Zhang    This matrix type is identical to MATSEQSELL when constructed with a single process communicator,
12*d4002b98SHong Zhang    and MATMPISELL otherwise.  As a result, for single process communicators,
13*d4002b98SHong Zhang   MatSeqSELLSetPreallocation is supported, and similarly MatMPISELLSetPreallocation is supported
14*d4002b98SHong Zhang   for communicators controlling multiple processes.  It is recommended that you call both of
15*d4002b98SHong Zhang   the above preallocation routines for simplicity.
16*d4002b98SHong Zhang 
17*d4002b98SHong Zhang    Options Database Keys:
18*d4002b98SHong Zhang . -mat_type sell - sets the matrix type to "sell" during a call to MatSetFromOptions()
19*d4002b98SHong Zhang 
20*d4002b98SHong Zhang   Developer Notes: Subclasses include MATSELLCUSP, MATSELLCUSPARSE, MATSELLPERM, MATSELLCRL, and also automatically switches over to use inodes when
21*d4002b98SHong Zhang    enough exist.
22*d4002b98SHong Zhang 
23*d4002b98SHong Zhang   Level: beginner
24*d4002b98SHong Zhang 
25*d4002b98SHong Zhang .seealso: MatCreateSELL(), MatCreateSeqSELL(), MATSEQSELL, MATMPISELL
26*d4002b98SHong Zhang M*/
27*d4002b98SHong Zhang 
28*d4002b98SHong Zhang PetscErrorCode MatDiagonalSet_MPISELL(Mat Y,Vec D,InsertMode is)
29*d4002b98SHong Zhang {
30*d4002b98SHong Zhang   PetscErrorCode ierr;
31*d4002b98SHong Zhang   Mat_MPISELL    *sell=(Mat_MPISELL*)Y->data;
32*d4002b98SHong Zhang 
33*d4002b98SHong Zhang   PetscFunctionBegin;
34*d4002b98SHong Zhang   if (Y->assembled && Y->rmap->rstart == Y->cmap->rstart && Y->rmap->rend == Y->cmap->rend) {
35*d4002b98SHong Zhang     ierr = MatDiagonalSet(sell->A,D,is);CHKERRQ(ierr);
36*d4002b98SHong Zhang   } else {
37*d4002b98SHong Zhang     ierr = MatDiagonalSet_Default(Y,D,is);CHKERRQ(ierr);
38*d4002b98SHong Zhang   }
39*d4002b98SHong Zhang   PetscFunctionReturn(0);
40*d4002b98SHong Zhang }
41*d4002b98SHong Zhang 
42*d4002b98SHong Zhang /*
43*d4002b98SHong Zhang   Local utility routine that creates a mapping from the global column
44*d4002b98SHong Zhang number to the local number in the off-diagonal part of the local
45*d4002b98SHong Zhang storage of the matrix.  When PETSC_USE_CTABLE is used this is scalable at
46*d4002b98SHong Zhang a slightly higher hash table cost; without it it is not scalable (each processor
47*d4002b98SHong Zhang has an order N integer array but is fast to acess.
48*d4002b98SHong Zhang */
49*d4002b98SHong Zhang PetscErrorCode MatCreateColmap_MPISELL_Private(Mat mat)
50*d4002b98SHong Zhang {
51*d4002b98SHong Zhang   Mat_MPISELL    *sell=(Mat_MPISELL*)mat->data;
52*d4002b98SHong Zhang   PetscErrorCode ierr;
53*d4002b98SHong Zhang   PetscInt       n=sell->B->cmap->n,i;
54*d4002b98SHong Zhang 
55*d4002b98SHong Zhang   PetscFunctionBegin;
56*d4002b98SHong Zhang   if (!sell->garray) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"MPISELL Matrix was assembled but is missing garray");
57*d4002b98SHong Zhang #if defined(PETSC_USE_CTABLE)
58*d4002b98SHong Zhang   ierr = PetscTableCreate(n,mat->cmap->N+1,&sell->colmap);CHKERRQ(ierr);
59*d4002b98SHong Zhang   for (i=0; i<n; i++) {
60*d4002b98SHong Zhang     ierr = PetscTableAdd(sell->colmap,sell->garray[i]+1,i+1,INSERT_VALUES);CHKERRQ(ierr);
61*d4002b98SHong Zhang   }
62*d4002b98SHong Zhang #else
63*d4002b98SHong Zhang   ierr = PetscCalloc1(mat->cmap->N+1,&sell->colmap);CHKERRQ(ierr);
64*d4002b98SHong Zhang   ierr = PetscLogObjectMemory((PetscObject)mat,(mat->cmap->N+1)*sizeof(PetscInt));CHKERRQ(ierr);
65*d4002b98SHong Zhang   for (i=0; i<n; i++) sell->colmap[sell->garray[i]] = i+1;
66*d4002b98SHong Zhang #endif
67*d4002b98SHong Zhang   PetscFunctionReturn(0);
68*d4002b98SHong Zhang }
69*d4002b98SHong Zhang 
70*d4002b98SHong Zhang #define MatSetValues_SeqSELL_A_Private(row,col,value,addv,orow,ocol) \
71*d4002b98SHong Zhang   { \
72*d4002b98SHong Zhang     if (col <= lastcol1) low1 = 0; \
73*d4002b98SHong Zhang     else                high1 = nrow1; \
74*d4002b98SHong Zhang     lastcol1 = col; \
75*d4002b98SHong Zhang     while (high1-low1 > 5) { \
76*d4002b98SHong Zhang       t = (low1+high1)/2; \
77*d4002b98SHong Zhang       if (*(cp1+8*t) > col) high1 = t; \
78*d4002b98SHong Zhang       else                   low1 = t; \
79*d4002b98SHong Zhang     } \
80*d4002b98SHong Zhang     for (_i=low1; _i<high1; _i++) { \
81*d4002b98SHong Zhang       if (*(cp1+8*_i) > col) break; \
82*d4002b98SHong Zhang       if (*(cp1+8*_i) == col) { \
83*d4002b98SHong Zhang         if (addv == ADD_VALUES) *(vp1+8*_i) += value;   \
84*d4002b98SHong Zhang         else                     *(vp1+8*_i) = value; \
85*d4002b98SHong Zhang         goto a_noinsert; \
86*d4002b98SHong Zhang       } \
87*d4002b98SHong Zhang     }  \
88*d4002b98SHong Zhang     if (value == 0.0 && ignorezeroentries) {low1 = 0; high1 = nrow1;goto a_noinsert;} \
89*d4002b98SHong Zhang     if (nonew == 1) {low1 = 0; high1 = nrow1; goto a_noinsert;} \
90*d4002b98SHong Zhang     if (nonew == -1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero at global row/column (%D, %D) into matrix", orow, ocol); \
91*d4002b98SHong Zhang     MatSeqXSELLReallocateSELL(A,am,1,nrow1,a->sliidx,row/8,row,col,a->colidx,a->val,cp1,vp1,nonew,MatScalar); \
92*d4002b98SHong Zhang     /* shift up all the later entries in this row */ \
93*d4002b98SHong Zhang     for (ii=nrow1-1; ii>=_i; ii--) { \
94*d4002b98SHong Zhang       *(cp1+8*(ii+1)) = *(cp1+8*ii); \
95*d4002b98SHong Zhang       *(vp1+8*(ii+1)) = *(vp1+8*ii); \
96*d4002b98SHong Zhang     } \
97*d4002b98SHong Zhang     *(cp1+8*_i) = col; \
98*d4002b98SHong Zhang     *(vp1+8*_i) = value; \
99*d4002b98SHong Zhang     a->nz++; nrow1++; A->nonzerostate++; \
100*d4002b98SHong Zhang     a_noinsert: ; \
101*d4002b98SHong Zhang     a->rlen[row] = nrow1; \
102*d4002b98SHong Zhang   }
103*d4002b98SHong Zhang 
104*d4002b98SHong Zhang #define MatSetValues_SeqSELL_B_Private(row,col,value,addv,orow,ocol) \
105*d4002b98SHong Zhang   { \
106*d4002b98SHong Zhang     if (col <= lastcol2) low2 = 0; \
107*d4002b98SHong Zhang     else                high2 = nrow2; \
108*d4002b98SHong Zhang     lastcol2 = col; \
109*d4002b98SHong Zhang     while (high2-low2 > 5) { \
110*d4002b98SHong Zhang       t = (low2+high2)/2; \
111*d4002b98SHong Zhang       if (*(cp2+8*t) > col) high2 = t; \
112*d4002b98SHong Zhang       else low2  = t; \
113*d4002b98SHong Zhang     } \
114*d4002b98SHong Zhang     for (_i=low2; _i<high2; _i++) { \
115*d4002b98SHong Zhang       if (*(cp2+8*_i) > col) break; \
116*d4002b98SHong Zhang       if (*(cp2+8*_i) == col) { \
117*d4002b98SHong Zhang         if (addv == ADD_VALUES) *(vp2+8*_i) += value; \
118*d4002b98SHong Zhang         else                     *(vp2+8*_i) = value; \
119*d4002b98SHong Zhang         goto b_noinsert; \
120*d4002b98SHong Zhang       } \
121*d4002b98SHong Zhang     } \
122*d4002b98SHong Zhang     if (value == 0.0 && ignorezeroentries) {low2 = 0; high2 = nrow2; goto b_noinsert;} \
123*d4002b98SHong Zhang     if (nonew == 1) {low2 = 0; high2 = nrow2; goto b_noinsert;} \
124*d4002b98SHong Zhang     if (nonew == -1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero at global row/column (%D, %D) into matrix", orow, ocol); \
125*d4002b98SHong Zhang     MatSeqXSELLReallocateSELL(B,bm,1,nrow2,b->sliidx,row/8,row,col,b->colidx,b->val,cp2,vp2,nonew,MatScalar); \
126*d4002b98SHong Zhang     /* shift up all the later entries in this row */ \
127*d4002b98SHong Zhang     for (ii=nrow2-1; ii>=_i; ii--) { \
128*d4002b98SHong Zhang       *(cp2+8*(ii+1)) = *(cp2+8*ii); \
129*d4002b98SHong Zhang       *(vp2+8*(ii+1)) = *(vp2+8*ii); \
130*d4002b98SHong Zhang     } \
131*d4002b98SHong Zhang     *(cp2+8*_i) = col; \
132*d4002b98SHong Zhang     *(vp2+8*_i) = value; \
133*d4002b98SHong Zhang     b->nz++; nrow2++; B->nonzerostate++; \
134*d4002b98SHong Zhang     b_noinsert: ; \
135*d4002b98SHong Zhang     b->rlen[row] = nrow2; \
136*d4002b98SHong Zhang   }
137*d4002b98SHong Zhang 
138*d4002b98SHong Zhang PetscErrorCode MatSetValues_MPISELL(Mat mat,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode addv)
139*d4002b98SHong Zhang {
140*d4002b98SHong Zhang   Mat_MPISELL    *sell=(Mat_MPISELL*)mat->data;
141*d4002b98SHong Zhang   PetscScalar    value;
142*d4002b98SHong Zhang   PetscErrorCode ierr;
143*d4002b98SHong Zhang   PetscInt       i,j,rstart=mat->rmap->rstart,rend=mat->rmap->rend,shift1,shift2;
144*d4002b98SHong Zhang   PetscInt       cstart=mat->cmap->rstart,cend=mat->cmap->rend,row,col;
145*d4002b98SHong Zhang   PetscBool      roworiented=sell->roworiented;
146*d4002b98SHong Zhang 
147*d4002b98SHong Zhang   /* Some Variables required in the macro */
148*d4002b98SHong Zhang   Mat            A=sell->A;
149*d4002b98SHong Zhang   Mat_SeqSELL    *a=(Mat_SeqSELL*)A->data;
150*d4002b98SHong Zhang   PetscBool      ignorezeroentries=a->ignorezeroentries,found;
151*d4002b98SHong Zhang   Mat            B=sell->B;
152*d4002b98SHong Zhang   Mat_SeqSELL    *b=(Mat_SeqSELL*)B->data;
153*d4002b98SHong Zhang   PetscInt       *cp1,*cp2,ii,_i,nrow1,nrow2,low1,high1,low2,high2,t,lastcol1,lastcol2;
154*d4002b98SHong Zhang   MatScalar      *vp1,*vp2;
155*d4002b98SHong Zhang 
156*d4002b98SHong Zhang   PetscFunctionBegin;
157*d4002b98SHong Zhang   for (i=0; i<m; i++) {
158*d4002b98SHong Zhang     if (im[i] < 0) continue;
159*d4002b98SHong Zhang #if defined(PETSC_USE_DEBUG)
160*d4002b98SHong Zhang     if (im[i] >= mat->rmap->N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",im[i],mat->rmap->N-1);
161*d4002b98SHong Zhang #endif
162*d4002b98SHong Zhang     if (im[i] >= rstart && im[i] < rend) {
163*d4002b98SHong Zhang       row      = im[i] - rstart;
164*d4002b98SHong Zhang       lastcol1 = -1;
165*d4002b98SHong Zhang       shift1   = a->sliidx[row>>3]+(row&0x07); /* starting index of the row */
166*d4002b98SHong Zhang       cp1      = a->colidx+shift1;
167*d4002b98SHong Zhang       vp1      = a->val+shift1;
168*d4002b98SHong Zhang       nrow1    = a->rlen[row];
169*d4002b98SHong Zhang       low1     = 0;
170*d4002b98SHong Zhang       high1    = nrow1;
171*d4002b98SHong Zhang       lastcol2 = -1;
172*d4002b98SHong Zhang       shift2   = b->sliidx[row>>3]+(row&0x07); /* starting index of the row */
173*d4002b98SHong Zhang       cp2      = b->colidx+shift2;
174*d4002b98SHong Zhang       vp2      = b->val+shift2;
175*d4002b98SHong Zhang       nrow2    = b->rlen[row];
176*d4002b98SHong Zhang       low2     = 0;
177*d4002b98SHong Zhang       high2    = nrow2;
178*d4002b98SHong Zhang 
179*d4002b98SHong Zhang       for (j=0; j<n; j++) {
180*d4002b98SHong Zhang         if (roworiented) value = v[i*n+j];
181*d4002b98SHong Zhang         else             value = v[i+j*m];
182*d4002b98SHong Zhang         if (ignorezeroentries && value == 0.0 && (addv == ADD_VALUES)) continue;
183*d4002b98SHong Zhang         if (in[j] >= cstart && in[j] < cend) {
184*d4002b98SHong Zhang           col   = in[j] - cstart;
185*d4002b98SHong Zhang           MatSetValue_SeqSELL_Private(A,row,col,value,addv,im[i],in[j],cp1,vp1,lastcol1,low1,high1); /* set one value */
186*d4002b98SHong Zhang         } else if (in[j] < 0) continue;
187*d4002b98SHong Zhang #if defined(PETSC_USE_DEBUG)
188*d4002b98SHong Zhang         else if (in[j] >= mat->cmap->N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",in[j],mat->cmap->N-1);
189*d4002b98SHong Zhang #endif
190*d4002b98SHong Zhang         else {
191*d4002b98SHong Zhang           if (mat->was_assembled) {
192*d4002b98SHong Zhang             if (!sell->colmap) {
193*d4002b98SHong Zhang               ierr = MatCreateColmap_MPISELL_Private(mat);CHKERRQ(ierr);
194*d4002b98SHong Zhang             }
195*d4002b98SHong Zhang #if defined(PETSC_USE_CTABLE)
196*d4002b98SHong Zhang             ierr = PetscTableFind(sell->colmap,in[j]+1,&col);CHKERRQ(ierr);
197*d4002b98SHong Zhang             col--;
198*d4002b98SHong Zhang #else
199*d4002b98SHong Zhang             col = sell->colmap[in[j]] - 1;
200*d4002b98SHong Zhang #endif
201*d4002b98SHong Zhang             if (col < 0 && !((Mat_SeqSELL*)(sell->B->data))->nonew) {
202*d4002b98SHong Zhang               ierr   = MatDisAssemble_MPISELL(mat);CHKERRQ(ierr);
203*d4002b98SHong Zhang               col    = in[j];
204*d4002b98SHong Zhang               /* Reinitialize the variables required by MatSetValues_SeqSELL_B_Private() */
205*d4002b98SHong Zhang               B      = sell->B;
206*d4002b98SHong Zhang               b      = (Mat_SeqSELL*)B->data;
207*d4002b98SHong Zhang               shift2 = b->sliidx[row>>3]+(row&0x07); /* starting index of the row */
208*d4002b98SHong Zhang               cp2    = b->colidx+shift2;
209*d4002b98SHong Zhang               vp2    = b->val+shift2;
210*d4002b98SHong Zhang               nrow2  = b->rlen[row];
211*d4002b98SHong Zhang               low2   = 0;
212*d4002b98SHong Zhang               high2  = nrow2;
213*d4002b98SHong Zhang             } else if (col < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero at global row/column (%D, %D) into matrix", im[i], in[j]);
214*d4002b98SHong Zhang           } else col = in[j];
215*d4002b98SHong Zhang           MatSetValue_SeqSELL_Private(B,row,col,value,addv,im[i],in[j],cp2,vp2,lastcol2,low2,high2); /* set one value */
216*d4002b98SHong Zhang         }
217*d4002b98SHong Zhang       }
218*d4002b98SHong Zhang     } else {
219*d4002b98SHong Zhang       if (mat->nooffprocentries) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Setting off process row %D even though MatSetOption(,MAT_NO_OFF_PROC_ENTRIES,PETSC_TRUE) was set",im[i]);
220*d4002b98SHong Zhang       if (!sell->donotstash) {
221*d4002b98SHong Zhang         mat->assembled = PETSC_FALSE;
222*d4002b98SHong Zhang         if (roworiented) {
223*d4002b98SHong Zhang           ierr = MatStashValuesRow_Private(&mat->stash,im[i],n,in,v+i*n,(PetscBool)(ignorezeroentries && (addv == ADD_VALUES)));CHKERRQ(ierr);
224*d4002b98SHong Zhang         } else {
225*d4002b98SHong Zhang           ierr = MatStashValuesCol_Private(&mat->stash,im[i],n,in,v+i,m,(PetscBool)(ignorezeroentries && (addv == ADD_VALUES)));CHKERRQ(ierr);
226*d4002b98SHong Zhang         }
227*d4002b98SHong Zhang       }
228*d4002b98SHong Zhang     }
229*d4002b98SHong Zhang   }
230*d4002b98SHong Zhang   PetscFunctionReturn(0);
231*d4002b98SHong Zhang }
232*d4002b98SHong Zhang 
233*d4002b98SHong Zhang PetscErrorCode MatGetValues_MPISELL(Mat mat,PetscInt m,const PetscInt idxm[],PetscInt n,const PetscInt idxn[],PetscScalar v[])
234*d4002b98SHong Zhang {
235*d4002b98SHong Zhang   Mat_MPISELL    *sell=(Mat_MPISELL*)mat->data;
236*d4002b98SHong Zhang   PetscErrorCode ierr;
237*d4002b98SHong Zhang   PetscInt       i,j,rstart=mat->rmap->rstart,rend=mat->rmap->rend;
238*d4002b98SHong Zhang   PetscInt       cstart=mat->cmap->rstart,cend=mat->cmap->rend,row,col;
239*d4002b98SHong Zhang 
240*d4002b98SHong Zhang   PetscFunctionBegin;
241*d4002b98SHong Zhang   for (i=0; i<m; i++) {
242*d4002b98SHong Zhang     if (idxm[i] < 0) continue; /* SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative row: %D",idxm[i]);*/
243*d4002b98SHong Zhang     if (idxm[i] >= mat->rmap->N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",idxm[i],mat->rmap->N-1);
244*d4002b98SHong Zhang     if (idxm[i] >= rstart && idxm[i] < rend) {
245*d4002b98SHong Zhang       row = idxm[i] - rstart;
246*d4002b98SHong Zhang       for (j=0; j<n; j++) {
247*d4002b98SHong Zhang         if (idxn[j] < 0) continue; /* SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column: %D",idxn[j]); */
248*d4002b98SHong Zhang         if (idxn[j] >= mat->cmap->N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",idxn[j],mat->cmap->N-1);
249*d4002b98SHong Zhang         if (idxn[j] >= cstart && idxn[j] < cend) {
250*d4002b98SHong Zhang           col  = idxn[j] - cstart;
251*d4002b98SHong Zhang           ierr = MatGetValues(sell->A,1,&row,1,&col,v+i*n+j);CHKERRQ(ierr);
252*d4002b98SHong Zhang         } else {
253*d4002b98SHong Zhang           if (!sell->colmap) {
254*d4002b98SHong Zhang             ierr = MatCreateColmap_MPISELL_Private(mat);CHKERRQ(ierr);
255*d4002b98SHong Zhang           }
256*d4002b98SHong Zhang #if defined(PETSC_USE_CTABLE)
257*d4002b98SHong Zhang           ierr = PetscTableFind(sell->colmap,idxn[j]+1,&col);CHKERRQ(ierr);
258*d4002b98SHong Zhang           col--;
259*d4002b98SHong Zhang #else
260*d4002b98SHong Zhang           col = sell->colmap[idxn[j]] - 1;
261*d4002b98SHong Zhang #endif
262*d4002b98SHong Zhang           if ((col < 0) || (sell->garray[col] != idxn[j])) *(v+i*n+j) = 0.0;
263*d4002b98SHong Zhang           else {
264*d4002b98SHong Zhang             ierr = MatGetValues(sell->B,1,&row,1,&col,v+i*n+j);CHKERRQ(ierr);
265*d4002b98SHong Zhang           }
266*d4002b98SHong Zhang         }
267*d4002b98SHong Zhang       }
268*d4002b98SHong Zhang     } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only local values currently supported");
269*d4002b98SHong Zhang   }
270*d4002b98SHong Zhang   PetscFunctionReturn(0);
271*d4002b98SHong Zhang }
272*d4002b98SHong Zhang 
273*d4002b98SHong Zhang extern PetscErrorCode MatMultDiagonalBlock_MPISELL(Mat,Vec,Vec);
274*d4002b98SHong Zhang 
275*d4002b98SHong Zhang PetscErrorCode MatAssemblyBegin_MPISELL(Mat mat,MatAssemblyType mode)
276*d4002b98SHong Zhang {
277*d4002b98SHong Zhang   Mat_MPISELL    *sell=(Mat_MPISELL*)mat->data;
278*d4002b98SHong Zhang   PetscErrorCode ierr;
279*d4002b98SHong Zhang   PetscInt       nstash,reallocs;
280*d4002b98SHong Zhang 
281*d4002b98SHong Zhang   PetscFunctionBegin;
282*d4002b98SHong Zhang   if (sell->donotstash || mat->nooffprocentries) PetscFunctionReturn(0);
283*d4002b98SHong Zhang 
284*d4002b98SHong Zhang   ierr = MatStashScatterBegin_Private(mat,&mat->stash,mat->rmap->range);CHKERRQ(ierr);
285*d4002b98SHong Zhang   ierr = MatStashGetInfo_Private(&mat->stash,&nstash,&reallocs);CHKERRQ(ierr);
286*d4002b98SHong Zhang   ierr = PetscInfo2(sell->A,"Stash has %D entries, uses %D mallocs.\n",nstash,reallocs);CHKERRQ(ierr);
287*d4002b98SHong Zhang   PetscFunctionReturn(0);
288*d4002b98SHong Zhang }
289*d4002b98SHong Zhang 
290*d4002b98SHong Zhang PetscErrorCode MatAssemblyEnd_MPISELL(Mat mat,MatAssemblyType mode)
291*d4002b98SHong Zhang {
292*d4002b98SHong Zhang   Mat_MPISELL    *sell=(Mat_MPISELL*)mat->data;
293*d4002b98SHong Zhang   PetscErrorCode ierr;
294*d4002b98SHong Zhang   PetscMPIInt    n;
295*d4002b98SHong Zhang   PetscInt       i,flg;
296*d4002b98SHong Zhang   PetscInt       *row,*col;
297*d4002b98SHong Zhang   PetscScalar    *val;
298*d4002b98SHong Zhang   PetscBool      other_disassembled;
299*d4002b98SHong Zhang   /* do not use 'b = (Mat_SeqSELL*)sell->B->data' as B can be reset in disassembly */
300*d4002b98SHong Zhang   PetscFunctionBegin;
301*d4002b98SHong Zhang   if (!sell->donotstash && !mat->nooffprocentries) {
302*d4002b98SHong Zhang     while (1) {
303*d4002b98SHong Zhang       ierr = MatStashScatterGetMesg_Private(&mat->stash,&n,&row,&col,&val,&flg);CHKERRQ(ierr);
304*d4002b98SHong Zhang       if (!flg) break;
305*d4002b98SHong Zhang 
306*d4002b98SHong Zhang       for (i=0; i<n; i++) { /* assemble one by one */
307*d4002b98SHong Zhang         ierr = MatSetValues_MPISELL(mat,1,row+i,1,col+i,val+i,mat->insertmode);CHKERRQ(ierr);
308*d4002b98SHong Zhang       }
309*d4002b98SHong Zhang     }
310*d4002b98SHong Zhang     ierr = MatStashScatterEnd_Private(&mat->stash);CHKERRQ(ierr);
311*d4002b98SHong Zhang   }
312*d4002b98SHong Zhang   ierr = MatAssemblyBegin(sell->A,mode);CHKERRQ(ierr);
313*d4002b98SHong Zhang   ierr = MatAssemblyEnd(sell->A,mode);CHKERRQ(ierr);
314*d4002b98SHong Zhang 
315*d4002b98SHong Zhang   /*
316*d4002b98SHong Zhang      determine if any processor has disassembled, if so we must
317*d4002b98SHong Zhang      also disassemble ourselfs, in order that we may reassemble.
318*d4002b98SHong Zhang   */
319*d4002b98SHong Zhang   /*
320*d4002b98SHong Zhang      if nonzero structure of submatrix B cannot change then we know that
321*d4002b98SHong Zhang      no processor disassembled thus we can skip this stuff
322*d4002b98SHong Zhang   */
323*d4002b98SHong Zhang   if (!((Mat_SeqSELL*)sell->B->data)->nonew) {
324*d4002b98SHong Zhang     ierr = MPIU_Allreduce(&mat->was_assembled,&other_disassembled,1,MPIU_BOOL,MPI_PROD,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
325*d4002b98SHong Zhang     if (mat->was_assembled && !other_disassembled) {
326*d4002b98SHong Zhang       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"MatDisAssemble not implemented yet\n");
327*d4002b98SHong Zhang       ierr = MatDisAssemble_MPISELL(mat);CHKERRQ(ierr);
328*d4002b98SHong Zhang     }
329*d4002b98SHong Zhang   }
330*d4002b98SHong Zhang   if (!mat->was_assembled && mode == MAT_FINAL_ASSEMBLY) {
331*d4002b98SHong Zhang     ierr = MatSetUpMultiply_MPISELL(mat);CHKERRQ(ierr);
332*d4002b98SHong Zhang   }
333*d4002b98SHong Zhang   /*
334*d4002b98SHong Zhang   ierr = MatSetOption(sell->B,MAT_USE_INODES,PETSC_FALSE);CHKERRQ(ierr);
335*d4002b98SHong Zhang   */
336*d4002b98SHong Zhang   ierr = MatAssemblyBegin(sell->B,mode);CHKERRQ(ierr);
337*d4002b98SHong Zhang   ierr = MatAssemblyEnd(sell->B,mode);CHKERRQ(ierr);
338*d4002b98SHong Zhang   ierr = PetscFree2(sell->rowvalues,sell->rowindices);CHKERRQ(ierr);
339*d4002b98SHong Zhang   sell->rowvalues = 0;
340*d4002b98SHong Zhang   ierr = VecDestroy(&sell->diag);CHKERRQ(ierr);
341*d4002b98SHong Zhang 
342*d4002b98SHong Zhang   /* if no new nonzero locations are allowed in matrix then only set the matrix state the first time through */
343*d4002b98SHong Zhang   if ((!mat->was_assembled && mode == MAT_FINAL_ASSEMBLY) || !((Mat_SeqSELL*)(sell->A->data))->nonew) {
344*d4002b98SHong Zhang     PetscObjectState state = sell->A->nonzerostate + sell->B->nonzerostate;
345*d4002b98SHong Zhang     ierr = MPIU_Allreduce(&state,&mat->nonzerostate,1,MPIU_INT64,MPI_SUM,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
346*d4002b98SHong Zhang   }
347*d4002b98SHong Zhang   PetscFunctionReturn(0);
348*d4002b98SHong Zhang }
349*d4002b98SHong Zhang 
350*d4002b98SHong Zhang PetscErrorCode MatZeroEntries_MPISELL(Mat A)
351*d4002b98SHong Zhang {
352*d4002b98SHong Zhang   Mat_MPISELL    *l=(Mat_MPISELL*)A->data;
353*d4002b98SHong Zhang   PetscErrorCode ierr;
354*d4002b98SHong Zhang 
355*d4002b98SHong Zhang   PetscFunctionBegin;
356*d4002b98SHong Zhang   ierr = MatZeroEntries(l->A);CHKERRQ(ierr);
357*d4002b98SHong Zhang   ierr = MatZeroEntries(l->B);CHKERRQ(ierr);
358*d4002b98SHong Zhang   PetscFunctionReturn(0);
359*d4002b98SHong Zhang }
360*d4002b98SHong Zhang 
361*d4002b98SHong Zhang PetscErrorCode MatMult_MPISELL(Mat A,Vec xx,Vec yy)
362*d4002b98SHong Zhang {
363*d4002b98SHong Zhang   Mat_MPISELL    *a=(Mat_MPISELL*)A->data;
364*d4002b98SHong Zhang   PetscErrorCode ierr;
365*d4002b98SHong Zhang   PetscInt       nt;
366*d4002b98SHong Zhang 
367*d4002b98SHong Zhang   PetscFunctionBegin;
368*d4002b98SHong Zhang   ierr = VecGetLocalSize(xx,&nt);CHKERRQ(ierr);
369*d4002b98SHong Zhang   if (nt != A->cmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Incompatible partition of A (%D) and xx (%D)",A->cmap->n,nt);
370*d4002b98SHong Zhang   ierr = VecScatterBegin(a->Mvctx,xx,a->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
371*d4002b98SHong Zhang   ierr = (*a->A->ops->mult)(a->A,xx,yy);CHKERRQ(ierr);
372*d4002b98SHong Zhang   ierr = VecScatterEnd(a->Mvctx,xx,a->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
373*d4002b98SHong Zhang   ierr = (*a->B->ops->multadd)(a->B,a->lvec,yy,yy);CHKERRQ(ierr);
374*d4002b98SHong Zhang   PetscFunctionReturn(0);
375*d4002b98SHong Zhang }
376*d4002b98SHong Zhang 
377*d4002b98SHong Zhang PetscErrorCode MatMultDiagonalBlock_MPISELL(Mat A,Vec bb,Vec xx)
378*d4002b98SHong Zhang {
379*d4002b98SHong Zhang   Mat_MPISELL    *a=(Mat_MPISELL*)A->data;
380*d4002b98SHong Zhang   PetscErrorCode ierr;
381*d4002b98SHong Zhang 
382*d4002b98SHong Zhang   PetscFunctionBegin;
383*d4002b98SHong Zhang   ierr = MatMultDiagonalBlock(a->A,bb,xx);CHKERRQ(ierr);
384*d4002b98SHong Zhang   PetscFunctionReturn(0);
385*d4002b98SHong Zhang }
386*d4002b98SHong Zhang 
387*d4002b98SHong Zhang PetscErrorCode MatMultAdd_MPISELL(Mat A,Vec xx,Vec yy,Vec zz)
388*d4002b98SHong Zhang {
389*d4002b98SHong Zhang   Mat_MPISELL    *a=(Mat_MPISELL*)A->data;
390*d4002b98SHong Zhang   PetscErrorCode ierr;
391*d4002b98SHong Zhang 
392*d4002b98SHong Zhang   PetscFunctionBegin;
393*d4002b98SHong Zhang   ierr = VecScatterBegin(a->Mvctx,xx,a->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
394*d4002b98SHong Zhang   ierr = (*a->A->ops->multadd)(a->A,xx,yy,zz);CHKERRQ(ierr);
395*d4002b98SHong Zhang   ierr = VecScatterEnd(a->Mvctx,xx,a->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
396*d4002b98SHong Zhang   ierr = (*a->B->ops->multadd)(a->B,a->lvec,zz,zz);CHKERRQ(ierr);
397*d4002b98SHong Zhang   PetscFunctionReturn(0);
398*d4002b98SHong Zhang }
399*d4002b98SHong Zhang 
400*d4002b98SHong Zhang PetscErrorCode MatMultTranspose_MPISELL(Mat A,Vec xx,Vec yy)
401*d4002b98SHong Zhang {
402*d4002b98SHong Zhang   Mat_MPISELL    *a=(Mat_MPISELL*)A->data;
403*d4002b98SHong Zhang   PetscErrorCode ierr;
404*d4002b98SHong Zhang   PetscBool      merged;
405*d4002b98SHong Zhang 
406*d4002b98SHong Zhang   PetscFunctionBegin;
407*d4002b98SHong Zhang   ierr = VecScatterGetMerged(a->Mvctx,&merged);CHKERRQ(ierr);
408*d4002b98SHong Zhang   /* do nondiagonal part */
409*d4002b98SHong Zhang   ierr = (*a->B->ops->multtranspose)(a->B,xx,a->lvec);CHKERRQ(ierr);
410*d4002b98SHong Zhang   if (!merged) {
411*d4002b98SHong Zhang     /* send it on its way */
412*d4002b98SHong Zhang     ierr = VecScatterBegin(a->Mvctx,a->lvec,yy,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
413*d4002b98SHong Zhang     /* do local part */
414*d4002b98SHong Zhang     ierr = (*a->A->ops->multtranspose)(a->A,xx,yy);CHKERRQ(ierr);
415*d4002b98SHong Zhang     /* receive remote parts: note this assumes the values are not actually */
416*d4002b98SHong Zhang     /* added in yy until the next line, */
417*d4002b98SHong Zhang     ierr = VecScatterEnd(a->Mvctx,a->lvec,yy,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
418*d4002b98SHong Zhang   } else {
419*d4002b98SHong Zhang     /* do local part */
420*d4002b98SHong Zhang     ierr = (*a->A->ops->multtranspose)(a->A,xx,yy);CHKERRQ(ierr);
421*d4002b98SHong Zhang     /* send it on its way */
422*d4002b98SHong Zhang     ierr = VecScatterBegin(a->Mvctx,a->lvec,yy,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
423*d4002b98SHong Zhang     /* values actually were received in the Begin() but we need to call this nop */
424*d4002b98SHong Zhang     ierr = VecScatterEnd(a->Mvctx,a->lvec,yy,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
425*d4002b98SHong Zhang   }
426*d4002b98SHong Zhang   PetscFunctionReturn(0);
427*d4002b98SHong Zhang }
428*d4002b98SHong Zhang 
429*d4002b98SHong Zhang PetscErrorCode MatIsTranspose_MPISELL(Mat Amat,Mat Bmat,PetscReal tol,PetscBool *f)
430*d4002b98SHong Zhang {
431*d4002b98SHong Zhang   MPI_Comm       comm;
432*d4002b98SHong Zhang   Mat_MPISELL    *Asell=(Mat_MPISELL*)Amat->data,*Bsell;
433*d4002b98SHong Zhang   Mat            Adia=Asell->A,Bdia,Aoff,Boff,*Aoffs,*Boffs;
434*d4002b98SHong Zhang   IS             Me,Notme;
435*d4002b98SHong Zhang   PetscErrorCode ierr;
436*d4002b98SHong Zhang   PetscInt       M,N,first,last,*notme,i;
437*d4002b98SHong Zhang   PetscMPIInt    size;
438*d4002b98SHong Zhang 
439*d4002b98SHong Zhang   PetscFunctionBegin;
440*d4002b98SHong Zhang   /* Easy test: symmetric diagonal block */
441*d4002b98SHong Zhang   Bsell = (Mat_MPISELL*)Bmat->data; Bdia = Bsell->A;
442*d4002b98SHong Zhang   ierr = MatIsTranspose(Adia,Bdia,tol,f);CHKERRQ(ierr);
443*d4002b98SHong Zhang   if (!*f) PetscFunctionReturn(0);
444*d4002b98SHong Zhang   ierr = PetscObjectGetComm((PetscObject)Amat,&comm);CHKERRQ(ierr);
445*d4002b98SHong Zhang   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
446*d4002b98SHong Zhang   if (size == 1) PetscFunctionReturn(0);
447*d4002b98SHong Zhang 
448*d4002b98SHong Zhang   /* Hard test: off-diagonal block. This takes a MatCreateSubMatrix. */
449*d4002b98SHong Zhang   ierr = MatGetSize(Amat,&M,&N);CHKERRQ(ierr);
450*d4002b98SHong Zhang   ierr = MatGetOwnershipRange(Amat,&first,&last);CHKERRQ(ierr);
451*d4002b98SHong Zhang   ierr = PetscMalloc1(N-last+first,&notme);CHKERRQ(ierr);
452*d4002b98SHong Zhang   for (i=0; i<first; i++) notme[i] = i;
453*d4002b98SHong Zhang   for (i=last; i<M; i++) notme[i-last+first] = i;
454*d4002b98SHong Zhang   ierr = ISCreateGeneral(MPI_COMM_SELF,N-last+first,notme,PETSC_COPY_VALUES,&Notme);CHKERRQ(ierr);
455*d4002b98SHong Zhang   ierr = ISCreateStride(MPI_COMM_SELF,last-first,first,1,&Me);CHKERRQ(ierr);
456*d4002b98SHong Zhang   ierr = MatCreateSubMatrices(Amat,1,&Me,&Notme,MAT_INITIAL_MATRIX,&Aoffs);CHKERRQ(ierr);
457*d4002b98SHong Zhang   Aoff = Aoffs[0];
458*d4002b98SHong Zhang   ierr = MatCreateSubMatrices(Bmat,1,&Notme,&Me,MAT_INITIAL_MATRIX,&Boffs);CHKERRQ(ierr);
459*d4002b98SHong Zhang   Boff = Boffs[0];
460*d4002b98SHong Zhang   ierr = MatIsTranspose(Aoff,Boff,tol,f);CHKERRQ(ierr);
461*d4002b98SHong Zhang   ierr = MatDestroyMatrices(1,&Aoffs);CHKERRQ(ierr);
462*d4002b98SHong Zhang   ierr = MatDestroyMatrices(1,&Boffs);CHKERRQ(ierr);
463*d4002b98SHong Zhang   ierr = ISDestroy(&Me);CHKERRQ(ierr);
464*d4002b98SHong Zhang   ierr = ISDestroy(&Notme);CHKERRQ(ierr);
465*d4002b98SHong Zhang   ierr = PetscFree(notme);CHKERRQ(ierr);
466*d4002b98SHong Zhang   PetscFunctionReturn(0);
467*d4002b98SHong Zhang }
468*d4002b98SHong Zhang 
469*d4002b98SHong Zhang PetscErrorCode MatMultTransposeAdd_MPISELL(Mat A,Vec xx,Vec yy,Vec zz)
470*d4002b98SHong Zhang {
471*d4002b98SHong Zhang   Mat_MPISELL    *a=(Mat_MPISELL*)A->data;
472*d4002b98SHong Zhang   PetscErrorCode ierr;
473*d4002b98SHong Zhang 
474*d4002b98SHong Zhang   PetscFunctionBegin;
475*d4002b98SHong Zhang   /* do nondiagonal part */
476*d4002b98SHong Zhang   ierr = (*a->B->ops->multtranspose)(a->B,xx,a->lvec);CHKERRQ(ierr);
477*d4002b98SHong Zhang   /* send it on its way */
478*d4002b98SHong Zhang   ierr = VecScatterBegin(a->Mvctx,a->lvec,zz,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
479*d4002b98SHong Zhang   /* do local part */
480*d4002b98SHong Zhang   ierr = (*a->A->ops->multtransposeadd)(a->A,xx,yy,zz);CHKERRQ(ierr);
481*d4002b98SHong Zhang   /* receive remote parts */
482*d4002b98SHong Zhang   ierr = VecScatterEnd(a->Mvctx,a->lvec,zz,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
483*d4002b98SHong Zhang   PetscFunctionReturn(0);
484*d4002b98SHong Zhang }
485*d4002b98SHong Zhang 
486*d4002b98SHong Zhang /*
487*d4002b98SHong Zhang   This only works correctly for square matrices where the subblock A->A is the
488*d4002b98SHong Zhang    diagonal block
489*d4002b98SHong Zhang */
490*d4002b98SHong Zhang PetscErrorCode MatGetDiagonal_MPISELL(Mat A,Vec v)
491*d4002b98SHong Zhang {
492*d4002b98SHong Zhang   PetscErrorCode ierr;
493*d4002b98SHong Zhang   Mat_MPISELL    *a=(Mat_MPISELL*)A->data;
494*d4002b98SHong Zhang 
495*d4002b98SHong Zhang   PetscFunctionBegin;
496*d4002b98SHong Zhang   if (A->rmap->N != A->cmap->N) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Supports only square matrix where A->A is diag block");
497*d4002b98SHong Zhang   if (A->rmap->rstart != A->cmap->rstart || A->rmap->rend != A->cmap->rend) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"row partition must equal col partition");
498*d4002b98SHong Zhang   ierr = MatGetDiagonal(a->A,v);CHKERRQ(ierr);
499*d4002b98SHong Zhang   PetscFunctionReturn(0);
500*d4002b98SHong Zhang }
501*d4002b98SHong Zhang 
502*d4002b98SHong Zhang PetscErrorCode MatScale_MPISELL(Mat A,PetscScalar aa)
503*d4002b98SHong Zhang {
504*d4002b98SHong Zhang   Mat_MPISELL    *a=(Mat_MPISELL*)A->data;
505*d4002b98SHong Zhang   PetscErrorCode ierr;
506*d4002b98SHong Zhang 
507*d4002b98SHong Zhang   PetscFunctionBegin;
508*d4002b98SHong Zhang   ierr = MatScale(a->A,aa);CHKERRQ(ierr);
509*d4002b98SHong Zhang   ierr = MatScale(a->B,aa);CHKERRQ(ierr);
510*d4002b98SHong Zhang   PetscFunctionReturn(0);
511*d4002b98SHong Zhang }
512*d4002b98SHong Zhang 
513*d4002b98SHong Zhang PetscErrorCode MatDestroy_MPISELL(Mat mat)
514*d4002b98SHong Zhang {
515*d4002b98SHong Zhang   Mat_MPISELL    *sell=(Mat_MPISELL*)mat->data;
516*d4002b98SHong Zhang   PetscErrorCode ierr;
517*d4002b98SHong Zhang 
518*d4002b98SHong Zhang   PetscFunctionBegin;
519*d4002b98SHong Zhang #if defined(PETSC_USE_LOG)
520*d4002b98SHong Zhang   PetscLogObjectState((PetscObject)mat,"Rows=%D, Cols=%D",mat->rmap->N,mat->cmap->N);
521*d4002b98SHong Zhang #endif
522*d4002b98SHong Zhang   ierr = MatStashDestroy_Private(&mat->stash);CHKERRQ(ierr);
523*d4002b98SHong Zhang   ierr = VecDestroy(&sell->diag);CHKERRQ(ierr);
524*d4002b98SHong Zhang   ierr = MatDestroy(&sell->A);CHKERRQ(ierr);
525*d4002b98SHong Zhang   ierr = MatDestroy(&sell->B);CHKERRQ(ierr);
526*d4002b98SHong Zhang #if defined(PETSC_USE_CTABLE)
527*d4002b98SHong Zhang   ierr = PetscTableDestroy(&sell->colmap);CHKERRQ(ierr);
528*d4002b98SHong Zhang #else
529*d4002b98SHong Zhang   ierr = PetscFree(sell->colmap);CHKERRQ(ierr);
530*d4002b98SHong Zhang #endif
531*d4002b98SHong Zhang   ierr = PetscFree(sell->garray);CHKERRQ(ierr);
532*d4002b98SHong Zhang   ierr = VecDestroy(&sell->lvec);CHKERRQ(ierr);
533*d4002b98SHong Zhang   ierr = VecScatterDestroy(&sell->Mvctx);CHKERRQ(ierr);
534*d4002b98SHong Zhang   ierr = PetscFree2(sell->rowvalues,sell->rowindices);CHKERRQ(ierr);
535*d4002b98SHong Zhang   ierr = PetscFree(sell->ld);CHKERRQ(ierr);
536*d4002b98SHong Zhang   ierr = PetscFree(mat->data);CHKERRQ(ierr);
537*d4002b98SHong Zhang 
538*d4002b98SHong Zhang   ierr = PetscObjectChangeTypeName((PetscObject)mat,0);CHKERRQ(ierr);
539*d4002b98SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatStoreValues_C",NULL);CHKERRQ(ierr);
540*d4002b98SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatRetrieveValues_C",NULL);CHKERRQ(ierr);
541*d4002b98SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatIsTranspose_C",NULL);CHKERRQ(ierr);
542*d4002b98SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatMPISELLSetPreallocation_C",NULL);CHKERRQ(ierr);
543*d4002b98SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatConvert_mpisell_mpiaij_C",NULL);CHKERRQ(ierr);
544*d4002b98SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDiagonalScaleLocal_C",NULL);CHKERRQ(ierr);
545*d4002b98SHong Zhang   PetscFunctionReturn(0);
546*d4002b98SHong Zhang }
547*d4002b98SHong Zhang 
548*d4002b98SHong Zhang #include <petscdraw.h>
549*d4002b98SHong Zhang PetscErrorCode MatView_MPISELL_ASCIIorDraworSocket(Mat mat,PetscViewer viewer)
550*d4002b98SHong Zhang {
551*d4002b98SHong Zhang   Mat_MPISELL       *sell=(Mat_MPISELL*)mat->data;
552*d4002b98SHong Zhang   PetscErrorCode    ierr;
553*d4002b98SHong Zhang   PetscMPIInt       rank=sell->rank,size=sell->size;
554*d4002b98SHong Zhang   PetscBool         isdraw,iascii,isbinary;
555*d4002b98SHong Zhang   PetscViewer       sviewer;
556*d4002b98SHong Zhang   PetscViewerFormat format;
557*d4002b98SHong Zhang 
558*d4002b98SHong Zhang   PetscFunctionBegin;
559*d4002b98SHong Zhang   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
560*d4002b98SHong Zhang   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
561*d4002b98SHong Zhang   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
562*d4002b98SHong Zhang   if (iascii) {
563*d4002b98SHong Zhang     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
564*d4002b98SHong Zhang     if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
565*d4002b98SHong Zhang       MatInfo   info;
566*d4002b98SHong Zhang       PetscBool inodes;
567*d4002b98SHong Zhang 
568*d4002b98SHong Zhang       ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr);
569*d4002b98SHong Zhang       ierr = MatGetInfo(mat,MAT_LOCAL,&info);CHKERRQ(ierr);
570*d4002b98SHong Zhang       ierr = MatInodeGetInodeSizes(sell->A,NULL,(PetscInt**)&inodes,NULL);CHKERRQ(ierr);
571*d4002b98SHong Zhang       ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr);
572*d4002b98SHong Zhang       if (!inodes) {
573*d4002b98SHong Zhang         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] Local rows %D nz %D nz alloced %D mem %D, not using I-node routines\n",
574*d4002b98SHong Zhang                                                   rank,mat->rmap->n,(PetscInt)info.nz_used,(PetscInt)info.nz_allocated,(PetscInt)info.memory);CHKERRQ(ierr);
575*d4002b98SHong Zhang       } else {
576*d4002b98SHong Zhang         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] Local rows %D nz %D nz alloced %D mem %D, using I-node routines\n",
577*d4002b98SHong Zhang                                                   rank,mat->rmap->n,(PetscInt)info.nz_used,(PetscInt)info.nz_allocated,(PetscInt)info.memory);CHKERRQ(ierr);
578*d4002b98SHong Zhang       }
579*d4002b98SHong Zhang       ierr = MatGetInfo(sell->A,MAT_LOCAL,&info);CHKERRQ(ierr);
580*d4002b98SHong Zhang       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] on-diagonal part: nz %D \n",rank,(PetscInt)info.nz_used);CHKERRQ(ierr);
581*d4002b98SHong Zhang       ierr = MatGetInfo(sell->B,MAT_LOCAL,&info);CHKERRQ(ierr);
582*d4002b98SHong Zhang       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] off-diagonal part: nz %D \n",rank,(PetscInt)info.nz_used);CHKERRQ(ierr);
583*d4002b98SHong Zhang       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
584*d4002b98SHong Zhang       ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr);
585*d4002b98SHong Zhang       ierr = PetscViewerASCIIPrintf(viewer,"Information on VecScatter used in matrix-vector product: \n");CHKERRQ(ierr);
586*d4002b98SHong Zhang       ierr = VecScatterView(sell->Mvctx,viewer);CHKERRQ(ierr);
587*d4002b98SHong Zhang       PetscFunctionReturn(0);
588*d4002b98SHong Zhang     } else if (format == PETSC_VIEWER_ASCII_INFO) {
589*d4002b98SHong Zhang       PetscInt inodecount,inodelimit,*inodes;
590*d4002b98SHong Zhang       ierr = MatInodeGetInodeSizes(sell->A,&inodecount,&inodes,&inodelimit);CHKERRQ(ierr);
591*d4002b98SHong Zhang       if (inodes) {
592*d4002b98SHong Zhang         ierr = PetscViewerASCIIPrintf(viewer,"using I-node (on process 0) routines: found %D nodes, limit used is %D\n",inodecount,inodelimit);CHKERRQ(ierr);
593*d4002b98SHong Zhang       } else {
594*d4002b98SHong Zhang         ierr = PetscViewerASCIIPrintf(viewer,"not using I-node (on process 0) routines\n");CHKERRQ(ierr);
595*d4002b98SHong Zhang       }
596*d4002b98SHong Zhang       PetscFunctionReturn(0);
597*d4002b98SHong Zhang     } else if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) {
598*d4002b98SHong Zhang       PetscFunctionReturn(0);
599*d4002b98SHong Zhang     }
600*d4002b98SHong Zhang   } else if (isbinary) {
601*d4002b98SHong Zhang     if (size == 1) {
602*d4002b98SHong Zhang       ierr = PetscObjectSetName((PetscObject)sell->A,((PetscObject)mat)->name);CHKERRQ(ierr);
603*d4002b98SHong Zhang       ierr = MatView(sell->A,viewer);CHKERRQ(ierr);
604*d4002b98SHong Zhang     } else {
605*d4002b98SHong Zhang       /* ierr = MatView_MPISELL_Binary(mat,viewer);CHKERRQ(ierr); */
606*d4002b98SHong Zhang     }
607*d4002b98SHong Zhang     PetscFunctionReturn(0);
608*d4002b98SHong Zhang   } else if (isdraw) {
609*d4002b98SHong Zhang     PetscDraw draw;
610*d4002b98SHong Zhang     PetscBool isnull;
611*d4002b98SHong Zhang     ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
612*d4002b98SHong Zhang     ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr);
613*d4002b98SHong Zhang     if (isnull) PetscFunctionReturn(0);
614*d4002b98SHong Zhang   }
615*d4002b98SHong Zhang 
616*d4002b98SHong Zhang   {
617*d4002b98SHong Zhang     /* assemble the entire matrix onto first processor. */
618*d4002b98SHong Zhang     Mat         A;
619*d4002b98SHong Zhang     Mat_SeqSELL *Aloc;
620*d4002b98SHong Zhang     PetscInt    M=mat->rmap->N,N=mat->cmap->N,*acolidx,row,col,i,j;
621*d4002b98SHong Zhang     MatScalar   *aval;
622*d4002b98SHong Zhang     PetscBool   isnonzero;
623*d4002b98SHong Zhang 
624*d4002b98SHong Zhang     ierr = MatCreate(PetscObjectComm((PetscObject)mat),&A);CHKERRQ(ierr);
625*d4002b98SHong Zhang     if (!rank) {
626*d4002b98SHong Zhang       ierr = MatSetSizes(A,M,N,M,N);CHKERRQ(ierr);
627*d4002b98SHong Zhang     } else {
628*d4002b98SHong Zhang       ierr = MatSetSizes(A,0,0,M,N);CHKERRQ(ierr);
629*d4002b98SHong Zhang     }
630*d4002b98SHong Zhang     /* This is just a temporary matrix, so explicitly using MATMPISELL is probably best */
631*d4002b98SHong Zhang     ierr = MatSetType(A,MATMPISELL);CHKERRQ(ierr);
632*d4002b98SHong Zhang     ierr = MatMPISELLSetPreallocation(A,0,NULL,0,NULL);CHKERRQ(ierr);
633*d4002b98SHong Zhang     ierr = MatSetOption(A,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
634*d4002b98SHong Zhang     ierr = PetscLogObjectParent((PetscObject)mat,(PetscObject)A);CHKERRQ(ierr);
635*d4002b98SHong Zhang 
636*d4002b98SHong Zhang     /* copy over the A part */
637*d4002b98SHong Zhang     Aloc = (Mat_SeqSELL*)sell->A->data;
638*d4002b98SHong Zhang     acolidx = Aloc->colidx; aval = Aloc->val;
639*d4002b98SHong Zhang     for (i=0; i<Aloc->totalslices; i++) { /* loop over slices */
640*d4002b98SHong Zhang       for (j=Aloc->sliidx[i]; j<Aloc->sliidx[i+1]; j++) {
641*d4002b98SHong Zhang         isnonzero = (PetscBool)((j-Aloc->sliidx[i])/8 < Aloc->rlen[(i<<3)+(j&0x07)]);
642*d4002b98SHong Zhang         if (isnonzero) { /* check the mask bit */
643*d4002b98SHong Zhang           row  = (i<<3)+(j&0x07) + mat->rmap->rstart; /* i<<3 is the starting row of this slice */
644*d4002b98SHong Zhang           col  = *acolidx + mat->rmap->rstart;
645*d4002b98SHong Zhang           ierr = MatSetValues(A,1,&row,1,&col,aval,INSERT_VALUES);CHKERRQ(ierr);
646*d4002b98SHong Zhang         }
647*d4002b98SHong Zhang         aval++; acolidx++;
648*d4002b98SHong Zhang       }
649*d4002b98SHong Zhang     }
650*d4002b98SHong Zhang 
651*d4002b98SHong Zhang     /* copy over the B part */
652*d4002b98SHong Zhang     Aloc = (Mat_SeqSELL*)sell->B->data;
653*d4002b98SHong Zhang     acolidx = Aloc->colidx; aval = Aloc->val;
654*d4002b98SHong Zhang     for (i=0; i<Aloc->totalslices; i++) {
655*d4002b98SHong Zhang       for (j=Aloc->sliidx[i]; j<Aloc->sliidx[i+1]; j++) {
656*d4002b98SHong Zhang         isnonzero = (PetscBool)((j-Aloc->sliidx[i])/8 < Aloc->rlen[(i<<3)+(j&0x07)]);
657*d4002b98SHong Zhang         if (isnonzero) {
658*d4002b98SHong Zhang           row  = (i<<3)+(j&0x07) + mat->rmap->rstart;
659*d4002b98SHong Zhang           col  = sell->garray[*acolidx];
660*d4002b98SHong Zhang           ierr = MatSetValues(A,1,&row,1,&col,aval,INSERT_VALUES);CHKERRQ(ierr);
661*d4002b98SHong Zhang         }
662*d4002b98SHong Zhang         aval++; acolidx++;
663*d4002b98SHong Zhang       }
664*d4002b98SHong Zhang     }
665*d4002b98SHong Zhang 
666*d4002b98SHong Zhang     ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
667*d4002b98SHong Zhang     ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
668*d4002b98SHong Zhang     /*
669*d4002b98SHong Zhang        Everyone has to call to draw the matrix since the graphics waits are
670*d4002b98SHong Zhang        synchronized across all processors that share the PetscDraw object
671*d4002b98SHong Zhang     */
672*d4002b98SHong Zhang     ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
673*d4002b98SHong Zhang     if (!rank) {
674*d4002b98SHong Zhang       ierr = PetscObjectSetName((PetscObject)((Mat_MPISELL*)(A->data))->A,((PetscObject)mat)->name);CHKERRQ(ierr);
675*d4002b98SHong Zhang       ierr = MatView_SeqSELL(((Mat_MPISELL*)(A->data))->A,sviewer);CHKERRQ(ierr);
676*d4002b98SHong Zhang     }
677*d4002b98SHong Zhang     ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
678*d4002b98SHong Zhang     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
679*d4002b98SHong Zhang     ierr = MatDestroy(&A);CHKERRQ(ierr);
680*d4002b98SHong Zhang   }
681*d4002b98SHong Zhang   PetscFunctionReturn(0);
682*d4002b98SHong Zhang }
683*d4002b98SHong Zhang 
684*d4002b98SHong Zhang PetscErrorCode MatView_MPISELL(Mat mat,PetscViewer viewer)
685*d4002b98SHong Zhang {
686*d4002b98SHong Zhang   PetscErrorCode ierr;
687*d4002b98SHong Zhang   PetscBool      iascii,isdraw,issocket,isbinary;
688*d4002b98SHong Zhang 
689*d4002b98SHong Zhang   PetscFunctionBegin;
690*d4002b98SHong Zhang   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
691*d4002b98SHong Zhang   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
692*d4002b98SHong Zhang   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
693*d4002b98SHong Zhang   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSOCKET,&issocket);CHKERRQ(ierr);
694*d4002b98SHong Zhang   if (iascii || isdraw || isbinary || issocket) {
695*d4002b98SHong Zhang     ierr = MatView_MPISELL_ASCIIorDraworSocket(mat,viewer);CHKERRQ(ierr);
696*d4002b98SHong Zhang   }
697*d4002b98SHong Zhang   PetscFunctionReturn(0);
698*d4002b98SHong Zhang }
699*d4002b98SHong Zhang 
700*d4002b98SHong Zhang PetscErrorCode MatGetGhosts_MPISELL(Mat mat,PetscInt *nghosts,const PetscInt *ghosts[])
701*d4002b98SHong Zhang {
702*d4002b98SHong Zhang   Mat_MPISELL    *sell=(Mat_MPISELL*)mat->data;
703*d4002b98SHong Zhang   PetscErrorCode ierr;
704*d4002b98SHong Zhang 
705*d4002b98SHong Zhang   PetscFunctionBegin;
706*d4002b98SHong Zhang   ierr = MatGetSize(sell->B,NULL,nghosts);CHKERRQ(ierr);
707*d4002b98SHong Zhang   if (ghosts) *ghosts = sell->garray;
708*d4002b98SHong Zhang   PetscFunctionReturn(0);
709*d4002b98SHong Zhang }
710*d4002b98SHong Zhang 
711*d4002b98SHong Zhang PetscErrorCode MatGetInfo_MPISELL(Mat matin,MatInfoType flag,MatInfo *info)
712*d4002b98SHong Zhang {
713*d4002b98SHong Zhang   Mat_MPISELL    *mat=(Mat_MPISELL*)matin->data;
714*d4002b98SHong Zhang   Mat            A=mat->A,B=mat->B;
715*d4002b98SHong Zhang   PetscErrorCode ierr;
716*d4002b98SHong Zhang   PetscReal      isend[5],irecv[5];
717*d4002b98SHong Zhang 
718*d4002b98SHong Zhang   PetscFunctionBegin;
719*d4002b98SHong Zhang   info->block_size = 1.0;
720*d4002b98SHong Zhang   ierr             = MatGetInfo(A,MAT_LOCAL,info);CHKERRQ(ierr);
721*d4002b98SHong Zhang 
722*d4002b98SHong Zhang   isend[0] = info->nz_used; isend[1] = info->nz_allocated; isend[2] = info->nz_unneeded;
723*d4002b98SHong Zhang   isend[3] = info->memory;  isend[4] = info->mallocs;
724*d4002b98SHong Zhang 
725*d4002b98SHong Zhang   ierr = MatGetInfo(B,MAT_LOCAL,info);CHKERRQ(ierr);
726*d4002b98SHong Zhang 
727*d4002b98SHong Zhang   isend[0] += info->nz_used; isend[1] += info->nz_allocated; isend[2] += info->nz_unneeded;
728*d4002b98SHong Zhang   isend[3] += info->memory;  isend[4] += info->mallocs;
729*d4002b98SHong Zhang   if (flag == MAT_LOCAL) {
730*d4002b98SHong Zhang     info->nz_used      = isend[0];
731*d4002b98SHong Zhang     info->nz_allocated = isend[1];
732*d4002b98SHong Zhang     info->nz_unneeded  = isend[2];
733*d4002b98SHong Zhang     info->memory       = isend[3];
734*d4002b98SHong Zhang     info->mallocs      = isend[4];
735*d4002b98SHong Zhang   } else if (flag == MAT_GLOBAL_MAX) {
736*d4002b98SHong Zhang     ierr = MPIU_Allreduce(isend,irecv,5,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)matin));CHKERRQ(ierr);
737*d4002b98SHong Zhang 
738*d4002b98SHong Zhang     info->nz_used      = irecv[0];
739*d4002b98SHong Zhang     info->nz_allocated = irecv[1];
740*d4002b98SHong Zhang     info->nz_unneeded  = irecv[2];
741*d4002b98SHong Zhang     info->memory       = irecv[3];
742*d4002b98SHong Zhang     info->mallocs      = irecv[4];
743*d4002b98SHong Zhang   } else if (flag == MAT_GLOBAL_SUM) {
744*d4002b98SHong Zhang     ierr = MPIU_Allreduce(isend,irecv,5,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)matin));CHKERRQ(ierr);
745*d4002b98SHong Zhang 
746*d4002b98SHong Zhang     info->nz_used      = irecv[0];
747*d4002b98SHong Zhang     info->nz_allocated = irecv[1];
748*d4002b98SHong Zhang     info->nz_unneeded  = irecv[2];
749*d4002b98SHong Zhang     info->memory       = irecv[3];
750*d4002b98SHong Zhang     info->mallocs      = irecv[4];
751*d4002b98SHong Zhang   }
752*d4002b98SHong Zhang   info->fill_ratio_given  = 0; /* no parallel LU/ILU/Cholesky */
753*d4002b98SHong Zhang   info->fill_ratio_needed = 0;
754*d4002b98SHong Zhang   info->factor_mallocs    = 0;
755*d4002b98SHong Zhang   PetscFunctionReturn(0);
756*d4002b98SHong Zhang }
757*d4002b98SHong Zhang 
758*d4002b98SHong Zhang PetscErrorCode MatSetOption_MPISELL(Mat A,MatOption op,PetscBool flg)
759*d4002b98SHong Zhang {
760*d4002b98SHong Zhang   Mat_MPISELL    *a=(Mat_MPISELL*)A->data;
761*d4002b98SHong Zhang   PetscErrorCode ierr;
762*d4002b98SHong Zhang 
763*d4002b98SHong Zhang   PetscFunctionBegin;
764*d4002b98SHong Zhang   switch (op) {
765*d4002b98SHong Zhang   case MAT_NEW_NONZERO_LOCATIONS:
766*d4002b98SHong Zhang   case MAT_NEW_NONZERO_ALLOCATION_ERR:
767*d4002b98SHong Zhang   case MAT_UNUSED_NONZERO_LOCATION_ERR:
768*d4002b98SHong Zhang   case MAT_KEEP_NONZERO_PATTERN:
769*d4002b98SHong Zhang   case MAT_NEW_NONZERO_LOCATION_ERR:
770*d4002b98SHong Zhang   case MAT_USE_INODES:
771*d4002b98SHong Zhang   case MAT_IGNORE_ZERO_ENTRIES:
772*d4002b98SHong Zhang     MatCheckPreallocated(A,1);
773*d4002b98SHong Zhang     ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr);
774*d4002b98SHong Zhang     ierr = MatSetOption(a->B,op,flg);CHKERRQ(ierr);
775*d4002b98SHong Zhang     break;
776*d4002b98SHong Zhang   case MAT_ROW_ORIENTED:
777*d4002b98SHong Zhang     MatCheckPreallocated(A,1);
778*d4002b98SHong Zhang     a->roworiented = flg;
779*d4002b98SHong Zhang 
780*d4002b98SHong Zhang     ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr);
781*d4002b98SHong Zhang     ierr = MatSetOption(a->B,op,flg);CHKERRQ(ierr);
782*d4002b98SHong Zhang     break;
783*d4002b98SHong Zhang   case MAT_NEW_DIAGONALS:
784*d4002b98SHong Zhang     ierr = PetscInfo1(A,"Option %s ignored\n",MatOptions[op]);CHKERRQ(ierr);
785*d4002b98SHong Zhang     break;
786*d4002b98SHong Zhang   case MAT_IGNORE_OFF_PROC_ENTRIES:
787*d4002b98SHong Zhang     a->donotstash = flg;
788*d4002b98SHong Zhang     break;
789*d4002b98SHong Zhang   case MAT_SPD:
790*d4002b98SHong Zhang     A->spd_set = PETSC_TRUE;
791*d4002b98SHong Zhang     A->spd     = flg;
792*d4002b98SHong Zhang     if (flg) {
793*d4002b98SHong Zhang       A->symmetric                  = PETSC_TRUE;
794*d4002b98SHong Zhang       A->structurally_symmetric     = PETSC_TRUE;
795*d4002b98SHong Zhang       A->symmetric_set              = PETSC_TRUE;
796*d4002b98SHong Zhang       A->structurally_symmetric_set = PETSC_TRUE;
797*d4002b98SHong Zhang     }
798*d4002b98SHong Zhang     break;
799*d4002b98SHong Zhang   case MAT_SYMMETRIC:
800*d4002b98SHong Zhang     MatCheckPreallocated(A,1);
801*d4002b98SHong Zhang     ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr);
802*d4002b98SHong Zhang     break;
803*d4002b98SHong Zhang   case MAT_STRUCTURALLY_SYMMETRIC:
804*d4002b98SHong Zhang     MatCheckPreallocated(A,1);
805*d4002b98SHong Zhang     ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr);
806*d4002b98SHong Zhang     break;
807*d4002b98SHong Zhang   case MAT_HERMITIAN:
808*d4002b98SHong Zhang     MatCheckPreallocated(A,1);
809*d4002b98SHong Zhang     ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr);
810*d4002b98SHong Zhang     break;
811*d4002b98SHong Zhang   case MAT_SYMMETRY_ETERNAL:
812*d4002b98SHong Zhang     MatCheckPreallocated(A,1);
813*d4002b98SHong Zhang     ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr);
814*d4002b98SHong Zhang     break;
815*d4002b98SHong Zhang   default:
816*d4002b98SHong Zhang     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"unknown option %d",op);
817*d4002b98SHong Zhang   }
818*d4002b98SHong Zhang   PetscFunctionReturn(0);
819*d4002b98SHong Zhang }
820*d4002b98SHong Zhang 
821*d4002b98SHong Zhang 
822*d4002b98SHong Zhang PetscErrorCode MatDiagonalScale_MPISELL(Mat mat,Vec ll,Vec rr)
823*d4002b98SHong Zhang {
824*d4002b98SHong Zhang   Mat_MPISELL    *sell=(Mat_MPISELL*)mat->data;
825*d4002b98SHong Zhang   Mat            a=sell->A,b=sell->B;
826*d4002b98SHong Zhang   PetscErrorCode ierr;
827*d4002b98SHong Zhang   PetscInt       s1,s2,s3;
828*d4002b98SHong Zhang 
829*d4002b98SHong Zhang   PetscFunctionBegin;
830*d4002b98SHong Zhang   ierr = MatGetLocalSize(mat,&s2,&s3);CHKERRQ(ierr);
831*d4002b98SHong Zhang   if (rr) {
832*d4002b98SHong Zhang     ierr = VecGetLocalSize(rr,&s1);CHKERRQ(ierr);
833*d4002b98SHong Zhang     if (s1!=s3) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"right vector non-conforming local size");
834*d4002b98SHong Zhang     /* Overlap communication with computation. */
835*d4002b98SHong Zhang     ierr = VecScatterBegin(sell->Mvctx,rr,sell->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
836*d4002b98SHong Zhang   }
837*d4002b98SHong Zhang   if (ll) {
838*d4002b98SHong Zhang     ierr = VecGetLocalSize(ll,&s1);CHKERRQ(ierr);
839*d4002b98SHong Zhang     if (s1!=s2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"left vector non-conforming local size");
840*d4002b98SHong Zhang     ierr = (*b->ops->diagonalscale)(b,ll,0);CHKERRQ(ierr);
841*d4002b98SHong Zhang   }
842*d4002b98SHong Zhang   /* scale  the diagonal block */
843*d4002b98SHong Zhang   ierr = (*a->ops->diagonalscale)(a,ll,rr);CHKERRQ(ierr);
844*d4002b98SHong Zhang 
845*d4002b98SHong Zhang   if (rr) {
846*d4002b98SHong Zhang     /* Do a scatter end and then right scale the off-diagonal block */
847*d4002b98SHong Zhang     ierr = VecScatterEnd(sell->Mvctx,rr,sell->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
848*d4002b98SHong Zhang     ierr = (*b->ops->diagonalscale)(b,0,sell->lvec);CHKERRQ(ierr);
849*d4002b98SHong Zhang   }
850*d4002b98SHong Zhang   PetscFunctionReturn(0);
851*d4002b98SHong Zhang }
852*d4002b98SHong Zhang 
853*d4002b98SHong Zhang PetscErrorCode MatSetUnfactored_MPISELL(Mat A)
854*d4002b98SHong Zhang {
855*d4002b98SHong Zhang   Mat_MPISELL    *a=(Mat_MPISELL*)A->data;
856*d4002b98SHong Zhang   PetscErrorCode ierr;
857*d4002b98SHong Zhang 
858*d4002b98SHong Zhang   PetscFunctionBegin;
859*d4002b98SHong Zhang   ierr = MatSetUnfactored(a->A);CHKERRQ(ierr);
860*d4002b98SHong Zhang   PetscFunctionReturn(0);
861*d4002b98SHong Zhang }
862*d4002b98SHong Zhang 
863*d4002b98SHong Zhang PetscErrorCode MatEqual_MPISELL(Mat A,Mat B,PetscBool  *flag)
864*d4002b98SHong Zhang {
865*d4002b98SHong Zhang   Mat_MPISELL    *matB=(Mat_MPISELL*)B->data,*matA=(Mat_MPISELL*)A->data;
866*d4002b98SHong Zhang   Mat            a,b,c,d;
867*d4002b98SHong Zhang   PetscBool      flg;
868*d4002b98SHong Zhang   PetscErrorCode ierr;
869*d4002b98SHong Zhang 
870*d4002b98SHong Zhang   PetscFunctionBegin;
871*d4002b98SHong Zhang   a = matA->A; b = matA->B;
872*d4002b98SHong Zhang   c = matB->A; d = matB->B;
873*d4002b98SHong Zhang 
874*d4002b98SHong Zhang   ierr = MatEqual(a,c,&flg);CHKERRQ(ierr);
875*d4002b98SHong Zhang   if (flg) {
876*d4002b98SHong Zhang     ierr = MatEqual(b,d,&flg);CHKERRQ(ierr);
877*d4002b98SHong Zhang   }
878*d4002b98SHong Zhang   ierr = MPIU_Allreduce(&flg,flag,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
879*d4002b98SHong Zhang   PetscFunctionReturn(0);
880*d4002b98SHong Zhang }
881*d4002b98SHong Zhang 
882*d4002b98SHong Zhang PetscErrorCode MatCopy_MPISELL(Mat A,Mat B,MatStructure str)
883*d4002b98SHong Zhang {
884*d4002b98SHong Zhang   PetscErrorCode ierr;
885*d4002b98SHong Zhang   Mat_MPISELL    *a=(Mat_MPISELL*)A->data;
886*d4002b98SHong Zhang   Mat_MPISELL    *b=(Mat_MPISELL*)B->data;
887*d4002b98SHong Zhang 
888*d4002b98SHong Zhang   PetscFunctionBegin;
889*d4002b98SHong Zhang   /* If the two matrices don't have the same copy implementation, they aren't compatible for fast copy. */
890*d4002b98SHong Zhang   if ((str != SAME_NONZERO_PATTERN) || (A->ops->copy != B->ops->copy)) {
891*d4002b98SHong Zhang     /* because of the column compression in the off-processor part of the matrix a->B,
892*d4002b98SHong Zhang        the number of columns in a->B and b->B may be different, hence we cannot call
893*d4002b98SHong Zhang        the MatCopy() directly on the two parts. If need be, we can provide a more
894*d4002b98SHong Zhang        efficient copy than the MatCopy_Basic() by first uncompressing the a->B matrices
895*d4002b98SHong Zhang        then copying the submatrices */
896*d4002b98SHong Zhang     ierr = MatCopy_Basic(A,B,str);CHKERRQ(ierr);
897*d4002b98SHong Zhang   } else {
898*d4002b98SHong Zhang     ierr = MatCopy(a->A,b->A,str);CHKERRQ(ierr);
899*d4002b98SHong Zhang     ierr = MatCopy(a->B,b->B,str);CHKERRQ(ierr);
900*d4002b98SHong Zhang   }
901*d4002b98SHong Zhang   PetscFunctionReturn(0);
902*d4002b98SHong Zhang }
903*d4002b98SHong Zhang 
904*d4002b98SHong Zhang PetscErrorCode MatSetUp_MPISELL(Mat A)
905*d4002b98SHong Zhang {
906*d4002b98SHong Zhang   PetscErrorCode ierr;
907*d4002b98SHong Zhang 
908*d4002b98SHong Zhang   PetscFunctionBegin;
909*d4002b98SHong Zhang   ierr =  MatMPISELLSetPreallocation(A,PETSC_DEFAULT,0,PETSC_DEFAULT,0);CHKERRQ(ierr);
910*d4002b98SHong Zhang   PetscFunctionReturn(0);
911*d4002b98SHong Zhang }
912*d4002b98SHong Zhang 
913*d4002b98SHong Zhang 
914*d4002b98SHong Zhang extern PetscErrorCode MatConjugate_SeqSELL(Mat);
915*d4002b98SHong Zhang 
916*d4002b98SHong Zhang PetscErrorCode MatConjugate_MPISELL(Mat mat)
917*d4002b98SHong Zhang {
918*d4002b98SHong Zhang #if defined(PETSC_USE_COMPLEX)
919*d4002b98SHong Zhang   PetscErrorCode ierr;
920*d4002b98SHong Zhang   Mat_MPISELL    *sell=(Mat_MPISELL*)mat->data;
921*d4002b98SHong Zhang 
922*d4002b98SHong Zhang   PetscFunctionBegin;
923*d4002b98SHong Zhang   ierr = MatConjugate_SeqSELL(sell->A);CHKERRQ(ierr);
924*d4002b98SHong Zhang   ierr = MatConjugate_SeqSELL(sell->B);CHKERRQ(ierr);
925*d4002b98SHong Zhang #else
926*d4002b98SHong Zhang   PetscFunctionBegin;
927*d4002b98SHong Zhang #endif
928*d4002b98SHong Zhang   PetscFunctionReturn(0);
929*d4002b98SHong Zhang }
930*d4002b98SHong Zhang 
931*d4002b98SHong Zhang PetscErrorCode MatRealPart_MPISELL(Mat A)
932*d4002b98SHong Zhang {
933*d4002b98SHong Zhang   Mat_MPISELL    *a=(Mat_MPISELL*)A->data;
934*d4002b98SHong Zhang   PetscErrorCode ierr;
935*d4002b98SHong Zhang 
936*d4002b98SHong Zhang   PetscFunctionBegin;
937*d4002b98SHong Zhang   ierr = MatRealPart(a->A);CHKERRQ(ierr);
938*d4002b98SHong Zhang   ierr = MatRealPart(a->B);CHKERRQ(ierr);
939*d4002b98SHong Zhang   PetscFunctionReturn(0);
940*d4002b98SHong Zhang }
941*d4002b98SHong Zhang 
942*d4002b98SHong Zhang PetscErrorCode MatImaginaryPart_MPISELL(Mat A)
943*d4002b98SHong Zhang {
944*d4002b98SHong Zhang   Mat_MPISELL    *a=(Mat_MPISELL*)A->data;
945*d4002b98SHong Zhang   PetscErrorCode ierr;
946*d4002b98SHong Zhang 
947*d4002b98SHong Zhang   PetscFunctionBegin;
948*d4002b98SHong Zhang   ierr = MatImaginaryPart(a->A);CHKERRQ(ierr);
949*d4002b98SHong Zhang   ierr = MatImaginaryPart(a->B);CHKERRQ(ierr);
950*d4002b98SHong Zhang   PetscFunctionReturn(0);
951*d4002b98SHong Zhang }
952*d4002b98SHong Zhang 
953*d4002b98SHong Zhang PetscErrorCode MatInvertBlockDiagonal_MPISELL(Mat A,const PetscScalar **values)
954*d4002b98SHong Zhang {
955*d4002b98SHong Zhang   Mat_MPISELL    *a=(Mat_MPISELL*)A->data;
956*d4002b98SHong Zhang   PetscErrorCode ierr;
957*d4002b98SHong Zhang 
958*d4002b98SHong Zhang   PetscFunctionBegin;
959*d4002b98SHong Zhang   ierr = MatInvertBlockDiagonal(a->A,values);CHKERRQ(ierr);
960*d4002b98SHong Zhang   A->factorerrortype = a->A->factorerrortype;
961*d4002b98SHong Zhang   PetscFunctionReturn(0);
962*d4002b98SHong Zhang }
963*d4002b98SHong Zhang 
964*d4002b98SHong Zhang static PetscErrorCode MatSetRandom_MPISELL(Mat x,PetscRandom rctx)
965*d4002b98SHong Zhang {
966*d4002b98SHong Zhang   PetscErrorCode ierr;
967*d4002b98SHong Zhang   Mat_MPISELL    *sell=(Mat_MPISELL*)x->data;
968*d4002b98SHong Zhang 
969*d4002b98SHong Zhang   PetscFunctionBegin;
970*d4002b98SHong Zhang   ierr = MatSetRandom(sell->A,rctx);CHKERRQ(ierr);
971*d4002b98SHong Zhang   ierr = MatSetRandom(sell->B,rctx);CHKERRQ(ierr);
972*d4002b98SHong Zhang   ierr = MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
973*d4002b98SHong Zhang   ierr = MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
974*d4002b98SHong Zhang   PetscFunctionReturn(0);
975*d4002b98SHong Zhang }
976*d4002b98SHong Zhang 
977*d4002b98SHong Zhang PetscErrorCode MatSetFromOptions_MPISELL(PetscOptionItems *PetscOptionsObject,Mat A)
978*d4002b98SHong Zhang {
979*d4002b98SHong Zhang   PetscErrorCode ierr;
980*d4002b98SHong Zhang 
981*d4002b98SHong Zhang   PetscFunctionBegin;
982*d4002b98SHong Zhang   ierr = PetscOptionsHead(PetscOptionsObject,"MPISELL options");CHKERRQ(ierr);
983*d4002b98SHong Zhang   ierr = PetscObjectOptionsBegin((PetscObject)A);
984*d4002b98SHong Zhang   ierr = PetscOptionsEnd();CHKERRQ(ierr);
985*d4002b98SHong Zhang   PetscFunctionReturn(0);
986*d4002b98SHong Zhang }
987*d4002b98SHong Zhang 
988*d4002b98SHong Zhang PetscErrorCode MatShift_MPISELL(Mat Y,PetscScalar a)
989*d4002b98SHong Zhang {
990*d4002b98SHong Zhang   PetscErrorCode ierr;
991*d4002b98SHong Zhang   Mat_MPISELL    *msell=(Mat_MPISELL*)Y->data;
992*d4002b98SHong Zhang   Mat_SeqSELL    *sell=(Mat_SeqSELL*)msell->A->data;
993*d4002b98SHong Zhang 
994*d4002b98SHong Zhang   PetscFunctionBegin;
995*d4002b98SHong Zhang   if (!Y->preallocated) {
996*d4002b98SHong Zhang     ierr = MatMPISELLSetPreallocation(Y,1,NULL,0,NULL);CHKERRQ(ierr);
997*d4002b98SHong Zhang   } else if (!sell->nz) {
998*d4002b98SHong Zhang     PetscInt nonew = sell->nonew;
999*d4002b98SHong Zhang     ierr = MatSeqSELLSetPreallocation(msell->A,1,NULL);CHKERRQ(ierr);
1000*d4002b98SHong Zhang     sell->nonew = nonew;
1001*d4002b98SHong Zhang   }
1002*d4002b98SHong Zhang   ierr = MatShift_Basic(Y,a);CHKERRQ(ierr);
1003*d4002b98SHong Zhang   PetscFunctionReturn(0);
1004*d4002b98SHong Zhang }
1005*d4002b98SHong Zhang 
1006*d4002b98SHong Zhang PetscErrorCode MatMissingDiagonal_MPISELL(Mat A,PetscBool  *missing,PetscInt *d)
1007*d4002b98SHong Zhang {
1008*d4002b98SHong Zhang   Mat_MPISELL    *a=(Mat_MPISELL*)A->data;
1009*d4002b98SHong Zhang   PetscErrorCode ierr;
1010*d4002b98SHong Zhang 
1011*d4002b98SHong Zhang   PetscFunctionBegin;
1012*d4002b98SHong Zhang   if (A->rmap->n != A->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only works for square matrices");
1013*d4002b98SHong Zhang   ierr = MatMissingDiagonal(a->A,missing,d);CHKERRQ(ierr);
1014*d4002b98SHong Zhang   if (d) {
1015*d4002b98SHong Zhang     PetscInt rstart;
1016*d4002b98SHong Zhang     ierr = MatGetOwnershipRange(A,&rstart,NULL);CHKERRQ(ierr);
1017*d4002b98SHong Zhang     *d += rstart;
1018*d4002b98SHong Zhang 
1019*d4002b98SHong Zhang   }
1020*d4002b98SHong Zhang   PetscFunctionReturn(0);
1021*d4002b98SHong Zhang }
1022*d4002b98SHong Zhang 
1023*d4002b98SHong Zhang PetscErrorCode MatGetDiagonalBlock_MPISELL(Mat A,Mat *a)
1024*d4002b98SHong Zhang {
1025*d4002b98SHong Zhang   PetscFunctionBegin;
1026*d4002b98SHong Zhang   *a = ((Mat_MPISELL*)A->data)->A;
1027*d4002b98SHong Zhang   PetscFunctionReturn(0);
1028*d4002b98SHong Zhang }
1029*d4002b98SHong Zhang 
1030*d4002b98SHong Zhang /* -------------------------------------------------------------------*/
1031*d4002b98SHong Zhang static struct _MatOps MatOps_Values = {MatSetValues_MPISELL,
1032*d4002b98SHong Zhang                                        0,
1033*d4002b98SHong Zhang                                        0,
1034*d4002b98SHong Zhang                                        MatMult_MPISELL,
1035*d4002b98SHong Zhang                                 /* 4*/ MatMultAdd_MPISELL,
1036*d4002b98SHong Zhang                                        MatMultTranspose_MPISELL,
1037*d4002b98SHong Zhang                                        MatMultTransposeAdd_MPISELL,
1038*d4002b98SHong Zhang                                        0,
1039*d4002b98SHong Zhang                                        0,
1040*d4002b98SHong Zhang                                        0,
1041*d4002b98SHong Zhang                                 /*10*/ 0,
1042*d4002b98SHong Zhang                                        0,
1043*d4002b98SHong Zhang                                        0,
1044*d4002b98SHong Zhang                                        MatSOR_MPISELL,
1045*d4002b98SHong Zhang                                        0,
1046*d4002b98SHong Zhang                                 /*15*/ MatGetInfo_MPISELL,
1047*d4002b98SHong Zhang                                        MatEqual_MPISELL,
1048*d4002b98SHong Zhang                                        MatGetDiagonal_MPISELL,
1049*d4002b98SHong Zhang                                        MatDiagonalScale_MPISELL,
1050*d4002b98SHong Zhang                                        0,
1051*d4002b98SHong Zhang                                 /*20*/ MatAssemblyBegin_MPISELL,
1052*d4002b98SHong Zhang                                        MatAssemblyEnd_MPISELL,
1053*d4002b98SHong Zhang                                        MatSetOption_MPISELL,
1054*d4002b98SHong Zhang                                        MatZeroEntries_MPISELL,
1055*d4002b98SHong Zhang                                 /*24*/ 0,
1056*d4002b98SHong Zhang                                        0,
1057*d4002b98SHong Zhang                                        0,
1058*d4002b98SHong Zhang                                        0,
1059*d4002b98SHong Zhang                                        0,
1060*d4002b98SHong Zhang                                 /*29*/ MatSetUp_MPISELL,
1061*d4002b98SHong Zhang                                        0,
1062*d4002b98SHong Zhang                                        0,
1063*d4002b98SHong Zhang                                        MatGetDiagonalBlock_MPISELL,
1064*d4002b98SHong Zhang                                        0,
1065*d4002b98SHong Zhang                                 /*34*/ MatDuplicate_MPISELL,
1066*d4002b98SHong Zhang                                        0,
1067*d4002b98SHong Zhang                                        0,
1068*d4002b98SHong Zhang                                        0,
1069*d4002b98SHong Zhang                                        0,
1070*d4002b98SHong Zhang                                 /*39*/ 0,
1071*d4002b98SHong Zhang                                        0,
1072*d4002b98SHong Zhang                                        0,
1073*d4002b98SHong Zhang                                        MatGetValues_MPISELL,
1074*d4002b98SHong Zhang                                        MatCopy_MPISELL,
1075*d4002b98SHong Zhang                                 /*44*/ 0,
1076*d4002b98SHong Zhang                                        MatScale_MPISELL,
1077*d4002b98SHong Zhang                                        MatShift_MPISELL,
1078*d4002b98SHong Zhang                                        MatDiagonalSet_MPISELL,
1079*d4002b98SHong Zhang                                        0,
1080*d4002b98SHong Zhang                                 /*49*/ MatSetRandom_MPISELL,
1081*d4002b98SHong Zhang                                        0,
1082*d4002b98SHong Zhang                                        0,
1083*d4002b98SHong Zhang                                        0,
1084*d4002b98SHong Zhang                                        0,
1085*d4002b98SHong Zhang                                 /*54*/ MatFDColoringCreate_MPIXAIJ,
1086*d4002b98SHong Zhang                                        0,
1087*d4002b98SHong Zhang                                        MatSetUnfactored_MPISELL,
1088*d4002b98SHong Zhang                                        0,
1089*d4002b98SHong Zhang                                        0,
1090*d4002b98SHong Zhang                                 /*59*/ 0,
1091*d4002b98SHong Zhang                                        MatDestroy_MPISELL,
1092*d4002b98SHong Zhang                                        MatView_MPISELL,
1093*d4002b98SHong Zhang                                        0,
1094*d4002b98SHong Zhang                                        0,
1095*d4002b98SHong Zhang                                 /*64*/ 0,
1096*d4002b98SHong Zhang                                        0,
1097*d4002b98SHong Zhang                                        0,
1098*d4002b98SHong Zhang                                        0,
1099*d4002b98SHong Zhang                                        0,
1100*d4002b98SHong Zhang                                 /*69*/ 0,
1101*d4002b98SHong Zhang                                        0,
1102*d4002b98SHong Zhang                                        0,
1103*d4002b98SHong Zhang                                        0,
1104*d4002b98SHong Zhang                                        0,
1105*d4002b98SHong Zhang                                        0,
1106*d4002b98SHong Zhang                                 /*75*/ MatFDColoringApply_AIJ, /* reuse AIJ function */
1107*d4002b98SHong Zhang                                        MatSetFromOptions_MPISELL,
1108*d4002b98SHong Zhang                                        0,
1109*d4002b98SHong Zhang                                        0,
1110*d4002b98SHong Zhang                                        0,
1111*d4002b98SHong Zhang                                 /*80*/ 0,
1112*d4002b98SHong Zhang                                        0,
1113*d4002b98SHong Zhang                                        0,
1114*d4002b98SHong Zhang                                 /*83*/ 0,
1115*d4002b98SHong Zhang                                        0,
1116*d4002b98SHong Zhang                                        0,
1117*d4002b98SHong Zhang                                        0,
1118*d4002b98SHong Zhang                                        0,
1119*d4002b98SHong Zhang                                        0,
1120*d4002b98SHong Zhang                                 /*89*/ 0,
1121*d4002b98SHong Zhang                                        0,
1122*d4002b98SHong Zhang                                        0,
1123*d4002b98SHong Zhang                                        0,
1124*d4002b98SHong Zhang                                        0,
1125*d4002b98SHong Zhang                                 /*94*/ 0,
1126*d4002b98SHong Zhang                                        0,
1127*d4002b98SHong Zhang                                        0,
1128*d4002b98SHong Zhang                                        0,
1129*d4002b98SHong Zhang                                        0,
1130*d4002b98SHong Zhang                                 /*99*/ 0,
1131*d4002b98SHong Zhang                                        0,
1132*d4002b98SHong Zhang                                        0,
1133*d4002b98SHong Zhang                                        MatConjugate_MPISELL,
1134*d4002b98SHong Zhang                                        0,
1135*d4002b98SHong Zhang                                 /*104*/0,
1136*d4002b98SHong Zhang                                        MatRealPart_MPISELL,
1137*d4002b98SHong Zhang                                        MatImaginaryPart_MPISELL,
1138*d4002b98SHong Zhang                                        0,
1139*d4002b98SHong Zhang                                        0,
1140*d4002b98SHong Zhang                                 /*109*/0,
1141*d4002b98SHong Zhang                                        0,
1142*d4002b98SHong Zhang                                        0,
1143*d4002b98SHong Zhang                                        0,
1144*d4002b98SHong Zhang                                        MatMissingDiagonal_MPISELL,
1145*d4002b98SHong Zhang                                 /*114*/0,
1146*d4002b98SHong Zhang                                        0,
1147*d4002b98SHong Zhang                                        MatGetGhosts_MPISELL,
1148*d4002b98SHong Zhang                                        0,
1149*d4002b98SHong Zhang                                        0,
1150*d4002b98SHong Zhang                                 /*119*/0,
1151*d4002b98SHong Zhang                                        0,
1152*d4002b98SHong Zhang                                        0,
1153*d4002b98SHong Zhang                                        0,
1154*d4002b98SHong Zhang                                        0,
1155*d4002b98SHong Zhang                                 /*124*/0,
1156*d4002b98SHong Zhang                                        0,
1157*d4002b98SHong Zhang                                        MatInvertBlockDiagonal_MPISELL,
1158*d4002b98SHong Zhang                                        0,
1159*d4002b98SHong Zhang                                        0,
1160*d4002b98SHong Zhang                                 /*129*/0,
1161*d4002b98SHong Zhang                                        0,
1162*d4002b98SHong Zhang                                        0,
1163*d4002b98SHong Zhang                                        0,
1164*d4002b98SHong Zhang                                        0,
1165*d4002b98SHong Zhang                                 /*134*/0,
1166*d4002b98SHong Zhang                                        0,
1167*d4002b98SHong Zhang                                        0,
1168*d4002b98SHong Zhang                                        0,
1169*d4002b98SHong Zhang                                        0,
1170*d4002b98SHong Zhang                                 /*139*/0,
1171*d4002b98SHong Zhang                                        0,
1172*d4002b98SHong Zhang                                        0,
1173*d4002b98SHong Zhang                                        MatFDColoringSetUp_MPIXAIJ,
1174*d4002b98SHong Zhang                                        0,
1175*d4002b98SHong Zhang                                 /*144*/0
1176*d4002b98SHong Zhang };
1177*d4002b98SHong Zhang 
1178*d4002b98SHong Zhang /* ----------------------------------------------------------------------------------------*/
1179*d4002b98SHong Zhang 
1180*d4002b98SHong Zhang PetscErrorCode MatStoreValues_MPISELL(Mat mat)
1181*d4002b98SHong Zhang {
1182*d4002b98SHong Zhang   Mat_MPISELL    *sell=(Mat_MPISELL*)mat->data;
1183*d4002b98SHong Zhang   PetscErrorCode ierr;
1184*d4002b98SHong Zhang 
1185*d4002b98SHong Zhang   PetscFunctionBegin;
1186*d4002b98SHong Zhang   ierr = MatStoreValues(sell->A);CHKERRQ(ierr);
1187*d4002b98SHong Zhang   ierr = MatStoreValues(sell->B);CHKERRQ(ierr);
1188*d4002b98SHong Zhang   PetscFunctionReturn(0);
1189*d4002b98SHong Zhang }
1190*d4002b98SHong Zhang 
1191*d4002b98SHong Zhang PetscErrorCode MatRetrieveValues_MPISELL(Mat mat)
1192*d4002b98SHong Zhang {
1193*d4002b98SHong Zhang   Mat_MPISELL    *sell=(Mat_MPISELL*)mat->data;
1194*d4002b98SHong Zhang   PetscErrorCode ierr;
1195*d4002b98SHong Zhang 
1196*d4002b98SHong Zhang   PetscFunctionBegin;
1197*d4002b98SHong Zhang   ierr = MatRetrieveValues(sell->A);CHKERRQ(ierr);
1198*d4002b98SHong Zhang   ierr = MatRetrieveValues(sell->B);CHKERRQ(ierr);
1199*d4002b98SHong Zhang   PetscFunctionReturn(0);
1200*d4002b98SHong Zhang }
1201*d4002b98SHong Zhang 
1202*d4002b98SHong Zhang PetscErrorCode MatMPISELLSetPreallocation_MPISELL(Mat B,PetscInt d_rlenmax,const PetscInt d_rlen[],PetscInt o_rlenmax,const PetscInt o_rlen[])
1203*d4002b98SHong Zhang {
1204*d4002b98SHong Zhang   Mat_MPISELL    *b;
1205*d4002b98SHong Zhang   PetscErrorCode ierr;
1206*d4002b98SHong Zhang 
1207*d4002b98SHong Zhang   PetscFunctionBegin;
1208*d4002b98SHong Zhang   ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr);
1209*d4002b98SHong Zhang   ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr);
1210*d4002b98SHong Zhang   b = (Mat_MPISELL*)B->data;
1211*d4002b98SHong Zhang 
1212*d4002b98SHong Zhang   if (!B->preallocated) {
1213*d4002b98SHong Zhang     /* Explicitly create 2 MATSEQSELL matrices. */
1214*d4002b98SHong Zhang     ierr = MatCreate(PETSC_COMM_SELF,&b->A);CHKERRQ(ierr);
1215*d4002b98SHong Zhang     ierr = MatSetSizes(b->A,B->rmap->n,B->cmap->n,B->rmap->n,B->cmap->n);CHKERRQ(ierr);
1216*d4002b98SHong Zhang     ierr = MatSetBlockSizesFromMats(b->A,B,B);CHKERRQ(ierr);
1217*d4002b98SHong Zhang     ierr = MatSetType(b->A,MATSEQSELL);CHKERRQ(ierr);
1218*d4002b98SHong Zhang     ierr = PetscLogObjectParent((PetscObject)B,(PetscObject)b->A);CHKERRQ(ierr);
1219*d4002b98SHong Zhang     ierr = MatCreate(PETSC_COMM_SELF,&b->B);CHKERRQ(ierr);
1220*d4002b98SHong Zhang     ierr = MatSetSizes(b->B,B->rmap->n,B->cmap->N,B->rmap->n,B->cmap->N);CHKERRQ(ierr);
1221*d4002b98SHong Zhang     ierr = MatSetBlockSizesFromMats(b->B,B,B);CHKERRQ(ierr);
1222*d4002b98SHong Zhang     ierr = MatSetType(b->B,MATSEQSELL);CHKERRQ(ierr);
1223*d4002b98SHong Zhang     ierr = PetscLogObjectParent((PetscObject)B,(PetscObject)b->B);CHKERRQ(ierr);
1224*d4002b98SHong Zhang   }
1225*d4002b98SHong Zhang 
1226*d4002b98SHong Zhang   ierr = MatSeqSELLSetPreallocation(b->A,d_rlenmax,d_rlen);CHKERRQ(ierr);
1227*d4002b98SHong Zhang   ierr = MatSeqSELLSetPreallocation(b->B,o_rlenmax,o_rlen);CHKERRQ(ierr);
1228*d4002b98SHong Zhang   B->preallocated  = PETSC_TRUE;
1229*d4002b98SHong Zhang   B->was_assembled = PETSC_FALSE;
1230*d4002b98SHong Zhang   /*
1231*d4002b98SHong Zhang     critical for MatAssemblyEnd to work.
1232*d4002b98SHong Zhang     MatAssemblyBegin checks it to set up was_assembled
1233*d4002b98SHong Zhang     and MatAssemblyEnd checks was_assembled to determine whether to build garray
1234*d4002b98SHong Zhang   */
1235*d4002b98SHong Zhang   B->assembled     = PETSC_FALSE;
1236*d4002b98SHong Zhang   PetscFunctionReturn(0);
1237*d4002b98SHong Zhang }
1238*d4002b98SHong Zhang 
1239*d4002b98SHong Zhang PetscErrorCode MatDuplicate_MPISELL(Mat matin,MatDuplicateOption cpvalues,Mat *newmat)
1240*d4002b98SHong Zhang {
1241*d4002b98SHong Zhang   Mat            mat;
1242*d4002b98SHong Zhang   Mat_MPISELL    *a,*oldmat=(Mat_MPISELL*)matin->data;
1243*d4002b98SHong Zhang   PetscErrorCode ierr;
1244*d4002b98SHong Zhang 
1245*d4002b98SHong Zhang   PetscFunctionBegin;
1246*d4002b98SHong Zhang   *newmat = 0;
1247*d4002b98SHong Zhang   ierr    = MatCreate(PetscObjectComm((PetscObject)matin),&mat);CHKERRQ(ierr);
1248*d4002b98SHong Zhang   ierr    = MatSetSizes(mat,matin->rmap->n,matin->cmap->n,matin->rmap->N,matin->cmap->N);CHKERRQ(ierr);
1249*d4002b98SHong Zhang   ierr    = MatSetBlockSizesFromMats(mat,matin,matin);CHKERRQ(ierr);
1250*d4002b98SHong Zhang   ierr    = MatSetType(mat,((PetscObject)matin)->type_name);CHKERRQ(ierr);
1251*d4002b98SHong Zhang   ierr    = PetscMemcpy(mat->ops,matin->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
1252*d4002b98SHong Zhang   a       = (Mat_MPISELL*)mat->data;
1253*d4002b98SHong Zhang 
1254*d4002b98SHong Zhang   mat->factortype   = matin->factortype;
1255*d4002b98SHong Zhang   mat->assembled    = PETSC_TRUE;
1256*d4002b98SHong Zhang   mat->insertmode   = NOT_SET_VALUES;
1257*d4002b98SHong Zhang   mat->preallocated = PETSC_TRUE;
1258*d4002b98SHong Zhang 
1259*d4002b98SHong Zhang   a->size         = oldmat->size;
1260*d4002b98SHong Zhang   a->rank         = oldmat->rank;
1261*d4002b98SHong Zhang   a->donotstash   = oldmat->donotstash;
1262*d4002b98SHong Zhang   a->roworiented  = oldmat->roworiented;
1263*d4002b98SHong Zhang   a->rowindices   = 0;
1264*d4002b98SHong Zhang   a->rowvalues    = 0;
1265*d4002b98SHong Zhang   a->getrowactive = PETSC_FALSE;
1266*d4002b98SHong Zhang 
1267*d4002b98SHong Zhang   ierr = PetscLayoutReference(matin->rmap,&mat->rmap);CHKERRQ(ierr);
1268*d4002b98SHong Zhang   ierr = PetscLayoutReference(matin->cmap,&mat->cmap);CHKERRQ(ierr);
1269*d4002b98SHong Zhang 
1270*d4002b98SHong Zhang   if (oldmat->colmap) {
1271*d4002b98SHong Zhang #if defined(PETSC_USE_CTABLE)
1272*d4002b98SHong Zhang     ierr = PetscTableCreateCopy(oldmat->colmap,&a->colmap);CHKERRQ(ierr);
1273*d4002b98SHong Zhang #else
1274*d4002b98SHong Zhang     ierr = PetscMalloc1(mat->cmap->N,&a->colmap);CHKERRQ(ierr);
1275*d4002b98SHong Zhang     ierr = PetscLogObjectMemory((PetscObject)mat,(mat->cmap->N)*sizeof(PetscInt));CHKERRQ(ierr);
1276*d4002b98SHong Zhang     ierr = PetscMemcpy(a->colmap,oldmat->colmap,(mat->cmap->N)*sizeof(PetscInt));CHKERRQ(ierr);
1277*d4002b98SHong Zhang #endif
1278*d4002b98SHong Zhang   } else a->colmap = 0;
1279*d4002b98SHong Zhang   if (oldmat->garray) {
1280*d4002b98SHong Zhang     PetscInt len;
1281*d4002b98SHong Zhang     len  = oldmat->B->cmap->n;
1282*d4002b98SHong Zhang     ierr = PetscMalloc1(len+1,&a->garray);CHKERRQ(ierr);
1283*d4002b98SHong Zhang     ierr = PetscLogObjectMemory((PetscObject)mat,len*sizeof(PetscInt));CHKERRQ(ierr);
1284*d4002b98SHong Zhang     if (len) { ierr = PetscMemcpy(a->garray,oldmat->garray,len*sizeof(PetscInt));CHKERRQ(ierr); }
1285*d4002b98SHong Zhang   } else a->garray = 0;
1286*d4002b98SHong Zhang 
1287*d4002b98SHong Zhang   ierr    = VecDuplicate(oldmat->lvec,&a->lvec);CHKERRQ(ierr);
1288*d4002b98SHong Zhang   ierr    = PetscLogObjectParent((PetscObject)mat,(PetscObject)a->lvec);CHKERRQ(ierr);
1289*d4002b98SHong Zhang   ierr    = VecScatterCopy(oldmat->Mvctx,&a->Mvctx);CHKERRQ(ierr);
1290*d4002b98SHong Zhang   ierr    = PetscLogObjectParent((PetscObject)mat,(PetscObject)a->Mvctx);CHKERRQ(ierr);
1291*d4002b98SHong Zhang   ierr    = MatDuplicate(oldmat->A,cpvalues,&a->A);CHKERRQ(ierr);
1292*d4002b98SHong Zhang   ierr    = PetscLogObjectParent((PetscObject)mat,(PetscObject)a->A);CHKERRQ(ierr);
1293*d4002b98SHong Zhang   ierr    = MatDuplicate(oldmat->B,cpvalues,&a->B);CHKERRQ(ierr);
1294*d4002b98SHong Zhang   ierr    = PetscLogObjectParent((PetscObject)mat,(PetscObject)a->B);CHKERRQ(ierr);
1295*d4002b98SHong Zhang   ierr    = PetscFunctionListDuplicate(((PetscObject)matin)->qlist,&((PetscObject)mat)->qlist);CHKERRQ(ierr);
1296*d4002b98SHong Zhang   *newmat = mat;
1297*d4002b98SHong Zhang   PetscFunctionReturn(0);
1298*d4002b98SHong Zhang }
1299*d4002b98SHong Zhang 
1300*d4002b98SHong Zhang /*@C
1301*d4002b98SHong Zhang    MatMPISELLSetPreallocation - Preallocates memory for a sparse parallel matrix in sell format.
1302*d4002b98SHong Zhang    For good matrix assembly performance the user should preallocate the matrix storage by
1303*d4002b98SHong Zhang    setting the parameters d_nz (or d_nnz) and o_nz (or o_nnz).
1304*d4002b98SHong Zhang 
1305*d4002b98SHong Zhang    Collective on MPI_Comm
1306*d4002b98SHong Zhang 
1307*d4002b98SHong Zhang    Input Parameters:
1308*d4002b98SHong Zhang +  B - the matrix
1309*d4002b98SHong Zhang .  d_nz  - number of nonzeros per row in DIAGONAL portion of local submatrix
1310*d4002b98SHong Zhang            (same value is used for all local rows)
1311*d4002b98SHong Zhang .  d_nnz - array containing the number of nonzeros in the various rows of the
1312*d4002b98SHong Zhang            DIAGONAL portion of the local submatrix (possibly different for each row)
1313*d4002b98SHong Zhang            or NULL (PETSC_NULL_INTEGER in Fortran), if d_nz is used to specify the nonzero structure.
1314*d4002b98SHong Zhang            The size of this array is equal to the number of local rows, i.e 'm'.
1315*d4002b98SHong Zhang            For matrices that will be factored, you must leave room for (and set)
1316*d4002b98SHong Zhang            the diagonal entry even if it is zero.
1317*d4002b98SHong Zhang .  o_nz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
1318*d4002b98SHong Zhang            submatrix (same value is used for all local rows).
1319*d4002b98SHong Zhang -  o_nnz - array containing the number of nonzeros in the various rows of the
1320*d4002b98SHong Zhang            OFF-DIAGONAL portion of the local submatrix (possibly different for
1321*d4002b98SHong Zhang            each row) or NULL (PETSC_NULL_INTEGER in Fortran), if o_nz is used to specify the nonzero
1322*d4002b98SHong Zhang            structure. The size of this array is equal to the number
1323*d4002b98SHong Zhang            of local rows, i.e 'm'.
1324*d4002b98SHong Zhang 
1325*d4002b98SHong Zhang    If the *_nnz parameter is given then the *_nz parameter is ignored
1326*d4002b98SHong Zhang 
1327*d4002b98SHong Zhang    The stored row and column indices begin with zero.
1328*d4002b98SHong Zhang 
1329*d4002b98SHong Zhang    The parallel matrix is partitioned such that the first m0 rows belong to
1330*d4002b98SHong Zhang    process 0, the next m1 rows belong to process 1, the next m2 rows belong
1331*d4002b98SHong Zhang    to process 2 etc.. where m0,m1,m2... are the input parameter 'm'.
1332*d4002b98SHong Zhang 
1333*d4002b98SHong Zhang    The DIAGONAL portion of the local submatrix of a processor can be defined
1334*d4002b98SHong Zhang    as the submatrix which is obtained by extraction the part corresponding to
1335*d4002b98SHong Zhang    the rows r1-r2 and columns c1-c2 of the global matrix, where r1 is the
1336*d4002b98SHong Zhang    first row that belongs to the processor, r2 is the last row belonging to
1337*d4002b98SHong Zhang    the this processor, and c1-c2 is range of indices of the local part of a
1338*d4002b98SHong Zhang    vector suitable for applying the matrix to.  This is an mxn matrix.  In the
1339*d4002b98SHong Zhang    common case of a square matrix, the row and column ranges are the same and
1340*d4002b98SHong Zhang    the DIAGONAL part is also square. The remaining portion of the local
1341*d4002b98SHong Zhang    submatrix (mxN) constitute the OFF-DIAGONAL portion.
1342*d4002b98SHong Zhang 
1343*d4002b98SHong Zhang    If o_nnz, d_nnz are specified, then o_nz, and d_nz are ignored.
1344*d4002b98SHong Zhang 
1345*d4002b98SHong Zhang    You can call MatGetInfo() to get information on how effective the preallocation was;
1346*d4002b98SHong Zhang    for example the fields mallocs,nz_allocated,nz_used,nz_unneeded;
1347*d4002b98SHong Zhang    You can also run with the option -info and look for messages with the string
1348*d4002b98SHong Zhang    malloc in them to see if additional memory allocation was needed.
1349*d4002b98SHong Zhang 
1350*d4002b98SHong Zhang    Example usage:
1351*d4002b98SHong Zhang 
1352*d4002b98SHong Zhang    Consider the following 8x8 matrix with 34 non-zero values, that is
1353*d4002b98SHong Zhang    assembled across 3 processors. Lets assume that proc0 owns 3 rows,
1354*d4002b98SHong Zhang    proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
1355*d4002b98SHong Zhang    as follows:
1356*d4002b98SHong Zhang 
1357*d4002b98SHong Zhang .vb
1358*d4002b98SHong Zhang             1  2  0  |  0  3  0  |  0  4
1359*d4002b98SHong Zhang     Proc0   0  5  6  |  7  0  0  |  8  0
1360*d4002b98SHong Zhang             9  0 10  | 11  0  0  | 12  0
1361*d4002b98SHong Zhang     -------------------------------------
1362*d4002b98SHong Zhang            13  0 14  | 15 16 17  |  0  0
1363*d4002b98SHong Zhang     Proc1   0 18  0  | 19 20 21  |  0  0
1364*d4002b98SHong Zhang             0  0  0  | 22 23  0  | 24  0
1365*d4002b98SHong Zhang     -------------------------------------
1366*d4002b98SHong Zhang     Proc2  25 26 27  |  0  0 28  | 29  0
1367*d4002b98SHong Zhang            30  0  0  | 31 32 33  |  0 34
1368*d4002b98SHong Zhang .ve
1369*d4002b98SHong Zhang 
1370*d4002b98SHong Zhang    This can be represented as a collection of submatrices as:
1371*d4002b98SHong Zhang 
1372*d4002b98SHong Zhang .vb
1373*d4002b98SHong Zhang       A B C
1374*d4002b98SHong Zhang       D E F
1375*d4002b98SHong Zhang       G H I
1376*d4002b98SHong Zhang .ve
1377*d4002b98SHong Zhang 
1378*d4002b98SHong Zhang    Where the submatrices A,B,C are owned by proc0, D,E,F are
1379*d4002b98SHong Zhang    owned by proc1, G,H,I are owned by proc2.
1380*d4002b98SHong Zhang 
1381*d4002b98SHong Zhang    The 'm' parameters for proc0,proc1,proc2 are 3,3,2 respectively.
1382*d4002b98SHong Zhang    The 'n' parameters for proc0,proc1,proc2 are 3,3,2 respectively.
1383*d4002b98SHong Zhang    The 'M','N' parameters are 8,8, and have the same values on all procs.
1384*d4002b98SHong Zhang 
1385*d4002b98SHong Zhang    The DIAGONAL submatrices corresponding to proc0,proc1,proc2 are
1386*d4002b98SHong Zhang    submatrices [A], [E], [I] respectively. The OFF-DIAGONAL submatrices
1387*d4002b98SHong Zhang    corresponding to proc0,proc1,proc2 are [BC], [DF], [GH] respectively.
1388*d4002b98SHong Zhang    Internally, each processor stores the DIAGONAL part, and the OFF-DIAGONAL
1389*d4002b98SHong Zhang    part as SeqSELL matrices. for eg: proc1 will store [E] as a SeqSELL
1390*d4002b98SHong Zhang    matrix, ans [DF] as another SeqSELL matrix.
1391*d4002b98SHong Zhang 
1392*d4002b98SHong Zhang    When d_nz, o_nz parameters are specified, d_nz storage elements are
1393*d4002b98SHong Zhang    allocated for every row of the local diagonal submatrix, and o_nz
1394*d4002b98SHong Zhang    storage locations are allocated for every row of the OFF-DIAGONAL submat.
1395*d4002b98SHong Zhang    One way to choose d_nz and o_nz is to use the max nonzerors per local
1396*d4002b98SHong Zhang    rows for each of the local DIAGONAL, and the OFF-DIAGONAL submatrices.
1397*d4002b98SHong Zhang    In this case, the values of d_nz,o_nz are:
1398*d4002b98SHong Zhang .vb
1399*d4002b98SHong Zhang      proc0 : dnz = 2, o_nz = 2
1400*d4002b98SHong Zhang      proc1 : dnz = 3, o_nz = 2
1401*d4002b98SHong Zhang      proc2 : dnz = 1, o_nz = 4
1402*d4002b98SHong Zhang .ve
1403*d4002b98SHong Zhang    We are allocating m*(d_nz+o_nz) storage locations for every proc. This
1404*d4002b98SHong Zhang    translates to 3*(2+2)=12 for proc0, 3*(3+2)=15 for proc1, 2*(1+4)=10
1405*d4002b98SHong Zhang    for proc3. i.e we are using 12+15+10=37 storage locations to store
1406*d4002b98SHong Zhang    34 values.
1407*d4002b98SHong Zhang 
1408*d4002b98SHong Zhang    When d_nnz, o_nnz parameters are specified, the storage is specified
1409*d4002b98SHong Zhang    for every row, coresponding to both DIAGONAL and OFF-DIAGONAL submatrices.
1410*d4002b98SHong Zhang    In the above case the values for d_nnz,o_nnz are:
1411*d4002b98SHong Zhang .vb
1412*d4002b98SHong Zhang      proc0: d_nnz = [2,2,2] and o_nnz = [2,2,2]
1413*d4002b98SHong Zhang      proc1: d_nnz = [3,3,2] and o_nnz = [2,1,1]
1414*d4002b98SHong Zhang      proc2: d_nnz = [1,1]   and o_nnz = [4,4]
1415*d4002b98SHong Zhang .ve
1416*d4002b98SHong Zhang    Here the space allocated is according to nz (or maximum values in the nnz
1417*d4002b98SHong Zhang    if nnz is provided) for DIAGONAL and OFF-DIAGONAL submatrices, i.e (2+2+3+2)*3+(1+4)*2=37
1418*d4002b98SHong Zhang 
1419*d4002b98SHong Zhang    Level: intermediate
1420*d4002b98SHong Zhang 
1421*d4002b98SHong Zhang .keywords: matrix, sell, sparse, parallel
1422*d4002b98SHong Zhang 
1423*d4002b98SHong Zhang .seealso: MatCreate(), MatCreateSeqSELL(), MatSetValues(), MatCreatesell(),
1424*d4002b98SHong Zhang           MATMPISELL, MatGetInfo(), PetscSplitOwnership()
1425*d4002b98SHong Zhang @*/
1426*d4002b98SHong Zhang PetscErrorCode MatMPISELLSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
1427*d4002b98SHong Zhang {
1428*d4002b98SHong Zhang   PetscErrorCode ierr;
1429*d4002b98SHong Zhang 
1430*d4002b98SHong Zhang   PetscFunctionBegin;
1431*d4002b98SHong Zhang   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
1432*d4002b98SHong Zhang   PetscValidType(B,1);
1433*d4002b98SHong Zhang   ierr = PetscTryMethod(B,"MatMPISELLSetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(B,d_nz,d_nnz,o_nz,o_nnz));CHKERRQ(ierr);
1434*d4002b98SHong Zhang   PetscFunctionReturn(0);
1435*d4002b98SHong Zhang }
1436*d4002b98SHong Zhang 
1437*d4002b98SHong Zhang /*@C
1438*d4002b98SHong Zhang    MatCreateSELL - Creates a sparse parallel matrix in SELL format.
1439*d4002b98SHong Zhang 
1440*d4002b98SHong Zhang    Collective on MPI_Comm
1441*d4002b98SHong Zhang 
1442*d4002b98SHong Zhang    Input Parameters:
1443*d4002b98SHong Zhang +  comm - MPI communicator
1444*d4002b98SHong Zhang .  m - number of local rows (or PETSC_DECIDE to have calculated if M is given)
1445*d4002b98SHong Zhang            This value should be the same as the local size used in creating the
1446*d4002b98SHong Zhang            y vector for the matrix-vector product y = Ax.
1447*d4002b98SHong Zhang .  n - This value should be the same as the local size used in creating the
1448*d4002b98SHong Zhang        x vector for the matrix-vector product y = Ax. (or PETSC_DECIDE to have
1449*d4002b98SHong Zhang        calculated if N is given) For square matrices n is almost always m.
1450*d4002b98SHong Zhang .  M - number of global rows (or PETSC_DETERMINE to have calculated if m is given)
1451*d4002b98SHong Zhang .  N - number of global columns (or PETSC_DETERMINE to have calculated if n is given)
1452*d4002b98SHong Zhang .  d_rlenmax - max number of nonzeros per row in DIAGONAL portion of local submatrix
1453*d4002b98SHong Zhang                (same value is used for all local rows)
1454*d4002b98SHong Zhang .  d_rlen - array containing the number of nonzeros in the various rows of the
1455*d4002b98SHong Zhang             DIAGONAL portion of the local submatrix (possibly different for each row)
1456*d4002b98SHong Zhang             or NULL, if d_rlenmax is used to specify the nonzero structure.
1457*d4002b98SHong Zhang             The size of this array is equal to the number of local rows, i.e 'm'.
1458*d4002b98SHong Zhang .  o_rlenmax - max number of nonzeros per row in the OFF-DIAGONAL portion of local
1459*d4002b98SHong Zhang                submatrix (same value is used for all local rows).
1460*d4002b98SHong Zhang -  o_rlen - array containing the number of nonzeros in the various rows of the
1461*d4002b98SHong Zhang             OFF-DIAGONAL portion of the local submatrix (possibly different for
1462*d4002b98SHong Zhang             each row) or NULL, if o_rlenmax is used to specify the nonzero
1463*d4002b98SHong Zhang             structure. The size of this array is equal to the number
1464*d4002b98SHong Zhang             of local rows, i.e 'm'.
1465*d4002b98SHong Zhang 
1466*d4002b98SHong Zhang    Output Parameter:
1467*d4002b98SHong Zhang .  A - the matrix
1468*d4002b98SHong Zhang 
1469*d4002b98SHong Zhang    It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(),
1470*d4002b98SHong Zhang    MatXXXXSetPreallocation() paradgm instead of this routine directly.
1471*d4002b98SHong Zhang    [MatXXXXSetPreallocation() is, for example, MatSeqSELLSetPreallocation]
1472*d4002b98SHong Zhang 
1473*d4002b98SHong Zhang    Notes:
1474*d4002b98SHong Zhang    If the *_rlen parameter is given then the *_rlenmax parameter is ignored
1475*d4002b98SHong Zhang 
1476*d4002b98SHong Zhang    m,n,M,N parameters specify the size of the matrix, and its partitioning across
1477*d4002b98SHong Zhang    processors, while d_rlenmax,d_rlen,o_rlenmax,o_rlen parameters specify the approximate
1478*d4002b98SHong Zhang    storage requirements for this matrix.
1479*d4002b98SHong Zhang 
1480*d4002b98SHong Zhang    If PETSC_DECIDE or  PETSC_DETERMINE is used for a particular argument on one
1481*d4002b98SHong Zhang    processor than it must be used on all processors that share the object for
1482*d4002b98SHong Zhang    that argument.
1483*d4002b98SHong Zhang 
1484*d4002b98SHong Zhang    The user MUST specify either the local or global matrix dimensions
1485*d4002b98SHong Zhang    (possibly both).
1486*d4002b98SHong Zhang 
1487*d4002b98SHong Zhang    The parallel matrix is partitioned across processors such that the
1488*d4002b98SHong Zhang    first m0 rows belong to process 0, the next m1 rows belong to
1489*d4002b98SHong Zhang    process 1, the next m2 rows belong to process 2 etc.. where
1490*d4002b98SHong Zhang    m0,m1,m2,.. are the input parameter 'm'. i.e each processor stores
1491*d4002b98SHong Zhang    values corresponding to [m x N] submatrix.
1492*d4002b98SHong Zhang 
1493*d4002b98SHong Zhang    The columns are logically partitioned with the n0 columns belonging
1494*d4002b98SHong Zhang    to 0th partition, the next n1 columns belonging to the next
1495*d4002b98SHong Zhang    partition etc.. where n0,n1,n2... are the input parameter 'n'.
1496*d4002b98SHong Zhang 
1497*d4002b98SHong Zhang    The DIAGONAL portion of the local submatrix on any given processor
1498*d4002b98SHong Zhang    is the submatrix corresponding to the rows and columns m,n
1499*d4002b98SHong Zhang    corresponding to the given processor. i.e diagonal matrix on
1500*d4002b98SHong Zhang    process 0 is [m0 x n0], diagonal matrix on process 1 is [m1 x n1]
1501*d4002b98SHong Zhang    etc. The remaining portion of the local submatrix [m x (N-n)]
1502*d4002b98SHong Zhang    constitute the OFF-DIAGONAL portion. The example below better
1503*d4002b98SHong Zhang    illustrates this concept.
1504*d4002b98SHong Zhang 
1505*d4002b98SHong Zhang    For a square global matrix we define each processor's diagonal portion
1506*d4002b98SHong Zhang    to be its local rows and the corresponding columns (a square submatrix);
1507*d4002b98SHong Zhang    each processor's off-diagonal portion encompasses the remainder of the
1508*d4002b98SHong Zhang    local matrix (a rectangular submatrix).
1509*d4002b98SHong Zhang 
1510*d4002b98SHong Zhang    If o_rlen, d_rlen are specified, then o_rlenmax, and d_rlenmax are ignored.
1511*d4002b98SHong Zhang 
1512*d4002b98SHong Zhang    When calling this routine with a single process communicator, a matrix of
1513*d4002b98SHong Zhang    type SEQSELL is returned.  If a matrix of type MATMPISELL is desired for this
1514*d4002b98SHong Zhang    type of communicator, use the construction mechanism:
1515*d4002b98SHong Zhang      MatCreate(...,&A); MatSetType(A,MATMPISELL); MatSetSizes(A, m,n,M,N); MatMPISELLSetPreallocation(A,...);
1516*d4002b98SHong Zhang 
1517*d4002b98SHong Zhang    Options Database Keys:
1518*d4002b98SHong Zhang -  -mat_sell_oneindex - Internally use indexing starting at 1
1519*d4002b98SHong Zhang         rather than 0.  Note that when calling MatSetValues(),
1520*d4002b98SHong Zhang         the user still MUST index entries starting at 0!
1521*d4002b98SHong Zhang 
1522*d4002b98SHong Zhang 
1523*d4002b98SHong Zhang    Example usage:
1524*d4002b98SHong Zhang 
1525*d4002b98SHong Zhang    Consider the following 8x8 matrix with 34 non-zero values, that is
1526*d4002b98SHong Zhang    assembled across 3 processors. Lets assume that proc0 owns 3 rows,
1527*d4002b98SHong Zhang    proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
1528*d4002b98SHong Zhang    as follows:
1529*d4002b98SHong Zhang 
1530*d4002b98SHong Zhang .vb
1531*d4002b98SHong Zhang             1  2  0  |  0  3  0  |  0  4
1532*d4002b98SHong Zhang     Proc0   0  5  6  |  7  0  0  |  8  0
1533*d4002b98SHong Zhang             9  0 10  | 11  0  0  | 12  0
1534*d4002b98SHong Zhang     -------------------------------------
1535*d4002b98SHong Zhang            13  0 14  | 15 16 17  |  0  0
1536*d4002b98SHong Zhang     Proc1   0 18  0  | 19 20 21  |  0  0
1537*d4002b98SHong Zhang             0  0  0  | 22 23  0  | 24  0
1538*d4002b98SHong Zhang     -------------------------------------
1539*d4002b98SHong Zhang     Proc2  25 26 27  |  0  0 28  | 29  0
1540*d4002b98SHong Zhang            30  0  0  | 31 32 33  |  0 34
1541*d4002b98SHong Zhang .ve
1542*d4002b98SHong Zhang 
1543*d4002b98SHong Zhang    This can be represented as a collection of submatrices as:
1544*d4002b98SHong Zhang 
1545*d4002b98SHong Zhang .vb
1546*d4002b98SHong Zhang       A B C
1547*d4002b98SHong Zhang       D E F
1548*d4002b98SHong Zhang       G H I
1549*d4002b98SHong Zhang .ve
1550*d4002b98SHong Zhang 
1551*d4002b98SHong Zhang    Where the submatrices A,B,C are owned by proc0, D,E,F are
1552*d4002b98SHong Zhang    owned by proc1, G,H,I are owned by proc2.
1553*d4002b98SHong Zhang 
1554*d4002b98SHong Zhang    The 'm' parameters for proc0,proc1,proc2 are 3,3,2 respectively.
1555*d4002b98SHong Zhang    The 'n' parameters for proc0,proc1,proc2 are 3,3,2 respectively.
1556*d4002b98SHong Zhang    The 'M','N' parameters are 8,8, and have the same values on all procs.
1557*d4002b98SHong Zhang 
1558*d4002b98SHong Zhang    The DIAGONAL submatrices corresponding to proc0,proc1,proc2 are
1559*d4002b98SHong Zhang    submatrices [A], [E], [I] respectively. The OFF-DIAGONAL submatrices
1560*d4002b98SHong Zhang    corresponding to proc0,proc1,proc2 are [BC], [DF], [GH] respectively.
1561*d4002b98SHong Zhang    Internally, each processor stores the DIAGONAL part, and the OFF-DIAGONAL
1562*d4002b98SHong Zhang    part as SeqSELL matrices. for eg: proc1 will store [E] as a SeqSELL
1563*d4002b98SHong Zhang    matrix, ans [DF] as another SeqSELL matrix.
1564*d4002b98SHong Zhang 
1565*d4002b98SHong Zhang    When d_rlenmax, o_rlenmax parameters are specified, d_rlenmax storage elements are
1566*d4002b98SHong Zhang    allocated for every row of the local diagonal submatrix, and o_rlenmax
1567*d4002b98SHong Zhang    storage locations are allocated for every row of the OFF-DIAGONAL submat.
1568*d4002b98SHong Zhang    One way to choose d_rlenmax and o_rlenmax is to use the max nonzerors per local
1569*d4002b98SHong Zhang    rows for each of the local DIAGONAL, and the OFF-DIAGONAL submatrices.
1570*d4002b98SHong Zhang    In this case, the values of d_rlenmax,o_rlenmax are:
1571*d4002b98SHong Zhang .vb
1572*d4002b98SHong Zhang      proc0 : d_rlenmax = 2, o_rlenmax = 2
1573*d4002b98SHong Zhang      proc1 : d_rlenmax = 3, o_rlenmax = 2
1574*d4002b98SHong Zhang      proc2 : d_rlenmax = 1, o_rlenmax = 4
1575*d4002b98SHong Zhang .ve
1576*d4002b98SHong Zhang    We are allocating m*(d_rlenmax+o_rlenmax) storage locations for every proc. This
1577*d4002b98SHong Zhang    translates to 3*(2+2)=12 for proc0, 3*(3+2)=15 for proc1, 2*(1+4)=10
1578*d4002b98SHong Zhang    for proc3. i.e we are using 12+15+10=37 storage locations to store
1579*d4002b98SHong Zhang    34 values.
1580*d4002b98SHong Zhang 
1581*d4002b98SHong Zhang    When d_rlen, o_rlen parameters are specified, the storage is specified
1582*d4002b98SHong Zhang    for every row, coresponding to both DIAGONAL and OFF-DIAGONAL submatrices.
1583*d4002b98SHong Zhang    In the above case the values for d_nnz,o_nnz are:
1584*d4002b98SHong Zhang .vb
1585*d4002b98SHong Zhang      proc0: d_nnz = [2,2,2] and o_nnz = [2,2,2]
1586*d4002b98SHong Zhang      proc1: d_nnz = [3,3,2] and o_nnz = [2,1,1]
1587*d4002b98SHong Zhang      proc2: d_nnz = [1,1]   and o_nnz = [4,4]
1588*d4002b98SHong Zhang .ve
1589*d4002b98SHong Zhang    Here the space allocated is still 37 though there are 34 nonzeros because
1590*d4002b98SHong Zhang    the allocation is always done according to rlenmax.
1591*d4002b98SHong Zhang 
1592*d4002b98SHong Zhang    Level: intermediate
1593*d4002b98SHong Zhang 
1594*d4002b98SHong Zhang .keywords: matrix, sell, sparse, parallel
1595*d4002b98SHong Zhang 
1596*d4002b98SHong Zhang .seealso: MatCreate(), MatCreateSeqSELL(), MatSetValues(), MatMPISELLSetPreallocation(), MatMPISELLSetPreallocationSELL(),
1597*d4002b98SHong Zhang           MATMPISELL, MatCreateMPISELLWithArrays()
1598*d4002b98SHong Zhang @*/
1599*d4002b98SHong Zhang PetscErrorCode MatCreateSELL(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt M,PetscInt N,PetscInt d_rlenmax,const PetscInt d_rlen[],PetscInt o_rlenmax,const PetscInt o_rlen[],Mat *A)
1600*d4002b98SHong Zhang {
1601*d4002b98SHong Zhang   PetscErrorCode ierr;
1602*d4002b98SHong Zhang   PetscMPIInt    size;
1603*d4002b98SHong Zhang 
1604*d4002b98SHong Zhang   PetscFunctionBegin;
1605*d4002b98SHong Zhang   ierr = MatCreate(comm,A);CHKERRQ(ierr);
1606*d4002b98SHong Zhang   ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr);
1607*d4002b98SHong Zhang   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
1608*d4002b98SHong Zhang   if (size > 1) {
1609*d4002b98SHong Zhang     ierr = MatSetType(*A,MATMPISELL);CHKERRQ(ierr);
1610*d4002b98SHong Zhang     ierr = MatMPISELLSetPreallocation(*A,d_rlenmax,d_rlen,o_rlenmax,o_rlen);CHKERRQ(ierr);
1611*d4002b98SHong Zhang   } else {
1612*d4002b98SHong Zhang     ierr = MatSetType(*A,MATSEQSELL);CHKERRQ(ierr);
1613*d4002b98SHong Zhang     ierr = MatSeqSELLSetPreallocation(*A,d_rlenmax,d_rlen);CHKERRQ(ierr);
1614*d4002b98SHong Zhang   }
1615*d4002b98SHong Zhang   PetscFunctionReturn(0);
1616*d4002b98SHong Zhang }
1617*d4002b98SHong Zhang 
1618*d4002b98SHong Zhang PetscErrorCode MatMPISELLGetSeqSELL(Mat A,Mat *Ad,Mat *Ao,const PetscInt *colmap[])
1619*d4002b98SHong Zhang {
1620*d4002b98SHong Zhang   Mat_MPISELL    *a=(Mat_MPISELL*)A->data;
1621*d4002b98SHong Zhang   PetscBool      flg;
1622*d4002b98SHong Zhang   PetscErrorCode ierr;
1623*d4002b98SHong Zhang 
1624*d4002b98SHong Zhang   PetscFunctionBegin;
1625*d4002b98SHong Zhang   ierr = PetscObjectTypeCompare((PetscObject)A,MATMPISELL,&flg);CHKERRQ(ierr);
1626*d4002b98SHong Zhang   if (!flg) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"This function requires a MATMPISELL matrix as input");
1627*d4002b98SHong Zhang   if (Ad)     *Ad     = a->A;
1628*d4002b98SHong Zhang   if (Ao)     *Ao     = a->B;
1629*d4002b98SHong Zhang   if (colmap) *colmap = a->garray;
1630*d4002b98SHong Zhang   PetscFunctionReturn(0);
1631*d4002b98SHong Zhang }
1632*d4002b98SHong Zhang 
1633*d4002b98SHong Zhang /*@C
1634*d4002b98SHong Zhang      MatMPISELLGetLocalMatCondensed - Creates a SeqSELL matrix from an MATMPISELL matrix by taking all its local rows and NON-ZERO columns
1635*d4002b98SHong Zhang 
1636*d4002b98SHong Zhang     Not Collective
1637*d4002b98SHong Zhang 
1638*d4002b98SHong Zhang    Input Parameters:
1639*d4002b98SHong Zhang +    A - the matrix
1640*d4002b98SHong Zhang .    scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
1641*d4002b98SHong Zhang -    row, col - index sets of rows and columns to extract (or NULL)
1642*d4002b98SHong Zhang 
1643*d4002b98SHong Zhang    Output Parameter:
1644*d4002b98SHong Zhang .    A_loc - the local sequential matrix generated
1645*d4002b98SHong Zhang 
1646*d4002b98SHong Zhang     Level: developer
1647*d4002b98SHong Zhang 
1648*d4002b98SHong Zhang .seealso: MatGetOwnershipRange(), MatMPISELLGetLocalMat()
1649*d4002b98SHong Zhang 
1650*d4002b98SHong Zhang @*/
1651*d4002b98SHong Zhang PetscErrorCode MatMPISELLGetLocalMatCondensed(Mat A,MatReuse scall,IS *row,IS *col,Mat *A_loc)
1652*d4002b98SHong Zhang {
1653*d4002b98SHong Zhang   Mat_MPISELL    *a=(Mat_MPISELL*)A->data;
1654*d4002b98SHong Zhang   PetscErrorCode ierr;
1655*d4002b98SHong Zhang   PetscInt       i,start,end,ncols,nzA,nzB,*cmap,imark,*idx;
1656*d4002b98SHong Zhang   IS             isrowa,iscola;
1657*d4002b98SHong Zhang   Mat            *aloc;
1658*d4002b98SHong Zhang   PetscBool      match;
1659*d4002b98SHong Zhang 
1660*d4002b98SHong Zhang   PetscFunctionBegin;
1661*d4002b98SHong Zhang   ierr = PetscObjectTypeCompare((PetscObject)A,MATMPISELL,&match);CHKERRQ(ierr);
1662*d4002b98SHong Zhang   if (!match) SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_SUP,"Requires MATMPISELL matrix as input");
1663*d4002b98SHong Zhang   ierr = PetscLogEventBegin(MAT_Getlocalmatcondensed,A,0,0,0);CHKERRQ(ierr);
1664*d4002b98SHong Zhang   if (!row) {
1665*d4002b98SHong Zhang     start = A->rmap->rstart; end = A->rmap->rend;
1666*d4002b98SHong Zhang     ierr  = ISCreateStride(PETSC_COMM_SELF,end-start,start,1,&isrowa);CHKERRQ(ierr);
1667*d4002b98SHong Zhang   } else {
1668*d4002b98SHong Zhang     isrowa = *row;
1669*d4002b98SHong Zhang   }
1670*d4002b98SHong Zhang   if (!col) {
1671*d4002b98SHong Zhang     start = A->cmap->rstart;
1672*d4002b98SHong Zhang     cmap  = a->garray;
1673*d4002b98SHong Zhang     nzA   = a->A->cmap->n;
1674*d4002b98SHong Zhang     nzB   = a->B->cmap->n;
1675*d4002b98SHong Zhang     ierr  = PetscMalloc1(nzA+nzB, &idx);CHKERRQ(ierr);
1676*d4002b98SHong Zhang     ncols = 0;
1677*d4002b98SHong Zhang     for (i=0; i<nzB; i++) {
1678*d4002b98SHong Zhang       if (cmap[i] < start) idx[ncols++] = cmap[i];
1679*d4002b98SHong Zhang       else break;
1680*d4002b98SHong Zhang     }
1681*d4002b98SHong Zhang     imark = i;
1682*d4002b98SHong Zhang     for (i=0; i<nzA; i++) idx[ncols++] = start + i;
1683*d4002b98SHong Zhang     for (i=imark; i<nzB; i++) idx[ncols++] = cmap[i];
1684*d4002b98SHong Zhang     ierr = ISCreateGeneral(PETSC_COMM_SELF,ncols,idx,PETSC_OWN_POINTER,&iscola);CHKERRQ(ierr);
1685*d4002b98SHong Zhang   } else {
1686*d4002b98SHong Zhang     iscola = *col;
1687*d4002b98SHong Zhang   }
1688*d4002b98SHong Zhang   if (scall != MAT_INITIAL_MATRIX) {
1689*d4002b98SHong Zhang     ierr    = PetscMalloc1(1,&aloc);CHKERRQ(ierr);
1690*d4002b98SHong Zhang     aloc[0] = *A_loc;
1691*d4002b98SHong Zhang   }
1692*d4002b98SHong Zhang   ierr   = MatCreateSubMatrices(A,1,&isrowa,&iscola,scall,&aloc);CHKERRQ(ierr);
1693*d4002b98SHong Zhang   *A_loc = aloc[0];
1694*d4002b98SHong Zhang   ierr   = PetscFree(aloc);CHKERRQ(ierr);
1695*d4002b98SHong Zhang   if (!row) {
1696*d4002b98SHong Zhang     ierr = ISDestroy(&isrowa);CHKERRQ(ierr);
1697*d4002b98SHong Zhang   }
1698*d4002b98SHong Zhang   if (!col) {
1699*d4002b98SHong Zhang     ierr = ISDestroy(&iscola);CHKERRQ(ierr);
1700*d4002b98SHong Zhang   }
1701*d4002b98SHong Zhang   ierr = PetscLogEventEnd(MAT_Getlocalmatcondensed,A,0,0,0);CHKERRQ(ierr);
1702*d4002b98SHong Zhang   PetscFunctionReturn(0);
1703*d4002b98SHong Zhang }
1704*d4002b98SHong Zhang 
1705*d4002b98SHong Zhang #include <../src/mat/impls/aij/mpi/mpiaij.h>
1706*d4002b98SHong Zhang 
1707*d4002b98SHong Zhang PetscErrorCode MatConvert_MPISELL_MPIAIJ(Mat A,MatType newtype,MatReuse reuse,Mat *newmat)
1708*d4002b98SHong Zhang {
1709*d4002b98SHong Zhang   PetscErrorCode ierr;
1710*d4002b98SHong Zhang   Mat_MPISELL    *a=(Mat_MPISELL*)A->data;
1711*d4002b98SHong Zhang   Mat            B;
1712*d4002b98SHong Zhang   Mat_MPIAIJ     *b;
1713*d4002b98SHong Zhang 
1714*d4002b98SHong Zhang   PetscFunctionBegin;
1715*d4002b98SHong Zhang   if (!A->assembled) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Matrix must be assembled");
1716*d4002b98SHong Zhang 
1717*d4002b98SHong Zhang   ierr = MatCreate(PetscObjectComm((PetscObject)A),&B);CHKERRQ(ierr);
1718*d4002b98SHong Zhang   ierr = MatSetType(B,MATMPIAIJ);CHKERRQ(ierr);
1719*d4002b98SHong Zhang   ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
1720*d4002b98SHong Zhang   ierr = MatSetBlockSizes(B,A->rmap->bs,A->cmap->bs);CHKERRQ(ierr);
1721*d4002b98SHong Zhang   ierr = MatSeqAIJSetPreallocation(B,0,NULL);CHKERRQ(ierr);
1722*d4002b98SHong Zhang   ierr = MatMPIAIJSetPreallocation(B,0,NULL,0,NULL);CHKERRQ(ierr);
1723*d4002b98SHong Zhang   b    = (Mat_MPIAIJ*) B->data;
1724*d4002b98SHong Zhang   ierr = MatDestroy(&b->A);CHKERRQ(ierr);
1725*d4002b98SHong Zhang   ierr = MatDestroy(&b->B);CHKERRQ(ierr);
1726*d4002b98SHong Zhang   ierr = MatDisAssemble_MPISELL(A);CHKERRQ(ierr);
1727*d4002b98SHong Zhang   ierr = MatConvert_SeqSELL_SeqAIJ(a->A, MATSEQAIJ, MAT_INITIAL_MATRIX, &b->A);CHKERRQ(ierr);
1728*d4002b98SHong Zhang   ierr = MatConvert_SeqSELL_SeqAIJ(a->B, MATSEQAIJ, MAT_INITIAL_MATRIX, &b->B);CHKERRQ(ierr);
1729*d4002b98SHong Zhang   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1730*d4002b98SHong Zhang   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1731*d4002b98SHong Zhang   ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1732*d4002b98SHong Zhang   ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1733*d4002b98SHong Zhang 
1734*d4002b98SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
1735*d4002b98SHong Zhang     ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr);
1736*d4002b98SHong Zhang   } else {
1737*d4002b98SHong Zhang     *newmat = B;
1738*d4002b98SHong Zhang   }
1739*d4002b98SHong Zhang   PetscFunctionReturn(0);
1740*d4002b98SHong Zhang }
1741*d4002b98SHong Zhang 
1742*d4002b98SHong Zhang PetscErrorCode MatConvert_MPIAIJ_MPISELL(Mat A,MatType newtype,MatReuse reuse,Mat *newmat)
1743*d4002b98SHong Zhang {
1744*d4002b98SHong Zhang   PetscErrorCode ierr;
1745*d4002b98SHong Zhang   Mat_MPIAIJ     *a=(Mat_MPIAIJ*)A->data;
1746*d4002b98SHong Zhang   Mat            B;
1747*d4002b98SHong Zhang   Mat_MPISELL    *b;
1748*d4002b98SHong Zhang 
1749*d4002b98SHong Zhang   PetscFunctionBegin;
1750*d4002b98SHong Zhang   if (!A->assembled) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Matrix must be assembled");
1751*d4002b98SHong Zhang 
1752*d4002b98SHong Zhang   ierr = MatCreate(PetscObjectComm((PetscObject)A),&B);CHKERRQ(ierr);
1753*d4002b98SHong Zhang   ierr = MatSetType(B,MATMPISELL);CHKERRQ(ierr);
1754*d4002b98SHong Zhang   ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
1755*d4002b98SHong Zhang   ierr = MatSetBlockSizes(B,A->rmap->bs,A->cmap->bs);CHKERRQ(ierr);
1756*d4002b98SHong Zhang   ierr = MatSeqAIJSetPreallocation(B,0,NULL);CHKERRQ(ierr);
1757*d4002b98SHong Zhang   ierr = MatMPIAIJSetPreallocation(B,0,NULL,0,NULL);CHKERRQ(ierr);
1758*d4002b98SHong Zhang   b    = (Mat_MPISELL*) B->data;
1759*d4002b98SHong Zhang   ierr = MatDestroy(&b->A);CHKERRQ(ierr);
1760*d4002b98SHong Zhang   ierr = MatDestroy(&b->B);CHKERRQ(ierr);
1761*d4002b98SHong Zhang   ierr = MatDisAssemble_MPIAIJ(A);CHKERRQ(ierr);
1762*d4002b98SHong Zhang   ierr = MatConvert_SeqAIJ_SeqSELL(a->A, MATSEQSELL, MAT_INITIAL_MATRIX, &b->A);CHKERRQ(ierr);
1763*d4002b98SHong Zhang   ierr = MatConvert_SeqAIJ_SeqSELL(a->B, MATSEQSELL, MAT_INITIAL_MATRIX, &b->B);CHKERRQ(ierr);
1764*d4002b98SHong Zhang   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1765*d4002b98SHong Zhang   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1766*d4002b98SHong Zhang   ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1767*d4002b98SHong Zhang   ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1768*d4002b98SHong Zhang 
1769*d4002b98SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
1770*d4002b98SHong Zhang     ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr);
1771*d4002b98SHong Zhang   } else {
1772*d4002b98SHong Zhang     *newmat = B;
1773*d4002b98SHong Zhang   }
1774*d4002b98SHong Zhang   PetscFunctionReturn(0);
1775*d4002b98SHong Zhang }
1776*d4002b98SHong Zhang 
1777*d4002b98SHong Zhang PetscErrorCode MatSOR_MPISELL(Mat matin,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx)
1778*d4002b98SHong Zhang {
1779*d4002b98SHong Zhang   Mat_MPISELL    *mat=(Mat_MPISELL*)matin->data;
1780*d4002b98SHong Zhang   PetscErrorCode ierr;
1781*d4002b98SHong Zhang   Vec            bb1=0;
1782*d4002b98SHong Zhang 
1783*d4002b98SHong Zhang   PetscFunctionBegin;
1784*d4002b98SHong Zhang   if (flag == SOR_APPLY_UPPER) {
1785*d4002b98SHong Zhang     ierr = (*mat->A->ops->sor)(mat->A,bb,omega,flag,fshift,lits,1,xx);CHKERRQ(ierr);
1786*d4002b98SHong Zhang     PetscFunctionReturn(0);
1787*d4002b98SHong Zhang   }
1788*d4002b98SHong Zhang 
1789*d4002b98SHong Zhang   if (its > 1 || ~flag & SOR_ZERO_INITIAL_GUESS || flag & SOR_EISENSTAT) {
1790*d4002b98SHong Zhang     ierr = VecDuplicate(bb,&bb1);CHKERRQ(ierr);
1791*d4002b98SHong Zhang   }
1792*d4002b98SHong Zhang 
1793*d4002b98SHong Zhang   if ((flag & SOR_LOCAL_SYMMETRIC_SWEEP) == SOR_LOCAL_SYMMETRIC_SWEEP) {
1794*d4002b98SHong Zhang     if (flag & SOR_ZERO_INITIAL_GUESS) {
1795*d4002b98SHong Zhang       ierr = (*mat->A->ops->sor)(mat->A,bb,omega,flag,fshift,lits,1,xx);CHKERRQ(ierr);
1796*d4002b98SHong Zhang       its--;
1797*d4002b98SHong Zhang     }
1798*d4002b98SHong Zhang 
1799*d4002b98SHong Zhang     while (its--) {
1800*d4002b98SHong Zhang       ierr = VecScatterBegin(mat->Mvctx,xx,mat->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1801*d4002b98SHong Zhang       ierr = VecScatterEnd(mat->Mvctx,xx,mat->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1802*d4002b98SHong Zhang 
1803*d4002b98SHong Zhang       /* update rhs: bb1 = bb - B*x */
1804*d4002b98SHong Zhang       ierr = VecScale(mat->lvec,-1.0);CHKERRQ(ierr);
1805*d4002b98SHong Zhang       ierr = (*mat->B->ops->multadd)(mat->B,mat->lvec,bb,bb1);CHKERRQ(ierr);
1806*d4002b98SHong Zhang 
1807*d4002b98SHong Zhang       /* local sweep */
1808*d4002b98SHong Zhang       ierr = (*mat->A->ops->sor)(mat->A,bb1,omega,SOR_SYMMETRIC_SWEEP,fshift,lits,1,xx);CHKERRQ(ierr);
1809*d4002b98SHong Zhang     }
1810*d4002b98SHong Zhang   } else if (flag & SOR_LOCAL_FORWARD_SWEEP) {
1811*d4002b98SHong Zhang     if (flag & SOR_ZERO_INITIAL_GUESS) {
1812*d4002b98SHong Zhang       ierr = (*mat->A->ops->sor)(mat->A,bb,omega,flag,fshift,lits,1,xx);CHKERRQ(ierr);
1813*d4002b98SHong Zhang       its--;
1814*d4002b98SHong Zhang     }
1815*d4002b98SHong Zhang     while (its--) {
1816*d4002b98SHong Zhang       ierr = VecScatterBegin(mat->Mvctx,xx,mat->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1817*d4002b98SHong Zhang       ierr = VecScatterEnd(mat->Mvctx,xx,mat->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1818*d4002b98SHong Zhang 
1819*d4002b98SHong Zhang       /* update rhs: bb1 = bb - B*x */
1820*d4002b98SHong Zhang       ierr = VecScale(mat->lvec,-1.0);CHKERRQ(ierr);
1821*d4002b98SHong Zhang       ierr = (*mat->B->ops->multadd)(mat->B,mat->lvec,bb,bb1);CHKERRQ(ierr);
1822*d4002b98SHong Zhang 
1823*d4002b98SHong Zhang       /* local sweep */
1824*d4002b98SHong Zhang       ierr = (*mat->A->ops->sor)(mat->A,bb1,omega,SOR_FORWARD_SWEEP,fshift,lits,1,xx);CHKERRQ(ierr);
1825*d4002b98SHong Zhang     }
1826*d4002b98SHong Zhang   } else if (flag & SOR_LOCAL_BACKWARD_SWEEP) {
1827*d4002b98SHong Zhang     if (flag & SOR_ZERO_INITIAL_GUESS) {
1828*d4002b98SHong Zhang       ierr = (*mat->A->ops->sor)(mat->A,bb,omega,flag,fshift,lits,1,xx);CHKERRQ(ierr);
1829*d4002b98SHong Zhang       its--;
1830*d4002b98SHong Zhang     }
1831*d4002b98SHong Zhang     while (its--) {
1832*d4002b98SHong Zhang       ierr = VecScatterBegin(mat->Mvctx,xx,mat->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1833*d4002b98SHong Zhang       ierr = VecScatterEnd(mat->Mvctx,xx,mat->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1834*d4002b98SHong Zhang 
1835*d4002b98SHong Zhang       /* update rhs: bb1 = bb - B*x */
1836*d4002b98SHong Zhang       ierr = VecScale(mat->lvec,-1.0);CHKERRQ(ierr);
1837*d4002b98SHong Zhang       ierr = (*mat->B->ops->multadd)(mat->B,mat->lvec,bb,bb1);CHKERRQ(ierr);
1838*d4002b98SHong Zhang 
1839*d4002b98SHong Zhang       /* local sweep */
1840*d4002b98SHong Zhang       ierr = (*mat->A->ops->sor)(mat->A,bb1,omega,SOR_BACKWARD_SWEEP,fshift,lits,1,xx);CHKERRQ(ierr);
1841*d4002b98SHong Zhang     }
1842*d4002b98SHong Zhang   } else SETERRQ(PetscObjectComm((PetscObject)matin),PETSC_ERR_SUP,"Parallel SOR not supported");
1843*d4002b98SHong Zhang 
1844*d4002b98SHong Zhang   ierr = VecDestroy(&bb1);CHKERRQ(ierr);
1845*d4002b98SHong Zhang 
1846*d4002b98SHong Zhang   matin->factorerrortype = mat->A->factorerrortype;
1847*d4002b98SHong Zhang   PetscFunctionReturn(0);
1848*d4002b98SHong Zhang }
1849*d4002b98SHong Zhang 
1850*d4002b98SHong Zhang /*MC
1851*d4002b98SHong Zhang    MATMPISELL - MATMPISELL = "MPISELL" - A matrix type to be used for parallel sparse matrices.
1852*d4002b98SHong Zhang 
1853*d4002b98SHong Zhang    Options Database Keys:
1854*d4002b98SHong Zhang . -mat_type MPISELL - sets the matrix type to "MPISELL" during a call to MatSetFromOptions()
1855*d4002b98SHong Zhang 
1856*d4002b98SHong Zhang   Level: beginner
1857*d4002b98SHong Zhang 
1858*d4002b98SHong Zhang .seealso: MatCreateSELL()
1859*d4002b98SHong Zhang M*/
1860*d4002b98SHong Zhang PETSC_EXTERN PetscErrorCode MatCreate_MPISELL(Mat B)
1861*d4002b98SHong Zhang {
1862*d4002b98SHong Zhang   Mat_MPISELL    *b;
1863*d4002b98SHong Zhang   PetscErrorCode ierr;
1864*d4002b98SHong Zhang   PetscMPIInt    size;
1865*d4002b98SHong Zhang 
1866*d4002b98SHong Zhang   PetscFunctionBegin;
1867*d4002b98SHong Zhang   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)B),&size);CHKERRQ(ierr);
1868*d4002b98SHong Zhang   ierr          = PetscNewLog(B,&b);CHKERRQ(ierr);
1869*d4002b98SHong Zhang   B->data       = (void*)b;
1870*d4002b98SHong Zhang   ierr          = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
1871*d4002b98SHong Zhang   B->assembled  = PETSC_FALSE;
1872*d4002b98SHong Zhang   B->insertmode = NOT_SET_VALUES;
1873*d4002b98SHong Zhang   b->size       = size;
1874*d4002b98SHong Zhang   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)B),&b->rank);CHKERRQ(ierr);
1875*d4002b98SHong Zhang   /* build cache for off array entries formed */
1876*d4002b98SHong Zhang   ierr = MatStashCreate_Private(PetscObjectComm((PetscObject)B),1,&B->stash);CHKERRQ(ierr);
1877*d4002b98SHong Zhang 
1878*d4002b98SHong Zhang   b->donotstash  = PETSC_FALSE;
1879*d4002b98SHong Zhang   b->colmap      = 0;
1880*d4002b98SHong Zhang   b->garray      = 0;
1881*d4002b98SHong Zhang   b->roworiented = PETSC_TRUE;
1882*d4002b98SHong Zhang 
1883*d4002b98SHong Zhang   /* stuff used for matrix vector multiply */
1884*d4002b98SHong Zhang   b->lvec  = NULL;
1885*d4002b98SHong Zhang   b->Mvctx = NULL;
1886*d4002b98SHong Zhang 
1887*d4002b98SHong Zhang   /* stuff for MatGetRow() */
1888*d4002b98SHong Zhang   b->rowindices   = 0;
1889*d4002b98SHong Zhang   b->rowvalues    = 0;
1890*d4002b98SHong Zhang   b->getrowactive = PETSC_FALSE;
1891*d4002b98SHong Zhang 
1892*d4002b98SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatStoreValues_C",MatStoreValues_MPISELL);CHKERRQ(ierr);
1893*d4002b98SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatRetrieveValues_C",MatRetrieveValues_MPISELL);CHKERRQ(ierr);
1894*d4002b98SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatIsTranspose_C",MatIsTranspose_MPISELL);CHKERRQ(ierr);
1895*d4002b98SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatMPISELLSetPreallocation_C",MatMPISELLSetPreallocation_MPISELL);CHKERRQ(ierr);
1896*d4002b98SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_mpisell_mpiaij_C",MatConvert_MPISELL_MPIAIJ);CHKERRQ(ierr);
1897*d4002b98SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatDiagonalScaleLocal_C",MatDiagonalScaleLocal_MPISELL);CHKERRQ(ierr);
1898*d4002b98SHong Zhang   ierr = PetscObjectChangeTypeName((PetscObject)B,MATMPISELL);CHKERRQ(ierr);
1899*d4002b98SHong Zhang   PetscFunctionReturn(0);
1900*d4002b98SHong Zhang }
1901