1*d4002b98SHong Zhang 2*d4002b98SHong Zhang #if !defined(__SELL_H) 3*d4002b98SHong Zhang #define __SELL_H 4*d4002b98SHong Zhang 5*d4002b98SHong Zhang #include <petsc/private/matimpl.h> 6*d4002b98SHong Zhang #include <petscctable.h> 7*d4002b98SHong Zhang 8*d4002b98SHong Zhang /* 9*d4002b98SHong Zhang Struct header for SeqSELL matrix format 10*d4002b98SHong Zhang */ 11*d4002b98SHong Zhang #define SEQSELLHEADER(datatype) \ 12*d4002b98SHong Zhang PetscBool roworiented; /* if true, row-oriented input, default */ \ 13*d4002b98SHong Zhang PetscInt nonew; /* 1 don't add new nonzeros, -1 generate error on new */ \ 14*d4002b98SHong Zhang PetscInt nounused; /* -1 generate error on unused space */ \ 15*d4002b98SHong Zhang PetscBool singlemalloc; /* if true a, i, and j have been obtained with one big malloc */ \ 16*d4002b98SHong Zhang PetscInt maxallocmat; /* max allocated space for the matrix */ \ 17*d4002b98SHong Zhang PetscInt maxallocrow; /* max allocated space for each row */ \ 18*d4002b98SHong Zhang PetscInt nz; /* actual nonzeros */ \ 19*d4002b98SHong Zhang PetscInt rlenmax; /* max actual row length, rmax cannot exceed maxallocrow */ \ 20*d4002b98SHong Zhang PetscInt *rlen; /* actual length of each row (padding zeros excluded) */ \ 21*d4002b98SHong Zhang PetscBool free_rlen; /* free rlen array ? */ \ 22*d4002b98SHong Zhang PetscInt reallocs; /* number of mallocs done during MatSetValues() \ 23*d4002b98SHong Zhang as more values are set than were prealloced */\ 24*d4002b98SHong Zhang PetscBool keepnonzeropattern;/* keeps matrix structure same in calls to MatZeroRows()*/ \ 25*d4002b98SHong Zhang PetscBool ignorezeroentries; \ 26*d4002b98SHong Zhang PetscBool free_colidx; /* free the column indices colidx when the matrix is destroyed */ \ 27*d4002b98SHong Zhang PetscBool free_val; /* free the numerical values when matrix is destroy */ \ 28*d4002b98SHong Zhang PetscInt *colidx; /* column index */ \ 29*d4002b98SHong Zhang PetscInt *diag; /* pointers to diagonal elements */ \ 30*d4002b98SHong Zhang PetscInt nonzerorowcnt; /* how many rows have nonzero entries */ \ 31*d4002b98SHong Zhang PetscBool free_diag; /* free diag ? */ \ 32*d4002b98SHong Zhang datatype *val; /* elements including nonzeros and padding zeros */ \ 33*d4002b98SHong Zhang PetscScalar *solve_work; /* work space used in MatSolve */ \ 34*d4002b98SHong Zhang IS row, col, icol; /* index sets, used for reorderings */ \ 35*d4002b98SHong Zhang PetscBool pivotinblocks; /* pivot inside factorization of each diagonal block */ \ 36*d4002b98SHong Zhang Mat parent; /* set if this matrix was formed with MatDuplicate(...,MAT_SHARE_NONZERO_PATTERN,....); 37*d4002b98SHong Zhang means that this shares some data structures with the parent including diag, ilen, imax, i, j */ \ 38*d4002b98SHong Zhang PetscInt *sliidx; /* slice index */ \ 39*d4002b98SHong Zhang PetscInt totalslices; /* total number of slices */ \ 40*d4002b98SHong Zhang 41*d4002b98SHong Zhang typedef struct { 42*d4002b98SHong Zhang SEQSELLHEADER(MatScalar); 43*d4002b98SHong Zhang MatScalar *saved_values; /* location for stashing nonzero values of matrix */ 44*d4002b98SHong Zhang PetscScalar *idiag,*mdiag,*ssor_work; /* inverse of diagonal entries, diagonal values and workspace for Eisenstat trick */ 45*d4002b98SHong Zhang PetscBool idiagvalid; /* current idiag[] and mdiag[] are valid */ 46*d4002b98SHong Zhang PetscScalar *ibdiag; /* inverses of block diagonals */ 47*d4002b98SHong Zhang PetscBool ibdiagvalid; /* inverses of block diagonals are valid. */ 48*d4002b98SHong Zhang PetscScalar fshift,omega; /* last used omega and fshift */ 49*d4002b98SHong Zhang ISColoring coloring; /* set with MatADSetColoring() used by MatADSetValues() */ 50*d4002b98SHong Zhang } Mat_SeqSELL; 51*d4002b98SHong Zhang 52*d4002b98SHong Zhang /* 53*d4002b98SHong Zhang Frees the arrays from the XSELLPACK matrix type 54*d4002b98SHong Zhang */ 55*d4002b98SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSeqXSELLFreeSELL(Mat AA,MatScalar **val,PetscInt **colidx) 56*d4002b98SHong Zhang { 57*d4002b98SHong Zhang Mat_SeqSELL *A = (Mat_SeqSELL*) AA->data; 58*d4002b98SHong Zhang PetscErrorCode ierr; 59*d4002b98SHong Zhang if (A->singlemalloc) { 60*d4002b98SHong Zhang ierr = PetscFree2(*val,*colidx);CHKERRQ(ierr); 61*d4002b98SHong Zhang } else { 62*d4002b98SHong Zhang if (A->free_val) {ierr = PetscFree(*val);CHKERRQ(ierr);} 63*d4002b98SHong Zhang if (A->free_colidx) {ierr = PetscFree(*colidx);CHKERRQ(ierr);} 64*d4002b98SHong Zhang } 65*d4002b98SHong Zhang return 0; 66*d4002b98SHong Zhang } 67*d4002b98SHong Zhang 68*d4002b98SHong Zhang #define MatSeqXSELLReallocateSELL(Amat,AM,BS2,WIDTH,SIDX,SID,ROW,COL,COLIDX,VAL,CP,VP,NONEW,datatype) \ 69*d4002b98SHong Zhang if (WIDTH >= (SIDX[SID+1]-SIDX[SID])/8) { \ 70*d4002b98SHong Zhang Mat_SeqSELL *Ain = (Mat_SeqSELL*)Amat->data; \ 71*d4002b98SHong Zhang /* there is no extra room in row, therefore enlarge 8 elements (1 slice column) */ \ 72*d4002b98SHong Zhang PetscInt new_size=Ain->maxallocmat+8,*new_colidx; \ 73*d4002b98SHong Zhang datatype *new_val; \ 74*d4002b98SHong Zhang \ 75*d4002b98SHong Zhang if (NONEW == -2) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"New nonzero at (%D,%D) caused a malloc\nUse MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE) to turn off this check",ROW,COL); \ 76*d4002b98SHong Zhang /* malloc new storage space */ \ 77*d4002b98SHong Zhang ierr = PetscMalloc2(BS2*new_size,&new_val,BS2*new_size,&new_colidx);CHKERRQ(ierr); \ 78*d4002b98SHong Zhang \ 79*d4002b98SHong Zhang /* copy over old data into new slots by two steps: one step for data before the current slice and the other for the rest */ \ 80*d4002b98SHong Zhang ierr = PetscMemcpy(new_val,VAL,SIDX[SID+1]*sizeof(datatype));CHKERRQ(ierr); \ 81*d4002b98SHong Zhang ierr = PetscMemcpy(new_colidx,COLIDX,SIDX[SID+1]*sizeof(PetscInt));CHKERRQ(ierr); \ 82*d4002b98SHong Zhang ierr = PetscMemcpy(new_val+SIDX[SID+1]+8,VAL+SIDX[SID+1],(SIDX[AM>>3]-SIDX[SID+1])*sizeof(datatype));CHKERRQ(ierr); \ 83*d4002b98SHong Zhang ierr = PetscMemcpy(new_colidx+SIDX[SID+1]+8,COLIDX+SIDX[SID+1],(SIDX[AM>>3]-SIDX[SID+1])*sizeof(PetscInt));CHKERRQ(ierr); \ 84*d4002b98SHong Zhang /* update slice_idx */ \ 85*d4002b98SHong Zhang for (ii=SID+1;ii<=AM>>3;ii++) { SIDX[ii] += 8; } \ 86*d4002b98SHong Zhang /* update pointers. Notice that they point to the FIRST postion of the row */ \ 87*d4002b98SHong Zhang CP = new_colidx+SIDX[SID]+(ROW & 0x07); \ 88*d4002b98SHong Zhang VP = new_val+SIDX[SID]+(ROW & 0x07); \ 89*d4002b98SHong Zhang /* free up old matrix storage */ \ 90*d4002b98SHong Zhang ierr = MatSeqXSELLFreeSELL(A,&Ain->val,&Ain->colidx);CHKERRQ(ierr); \ 91*d4002b98SHong Zhang Ain->val = (MatScalar*) new_val; \ 92*d4002b98SHong Zhang Ain->colidx = new_colidx; \ 93*d4002b98SHong Zhang Ain->singlemalloc = PETSC_TRUE; \ 94*d4002b98SHong Zhang Ain->maxallocmat = new_size; \ 95*d4002b98SHong Zhang Ain->reallocs++; \ 96*d4002b98SHong Zhang if (WIDTH>=Ain->maxallocrow) Ain->maxallocrow++; \ 97*d4002b98SHong Zhang if (WIDTH>=Ain->rlenmax) Ain->rlenmax++; \ 98*d4002b98SHong Zhang } \ 99*d4002b98SHong Zhang 100*d4002b98SHong Zhang #define MatSetValue_SeqSELL_Private(A,row,col,value,addv,orow,ocol,cp,vp,lastcol,low,high) \ 101*d4002b98SHong Zhang { \ 102*d4002b98SHong Zhang Mat_SeqSELL *a=(Mat_SeqSELL*)A->data; \ 103*d4002b98SHong Zhang found=PETSC_FALSE; \ 104*d4002b98SHong Zhang if (col <= lastcol) low = 0; \ 105*d4002b98SHong Zhang else high = a->rlen[row]; \ 106*d4002b98SHong Zhang lastcol = col; \ 107*d4002b98SHong Zhang while (high-low > 5) { \ 108*d4002b98SHong Zhang t = (low+high)/2; \ 109*d4002b98SHong Zhang if (*(cp+8*t) > col) high = t; \ 110*d4002b98SHong Zhang else low = t; \ 111*d4002b98SHong Zhang } \ 112*d4002b98SHong Zhang for (_i=low; _i<high; _i++) { \ 113*d4002b98SHong Zhang if (*(cp+8*_i) > col) break; \ 114*d4002b98SHong Zhang if (*(cp+8*_i) == col) { \ 115*d4002b98SHong Zhang if (addv == ADD_VALUES)*(vp+8*_i) += value; \ 116*d4002b98SHong Zhang else *(vp+8*_i) = value; \ 117*d4002b98SHong Zhang found = PETSC_TRUE; \ 118*d4002b98SHong Zhang break; \ 119*d4002b98SHong Zhang } \ 120*d4002b98SHong Zhang } \ 121*d4002b98SHong Zhang if (!found) { \ 122*d4002b98SHong Zhang if (a->nonew == -1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero at global row/column (%D, %D) into matrix", orow, ocol); \ 123*d4002b98SHong Zhang if (a->nonew != 1 && !(value == 0.0 && a->ignorezeroentries) && a->rlen[row] >= (a->sliidx[row/8+1]-a->sliidx[row/8])/8) { \ 124*d4002b98SHong Zhang /* there is no extra room in row, therefore enlarge 8 elements (1 slice column) */ \ 125*d4002b98SHong Zhang if (a->maxallocmat < a->sliidx[a->totalslices]+8) { \ 126*d4002b98SHong Zhang /* allocates a larger array for the XSELL matrix types; only extend the current slice by one more column. */ \ 127*d4002b98SHong Zhang PetscInt new_size=a->maxallocmat+8,*new_colidx; \ 128*d4002b98SHong Zhang MatScalar *new_val; \ 129*d4002b98SHong Zhang if (a->nonew == -2) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"New nonzero at (%D,%D) caused a malloc\nUse MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE) to turn off this check",orow,ocol); \ 130*d4002b98SHong Zhang /* malloc new storage space */ \ 131*d4002b98SHong Zhang ierr = PetscMalloc2(new_size,&new_val,new_size,&new_colidx);CHKERRQ(ierr); \ 132*d4002b98SHong Zhang /* copy over old data into new slots by two steps: one step for data before the current slice and the other for the rest */ \ 133*d4002b98SHong Zhang ierr = PetscMemcpy(new_val,a->val,a->sliidx[row/8+1]*sizeof(MatScalar));CHKERRQ(ierr); \ 134*d4002b98SHong Zhang ierr = PetscMemcpy(new_colidx,a->colidx,a->sliidx[row/8+1]*sizeof(PetscInt));CHKERRQ(ierr); \ 135*d4002b98SHong Zhang ierr = PetscMemcpy(new_val+a->sliidx[row/8+1]+8,a->val+a->sliidx[row/8+1],(a->sliidx[a->totalslices]-a->sliidx[row/8+1])*sizeof(MatScalar));CHKERRQ(ierr); \ 136*d4002b98SHong Zhang ierr = PetscMemcpy(new_colidx+a->sliidx[row/8+1]+8,a->colidx+a->sliidx[row/8+1],(a->sliidx[a->totalslices]-a->sliidx[row/8+1])*sizeof(PetscInt));CHKERRQ(ierr); \ 137*d4002b98SHong Zhang /* update pointers. Notice that they point to the FIRST postion of the row */ \ 138*d4002b98SHong Zhang cp = new_colidx+a->sliidx[row/8]+(row & 0x07); \ 139*d4002b98SHong Zhang vp = new_val+a->sliidx[row/8]+(row & 0x07); \ 140*d4002b98SHong Zhang /* free up old matrix storage */ \ 141*d4002b98SHong Zhang ierr = MatSeqXSELLFreeSELL(A,&a->val,&a->colidx);CHKERRQ(ierr); \ 142*d4002b98SHong Zhang a->val = (MatScalar*)new_val; \ 143*d4002b98SHong Zhang a->colidx = new_colidx; \ 144*d4002b98SHong Zhang a->singlemalloc = PETSC_TRUE; \ 145*d4002b98SHong Zhang a->maxallocmat = new_size; \ 146*d4002b98SHong Zhang a->reallocs++; \ 147*d4002b98SHong Zhang } else { \ 148*d4002b98SHong Zhang /* no need to reallocate, just shift the following slices to create space for the added slice column */ \ 149*d4002b98SHong Zhang ierr = PetscMemmove(a->val+a->sliidx[row/8+1]+8,a->val+a->sliidx[row/8+1],(a->sliidx[a->totalslices]-a->sliidx[row/8+1])*sizeof(MatScalar));CHKERRQ(ierr); \ 150*d4002b98SHong Zhang ierr = PetscMemmove(a->colidx+a->sliidx[row/8+1]+8,a->colidx+a->sliidx[row/8+1],(a->sliidx[a->totalslices]-a->sliidx[row/8+1])*sizeof(PetscInt));CHKERRQ(ierr); \ 151*d4002b98SHong Zhang } \ 152*d4002b98SHong Zhang /* update slice_idx */ \ 153*d4002b98SHong Zhang for (ii=row/8+1;ii<=a->totalslices;ii++) a->sliidx[ii] += 8; \ 154*d4002b98SHong Zhang if (a->rlen[row]>=a->maxallocrow) a->maxallocrow++; \ 155*d4002b98SHong Zhang if (a->rlen[row]>=a->rlenmax) a->rlenmax++; \ 156*d4002b98SHong Zhang } \ 157*d4002b98SHong Zhang /* shift up all the later entries in this row */ \ 158*d4002b98SHong Zhang for (ii=a->rlen[row]-1; ii>=_i; ii--) { \ 159*d4002b98SHong Zhang *(cp+8*(ii+1)) = *(cp+8*ii); \ 160*d4002b98SHong Zhang *(vp+8*(ii+1)) = *(vp+8*ii); \ 161*d4002b98SHong Zhang } \ 162*d4002b98SHong Zhang *(cp+8*_i) = col; \ 163*d4002b98SHong Zhang *(vp+8*_i) = value; \ 164*d4002b98SHong Zhang a->nz++; a->rlen[row]++; A->nonzerostate++; \ 165*d4002b98SHong Zhang low = _i+1; high++; \ 166*d4002b98SHong Zhang } \ 167*d4002b98SHong Zhang } \ 168*d4002b98SHong Zhang 169*d4002b98SHong Zhang PETSC_INTERN PetscErrorCode MatSeqSELLSetPreallocation_SeqSELL(Mat,PetscInt,const PetscInt[]); 170*d4002b98SHong Zhang PETSC_INTERN PetscErrorCode MatMult_SeqSELL(Mat,Vec,Vec); 171*d4002b98SHong Zhang PETSC_INTERN PetscErrorCode MatMultAdd_SeqSELL(Mat,Vec,Vec,Vec); 172*d4002b98SHong Zhang PETSC_INTERN PetscErrorCode MatMultTranspose_SeqSELL(Mat,Vec,Vec); 173*d4002b98SHong Zhang PETSC_INTERN PetscErrorCode MatMultTransposeAdd_SeqSELL(Mat,Vec,Vec,Vec); 174*d4002b98SHong Zhang PETSC_INTERN PetscErrorCode MatMissingDiagonal_SeqSELL(Mat,PetscBool*,PetscInt*); 175*d4002b98SHong Zhang PETSC_INTERN PetscErrorCode MatMarkDiagonal_SeqSELL(Mat); 176*d4002b98SHong Zhang PETSC_INTERN PetscErrorCode MatInvertDiagonal_SeqSELL(Mat,PetscScalar,PetscScalar); 177*d4002b98SHong Zhang PETSC_INTERN PetscErrorCode MatZeroEntries_SeqSELL(Mat); 178*d4002b98SHong Zhang PETSC_INTERN PetscErrorCode MatDestroy_SeqSELL(Mat); 179*d4002b98SHong Zhang PETSC_INTERN PetscErrorCode MatSetOption_SeqSELL(Mat,MatOption,PetscBool); 180*d4002b98SHong Zhang PETSC_INTERN PetscErrorCode MatGetDiagonal_SeqSELL(Mat,Vec v); 181*d4002b98SHong Zhang PETSC_INTERN PetscErrorCode MatGetValues_SeqSELL(Mat,PetscInt,const PetscInt [],PetscInt,const PetscInt[],PetscScalar[]); 182*d4002b98SHong Zhang PETSC_INTERN PetscErrorCode MatView_SeqSELL(Mat,PetscViewer); 183*d4002b98SHong Zhang PETSC_INTERN PetscErrorCode MatAssemblyEnd_SeqSELL(Mat,MatAssemblyType); 184*d4002b98SHong Zhang PETSC_INTERN PetscErrorCode MatGetInfo_SeqSELL(Mat,MatInfoType,MatInfo*); 185*d4002b98SHong Zhang PETSC_INTERN PetscErrorCode MatSetValues_SeqSELL(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[],const PetscScalar[],InsertMode); 186*d4002b98SHong Zhang PETSC_INTERN PetscErrorCode MatCopy_SeqSELL(Mat,Mat,MatStructure); 187*d4002b98SHong Zhang PETSC_INTERN PetscErrorCode MatSetUp_SeqSELL(Mat); 188*d4002b98SHong Zhang PETSC_INTERN PetscErrorCode MatSeqSELLGetArray_SeqSELL(Mat,PetscScalar *[]); 189*d4002b98SHong Zhang PETSC_INTERN PetscErrorCode MatSeqSELLRestoreArray_SeqSELL(Mat,PetscScalar *[]); 190*d4002b98SHong Zhang PETSC_INTERN PetscErrorCode MatShift_SeqSELL(Mat,PetscScalar); 191*d4002b98SHong Zhang PETSC_INTERN PetscErrorCode MatSOR_SeqSELL(Mat,Vec,PetscReal,MatSORType,PetscReal,PetscInt,PetscInt,Vec); 192*d4002b98SHong Zhang PETSC_EXTERN PetscErrorCode MatCreate_SeqSELL(Mat); 193*d4002b98SHong Zhang PETSC_INTERN PetscErrorCode MatDuplicate_SeqSELL(Mat,MatDuplicateOption,Mat*); 194*d4002b98SHong Zhang PETSC_INTERN PetscErrorCode MatEqual_SeqSELL(Mat,Mat,PetscBool*); 195*d4002b98SHong Zhang PETSC_INTERN PetscErrorCode MatSeqSELLInvalidateDiagonal(Mat); 196*d4002b98SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqSELL_SeqAIJ(Mat,MatType,MatReuse,Mat*); 197*d4002b98SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqSELL(Mat,MatType,MatReuse,Mat*); 198*d4002b98SHong Zhang PETSC_INTERN PetscErrorCode MatFDColoringCreate_SeqSELL(Mat,ISColoring,MatFDColoring); 199*d4002b98SHong Zhang PETSC_INTERN PetscErrorCode MatFDColoringSetUp_SeqSELL(Mat,ISColoring,MatFDColoring); 200*d4002b98SHong Zhang PETSC_INTERN PetscErrorCode MatGetColumnIJ_SeqSELL_Color(Mat,PetscInt,PetscBool,PetscBool,PetscInt*,const PetscInt *[],const PetscInt *[],PetscInt *[],PetscBool*); 201*d4002b98SHong Zhang PETSC_INTERN PetscErrorCode MatRestoreColumnIJ_SeqSELL_Color(Mat,PetscInt,PetscBool,PetscBool,PetscInt*,const PetscInt *[],const PetscInt *[],PetscInt *[],PetscBool*); 202*d4002b98SHong Zhang PETSC_INTERN PetscErrorCode MatConjugate_SeqSELL(Mat A); 203*d4002b98SHong Zhang PETSC_INTERN PetscErrorCode MatScale_SeqSELL(Mat,PetscScalar); 204*d4002b98SHong Zhang PETSC_INTERN PetscErrorCode MatDiagonalScale_SeqSELL(Mat,Vec,Vec); 205*d4002b98SHong Zhang #endif 206