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,¬me);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