1421e10b8SBarry Smith #define PETSCMAT_DLL 2421e10b8SBarry Smith 3421e10b8SBarry Smith /* 4421e10b8SBarry Smith This provides a matrix that consists of Mats 5421e10b8SBarry Smith */ 6421e10b8SBarry Smith 7421e10b8SBarry Smith #include "src/mat/matimpl.h" /*I "petscmat.h" I*/ 8421e10b8SBarry Smith #include "src/mat/impls/baij/seq/baij.h" /* use the common AIJ data-structure */ 9ccb205f8SBarry Smith #include "petscksp.h" 10421e10b8SBarry Smith 11421e10b8SBarry Smith #define CHUNKSIZE 15 12421e10b8SBarry Smith 13421e10b8SBarry Smith typedef struct { 14421e10b8SBarry Smith SEQAIJHEADER(Mat); 15421e10b8SBarry Smith SEQBAIJHEADER; 16ccb205f8SBarry Smith Mat *diags; 17421e10b8SBarry Smith 18*6e63c7a1SBarry Smith Vec left,right,middle,workb; /* dummy vectors to perform local parts of product */ 19421e10b8SBarry Smith } Mat_BlockMat; 20421e10b8SBarry Smith 21421e10b8SBarry Smith #undef __FUNCT__ 22290bbb0aSBarry Smith #define __FUNCT__ "MatRelax_BlockMat_Symmetric" 23290bbb0aSBarry Smith PetscErrorCode MatRelax_BlockMat_Symmetric(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx) 24290bbb0aSBarry Smith { 25290bbb0aSBarry Smith Mat_BlockMat *a = (Mat_BlockMat*)A->data; 26290bbb0aSBarry Smith PetscScalar *x; 27290bbb0aSBarry Smith const Mat *v = a->a; 28290bbb0aSBarry Smith const PetscScalar *b; 29290bbb0aSBarry Smith PetscErrorCode ierr; 30290bbb0aSBarry Smith PetscInt n = A->cmap.n,i,mbs = n/A->rmap.bs,j,bs = A->rmap.bs; 31290bbb0aSBarry Smith const PetscInt *idx; 32290bbb0aSBarry Smith IS row,col; 33290bbb0aSBarry Smith MatFactorInfo info; 34*6e63c7a1SBarry Smith Vec left = a->left,right = a->right, middle = a->middle; 35290bbb0aSBarry Smith Mat *diag; 36290bbb0aSBarry Smith 37290bbb0aSBarry Smith PetscFunctionBegin; 38290bbb0aSBarry Smith its = its*lits; 39290bbb0aSBarry Smith if (its <= 0) SETERRQ2(PETSC_ERR_ARG_WRONG,"Relaxation requires global its %D and local its %D both positive",its,lits); 40290bbb0aSBarry Smith if (flag & SOR_EISENSTAT) SETERRQ(PETSC_ERR_SUP,"No support yet for Eisenstat"); 41290bbb0aSBarry Smith if (omega != 1.0) SETERRQ(PETSC_ERR_SUP,"No support yet for omega not equal to 1.0"); 42290bbb0aSBarry Smith if (fshift) SETERRQ(PETSC_ERR_SUP,"No support yet for fshift"); 43290bbb0aSBarry Smith if ((flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) && !(flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP)) 44290bbb0aSBarry Smith SETERRQ(PETSC_ERR_SUP,"Cannot do backward sweep without forward sweep"); 45290bbb0aSBarry Smith 46290bbb0aSBarry Smith if (!a->diags) { 47290bbb0aSBarry Smith ierr = PetscMalloc(mbs*sizeof(Mat),&a->diags);CHKERRQ(ierr); 48290bbb0aSBarry Smith ierr = MatFactorInfoInitialize(&info);CHKERRQ(ierr); 49290bbb0aSBarry Smith for (i=0; i<mbs; i++) { 50290bbb0aSBarry Smith ierr = MatGetOrdering(a->a[a->diag[i]], MATORDERING_ND,&row,&col);CHKERRQ(ierr); 51*6e63c7a1SBarry Smith ierr = MatCholeskyFactorSymbolic(a->a[a->diag[i]],row,&info,a->diags+i);CHKERRQ(ierr); 52*6e63c7a1SBarry Smith ierr = MatCholeskyFactorNumeric(a->a[a->diag[i]],&info,a->diags+i);CHKERRQ(ierr); 53290bbb0aSBarry Smith ierr = ISDestroy(row);CHKERRQ(ierr); 54290bbb0aSBarry Smith ierr = ISDestroy(col);CHKERRQ(ierr); 55290bbb0aSBarry Smith } 56*6e63c7a1SBarry Smith ierr = VecDuplicate(bb,&a->workb);CHKERRQ(ierr); 57290bbb0aSBarry Smith } 58290bbb0aSBarry Smith diag = a->diags; 59290bbb0aSBarry Smith 60290bbb0aSBarry Smith ierr = VecSet(xx,0.0);CHKERRQ(ierr); 61290bbb0aSBarry Smith ierr = VecGetArray(xx,&x);CHKERRQ(ierr); 62290bbb0aSBarry Smith /* copy right hand side because it must be modified during iteration */ 63*6e63c7a1SBarry Smith ierr = VecCopy(bb,a->workb);CHKERRQ(ierr); 64*6e63c7a1SBarry Smith ierr = VecGetArray(a->workb,(PetscScalar**)&b);CHKERRQ(ierr); 65290bbb0aSBarry Smith 66290bbb0aSBarry Smith /* need to add code for when initial guess is zero, see MatRelax_SeqAIJ */ 67290bbb0aSBarry Smith while (its--) { 68290bbb0aSBarry Smith if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){ 69290bbb0aSBarry Smith 70290bbb0aSBarry Smith for (i=0; i<mbs; i++) { 71*6e63c7a1SBarry Smith n = a->i[i+1] - a->i[i] - 1; 72*6e63c7a1SBarry Smith idx = a->j + a->i[i] + 1; 73*6e63c7a1SBarry Smith v = a->a + a->i[i] + 1; 74290bbb0aSBarry Smith 75290bbb0aSBarry Smith ierr = VecSet(left,0.0);CHKERRQ(ierr); 76290bbb0aSBarry Smith for (j=0; j<n; j++) { 77290bbb0aSBarry Smith ierr = VecPlaceArray(right,x + idx[j]*bs);CHKERRQ(ierr); 78290bbb0aSBarry Smith ierr = MatMultAdd(v[j],right,left,left);CHKERRQ(ierr); 79290bbb0aSBarry Smith ierr = VecResetArray(right);CHKERRQ(ierr); 80290bbb0aSBarry Smith } 81290bbb0aSBarry Smith ierr = VecPlaceArray(right,b + i*bs);CHKERRQ(ierr); 82290bbb0aSBarry Smith ierr = VecAYPX(left,-1.0,right);CHKERRQ(ierr); 83290bbb0aSBarry Smith ierr = VecResetArray(right);CHKERRQ(ierr); 84290bbb0aSBarry Smith 85290bbb0aSBarry Smith ierr = VecPlaceArray(right,x + i*bs);CHKERRQ(ierr); 86290bbb0aSBarry Smith ierr = MatSolve(diag[i],left,right);CHKERRQ(ierr); 87*6e63c7a1SBarry Smith 88*6e63c7a1SBarry Smith /* now adjust right hand side, see MatRelax_SeqSBAIJ */ 89*6e63c7a1SBarry Smith for (j=0; j<n; j++) { 90*6e63c7a1SBarry Smith ierr = MatMultTranspose(v[j],right,left);CHKERRQ(ierr); 91*6e63c7a1SBarry Smith ierr = VecPlaceArray(middle,b + idx[j]*bs);CHKERRQ(ierr); 92*6e63c7a1SBarry Smith ierr = VecAXPY(middle,-1.0,left);CHKERRQ(ierr); 93*6e63c7a1SBarry Smith ierr = VecResetArray(middle);CHKERRQ(ierr); 94*6e63c7a1SBarry Smith } 95290bbb0aSBarry Smith ierr = VecResetArray(right);CHKERRQ(ierr); 96*6e63c7a1SBarry Smith 97290bbb0aSBarry Smith } 98290bbb0aSBarry Smith } 99290bbb0aSBarry Smith if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){ 100290bbb0aSBarry Smith 101290bbb0aSBarry Smith for (i=mbs-1; i>=0; i--) { 102*6e63c7a1SBarry Smith n = a->i[i+1] - a->i[i] - 1; 103*6e63c7a1SBarry Smith idx = a->j + a->i[i] + 1; 104*6e63c7a1SBarry Smith v = a->a + a->i[i] + 1; 105290bbb0aSBarry Smith 106290bbb0aSBarry Smith ierr = VecSet(left,0.0);CHKERRQ(ierr); 107290bbb0aSBarry Smith for (j=0; j<n; j++) { 108290bbb0aSBarry Smith ierr = VecPlaceArray(right,x + idx[j]*bs);CHKERRQ(ierr); 109290bbb0aSBarry Smith ierr = MatMultAdd(v[j],right,left,left);CHKERRQ(ierr); 110290bbb0aSBarry Smith ierr = VecResetArray(right);CHKERRQ(ierr); 111290bbb0aSBarry Smith } 112290bbb0aSBarry Smith ierr = VecPlaceArray(right,b + i*bs);CHKERRQ(ierr); 113290bbb0aSBarry Smith ierr = VecAYPX(left,-1.0,right);CHKERRQ(ierr); 114290bbb0aSBarry Smith ierr = VecResetArray(right);CHKERRQ(ierr); 115290bbb0aSBarry Smith 116290bbb0aSBarry Smith ierr = VecPlaceArray(right,x + i*bs);CHKERRQ(ierr); 117290bbb0aSBarry Smith ierr = MatSolve(diag[i],left,right);CHKERRQ(ierr); 118290bbb0aSBarry Smith ierr = VecResetArray(right);CHKERRQ(ierr); 119290bbb0aSBarry Smith 120290bbb0aSBarry Smith } 121290bbb0aSBarry Smith } 122290bbb0aSBarry Smith } 123290bbb0aSBarry Smith ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 124*6e63c7a1SBarry Smith ierr = VecRestoreArray(a->workb,(PetscScalar**)&b);CHKERRQ(ierr); 125290bbb0aSBarry Smith PetscFunctionReturn(0); 126290bbb0aSBarry Smith } 127290bbb0aSBarry Smith 128290bbb0aSBarry Smith #undef __FUNCT__ 129ccb205f8SBarry Smith #define __FUNCT__ "MatRelax_BlockMat" 130ccb205f8SBarry Smith PetscErrorCode MatRelax_BlockMat(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx) 131ccb205f8SBarry Smith { 132ccb205f8SBarry Smith Mat_BlockMat *a = (Mat_BlockMat*)A->data; 133ccb205f8SBarry Smith PetscScalar *x; 134ccb205f8SBarry Smith const Mat *v = a->a; 135ccb205f8SBarry Smith const PetscScalar *b; 136ccb205f8SBarry Smith PetscErrorCode ierr; 137ccb205f8SBarry Smith PetscInt n = A->cmap.n,i,mbs = n/A->rmap.bs,j,bs = A->rmap.bs; 138ccb205f8SBarry Smith const PetscInt *idx; 139ccb205f8SBarry Smith IS row,col; 140ccb205f8SBarry Smith MatFactorInfo info; 141ccb205f8SBarry Smith Vec left = a->left,right = a->right; 142ccb205f8SBarry Smith Mat *diag; 143ccb205f8SBarry Smith 144ccb205f8SBarry Smith PetscFunctionBegin; 145ccb205f8SBarry Smith its = its*lits; 146ccb205f8SBarry Smith if (its <= 0) SETERRQ2(PETSC_ERR_ARG_WRONG,"Relaxation requires global its %D and local its %D both positive",its,lits); 147ccb205f8SBarry Smith if (flag & SOR_EISENSTAT) SETERRQ(PETSC_ERR_SUP,"No support yet for Eisenstat"); 148ccb205f8SBarry Smith if (omega != 1.0) SETERRQ(PETSC_ERR_SUP,"No support yet for omega not equal to 1.0"); 149ccb205f8SBarry Smith if (fshift) SETERRQ(PETSC_ERR_SUP,"No support yet for fshift"); 150ccb205f8SBarry Smith 151ccb205f8SBarry Smith if (!a->diags) { 152ccb205f8SBarry Smith ierr = PetscMalloc(mbs*sizeof(Mat),&a->diags);CHKERRQ(ierr); 153ccb205f8SBarry Smith ierr = MatFactorInfoInitialize(&info);CHKERRQ(ierr); 154ccb205f8SBarry Smith for (i=0; i<mbs; i++) { 155ccb205f8SBarry Smith ierr = MatGetOrdering(a->a[a->diag[i]], MATORDERING_ND,&row,&col);CHKERRQ(ierr); 156ccb205f8SBarry Smith ierr = MatLUFactorSymbolic(a->a[a->diag[i]],row,col,&info,a->diags+i);CHKERRQ(ierr); 157ccb205f8SBarry Smith ierr = MatLUFactorNumeric(a->a[a->diag[i]],&info,a->diags+i);CHKERRQ(ierr); 158ccb205f8SBarry Smith ierr = ISDestroy(row);CHKERRQ(ierr); 159ccb205f8SBarry Smith ierr = ISDestroy(col);CHKERRQ(ierr); 160ccb205f8SBarry Smith } 161ccb205f8SBarry Smith } 162ccb205f8SBarry Smith diag = a->diags; 163ccb205f8SBarry Smith 164ccb205f8SBarry Smith ierr = VecSet(xx,0.0);CHKERRQ(ierr); 165ccb205f8SBarry Smith ierr = VecGetArray(xx,&x);CHKERRQ(ierr); 166ccb205f8SBarry Smith ierr = VecGetArray(bb,(PetscScalar**)&b);CHKERRQ(ierr); 167ccb205f8SBarry Smith 168ccb205f8SBarry Smith /* need to add code for when initial guess is zero, see MatRelax_SeqAIJ */ 169ccb205f8SBarry Smith while (its--) { 170ccb205f8SBarry Smith if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){ 171ccb205f8SBarry Smith 172ccb205f8SBarry Smith for (i=0; i<mbs; i++) { 173ccb205f8SBarry Smith n = a->i[i+1] - a->i[i]; 174ccb205f8SBarry Smith idx = a->j + a->i[i]; 175ccb205f8SBarry Smith v = a->a + a->i[i]; 176ccb205f8SBarry Smith 177ccb205f8SBarry Smith ierr = VecSet(left,0.0);CHKERRQ(ierr); 178ccb205f8SBarry Smith for (j=0; j<n; j++) { 179ccb205f8SBarry Smith if (idx[j] != i) { 180ccb205f8SBarry Smith ierr = VecPlaceArray(right,x + idx[j]*bs);CHKERRQ(ierr); 181ccb205f8SBarry Smith ierr = MatMultAdd(v[j],right,left,left);CHKERRQ(ierr); 182ccb205f8SBarry Smith ierr = VecResetArray(right);CHKERRQ(ierr); 183ccb205f8SBarry Smith } 184ccb205f8SBarry Smith } 185ccb205f8SBarry Smith ierr = VecPlaceArray(right,b + i*bs);CHKERRQ(ierr); 186ccb205f8SBarry Smith ierr = VecAYPX(left,-1.0,right);CHKERRQ(ierr); 187ccb205f8SBarry Smith ierr = VecResetArray(right);CHKERRQ(ierr); 188ccb205f8SBarry Smith 189ccb205f8SBarry Smith ierr = VecPlaceArray(right,x + i*bs);CHKERRQ(ierr); 190ccb205f8SBarry Smith ierr = MatSolve(diag[i],left,right);CHKERRQ(ierr); 191ccb205f8SBarry Smith ierr = VecResetArray(right);CHKERRQ(ierr); 192ccb205f8SBarry Smith } 193ccb205f8SBarry Smith } 194ccb205f8SBarry Smith if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){ 195ccb205f8SBarry Smith 196ccb205f8SBarry Smith for (i=mbs-1; i>=0; i--) { 197ccb205f8SBarry Smith n = a->i[i+1] - a->i[i]; 198ccb205f8SBarry Smith idx = a->j + a->i[i]; 199ccb205f8SBarry Smith v = a->a + a->i[i]; 200ccb205f8SBarry Smith 201ccb205f8SBarry Smith ierr = VecSet(left,0.0);CHKERRQ(ierr); 202ccb205f8SBarry Smith for (j=0; j<n; j++) { 203ccb205f8SBarry Smith if (idx[j] != i) { 204ccb205f8SBarry Smith ierr = VecPlaceArray(right,x + idx[j]*bs);CHKERRQ(ierr); 205ccb205f8SBarry Smith ierr = MatMultAdd(v[j],right,left,left);CHKERRQ(ierr); 206ccb205f8SBarry Smith ierr = VecResetArray(right);CHKERRQ(ierr); 207ccb205f8SBarry Smith } 208ccb205f8SBarry Smith } 209ccb205f8SBarry Smith ierr = VecPlaceArray(right,b + i*bs);CHKERRQ(ierr); 210ccb205f8SBarry Smith ierr = VecAYPX(left,-1.0,right);CHKERRQ(ierr); 211ccb205f8SBarry Smith ierr = VecResetArray(right);CHKERRQ(ierr); 212ccb205f8SBarry Smith 213ccb205f8SBarry Smith ierr = VecPlaceArray(right,x + i*bs);CHKERRQ(ierr); 214ccb205f8SBarry Smith ierr = MatSolve(diag[i],left,right);CHKERRQ(ierr); 215ccb205f8SBarry Smith ierr = VecResetArray(right);CHKERRQ(ierr); 216ccb205f8SBarry Smith 217ccb205f8SBarry Smith } 218ccb205f8SBarry Smith } 219ccb205f8SBarry Smith } 220ccb205f8SBarry Smith ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 221ccb205f8SBarry Smith ierr = VecRestoreArray(bb,(PetscScalar**)&b);CHKERRQ(ierr); 222ccb205f8SBarry Smith PetscFunctionReturn(0); 223ccb205f8SBarry Smith } 224ccb205f8SBarry Smith 225ccb205f8SBarry Smith #undef __FUNCT__ 226421e10b8SBarry Smith #define __FUNCT__ "MatSetValues_BlockMat" 227421e10b8SBarry Smith PetscErrorCode MatSetValues_BlockMat(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is) 228421e10b8SBarry Smith { 229421e10b8SBarry Smith Mat_BlockMat *a = (Mat_BlockMat*)A->data; 230421e10b8SBarry Smith PetscInt *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N,lastcol = -1; 231421e10b8SBarry Smith PetscInt *imax=a->imax,*ai=a->i,*ailen=a->ilen; 232421e10b8SBarry Smith PetscInt *aj=a->j,nonew=a->nonew,bs=A->rmap.bs,brow,bcol; 233421e10b8SBarry Smith PetscErrorCode ierr; 234421e10b8SBarry Smith PetscInt ridx,cidx; 235421e10b8SBarry Smith PetscTruth roworiented=a->roworiented; 236421e10b8SBarry Smith MatScalar value; 237421e10b8SBarry Smith Mat *ap,*aa = a->a; 238421e10b8SBarry Smith 239421e10b8SBarry Smith PetscFunctionBegin; 240421e10b8SBarry Smith for (k=0; k<m; k++) { /* loop over added rows */ 241421e10b8SBarry Smith row = im[k]; 242421e10b8SBarry Smith brow = row/bs; 243421e10b8SBarry Smith if (row < 0) continue; 244421e10b8SBarry Smith #if defined(PETSC_USE_DEBUG) 245421e10b8SBarry Smith if (row >= A->rmap.N) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",row,A->rmap.N-1); 246421e10b8SBarry Smith #endif 247421e10b8SBarry Smith rp = aj + ai[brow]; 248421e10b8SBarry Smith ap = aa + ai[brow]; 249421e10b8SBarry Smith rmax = imax[brow]; 250421e10b8SBarry Smith nrow = ailen[brow]; 251421e10b8SBarry Smith low = 0; 252421e10b8SBarry Smith high = nrow; 253421e10b8SBarry Smith for (l=0; l<n; l++) { /* loop over added columns */ 254421e10b8SBarry Smith if (in[l] < 0) continue; 255421e10b8SBarry Smith #if defined(PETSC_USE_DEBUG) 256421e10b8SBarry Smith if (in[l] >= A->cmap.n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",in[l],A->cmap.n-1); 257421e10b8SBarry Smith #endif 258421e10b8SBarry Smith col = in[l]; bcol = col/bs; 259*6e63c7a1SBarry Smith if (A->symmetric && brow > bcol) continue; 260421e10b8SBarry Smith ridx = row % bs; cidx = col % bs; 261421e10b8SBarry Smith if (roworiented) { 262421e10b8SBarry Smith value = v[l + k*n]; 263421e10b8SBarry Smith } else { 264421e10b8SBarry Smith value = v[k + l*m]; 265421e10b8SBarry Smith } 266421e10b8SBarry Smith if (col <= lastcol) low = 0; else high = nrow; 267421e10b8SBarry Smith lastcol = col; 268421e10b8SBarry Smith while (high-low > 7) { 269421e10b8SBarry Smith t = (low+high)/2; 270421e10b8SBarry Smith if (rp[t] > bcol) high = t; 271421e10b8SBarry Smith else low = t; 272421e10b8SBarry Smith } 273421e10b8SBarry Smith for (i=low; i<high; i++) { 274421e10b8SBarry Smith if (rp[i] > bcol) break; 275421e10b8SBarry Smith if (rp[i] == bcol) { 276ccb205f8SBarry Smith /* printf("row %d col %d found i %d\n",brow,bcol,i);*/ 277421e10b8SBarry Smith goto noinsert1; 278421e10b8SBarry Smith } 279421e10b8SBarry Smith } 280421e10b8SBarry Smith if (nonew == 1) goto noinsert1; 281421e10b8SBarry Smith if (nonew == -1) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero (%D, %D) in the matrix", row, col); 282421e10b8SBarry Smith MatSeqXAIJReallocateAIJ(A,a->mbs,1,nrow,brow,bcol,rmax,aa,ai,aj,rp,ap,imax,nonew,Mat); 283421e10b8SBarry Smith N = nrow++ - 1; high++; 284421e10b8SBarry Smith /* shift up all the later entries in this row */ 285ccb205f8SBarry Smith /* printf("N %d i %d\n",N,i);*/ 286421e10b8SBarry Smith for (ii=N; ii>=i; ii--) { 287421e10b8SBarry Smith rp[ii+1] = rp[ii]; 288421e10b8SBarry Smith ap[ii+1] = ap[ii]; 289421e10b8SBarry Smith } 290421e10b8SBarry Smith if (N>=i) ap[i] = 0; 291421e10b8SBarry Smith rp[i] = bcol; 292421e10b8SBarry Smith a->nz++; 293421e10b8SBarry Smith noinsert1:; 294421e10b8SBarry Smith if (!*(ap+i)) { 295ccb205f8SBarry Smith /* printf("create matrix at i %d rw %d col %d\n",i,brow,bcol);*/ 296b0223207SBarry Smith if (A->symmetric && brow == bcol) { 297*6e63c7a1SBarry Smith /* don't use SBAIJ since want to reorder in sparse factorization */ 298*6e63c7a1SBarry Smith ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,bs,bs,0,0,ap+i);CHKERRQ(ierr); 299b0223207SBarry Smith } else { 300421e10b8SBarry Smith ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,bs,bs,0,0,ap+i);CHKERRQ(ierr); 301421e10b8SBarry Smith } 302b0223207SBarry Smith } 303ccb205f8SBarry Smith /* printf("numerical value at i %d row %d col %d cidx %d ridx %d value %g\n",i,brow,bcol,cidx,ridx,value);*/ 304421e10b8SBarry Smith ierr = MatSetValues(ap[i],1,&ridx,1,&cidx,&value,is);CHKERRQ(ierr); 305421e10b8SBarry Smith low = i; 306421e10b8SBarry Smith } 307ccb205f8SBarry Smith /* printf("nrow for row %d %d\n",nrow,brow);*/ 308421e10b8SBarry Smith ailen[brow] = nrow; 309421e10b8SBarry Smith } 310421e10b8SBarry Smith A->same_nonzero = PETSC_FALSE; 311421e10b8SBarry Smith PetscFunctionReturn(0); 312421e10b8SBarry Smith } 313421e10b8SBarry Smith 314421e10b8SBarry Smith #undef __FUNCT__ 315421e10b8SBarry Smith #define __FUNCT__ "MatLoad_BlockMat" 316421e10b8SBarry Smith PetscErrorCode MatLoad_BlockMat(PetscViewer viewer, MatType type,Mat *A) 317421e10b8SBarry Smith { 318421e10b8SBarry Smith PetscErrorCode ierr; 319421e10b8SBarry Smith Mat tmpA; 320421e10b8SBarry Smith PetscInt i,m,n,bs = 1,ncols; 321421e10b8SBarry Smith const PetscInt *cols; 322421e10b8SBarry Smith const PetscScalar *values; 323290bbb0aSBarry Smith PetscTruth flg; 324421e10b8SBarry Smith 325421e10b8SBarry Smith PetscFunctionBegin; 326421e10b8SBarry Smith ierr = MatLoad_SeqAIJ(viewer,MATSEQAIJ,&tmpA);CHKERRQ(ierr); 327421e10b8SBarry Smith 328421e10b8SBarry Smith ierr = MatGetLocalSize(tmpA,&m,&n);CHKERRQ(ierr); 329421e10b8SBarry Smith ierr = PetscOptionsBegin(PETSC_COMM_SELF,PETSC_NULL,"Options for loading BlockMat matrix","Mat");CHKERRQ(ierr); 330421e10b8SBarry Smith ierr = PetscOptionsInt("-matload_block_size","Set the blocksize used to store the matrix","MatLoad",bs,&bs,PETSC_NULL);CHKERRQ(ierr); 331421e10b8SBarry Smith ierr = PetscOptionsEnd();CHKERRQ(ierr); 332421e10b8SBarry Smith ierr = MatCreateBlockMat(PETSC_COMM_SELF,m,n,bs,A);CHKERRQ(ierr); 333290bbb0aSBarry Smith ierr = PetscOptionsBegin(PETSC_COMM_SELF,PETSC_NULL,"Options for loading BlockMat matrix","Mat");CHKERRQ(ierr); 334290bbb0aSBarry Smith ierr = PetscOptionsName("-matload_symmetric","Store the matrix as symmetric","MatLoad",&flg);CHKERRQ(ierr); 335290bbb0aSBarry Smith if (flg) { 336290bbb0aSBarry Smith ierr = MatSetOption(*A,MAT_SYMMETRIC);CHKERRQ(ierr); 337290bbb0aSBarry Smith } 338290bbb0aSBarry Smith ierr = PetscOptionsEnd();CHKERRQ(ierr); 339421e10b8SBarry Smith for (i=0; i<m; i++) { 340421e10b8SBarry Smith ierr = MatGetRow(tmpA,i,&ncols,&cols,&values);CHKERRQ(ierr); 341421e10b8SBarry Smith ierr = MatSetValues(*A,1,&i,ncols,cols,values,INSERT_VALUES);CHKERRQ(ierr); 342ccb205f8SBarry Smith ierr = MatRestoreRow(tmpA,i,&ncols,&cols,&values);CHKERRQ(ierr); 343421e10b8SBarry Smith } 344421e10b8SBarry Smith ierr = MatAssemblyBegin(*A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 345421e10b8SBarry Smith ierr = MatAssemblyEnd(*A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 346421e10b8SBarry Smith PetscFunctionReturn(0); 347421e10b8SBarry Smith } 348421e10b8SBarry Smith 349ccb205f8SBarry Smith #undef __FUNCT__ 350ccb205f8SBarry Smith #define __FUNCT__ "MatView_BlockMat" 351ccb205f8SBarry Smith PetscErrorCode MatView_BlockMat(Mat A,PetscViewer viewer) 352ccb205f8SBarry Smith { 353ccb205f8SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 354ccb205f8SBarry Smith PetscErrorCode ierr; 355ccb205f8SBarry Smith const char *name; 356ccb205f8SBarry Smith PetscViewerFormat format; 357ccb205f8SBarry Smith 358ccb205f8SBarry Smith PetscFunctionBegin; 359ccb205f8SBarry Smith ierr = PetscObjectGetName((PetscObject)A,&name);CHKERRQ(ierr); 360ccb205f8SBarry Smith ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr); 361ccb205f8SBarry Smith if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO) { 362ccb205f8SBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"Nonzero block matrices = %D \n",a->nz);CHKERRQ(ierr); 363ccb205f8SBarry Smith } 364ccb205f8SBarry Smith PetscFunctionReturn(0); 365ccb205f8SBarry Smith } 366421e10b8SBarry Smith 367421e10b8SBarry Smith #undef __FUNCT__ 368421e10b8SBarry Smith #define __FUNCT__ "MatDestroy_BlockMat" 369421e10b8SBarry Smith PetscErrorCode MatDestroy_BlockMat(Mat mat) 370421e10b8SBarry Smith { 371421e10b8SBarry Smith PetscErrorCode ierr; 372421e10b8SBarry Smith Mat_BlockMat *bmat = (Mat_BlockMat*)mat->data; 373ccb205f8SBarry Smith PetscInt i; 374421e10b8SBarry Smith 375421e10b8SBarry Smith PetscFunctionBegin; 376421e10b8SBarry Smith if (bmat->right) { 377421e10b8SBarry Smith ierr = VecDestroy(bmat->right);CHKERRQ(ierr); 378421e10b8SBarry Smith } 379421e10b8SBarry Smith if (bmat->left) { 380421e10b8SBarry Smith ierr = VecDestroy(bmat->left);CHKERRQ(ierr); 381421e10b8SBarry Smith } 382290bbb0aSBarry Smith if (bmat->middle) { 383290bbb0aSBarry Smith ierr = VecDestroy(bmat->middle);CHKERRQ(ierr); 384290bbb0aSBarry Smith } 385*6e63c7a1SBarry Smith if (bmat->workb) { 386*6e63c7a1SBarry Smith ierr = VecDestroy(bmat->workb);CHKERRQ(ierr); 387*6e63c7a1SBarry Smith } 388ccb205f8SBarry Smith if (bmat->diags) { 389ccb205f8SBarry Smith for (i=0; i<mat->rmap.n/mat->rmap.bs; i++) { 390ccb205f8SBarry Smith if (bmat->diags[i]) {ierr = MatDestroy(bmat->diags[i]);CHKERRQ(ierr);} 391ccb205f8SBarry Smith } 392ccb205f8SBarry Smith } 393ccb205f8SBarry Smith if (bmat->a) { 394ccb205f8SBarry Smith for (i=0; i<bmat->nz; i++) { 395ccb205f8SBarry Smith if (bmat->a[i]) {ierr = MatDestroy(bmat->a[i]);CHKERRQ(ierr);} 396ccb205f8SBarry Smith } 397ccb205f8SBarry Smith } 398ccb205f8SBarry Smith ierr = MatSeqXAIJFreeAIJ(mat,(PetscScalar**)&bmat->a,&bmat->j,&bmat->i);CHKERRQ(ierr); 399421e10b8SBarry Smith ierr = PetscFree(bmat);CHKERRQ(ierr); 400421e10b8SBarry Smith PetscFunctionReturn(0); 401421e10b8SBarry Smith } 402421e10b8SBarry Smith 403421e10b8SBarry Smith #undef __FUNCT__ 404421e10b8SBarry Smith #define __FUNCT__ "MatMult_BlockMat" 405421e10b8SBarry Smith PetscErrorCode MatMult_BlockMat(Mat A,Vec x,Vec y) 406421e10b8SBarry Smith { 407421e10b8SBarry Smith Mat_BlockMat *bmat = (Mat_BlockMat*)A->data; 408421e10b8SBarry Smith PetscErrorCode ierr; 409421e10b8SBarry Smith PetscScalar *xx,*yy; 410421e10b8SBarry Smith PetscInt *aj,i,*ii,jrow,m = A->rmap.n/A->rmap.bs,bs = A->rmap.bs,n,j; 411421e10b8SBarry Smith Mat *aa; 412421e10b8SBarry Smith 413421e10b8SBarry Smith PetscFunctionBegin; 414ccb205f8SBarry Smith CHKMEMQ; 415421e10b8SBarry Smith /* 416421e10b8SBarry Smith Standard CSR multiply except each entry is a Mat 417421e10b8SBarry Smith */ 418421e10b8SBarry Smith ierr = VecGetArray(x,&xx);CHKERRQ(ierr); 419ccb205f8SBarry Smith 420421e10b8SBarry Smith ierr = VecSet(y,0.0);CHKERRQ(ierr); 421421e10b8SBarry Smith ierr = VecGetArray(y,&yy);CHKERRQ(ierr); 422421e10b8SBarry Smith aj = bmat->j; 423421e10b8SBarry Smith aa = bmat->a; 424421e10b8SBarry Smith ii = bmat->i; 425421e10b8SBarry Smith for (i=0; i<m; i++) { 426421e10b8SBarry Smith jrow = ii[i]; 427ccb205f8SBarry Smith ierr = VecPlaceArray(bmat->left,yy + bs*i);CHKERRQ(ierr); 428421e10b8SBarry Smith n = ii[i+1] - jrow; 429421e10b8SBarry Smith for (j=0; j<n; j++) { 430421e10b8SBarry Smith ierr = VecPlaceArray(bmat->right,xx + bs*aj[jrow]);CHKERRQ(ierr); 431ccb205f8SBarry Smith ierr = MatMultAdd(aa[jrow],bmat->right,bmat->left,bmat->left);CHKERRQ(ierr); 432421e10b8SBarry Smith ierr = VecResetArray(bmat->right);CHKERRQ(ierr); 433421e10b8SBarry Smith jrow++; 434421e10b8SBarry Smith } 435421e10b8SBarry Smith ierr = VecResetArray(bmat->left);CHKERRQ(ierr); 436421e10b8SBarry Smith } 437421e10b8SBarry Smith ierr = VecRestoreArray(x,&xx);CHKERRQ(ierr); 438421e10b8SBarry Smith ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr); 439ccb205f8SBarry Smith CHKMEMQ; 440421e10b8SBarry Smith PetscFunctionReturn(0); 441421e10b8SBarry Smith } 442421e10b8SBarry Smith 443421e10b8SBarry Smith #undef __FUNCT__ 444290bbb0aSBarry Smith #define __FUNCT__ "MatMult_BlockMat_Symmetric" 445290bbb0aSBarry Smith PetscErrorCode MatMult_BlockMat_Symmetric(Mat A,Vec x,Vec y) 446290bbb0aSBarry Smith { 447290bbb0aSBarry Smith Mat_BlockMat *bmat = (Mat_BlockMat*)A->data; 448290bbb0aSBarry Smith PetscErrorCode ierr; 449290bbb0aSBarry Smith PetscScalar *xx,*yy; 450290bbb0aSBarry Smith PetscInt *aj,i,*ii,jrow,m = A->rmap.n/A->rmap.bs,bs = A->rmap.bs,n,j; 451290bbb0aSBarry Smith Mat *aa; 452290bbb0aSBarry Smith 453290bbb0aSBarry Smith PetscFunctionBegin; 454290bbb0aSBarry Smith CHKMEMQ; 455290bbb0aSBarry Smith /* 456290bbb0aSBarry Smith Standard CSR multiply except each entry is a Mat 457290bbb0aSBarry Smith */ 458290bbb0aSBarry Smith ierr = VecGetArray(x,&xx);CHKERRQ(ierr); 459290bbb0aSBarry Smith 460290bbb0aSBarry Smith ierr = VecSet(y,0.0);CHKERRQ(ierr); 461290bbb0aSBarry Smith ierr = VecGetArray(y,&yy);CHKERRQ(ierr); 462290bbb0aSBarry Smith aj = bmat->j; 463290bbb0aSBarry Smith aa = bmat->a; 464290bbb0aSBarry Smith ii = bmat->i; 465290bbb0aSBarry Smith for (i=0; i<m; i++) { 466290bbb0aSBarry Smith jrow = ii[i]; 467290bbb0aSBarry Smith n = ii[i+1] - jrow; 468290bbb0aSBarry Smith ierr = VecPlaceArray(bmat->left,yy + bs*i);CHKERRQ(ierr); 469290bbb0aSBarry Smith ierr = VecPlaceArray(bmat->middle,xx + bs*i);CHKERRQ(ierr); 470290bbb0aSBarry Smith /* if we ALWAYS required a diagonal entry then could remove this if test */ 471290bbb0aSBarry Smith if (aj[jrow] == i) { 472290bbb0aSBarry Smith ierr = VecPlaceArray(bmat->right,xx + bs*aj[jrow]);CHKERRQ(ierr); 473290bbb0aSBarry Smith ierr = MatMultAdd(aa[jrow],bmat->right,bmat->left,bmat->left);CHKERRQ(ierr); 474290bbb0aSBarry Smith ierr = VecResetArray(bmat->right);CHKERRQ(ierr); 475290bbb0aSBarry Smith jrow++; 476290bbb0aSBarry Smith n--; 477290bbb0aSBarry Smith } 478290bbb0aSBarry Smith for (j=0; j<n; j++) { 479290bbb0aSBarry Smith ierr = VecPlaceArray(bmat->right,xx + bs*aj[jrow]);CHKERRQ(ierr); /* upper triangular part */ 480290bbb0aSBarry Smith ierr = MatMultAdd(aa[jrow],bmat->right,bmat->left,bmat->left);CHKERRQ(ierr); 481290bbb0aSBarry Smith ierr = VecResetArray(bmat->right);CHKERRQ(ierr); 482290bbb0aSBarry Smith 483290bbb0aSBarry Smith ierr = VecPlaceArray(bmat->right,yy + bs*aj[jrow]);CHKERRQ(ierr); /* lower triangular part */ 484290bbb0aSBarry Smith ierr = MatMultTransposeAdd(aa[jrow],bmat->middle,bmat->right,bmat->right);CHKERRQ(ierr); 485290bbb0aSBarry Smith ierr = VecResetArray(bmat->right);CHKERRQ(ierr); 486290bbb0aSBarry Smith jrow++; 487290bbb0aSBarry Smith } 488290bbb0aSBarry Smith ierr = VecResetArray(bmat->left);CHKERRQ(ierr); 489290bbb0aSBarry Smith ierr = VecResetArray(bmat->middle);CHKERRQ(ierr); 490290bbb0aSBarry Smith } 491290bbb0aSBarry Smith ierr = VecRestoreArray(x,&xx);CHKERRQ(ierr); 492290bbb0aSBarry Smith ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr); 493290bbb0aSBarry Smith CHKMEMQ; 494290bbb0aSBarry Smith PetscFunctionReturn(0); 495290bbb0aSBarry Smith } 496290bbb0aSBarry Smith 497290bbb0aSBarry Smith #undef __FUNCT__ 498421e10b8SBarry Smith #define __FUNCT__ "MatMultAdd_BlockMat" 499421e10b8SBarry Smith PetscErrorCode MatMultAdd_BlockMat(Mat A,Vec x,Vec y,Vec z) 500421e10b8SBarry Smith { 501421e10b8SBarry Smith PetscFunctionBegin; 502421e10b8SBarry Smith PetscFunctionReturn(0); 503421e10b8SBarry Smith } 504421e10b8SBarry Smith 505421e10b8SBarry Smith #undef __FUNCT__ 506421e10b8SBarry Smith #define __FUNCT__ "MatMultTranspose_BlockMat" 507421e10b8SBarry Smith PetscErrorCode MatMultTranspose_BlockMat(Mat A,Vec x,Vec y) 508421e10b8SBarry Smith { 509421e10b8SBarry Smith PetscFunctionBegin; 510421e10b8SBarry Smith PetscFunctionReturn(0); 511421e10b8SBarry Smith } 512421e10b8SBarry Smith 513421e10b8SBarry Smith #undef __FUNCT__ 514421e10b8SBarry Smith #define __FUNCT__ "MatMultTransposeAdd_BlockMat" 515421e10b8SBarry Smith PetscErrorCode MatMultTransposeAdd_BlockMat(Mat A,Vec x,Vec y,Vec z) 516421e10b8SBarry Smith { 517421e10b8SBarry Smith PetscFunctionBegin; 518421e10b8SBarry Smith PetscFunctionReturn(0); 519421e10b8SBarry Smith } 520421e10b8SBarry Smith 521421e10b8SBarry Smith #undef __FUNCT__ 522421e10b8SBarry Smith #define __FUNCT__ "MatSetBlockSize_BlockMat" 523421e10b8SBarry Smith PetscErrorCode MatSetBlockSize_BlockMat(Mat A,PetscInt bs) 524421e10b8SBarry Smith { 525421e10b8SBarry Smith Mat_BlockMat *bmat = (Mat_BlockMat*)A->data; 526421e10b8SBarry Smith PetscErrorCode ierr; 527ccb205f8SBarry Smith PetscInt nz = 10,i; 528421e10b8SBarry Smith 529421e10b8SBarry Smith PetscFunctionBegin; 530ccb205f8SBarry Smith if (A->rmap.n % bs) SETERRQ2(PETSC_ERR_ARG_INCOMP,"Blocksize %D does not divide number of rows %D",bs,A->rmap.n); 531ccb205f8SBarry Smith if (A->cmap.n % bs) SETERRQ2(PETSC_ERR_ARG_INCOMP,"Blocksize %D does not divide number of columns %D",bs,A->cmap.n); 532421e10b8SBarry Smith A->rmap.bs = A->cmap.bs = bs; 533421e10b8SBarry Smith 534ccb205f8SBarry Smith ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,bs,PETSC_NULL,&bmat->right);CHKERRQ(ierr); 535*6e63c7a1SBarry Smith ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,bs,PETSC_NULL,&bmat->middle);CHKERRQ(ierr); 536ccb205f8SBarry Smith ierr = VecCreateSeq(PETSC_COMM_SELF,bs,&bmat->left);CHKERRQ(ierr); 537ccb205f8SBarry Smith 538421e10b8SBarry Smith ierr = PetscMalloc2(A->rmap.n,PetscInt,&bmat->imax,A->rmap.n,PetscInt,&bmat->ilen);CHKERRQ(ierr); 539421e10b8SBarry Smith for (i=0; i<A->rmap.n; i++) bmat->imax[i] = nz; 540421e10b8SBarry Smith nz = nz*A->rmap.n; 541421e10b8SBarry Smith 542ccb205f8SBarry Smith bmat->mbs = A->rmap.n/A->rmap.bs; 543421e10b8SBarry Smith 544421e10b8SBarry Smith /* bmat->ilen will count nonzeros in each row so far. */ 545ccb205f8SBarry Smith for (i=0; i<bmat->mbs; i++) { bmat->ilen[i] = 0;} 546421e10b8SBarry Smith 547421e10b8SBarry Smith /* allocate the matrix space */ 548421e10b8SBarry Smith ierr = PetscMalloc3(nz,Mat,&bmat->a,nz,PetscInt,&bmat->j,A->rmap.n+1,PetscInt,&bmat->i);CHKERRQ(ierr); 549421e10b8SBarry Smith bmat->i[0] = 0; 550ccb205f8SBarry Smith for (i=1; i<bmat->mbs+1; i++) { 551421e10b8SBarry Smith bmat->i[i] = bmat->i[i-1] + bmat->imax[i-1]; 552421e10b8SBarry Smith } 553421e10b8SBarry Smith bmat->singlemalloc = PETSC_TRUE; 554421e10b8SBarry Smith bmat->free_a = PETSC_TRUE; 555421e10b8SBarry Smith bmat->free_ij = PETSC_TRUE; 556421e10b8SBarry Smith 557421e10b8SBarry Smith bmat->nz = 0; 558421e10b8SBarry Smith bmat->maxnz = nz; 559421e10b8SBarry Smith A->info.nz_unneeded = (double)bmat->maxnz; 560421e10b8SBarry Smith 561421e10b8SBarry Smith PetscFunctionReturn(0); 562421e10b8SBarry Smith } 563421e10b8SBarry Smith 564ccb205f8SBarry Smith /* 565ccb205f8SBarry Smith Adds diagonal pointers to sparse matrix structure. 566ccb205f8SBarry Smith */ 567ccb205f8SBarry Smith #undef __FUNCT__ 568ccb205f8SBarry Smith #define __FUNCT__ "MatMarkDiagonal_BlockMat" 569ccb205f8SBarry Smith PetscErrorCode MatMarkDiagonal_BlockMat(Mat A) 570ccb205f8SBarry Smith { 571ccb205f8SBarry Smith Mat_BlockMat *a = (Mat_BlockMat*)A->data; 572ccb205f8SBarry Smith PetscErrorCode ierr; 573ccb205f8SBarry Smith PetscInt i,j,mbs = A->rmap.n/A->rmap.bs; 574ccb205f8SBarry Smith 575ccb205f8SBarry Smith PetscFunctionBegin; 576ccb205f8SBarry Smith if (!a->diag) { 577ccb205f8SBarry Smith ierr = PetscMalloc(mbs*sizeof(PetscInt),&a->diag);CHKERRQ(ierr); 578ccb205f8SBarry Smith } 579ccb205f8SBarry Smith for (i=0; i<mbs; i++) { 580ccb205f8SBarry Smith a->diag[i] = a->i[i+1]; 581ccb205f8SBarry Smith for (j=a->i[i]; j<a->i[i+1]; j++) { 582ccb205f8SBarry Smith if (a->j[j] == i) { 583ccb205f8SBarry Smith a->diag[i] = j; 584ccb205f8SBarry Smith break; 585ccb205f8SBarry Smith } 586ccb205f8SBarry Smith } 587ccb205f8SBarry Smith } 588ccb205f8SBarry Smith PetscFunctionReturn(0); 589ccb205f8SBarry Smith } 590ccb205f8SBarry Smith 591ccb205f8SBarry Smith #undef __FUNCT__ 592ccb205f8SBarry Smith #define __FUNCT__ "MatGetSubMatrix_BlockMat" 593ccb205f8SBarry Smith PetscErrorCode MatGetSubMatrix_BlockMat(Mat A,IS isrow,IS iscol,PetscInt csize,MatReuse scall,Mat *B) 594ccb205f8SBarry Smith { 595ccb205f8SBarry Smith Mat_BlockMat *a = (Mat_BlockMat*)A->data; 596ccb205f8SBarry Smith Mat_SeqAIJ *c; 597ccb205f8SBarry Smith PetscErrorCode ierr; 598ccb205f8SBarry Smith PetscInt i,k,first,step,lensi,nrows,ncols; 599ccb205f8SBarry Smith PetscInt *j_new,*i_new,*aj = a->j,*ai = a->i,ii,*ailen = a->ilen; 600ccb205f8SBarry Smith PetscScalar *a_new,value; 601ccb205f8SBarry Smith Mat C,*aa = a->a; 602ccb205f8SBarry Smith PetscTruth stride,equal; 603ccb205f8SBarry Smith 604ccb205f8SBarry Smith PetscFunctionBegin; 605ccb205f8SBarry Smith ierr = ISEqual(isrow,iscol,&equal);CHKERRQ(ierr); 606ccb205f8SBarry Smith if (!equal) SETERRQ(PETSC_ERR_SUP,"Only for idential column and row indices"); 607ccb205f8SBarry Smith ierr = ISStride(iscol,&stride);CHKERRQ(ierr); 608ccb205f8SBarry Smith if (!stride) SETERRQ(PETSC_ERR_SUP,"Only for stride indices"); 609ccb205f8SBarry Smith ierr = ISStrideGetInfo(iscol,&first,&step);CHKERRQ(ierr); 610ccb205f8SBarry Smith if (step != A->rmap.bs) SETERRQ(PETSC_ERR_SUP,"Can only select one entry from each block"); 611ccb205f8SBarry Smith 612ccb205f8SBarry Smith ierr = ISGetLocalSize(isrow,&nrows);CHKERRQ(ierr); 613ccb205f8SBarry Smith ncols = nrows; 614ccb205f8SBarry Smith 615ccb205f8SBarry Smith /* create submatrix */ 616ccb205f8SBarry Smith if (scall == MAT_REUSE_MATRIX) { 617ccb205f8SBarry Smith PetscInt n_cols,n_rows; 618ccb205f8SBarry Smith C = *B; 619ccb205f8SBarry Smith ierr = MatGetSize(C,&n_rows,&n_cols);CHKERRQ(ierr); 620ccb205f8SBarry Smith if (n_rows != nrows || n_cols != ncols) SETERRQ(PETSC_ERR_ARG_SIZ,"Reused submatrix wrong size"); 621ccb205f8SBarry Smith ierr = MatZeroEntries(C);CHKERRQ(ierr); 622ccb205f8SBarry Smith } else { 623ccb205f8SBarry Smith ierr = MatCreate(A->comm,&C);CHKERRQ(ierr); 624ccb205f8SBarry Smith ierr = MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); 625*6e63c7a1SBarry Smith if (A->symmetric) { 626*6e63c7a1SBarry Smith ierr = MatSetType(C,MATSEQSBAIJ);CHKERRQ(ierr); 627*6e63c7a1SBarry Smith } else { 628ccb205f8SBarry Smith ierr = MatSetType(C,MATSEQAIJ);CHKERRQ(ierr); 629*6e63c7a1SBarry Smith } 630*6e63c7a1SBarry Smith ierr = MatSeqAIJSetPreallocation(C,0,ailen);CHKERRQ(ierr); 631*6e63c7a1SBarry Smith ierr = MatSeqSBAIJSetPreallocation(C,1,0,ailen);CHKERRQ(ierr); 632ccb205f8SBarry Smith } 633ccb205f8SBarry Smith c = (Mat_SeqAIJ*)C->data; 634ccb205f8SBarry Smith 635ccb205f8SBarry Smith /* loop over rows inserting into submatrix */ 636ccb205f8SBarry Smith a_new = c->a; 637ccb205f8SBarry Smith j_new = c->j; 638ccb205f8SBarry Smith i_new = c->i; 639ccb205f8SBarry Smith 640ccb205f8SBarry Smith for (i=0; i<nrows; i++) { 641ccb205f8SBarry Smith ii = ai[i]; 642ccb205f8SBarry Smith lensi = ailen[i]; 643ccb205f8SBarry Smith for (k=0; k<lensi; k++) { 644ccb205f8SBarry Smith *j_new++ = *aj++; 645ccb205f8SBarry Smith ierr = MatGetValue(*aa++,first,first,value);CHKERRQ(ierr); 646ccb205f8SBarry Smith *a_new++ = value; 647ccb205f8SBarry Smith } 648ccb205f8SBarry Smith i_new[i+1] = i_new[i] + lensi; 649ccb205f8SBarry Smith c->ilen[i] = lensi; 650ccb205f8SBarry Smith } 651ccb205f8SBarry Smith 652ccb205f8SBarry Smith ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 653ccb205f8SBarry Smith ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 654ccb205f8SBarry Smith *B = C; 655ccb205f8SBarry Smith PetscFunctionReturn(0); 656ccb205f8SBarry Smith } 657ccb205f8SBarry Smith 658421e10b8SBarry Smith #undef __FUNCT__ 659421e10b8SBarry Smith #define __FUNCT__ "MatAssemblyEnd_BlockMat" 660421e10b8SBarry Smith PetscErrorCode MatAssemblyEnd_BlockMat(Mat A,MatAssemblyType mode) 661421e10b8SBarry Smith { 662421e10b8SBarry Smith Mat_BlockMat *a = (Mat_BlockMat*)A->data; 663421e10b8SBarry Smith PetscErrorCode ierr; 664421e10b8SBarry Smith PetscInt fshift = 0,i,j,*ai = a->i,*aj = a->j,*imax = a->imax; 665ccb205f8SBarry Smith PetscInt m = a->mbs,*ip,N,*ailen = a->ilen,rmax = 0; 666421e10b8SBarry Smith Mat *aa = a->a,*ap; 667421e10b8SBarry Smith 668421e10b8SBarry Smith PetscFunctionBegin; 669421e10b8SBarry Smith if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0); 670421e10b8SBarry Smith 671421e10b8SBarry Smith if (m) rmax = ailen[0]; /* determine row with most nonzeros */ 672421e10b8SBarry Smith for (i=1; i<m; i++) { 673421e10b8SBarry Smith /* move each row back by the amount of empty slots (fshift) before it*/ 674421e10b8SBarry Smith fshift += imax[i-1] - ailen[i-1]; 675421e10b8SBarry Smith rmax = PetscMax(rmax,ailen[i]); 676421e10b8SBarry Smith if (fshift) { 677421e10b8SBarry Smith ip = aj + ai[i] ; 678421e10b8SBarry Smith ap = aa + ai[i] ; 679421e10b8SBarry Smith N = ailen[i]; 680421e10b8SBarry Smith for (j=0; j<N; j++) { 681421e10b8SBarry Smith ip[j-fshift] = ip[j]; 682421e10b8SBarry Smith ap[j-fshift] = ap[j]; 683421e10b8SBarry Smith } 684421e10b8SBarry Smith } 685421e10b8SBarry Smith ai[i] = ai[i-1] + ailen[i-1]; 686421e10b8SBarry Smith } 687421e10b8SBarry Smith if (m) { 688421e10b8SBarry Smith fshift += imax[m-1] - ailen[m-1]; 689421e10b8SBarry Smith ai[m] = ai[m-1] + ailen[m-1]; 690421e10b8SBarry Smith } 691421e10b8SBarry Smith /* reset ilen and imax for each row */ 692421e10b8SBarry Smith for (i=0; i<m; i++) { 693421e10b8SBarry Smith ailen[i] = imax[i] = ai[i+1] - ai[i]; 694421e10b8SBarry Smith } 695421e10b8SBarry Smith a->nz = ai[m]; 696ccb205f8SBarry Smith for (i=0; i<a->nz; i++) { 697ccb205f8SBarry Smith #if defined(PETSC_USE_DEBUG) 698ccb205f8SBarry Smith if (!aa[i]) SETERRQ3(PETSC_ERR_PLIB,"Null matrix at location %D column %D nz %D",i,aj[i],a->nz); 699ccb205f8SBarry Smith #endif 700ccb205f8SBarry Smith ierr = MatAssemblyBegin(aa[i],MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 701ccb205f8SBarry Smith ierr = MatAssemblyEnd(aa[i],MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 702ccb205f8SBarry Smith } 703ccb205f8SBarry Smith CHKMEMQ; 704421e10b8SBarry Smith ierr = PetscInfo4(A,"Matrix size: %D X %D; storage space: %D unneeded,%D used\n",m,A->cmap.n,fshift,a->nz);CHKERRQ(ierr); 705421e10b8SBarry Smith ierr = PetscInfo1(A,"Number of mallocs during MatSetValues() is %D\n",a->reallocs);CHKERRQ(ierr); 706421e10b8SBarry Smith ierr = PetscInfo1(A,"Maximum nonzeros in any row is %D\n",rmax);CHKERRQ(ierr); 707421e10b8SBarry Smith a->reallocs = 0; 708421e10b8SBarry Smith A->info.nz_unneeded = (double)fshift; 709421e10b8SBarry Smith a->rmax = rmax; 710421e10b8SBarry Smith 711421e10b8SBarry Smith A->same_nonzero = PETSC_TRUE; 712ccb205f8SBarry Smith ierr = MatMarkDiagonal_BlockMat(A);CHKERRQ(ierr); 713421e10b8SBarry Smith PetscFunctionReturn(0); 714421e10b8SBarry Smith } 715421e10b8SBarry Smith 716290bbb0aSBarry Smith #undef __FUNCT__ 717290bbb0aSBarry Smith #define __FUNCT__ "MatSetOption_BlockMat" 718290bbb0aSBarry Smith PetscErrorCode MatSetOption_BlockMat(Mat A,MatOption opt) 719290bbb0aSBarry Smith { 720290bbb0aSBarry Smith PetscFunctionBegin; 721290bbb0aSBarry Smith if (opt == MAT_SYMMETRIC) { 722290bbb0aSBarry Smith A->ops->relax = MatRelax_BlockMat_Symmetric; 723290bbb0aSBarry Smith A->ops->mult = MatMult_BlockMat_Symmetric; 724290bbb0aSBarry Smith } else { 725290bbb0aSBarry Smith PetscInfo1(A,"Unused matrix option %s\n",MatOptions[opt]); 726290bbb0aSBarry Smith } 727290bbb0aSBarry Smith PetscFunctionReturn(0); 728290bbb0aSBarry Smith } 729290bbb0aSBarry Smith 730290bbb0aSBarry Smith 731421e10b8SBarry Smith static struct _MatOps MatOps_Values = {MatSetValues_BlockMat, 732421e10b8SBarry Smith 0, 733421e10b8SBarry Smith 0, 734421e10b8SBarry Smith MatMult_BlockMat, 735421e10b8SBarry Smith /* 4*/ MatMultAdd_BlockMat, 736421e10b8SBarry Smith MatMultTranspose_BlockMat, 737421e10b8SBarry Smith MatMultTransposeAdd_BlockMat, 738421e10b8SBarry Smith 0, 739421e10b8SBarry Smith 0, 740421e10b8SBarry Smith 0, 741421e10b8SBarry Smith /*10*/ 0, 742421e10b8SBarry Smith 0, 743421e10b8SBarry Smith 0, 744ccb205f8SBarry Smith MatRelax_BlockMat, 745421e10b8SBarry Smith 0, 746421e10b8SBarry Smith /*15*/ 0, 747421e10b8SBarry Smith 0, 748421e10b8SBarry Smith 0, 749421e10b8SBarry Smith 0, 750421e10b8SBarry Smith 0, 751421e10b8SBarry Smith /*20*/ 0, 752421e10b8SBarry Smith MatAssemblyEnd_BlockMat, 753421e10b8SBarry Smith 0, 754290bbb0aSBarry Smith MatSetOption_BlockMat, 755421e10b8SBarry Smith 0, 756421e10b8SBarry Smith /*25*/ 0, 757421e10b8SBarry Smith 0, 758421e10b8SBarry Smith 0, 759421e10b8SBarry Smith 0, 760421e10b8SBarry Smith 0, 761421e10b8SBarry Smith /*30*/ 0, 762421e10b8SBarry Smith 0, 763421e10b8SBarry Smith 0, 764421e10b8SBarry Smith 0, 765421e10b8SBarry Smith 0, 766421e10b8SBarry Smith /*35*/ 0, 767421e10b8SBarry Smith 0, 768421e10b8SBarry Smith 0, 769421e10b8SBarry Smith 0, 770421e10b8SBarry Smith 0, 771421e10b8SBarry Smith /*40*/ 0, 772421e10b8SBarry Smith 0, 773421e10b8SBarry Smith 0, 774421e10b8SBarry Smith 0, 775421e10b8SBarry Smith 0, 776421e10b8SBarry Smith /*45*/ 0, 777421e10b8SBarry Smith 0, 778421e10b8SBarry Smith 0, 779421e10b8SBarry Smith 0, 780421e10b8SBarry Smith 0, 781421e10b8SBarry Smith /*50*/ MatSetBlockSize_BlockMat, 782421e10b8SBarry Smith 0, 783421e10b8SBarry Smith 0, 784421e10b8SBarry Smith 0, 785421e10b8SBarry Smith 0, 786421e10b8SBarry Smith /*55*/ 0, 787421e10b8SBarry Smith 0, 788421e10b8SBarry Smith 0, 789421e10b8SBarry Smith 0, 790421e10b8SBarry Smith 0, 791ccb205f8SBarry Smith /*60*/ MatGetSubMatrix_BlockMat, 792421e10b8SBarry Smith MatDestroy_BlockMat, 793ccb205f8SBarry Smith MatView_BlockMat, 794421e10b8SBarry Smith 0, 795421e10b8SBarry Smith 0, 796421e10b8SBarry Smith /*65*/ 0, 797421e10b8SBarry Smith 0, 798421e10b8SBarry Smith 0, 799421e10b8SBarry Smith 0, 800421e10b8SBarry Smith 0, 801421e10b8SBarry Smith /*70*/ 0, 802421e10b8SBarry Smith 0, 803421e10b8SBarry Smith 0, 804421e10b8SBarry Smith 0, 805421e10b8SBarry Smith 0, 806421e10b8SBarry Smith /*75*/ 0, 807421e10b8SBarry Smith 0, 808421e10b8SBarry Smith 0, 809421e10b8SBarry Smith 0, 810421e10b8SBarry Smith 0, 811421e10b8SBarry Smith /*80*/ 0, 812421e10b8SBarry Smith 0, 813421e10b8SBarry Smith 0, 814421e10b8SBarry Smith 0, 815421e10b8SBarry Smith MatLoad_BlockMat, 816421e10b8SBarry Smith /*85*/ 0, 817421e10b8SBarry Smith 0, 818421e10b8SBarry Smith 0, 819421e10b8SBarry Smith 0, 820421e10b8SBarry Smith 0, 821421e10b8SBarry Smith /*90*/ 0, 822421e10b8SBarry Smith 0, 823421e10b8SBarry Smith 0, 824421e10b8SBarry Smith 0, 825421e10b8SBarry Smith 0, 826421e10b8SBarry Smith /*95*/ 0, 827421e10b8SBarry Smith 0, 828421e10b8SBarry Smith 0, 829421e10b8SBarry Smith 0}; 830421e10b8SBarry Smith 831421e10b8SBarry Smith /*MC 832421e10b8SBarry Smith MATBLOCKMAT - A matrix that is defined by a set of Mat's that represents a sparse block matrix 833421e10b8SBarry Smith consisting of (usually) sparse blocks. 834421e10b8SBarry Smith 835421e10b8SBarry Smith Level: advanced 836421e10b8SBarry Smith 837421e10b8SBarry Smith .seealso: MatCreateBlockMat() 838421e10b8SBarry Smith 839421e10b8SBarry Smith M*/ 840421e10b8SBarry Smith 841421e10b8SBarry Smith EXTERN_C_BEGIN 842421e10b8SBarry Smith #undef __FUNCT__ 843421e10b8SBarry Smith #define __FUNCT__ "MatCreate_BlockMat" 844421e10b8SBarry Smith PetscErrorCode PETSCMAT_DLLEXPORT MatCreate_BlockMat(Mat A) 845421e10b8SBarry Smith { 846421e10b8SBarry Smith Mat_BlockMat *b; 847421e10b8SBarry Smith PetscErrorCode ierr; 848421e10b8SBarry Smith 849421e10b8SBarry Smith PetscFunctionBegin; 850421e10b8SBarry Smith ierr = PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr); 851421e10b8SBarry Smith ierr = PetscNew(Mat_BlockMat,&b);CHKERRQ(ierr); 852421e10b8SBarry Smith 853421e10b8SBarry Smith A->data = (void*)b; 854421e10b8SBarry Smith 855421e10b8SBarry Smith ierr = PetscMapInitialize(A->comm,&A->rmap);CHKERRQ(ierr); 856421e10b8SBarry Smith ierr = PetscMapInitialize(A->comm,&A->cmap);CHKERRQ(ierr); 857421e10b8SBarry Smith 858421e10b8SBarry Smith A->assembled = PETSC_TRUE; 859421e10b8SBarry Smith A->preallocated = PETSC_FALSE; 860421e10b8SBarry Smith ierr = PetscObjectChangeTypeName((PetscObject)A,MATBLOCKMAT);CHKERRQ(ierr); 861290bbb0aSBarry Smith 862290bbb0aSBarry Smith ierr = PetscOptionsBegin(A->comm,A->prefix,"Matrix Option","Mat");CHKERRQ(ierr); 863290bbb0aSBarry Smith ierr = PetscOptionsEnd(); 864290bbb0aSBarry Smith 865421e10b8SBarry Smith PetscFunctionReturn(0); 866421e10b8SBarry Smith } 867421e10b8SBarry Smith EXTERN_C_END 868421e10b8SBarry Smith 869421e10b8SBarry Smith #undef __FUNCT__ 870421e10b8SBarry Smith #define __FUNCT__ "MatCreateBlockMat" 871421e10b8SBarry Smith /*@C 872421e10b8SBarry Smith MatCreateBlockMat - Creates a new matrix based sparse Mat storage 873421e10b8SBarry Smith 874421e10b8SBarry Smith Collective on MPI_Comm 875421e10b8SBarry Smith 876421e10b8SBarry Smith Input Parameters: 877421e10b8SBarry Smith + comm - MPI communicator 878421e10b8SBarry Smith . m - number of rows 879421e10b8SBarry Smith . n - number of columns 880421e10b8SBarry Smith - bs - size of each submatrix 881421e10b8SBarry Smith 882421e10b8SBarry Smith 883421e10b8SBarry Smith Output Parameter: 884421e10b8SBarry Smith . A - the matrix 885421e10b8SBarry Smith 886421e10b8SBarry Smith Level: intermediate 887421e10b8SBarry Smith 888421e10b8SBarry Smith PETSc requires that matrices and vectors being used for certain 889421e10b8SBarry Smith operations are partitioned accordingly. For example, when 890421e10b8SBarry Smith creating a bmat matrix, A, that supports parallel matrix-vector 891421e10b8SBarry Smith products using MatMult(A,x,y) the user should set the number 892421e10b8SBarry Smith of local matrix rows to be the number of local elements of the 893421e10b8SBarry Smith corresponding result vector, y. Note that this is information is 894421e10b8SBarry Smith required for use of the matrix interface routines, even though 895421e10b8SBarry Smith the bmat matrix may not actually be physically partitioned. 896421e10b8SBarry Smith For example, 897421e10b8SBarry Smith 898421e10b8SBarry Smith .keywords: matrix, bmat, create 899421e10b8SBarry Smith 900421e10b8SBarry Smith .seealso: MATBLOCKMAT 901421e10b8SBarry Smith @*/ 902421e10b8SBarry Smith PetscErrorCode PETSCMAT_DLLEXPORT MatCreateBlockMat(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt bs,Mat *A) 903421e10b8SBarry Smith { 904421e10b8SBarry Smith PetscErrorCode ierr; 905421e10b8SBarry Smith 906421e10b8SBarry Smith PetscFunctionBegin; 907421e10b8SBarry Smith ierr = MatCreate(comm,A);CHKERRQ(ierr); 908421e10b8SBarry Smith ierr = MatSetSizes(*A,m,n,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); 909421e10b8SBarry Smith ierr = MatSetType(*A,MATBLOCKMAT);CHKERRQ(ierr); 910421e10b8SBarry Smith ierr = MatSetBlockSize(*A,bs);CHKERRQ(ierr); 911421e10b8SBarry Smith PetscFunctionReturn(0); 912421e10b8SBarry Smith } 913421e10b8SBarry Smith 914421e10b8SBarry Smith 915421e10b8SBarry Smith 916