1421e10b8SBarry Smith 2421e10b8SBarry Smith /* 3421e10b8SBarry Smith This provides a matrix that consists of Mats 4421e10b8SBarry Smith */ 5421e10b8SBarry Smith 6af0996ceSBarry Smith #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/ 7c6db04a5SJed Brown #include <../src/mat/impls/baij/seq/baij.h> /* use the common AIJ data-structure */ 8421e10b8SBarry Smith 9421e10b8SBarry Smith typedef struct { 10421e10b8SBarry Smith SEQAIJHEADER(Mat); 11421e10b8SBarry Smith SEQBAIJHEADER; 12ccb205f8SBarry Smith Mat *diags; 13421e10b8SBarry Smith 146e63c7a1SBarry Smith Vec left,right,middle,workb; /* dummy vectors to perform local parts of product */ 15421e10b8SBarry Smith } Mat_BlockMat; 16421e10b8SBarry Smith 17e0877f53SBarry Smith static PetscErrorCode MatSOR_BlockMat_Symmetric(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx) 18290bbb0aSBarry Smith { 19290bbb0aSBarry Smith Mat_BlockMat *a = (Mat_BlockMat*)A->data; 20290bbb0aSBarry Smith PetscScalar *x; 21a2ea699eSBarry Smith const Mat *v; 22290bbb0aSBarry Smith const PetscScalar *b; 23d0f46423SBarry Smith PetscInt n = A->cmap->n,i,mbs = n/A->rmap->bs,j,bs = A->rmap->bs; 24290bbb0aSBarry Smith const PetscInt *idx; 25290bbb0aSBarry Smith IS row,col; 26290bbb0aSBarry Smith MatFactorInfo info; 276e63c7a1SBarry Smith Vec left = a->left,right = a->right, middle = a->middle; 28290bbb0aSBarry Smith Mat *diag; 29290bbb0aSBarry Smith 30290bbb0aSBarry Smith PetscFunctionBegin; 31290bbb0aSBarry Smith its = its*lits; 322c71b3e2SJacob Faibussowitsch PetscCheckFalse(its <= 0,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Relaxation requires global its %" PetscInt_FMT " and local its %" PetscInt_FMT " both positive",its,lits); 332c71b3e2SJacob Faibussowitsch PetscCheckFalse(flag & SOR_EISENSTAT,PETSC_COMM_SELF,PETSC_ERR_SUP,"No support yet for Eisenstat"); 342c71b3e2SJacob Faibussowitsch PetscCheckFalse(omega != 1.0,PETSC_COMM_SELF,PETSC_ERR_SUP,"No support yet for omega not equal to 1.0"); 35*28b400f6SJacob Faibussowitsch PetscCheck(!fshift,PETSC_COMM_SELF,PETSC_ERR_SUP,"No support yet for fshift"); 3626fbe8dcSKarl Rupp if ((flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) && !(flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP)) { 37e32f2f54SBarry Smith SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot do backward sweep without forward sweep"); 3826fbe8dcSKarl Rupp } 39290bbb0aSBarry Smith 40290bbb0aSBarry Smith if (!a->diags) { 415f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(mbs,&a->diags)); 425f80ce2aSJacob Faibussowitsch CHKERRQ(MatFactorInfoInitialize(&info)); 43290bbb0aSBarry Smith for (i=0; i<mbs; i++) { 445f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetOrdering(a->a[a->diag[i]], MATORDERINGND,&row,&col)); 455f80ce2aSJacob Faibussowitsch CHKERRQ(MatCholeskyFactorSymbolic(a->diags[i],a->a[a->diag[i]],row,&info)); 465f80ce2aSJacob Faibussowitsch CHKERRQ(MatCholeskyFactorNumeric(a->diags[i],a->a[a->diag[i]],&info)); 475f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&row)); 485f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&col)); 49290bbb0aSBarry Smith } 505f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(bb,&a->workb)); 51290bbb0aSBarry Smith } 52290bbb0aSBarry Smith diag = a->diags; 53290bbb0aSBarry Smith 545f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(xx,0.0)); 555f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(xx,&x)); 56290bbb0aSBarry Smith /* copy right hand side because it must be modified during iteration */ 575f80ce2aSJacob Faibussowitsch CHKERRQ(VecCopy(bb,a->workb)); 585f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(a->workb,&b)); 59290bbb0aSBarry Smith 6041f059aeSBarry Smith /* need to add code for when initial guess is zero, see MatSOR_SeqAIJ */ 61290bbb0aSBarry Smith while (its--) { 62290bbb0aSBarry Smith if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) { 63290bbb0aSBarry Smith 64290bbb0aSBarry Smith for (i=0; i<mbs; i++) { 656e63c7a1SBarry Smith n = a->i[i+1] - a->i[i] - 1; 666e63c7a1SBarry Smith idx = a->j + a->i[i] + 1; 676e63c7a1SBarry Smith v = a->a + a->i[i] + 1; 68290bbb0aSBarry Smith 695f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(left,0.0)); 70290bbb0aSBarry Smith for (j=0; j<n; j++) { 715f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(right,x + idx[j]*bs)); 725f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultAdd(v[j],right,left,left)); 735f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(right)); 74290bbb0aSBarry Smith } 755f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(right,b + i*bs)); 765f80ce2aSJacob Faibussowitsch CHKERRQ(VecAYPX(left,-1.0,right)); 775f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(right)); 78290bbb0aSBarry Smith 795f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(right,x + i*bs)); 805f80ce2aSJacob Faibussowitsch CHKERRQ(MatSolve(diag[i],left,right)); 816e63c7a1SBarry Smith 8241f059aeSBarry Smith /* now adjust right hand side, see MatSOR_SeqSBAIJ */ 836e63c7a1SBarry Smith for (j=0; j<n; j++) { 845f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultTranspose(v[j],right,left)); 855f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(middle,b + idx[j]*bs)); 865f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(middle,-1.0,left)); 875f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(middle)); 886e63c7a1SBarry Smith } 895f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(right)); 906e63c7a1SBarry Smith 91290bbb0aSBarry Smith } 92290bbb0aSBarry Smith } 93290bbb0aSBarry Smith if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) { 94290bbb0aSBarry Smith 95290bbb0aSBarry Smith for (i=mbs-1; i>=0; i--) { 966e63c7a1SBarry Smith n = a->i[i+1] - a->i[i] - 1; 976e63c7a1SBarry Smith idx = a->j + a->i[i] + 1; 986e63c7a1SBarry Smith v = a->a + a->i[i] + 1; 99290bbb0aSBarry Smith 1005f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(left,0.0)); 101290bbb0aSBarry Smith for (j=0; j<n; j++) { 1025f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(right,x + idx[j]*bs)); 1035f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultAdd(v[j],right,left,left)); 1045f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(right)); 105290bbb0aSBarry Smith } 1065f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(right,b + i*bs)); 1075f80ce2aSJacob Faibussowitsch CHKERRQ(VecAYPX(left,-1.0,right)); 1085f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(right)); 109290bbb0aSBarry Smith 1105f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(right,x + i*bs)); 1115f80ce2aSJacob Faibussowitsch CHKERRQ(MatSolve(diag[i],left,right)); 1125f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(right)); 113290bbb0aSBarry Smith 114290bbb0aSBarry Smith } 115290bbb0aSBarry Smith } 116290bbb0aSBarry Smith } 1175f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(xx,&x)); 1185f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(a->workb,&b)); 119290bbb0aSBarry Smith PetscFunctionReturn(0); 120290bbb0aSBarry Smith } 121290bbb0aSBarry Smith 12281f0254dSBarry Smith static PetscErrorCode MatSOR_BlockMat(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx) 123ccb205f8SBarry Smith { 124ccb205f8SBarry Smith Mat_BlockMat *a = (Mat_BlockMat*)A->data; 125ccb205f8SBarry Smith PetscScalar *x; 126a2ea699eSBarry Smith const Mat *v; 127ccb205f8SBarry Smith const PetscScalar *b; 128d0f46423SBarry Smith PetscInt n = A->cmap->n,i,mbs = n/A->rmap->bs,j,bs = A->rmap->bs; 129ccb205f8SBarry Smith const PetscInt *idx; 130ccb205f8SBarry Smith IS row,col; 131ccb205f8SBarry Smith MatFactorInfo info; 132ccb205f8SBarry Smith Vec left = a->left,right = a->right; 133ccb205f8SBarry Smith Mat *diag; 134ccb205f8SBarry Smith 135ccb205f8SBarry Smith PetscFunctionBegin; 136ccb205f8SBarry Smith its = its*lits; 1372c71b3e2SJacob Faibussowitsch PetscCheckFalse(its <= 0,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Relaxation requires global its %" PetscInt_FMT " and local its %" PetscInt_FMT " both positive",its,lits); 1382c71b3e2SJacob Faibussowitsch PetscCheckFalse(flag & SOR_EISENSTAT,PETSC_COMM_SELF,PETSC_ERR_SUP,"No support yet for Eisenstat"); 1392c71b3e2SJacob Faibussowitsch PetscCheckFalse(omega != 1.0,PETSC_COMM_SELF,PETSC_ERR_SUP,"No support yet for omega not equal to 1.0"); 140*28b400f6SJacob Faibussowitsch PetscCheck(!fshift,PETSC_COMM_SELF,PETSC_ERR_SUP,"No support yet for fshift"); 141ccb205f8SBarry Smith 142ccb205f8SBarry Smith if (!a->diags) { 1435f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(mbs,&a->diags)); 1445f80ce2aSJacob Faibussowitsch CHKERRQ(MatFactorInfoInitialize(&info)); 145ccb205f8SBarry Smith for (i=0; i<mbs; i++) { 1465f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetOrdering(a->a[a->diag[i]], MATORDERINGND,&row,&col)); 1475f80ce2aSJacob Faibussowitsch CHKERRQ(MatLUFactorSymbolic(a->diags[i],a->a[a->diag[i]],row,col,&info)); 1485f80ce2aSJacob Faibussowitsch CHKERRQ(MatLUFactorNumeric(a->diags[i],a->a[a->diag[i]],&info)); 1495f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&row)); 1505f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&col)); 151ccb205f8SBarry Smith } 152ccb205f8SBarry Smith } 153ccb205f8SBarry Smith diag = a->diags; 154ccb205f8SBarry Smith 1555f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(xx,0.0)); 1565f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(xx,&x)); 1575f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(bb,&b)); 158ccb205f8SBarry Smith 15941f059aeSBarry Smith /* need to add code for when initial guess is zero, see MatSOR_SeqAIJ */ 160ccb205f8SBarry Smith while (its--) { 161ccb205f8SBarry Smith if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) { 162ccb205f8SBarry Smith 163ccb205f8SBarry Smith for (i=0; i<mbs; i++) { 164ccb205f8SBarry Smith n = a->i[i+1] - a->i[i]; 165ccb205f8SBarry Smith idx = a->j + a->i[i]; 166ccb205f8SBarry Smith v = a->a + a->i[i]; 167ccb205f8SBarry Smith 1685f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(left,0.0)); 169ccb205f8SBarry Smith for (j=0; j<n; j++) { 170ccb205f8SBarry Smith if (idx[j] != i) { 1715f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(right,x + idx[j]*bs)); 1725f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultAdd(v[j],right,left,left)); 1735f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(right)); 174ccb205f8SBarry Smith } 175ccb205f8SBarry Smith } 1765f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(right,b + i*bs)); 1775f80ce2aSJacob Faibussowitsch CHKERRQ(VecAYPX(left,-1.0,right)); 1785f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(right)); 179ccb205f8SBarry Smith 1805f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(right,x + i*bs)); 1815f80ce2aSJacob Faibussowitsch CHKERRQ(MatSolve(diag[i],left,right)); 1825f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(right)); 183ccb205f8SBarry Smith } 184ccb205f8SBarry Smith } 185ccb205f8SBarry Smith if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) { 186ccb205f8SBarry Smith 187ccb205f8SBarry Smith for (i=mbs-1; i>=0; i--) { 188ccb205f8SBarry Smith n = a->i[i+1] - a->i[i]; 189ccb205f8SBarry Smith idx = a->j + a->i[i]; 190ccb205f8SBarry Smith v = a->a + a->i[i]; 191ccb205f8SBarry Smith 1925f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(left,0.0)); 193ccb205f8SBarry Smith for (j=0; j<n; j++) { 194ccb205f8SBarry Smith if (idx[j] != i) { 1955f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(right,x + idx[j]*bs)); 1965f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultAdd(v[j],right,left,left)); 1975f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(right)); 198ccb205f8SBarry Smith } 199ccb205f8SBarry Smith } 2005f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(right,b + i*bs)); 2015f80ce2aSJacob Faibussowitsch CHKERRQ(VecAYPX(left,-1.0,right)); 2025f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(right)); 203ccb205f8SBarry Smith 2045f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(right,x + i*bs)); 2055f80ce2aSJacob Faibussowitsch CHKERRQ(MatSolve(diag[i],left,right)); 2065f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(right)); 207ccb205f8SBarry Smith 208ccb205f8SBarry Smith } 209ccb205f8SBarry Smith } 210ccb205f8SBarry Smith } 2115f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(xx,&x)); 2125f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(bb,&b)); 213ccb205f8SBarry Smith PetscFunctionReturn(0); 214ccb205f8SBarry Smith } 215ccb205f8SBarry Smith 21681f0254dSBarry Smith static PetscErrorCode MatSetValues_BlockMat(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is) 217421e10b8SBarry Smith { 218421e10b8SBarry Smith Mat_BlockMat *a = (Mat_BlockMat*)A->data; 219421e10b8SBarry Smith PetscInt *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N,lastcol = -1; 220421e10b8SBarry Smith PetscInt *imax=a->imax,*ai=a->i,*ailen=a->ilen; 221d0f46423SBarry Smith PetscInt *aj =a->j,nonew=a->nonew,bs=A->rmap->bs,brow,bcol; 222421e10b8SBarry Smith PetscInt ridx,cidx; 223ace3abfcSBarry Smith PetscBool roworiented=a->roworiented; 224421e10b8SBarry Smith MatScalar value; 225421e10b8SBarry Smith Mat *ap,*aa = a->a; 226421e10b8SBarry Smith 227421e10b8SBarry Smith PetscFunctionBegin; 228421e10b8SBarry Smith for (k=0; k<m; k++) { /* loop over added rows */ 229421e10b8SBarry Smith row = im[k]; 230421e10b8SBarry Smith brow = row/bs; 231421e10b8SBarry Smith if (row < 0) continue; 2326bdcaf15SBarry Smith PetscCheck(row < A->rmap->N,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %" PetscInt_FMT " max %" PetscInt_FMT,row,A->rmap->N-1); 233421e10b8SBarry Smith rp = aj + ai[brow]; 234421e10b8SBarry Smith ap = aa + ai[brow]; 235421e10b8SBarry Smith rmax = imax[brow]; 236421e10b8SBarry Smith nrow = ailen[brow]; 237421e10b8SBarry Smith low = 0; 238421e10b8SBarry Smith high = nrow; 239421e10b8SBarry Smith for (l=0; l<n; l++) { /* loop over added columns */ 240421e10b8SBarry Smith if (in[l] < 0) continue; 2416bdcaf15SBarry Smith PetscCheck(in[l] < A->cmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %" PetscInt_FMT " max %" PetscInt_FMT,in[l],A->cmap->n-1); 242421e10b8SBarry Smith col = in[l]; bcol = col/bs; 2436e63c7a1SBarry Smith if (A->symmetric && brow > bcol) continue; 244421e10b8SBarry Smith ridx = row % bs; cidx = col % bs; 2452205254eSKarl Rupp if (roworiented) value = v[l + k*n]; 2462205254eSKarl Rupp else value = v[k + l*m]; 2472205254eSKarl Rupp 2482205254eSKarl Rupp if (col <= lastcol) low = 0; 2492205254eSKarl Rupp else high = nrow; 250421e10b8SBarry Smith lastcol = col; 251421e10b8SBarry Smith while (high-low > 7) { 252421e10b8SBarry Smith t = (low+high)/2; 253421e10b8SBarry Smith if (rp[t] > bcol) high = t; 254421e10b8SBarry Smith else low = t; 255421e10b8SBarry Smith } 256421e10b8SBarry Smith for (i=low; i<high; i++) { 257421e10b8SBarry Smith if (rp[i] > bcol) break; 2582205254eSKarl Rupp if (rp[i] == bcol) goto noinsert1; 259421e10b8SBarry Smith } 260421e10b8SBarry Smith if (nonew == 1) goto noinsert1; 2612c71b3e2SJacob Faibussowitsch PetscCheckFalse(nonew == -1,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero (%" PetscInt_FMT ", %" PetscInt_FMT ") in the matrix", row, col); 262fef13f97SBarry Smith MatSeqXAIJReallocateAIJ(A,a->mbs,1,nrow,brow,bcol,rmax,aa,ai,aj,rp,ap,imax,nonew,Mat); 263421e10b8SBarry Smith N = nrow++ - 1; high++; 264421e10b8SBarry Smith /* shift up all the later entries in this row */ 265421e10b8SBarry Smith for (ii=N; ii>=i; ii--) { 266421e10b8SBarry Smith rp[ii+1] = rp[ii]; 267421e10b8SBarry Smith ap[ii+1] = ap[ii]; 268421e10b8SBarry Smith } 269f4259b30SLisandro Dalcin if (N>=i) ap[i] = NULL; 270421e10b8SBarry Smith rp[i] = bcol; 271421e10b8SBarry Smith a->nz++; 272e56f5c9eSBarry Smith A->nonzerostate++; 273421e10b8SBarry Smith noinsert1:; 274421e10b8SBarry Smith if (!*(ap+i)) { 2755f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSeqAIJ(PETSC_COMM_SELF,bs,bs,0,NULL,ap+i)); 276b0223207SBarry Smith } 2775f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(ap[i],1,&ridx,1,&cidx,&value,is)); 278421e10b8SBarry Smith low = i; 279421e10b8SBarry Smith } 280421e10b8SBarry Smith ailen[brow] = nrow; 281421e10b8SBarry Smith } 282421e10b8SBarry Smith PetscFunctionReturn(0); 283421e10b8SBarry Smith } 284421e10b8SBarry Smith 28581f0254dSBarry Smith static PetscErrorCode MatLoad_BlockMat(Mat newmat, PetscViewer viewer) 286a5973382SShri Abhyankar { 287a5973382SShri Abhyankar PetscErrorCode ierr; 288a5973382SShri Abhyankar Mat tmpA; 289a5973382SShri Abhyankar PetscInt i,j,m,n,bs = 1,ncols,*lens,currentcol,mbs,**ii,*ilens,nextcol,*llens,cnt = 0; 290a5973382SShri Abhyankar const PetscInt *cols; 291a5973382SShri Abhyankar const PetscScalar *values; 292ace3abfcSBarry Smith PetscBool flg = PETSC_FALSE,notdone; 293a5973382SShri Abhyankar Mat_SeqAIJ *a; 294a5973382SShri Abhyankar Mat_BlockMat *amat; 295a5973382SShri Abhyankar 296a5973382SShri Abhyankar PetscFunctionBegin; 297c98fd787SBarry Smith /* force binary viewer to load .info file if it has not yet done so */ 2985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerSetUp(viewer)); 2995f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreate(PETSC_COMM_SELF,&tmpA)); 3005f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetType(tmpA,MATSEQAIJ)); 3015f80ce2aSJacob Faibussowitsch CHKERRQ(MatLoad_SeqAIJ(tmpA,viewer)); 302a5973382SShri Abhyankar 3035f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetLocalSize(tmpA,&m,&n)); 3040298fd71SBarry Smith ierr = PetscOptionsBegin(PETSC_COMM_SELF,NULL,"Options for loading BlockMat matrix 1","Mat");CHKERRQ(ierr); 3055f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsInt("-matload_block_size","Set the blocksize used to store the matrix","MatLoad",bs,&bs,NULL)); 3065f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-matload_symmetric","Store the matrix as symmetric","MatLoad",flg,&flg,NULL)); 307a5973382SShri Abhyankar ierr = PetscOptionsEnd();CHKERRQ(ierr); 308a5973382SShri Abhyankar 309a5973382SShri Abhyankar /* Determine number of nonzero blocks for each block row */ 310a5973382SShri Abhyankar a = (Mat_SeqAIJ*) tmpA->data; 311a5973382SShri Abhyankar mbs = m/bs; 3125f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc3(mbs,&lens,bs,&ii,bs,&ilens)); 3135f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArrayzero(lens,mbs)); 314a5973382SShri Abhyankar 315a5973382SShri Abhyankar for (i=0; i<mbs; i++) { 316a5973382SShri Abhyankar for (j=0; j<bs; j++) { 317a5973382SShri Abhyankar ii[j] = a->j + a->i[i*bs + j]; 318a5973382SShri Abhyankar ilens[j] = a->i[i*bs + j + 1] - a->i[i*bs + j]; 319a5973382SShri Abhyankar } 320a5973382SShri Abhyankar 321a5973382SShri Abhyankar currentcol = -1; 322a5973382SShri Abhyankar while (PETSC_TRUE) { 323a5973382SShri Abhyankar notdone = PETSC_FALSE; 324a5973382SShri Abhyankar nextcol = 1000000000; 325a5973382SShri Abhyankar for (j=0; j<bs; j++) { 326a5973382SShri Abhyankar while ((ilens[j] > 0 && ii[j][0]/bs <= currentcol)) { 327a5973382SShri Abhyankar ii[j]++; 328a5973382SShri Abhyankar ilens[j]--; 329a5973382SShri Abhyankar } 330a5973382SShri Abhyankar if (ilens[j] > 0) { 331a5973382SShri Abhyankar notdone = PETSC_TRUE; 332a5973382SShri Abhyankar nextcol = PetscMin(nextcol,ii[j][0]/bs); 333a5973382SShri Abhyankar } 334a5973382SShri Abhyankar } 335a5973382SShri Abhyankar if (!notdone) break; 336a5973382SShri Abhyankar if (!flg || (nextcol >= i)) lens[i]++; 337a5973382SShri Abhyankar currentcol = nextcol; 338a5973382SShri Abhyankar } 339a5973382SShri Abhyankar } 340a5973382SShri Abhyankar 341a5973382SShri Abhyankar if (newmat->rmap->n < 0 && newmat->rmap->N < 0 && newmat->cmap->n < 0 && newmat->cmap->N < 0) { 3425f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetSizes(newmat,m,n,PETSC_DETERMINE,PETSC_DETERMINE)); 343a5973382SShri Abhyankar } 3445f80ce2aSJacob Faibussowitsch CHKERRQ(MatBlockMatSetPreallocation(newmat,bs,0,lens)); 345a5973382SShri Abhyankar if (flg) { 3465f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetOption(newmat,MAT_SYMMETRIC,PETSC_TRUE)); 347a5973382SShri Abhyankar } 348a5973382SShri Abhyankar amat = (Mat_BlockMat*)(newmat)->data; 349a5973382SShri Abhyankar 350a5973382SShri Abhyankar /* preallocate the submatrices */ 3515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(bs,&llens)); 352a5973382SShri Abhyankar for (i=0; i<mbs; i++) { /* loops for block rows */ 353a5973382SShri Abhyankar for (j=0; j<bs; j++) { 354a5973382SShri Abhyankar ii[j] = a->j + a->i[i*bs + j]; 355a5973382SShri Abhyankar ilens[j] = a->i[i*bs + j + 1] - a->i[i*bs + j]; 356a5973382SShri Abhyankar } 357a5973382SShri Abhyankar 358a5973382SShri Abhyankar currentcol = 1000000000; 359a5973382SShri Abhyankar for (j=0; j<bs; j++) { /* loop over rows in block finding first nonzero block */ 360a5973382SShri Abhyankar if (ilens[j] > 0) { 361a5973382SShri Abhyankar currentcol = PetscMin(currentcol,ii[j][0]/bs); 362a5973382SShri Abhyankar } 363a5973382SShri Abhyankar } 364a5973382SShri Abhyankar 365a5973382SShri Abhyankar while (PETSC_TRUE) { /* loops over blocks in block row */ 366a5973382SShri Abhyankar notdone = PETSC_FALSE; 367a5973382SShri Abhyankar nextcol = 1000000000; 3685f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArrayzero(llens,bs)); 369a5973382SShri Abhyankar for (j=0; j<bs; j++) { /* loop over rows in block */ 370a5973382SShri Abhyankar while ((ilens[j] > 0 && ii[j][0]/bs <= currentcol)) { /* loop over columns in row */ 371a5973382SShri Abhyankar ii[j]++; 372a5973382SShri Abhyankar ilens[j]--; 373a5973382SShri Abhyankar llens[j]++; 374a5973382SShri Abhyankar } 375a5973382SShri Abhyankar if (ilens[j] > 0) { 376a5973382SShri Abhyankar notdone = PETSC_TRUE; 377a5973382SShri Abhyankar nextcol = PetscMin(nextcol,ii[j][0]/bs); 378a5973382SShri Abhyankar } 379a5973382SShri Abhyankar } 3802c71b3e2SJacob Faibussowitsch PetscCheckFalse(cnt >= amat->maxnz,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Number of blocks found greater than expected %" PetscInt_FMT,cnt); 381a5973382SShri Abhyankar if (!flg || currentcol >= i) { 382a5973382SShri Abhyankar amat->j[cnt] = currentcol; 3835f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSeqAIJ(PETSC_COMM_SELF,bs,bs,0,llens,amat->a+cnt++)); 384a5973382SShri Abhyankar } 385a5973382SShri Abhyankar 386a5973382SShri Abhyankar if (!notdone) break; 387a5973382SShri Abhyankar currentcol = nextcol; 388a5973382SShri Abhyankar } 389a5973382SShri Abhyankar amat->ilen[i] = lens[i]; 390a5973382SShri Abhyankar } 391a5973382SShri Abhyankar 3925f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree3(lens,ii,ilens)); 3935f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(llens)); 394a5973382SShri Abhyankar 395a5973382SShri Abhyankar /* copy over the matrix, one row at a time */ 396a5973382SShri Abhyankar for (i=0; i<m; i++) { 3975f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRow(tmpA,i,&ncols,&cols,&values)); 3985f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(newmat,1,&i,ncols,cols,values,INSERT_VALUES)); 3995f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRow(tmpA,i,&ncols,&cols,&values)); 400a5973382SShri Abhyankar } 4015f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(newmat,MAT_FINAL_ASSEMBLY)); 4025f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(newmat,MAT_FINAL_ASSEMBLY)); 403a5973382SShri Abhyankar PetscFunctionReturn(0); 404a5973382SShri Abhyankar } 405a5973382SShri Abhyankar 40681f0254dSBarry Smith static PetscErrorCode MatView_BlockMat(Mat A,PetscViewer viewer) 407ccb205f8SBarry Smith { 40864075487SBarry Smith Mat_BlockMat *a = (Mat_BlockMat*)A->data; 409ccb205f8SBarry Smith const char *name; 410ccb205f8SBarry Smith PetscViewerFormat format; 411ccb205f8SBarry Smith 412ccb205f8SBarry Smith PetscFunctionBegin; 4135f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetName((PetscObject)A,&name)); 4145f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerGetFormat(viewer,&format)); 415ccb205f8SBarry Smith if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO) { 4165f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer,"Nonzero block matrices = %" PetscInt_FMT " \n",a->nz)); 41764075487SBarry Smith if (A->symmetric) { 4185f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer,"Only upper triangular part of symmetric matrix is stored\n")); 41964075487SBarry Smith } 420ccb205f8SBarry Smith } 421ccb205f8SBarry Smith PetscFunctionReturn(0); 422ccb205f8SBarry Smith } 423421e10b8SBarry Smith 42481f0254dSBarry Smith static PetscErrorCode MatDestroy_BlockMat(Mat mat) 425421e10b8SBarry Smith { 426421e10b8SBarry Smith Mat_BlockMat *bmat = (Mat_BlockMat*)mat->data; 427ccb205f8SBarry Smith PetscInt i; 428421e10b8SBarry Smith 429421e10b8SBarry Smith PetscFunctionBegin; 4305f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&bmat->right)); 4315f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&bmat->left)); 4325f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&bmat->middle)); 4335f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&bmat->workb)); 434ccb205f8SBarry Smith if (bmat->diags) { 435d0f46423SBarry Smith for (i=0; i<mat->rmap->n/mat->rmap->bs; i++) { 4365f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&bmat->diags[i])); 437ccb205f8SBarry Smith } 438ccb205f8SBarry Smith } 439ccb205f8SBarry Smith if (bmat->a) { 440ccb205f8SBarry Smith for (i=0; i<bmat->nz; i++) { 4415f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&bmat->a[i])); 442ccb205f8SBarry Smith } 443ccb205f8SBarry Smith } 4445f80ce2aSJacob Faibussowitsch CHKERRQ(MatSeqXAIJFreeAIJ(mat,(PetscScalar**)&bmat->a,&bmat->j,&bmat->i)); 4455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(mat->data)); 446421e10b8SBarry Smith PetscFunctionReturn(0); 447421e10b8SBarry Smith } 448421e10b8SBarry Smith 44981f0254dSBarry Smith static PetscErrorCode MatMult_BlockMat(Mat A,Vec x,Vec y) 450421e10b8SBarry Smith { 451421e10b8SBarry Smith Mat_BlockMat *bmat = (Mat_BlockMat*)A->data; 452421e10b8SBarry Smith PetscScalar *xx,*yy; 453d0f46423SBarry Smith PetscInt *aj,i,*ii,jrow,m = A->rmap->n/A->rmap->bs,bs = A->rmap->bs,n,j; 454421e10b8SBarry Smith Mat *aa; 455421e10b8SBarry Smith 456421e10b8SBarry Smith PetscFunctionBegin; 457421e10b8SBarry Smith /* 458421e10b8SBarry Smith Standard CSR multiply except each entry is a Mat 459421e10b8SBarry Smith */ 4605f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(x,&xx)); 461ccb205f8SBarry Smith 4625f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(y,0.0)); 4635f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(y,&yy)); 464421e10b8SBarry Smith aj = bmat->j; 465421e10b8SBarry Smith aa = bmat->a; 466421e10b8SBarry Smith ii = bmat->i; 467421e10b8SBarry Smith for (i=0; i<m; i++) { 468421e10b8SBarry Smith jrow = ii[i]; 4695f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(bmat->left,yy + bs*i)); 470421e10b8SBarry Smith n = ii[i+1] - jrow; 471421e10b8SBarry Smith for (j=0; j<n; j++) { 4725f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(bmat->right,xx + bs*aj[jrow])); 4735f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultAdd(aa[jrow],bmat->right,bmat->left,bmat->left)); 4745f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(bmat->right)); 475421e10b8SBarry Smith jrow++; 476421e10b8SBarry Smith } 4775f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(bmat->left)); 478421e10b8SBarry Smith } 4795f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(x,&xx)); 4805f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(y,&yy)); 481421e10b8SBarry Smith PetscFunctionReturn(0); 482421e10b8SBarry Smith } 483421e10b8SBarry Smith 484290bbb0aSBarry Smith PetscErrorCode MatMult_BlockMat_Symmetric(Mat A,Vec x,Vec y) 485290bbb0aSBarry Smith { 486290bbb0aSBarry Smith Mat_BlockMat *bmat = (Mat_BlockMat*)A->data; 487290bbb0aSBarry Smith PetscScalar *xx,*yy; 488d0f46423SBarry Smith PetscInt *aj,i,*ii,jrow,m = A->rmap->n/A->rmap->bs,bs = A->rmap->bs,n,j; 489290bbb0aSBarry Smith Mat *aa; 490290bbb0aSBarry Smith 491290bbb0aSBarry Smith PetscFunctionBegin; 492290bbb0aSBarry Smith /* 493290bbb0aSBarry Smith Standard CSR multiply except each entry is a Mat 494290bbb0aSBarry Smith */ 4955f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(x,&xx)); 496290bbb0aSBarry Smith 4975f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(y,0.0)); 4985f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(y,&yy)); 499290bbb0aSBarry Smith aj = bmat->j; 500290bbb0aSBarry Smith aa = bmat->a; 501290bbb0aSBarry Smith ii = bmat->i; 502290bbb0aSBarry Smith for (i=0; i<m; i++) { 503290bbb0aSBarry Smith jrow = ii[i]; 504290bbb0aSBarry Smith n = ii[i+1] - jrow; 5055f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(bmat->left,yy + bs*i)); 5065f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(bmat->middle,xx + bs*i)); 507290bbb0aSBarry Smith /* if we ALWAYS required a diagonal entry then could remove this if test */ 508290bbb0aSBarry Smith if (aj[jrow] == i) { 5095f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(bmat->right,xx + bs*aj[jrow])); 5105f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultAdd(aa[jrow],bmat->right,bmat->left,bmat->left)); 5115f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(bmat->right)); 512290bbb0aSBarry Smith jrow++; 513290bbb0aSBarry Smith n--; 514290bbb0aSBarry Smith } 515290bbb0aSBarry Smith for (j=0; j<n; j++) { 5165f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(bmat->right,xx + bs*aj[jrow])); /* upper triangular part */ 5175f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultAdd(aa[jrow],bmat->right,bmat->left,bmat->left)); 5185f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(bmat->right)); 519290bbb0aSBarry Smith 5205f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(bmat->right,yy + bs*aj[jrow])); /* lower triangular part */ 5215f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultTransposeAdd(aa[jrow],bmat->middle,bmat->right,bmat->right)); 5225f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(bmat->right)); 523290bbb0aSBarry Smith jrow++; 524290bbb0aSBarry Smith } 5255f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(bmat->left)); 5265f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(bmat->middle)); 527290bbb0aSBarry Smith } 5285f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(x,&xx)); 5295f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(y,&yy)); 530290bbb0aSBarry Smith PetscFunctionReturn(0); 531290bbb0aSBarry Smith } 532290bbb0aSBarry Smith 53381f0254dSBarry Smith static PetscErrorCode MatMultAdd_BlockMat(Mat A,Vec x,Vec y,Vec z) 534421e10b8SBarry Smith { 535421e10b8SBarry Smith PetscFunctionBegin; 536421e10b8SBarry Smith PetscFunctionReturn(0); 537421e10b8SBarry Smith } 538421e10b8SBarry Smith 53981f0254dSBarry Smith static PetscErrorCode MatMultTranspose_BlockMat(Mat A,Vec x,Vec y) 540421e10b8SBarry Smith { 541421e10b8SBarry Smith PetscFunctionBegin; 542421e10b8SBarry Smith PetscFunctionReturn(0); 543421e10b8SBarry Smith } 544421e10b8SBarry Smith 54581f0254dSBarry Smith static PetscErrorCode MatMultTransposeAdd_BlockMat(Mat A,Vec x,Vec y,Vec z) 546421e10b8SBarry Smith { 547421e10b8SBarry Smith PetscFunctionBegin; 548421e10b8SBarry Smith PetscFunctionReturn(0); 549421e10b8SBarry Smith } 550421e10b8SBarry Smith 551ccb205f8SBarry Smith /* 552ccb205f8SBarry Smith Adds diagonal pointers to sparse matrix structure. 553ccb205f8SBarry Smith */ 55481f0254dSBarry Smith static PetscErrorCode MatMarkDiagonal_BlockMat(Mat A) 555ccb205f8SBarry Smith { 556ccb205f8SBarry Smith Mat_BlockMat *a = (Mat_BlockMat*)A->data; 557d0f46423SBarry Smith PetscInt i,j,mbs = A->rmap->n/A->rmap->bs; 558ccb205f8SBarry Smith 559ccb205f8SBarry Smith PetscFunctionBegin; 560ccb205f8SBarry Smith if (!a->diag) { 5615f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(mbs,&a->diag)); 562ccb205f8SBarry Smith } 563ccb205f8SBarry Smith for (i=0; i<mbs; i++) { 564ccb205f8SBarry Smith a->diag[i] = a->i[i+1]; 565ccb205f8SBarry Smith for (j=a->i[i]; j<a->i[i+1]; j++) { 566ccb205f8SBarry Smith if (a->j[j] == i) { 567ccb205f8SBarry Smith a->diag[i] = j; 568ccb205f8SBarry Smith break; 569ccb205f8SBarry Smith } 570ccb205f8SBarry Smith } 571ccb205f8SBarry Smith } 572ccb205f8SBarry Smith PetscFunctionReturn(0); 573ccb205f8SBarry Smith } 574ccb205f8SBarry Smith 5757dae84e0SHong Zhang static PetscErrorCode MatCreateSubMatrix_BlockMat(Mat A,IS isrow,IS iscol,MatReuse scall,Mat *B) 576ccb205f8SBarry Smith { 577ccb205f8SBarry Smith Mat_BlockMat *a = (Mat_BlockMat*)A->data; 578ccb205f8SBarry Smith Mat_SeqAIJ *c; 579ccb205f8SBarry Smith PetscInt i,k,first,step,lensi,nrows,ncols; 580d2a212eaSBarry Smith PetscInt *j_new,*i_new,*aj = a->j,*ailen = a->ilen; 5811620fd73SBarry Smith PetscScalar *a_new; 582ccb205f8SBarry Smith Mat C,*aa = a->a; 583ace3abfcSBarry Smith PetscBool stride,equal; 584ccb205f8SBarry Smith 585ccb205f8SBarry Smith PetscFunctionBegin; 5865f80ce2aSJacob Faibussowitsch CHKERRQ(ISEqual(isrow,iscol,&equal)); 587*28b400f6SJacob Faibussowitsch PetscCheck(equal,PETSC_COMM_SELF,PETSC_ERR_SUP,"Only for identical column and row indices"); 5885f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject)iscol,ISSTRIDE,&stride)); 589*28b400f6SJacob Faibussowitsch PetscCheck(stride,PETSC_COMM_SELF,PETSC_ERR_SUP,"Only for stride indices"); 5905f80ce2aSJacob Faibussowitsch CHKERRQ(ISStrideGetInfo(iscol,&first,&step)); 5912c71b3e2SJacob Faibussowitsch PetscCheckFalse(step != A->rmap->bs,PETSC_COMM_SELF,PETSC_ERR_SUP,"Can only select one entry from each block"); 592ccb205f8SBarry Smith 5935f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(isrow,&nrows)); 594ccb205f8SBarry Smith ncols = nrows; 595ccb205f8SBarry Smith 596ccb205f8SBarry Smith /* create submatrix */ 597ccb205f8SBarry Smith if (scall == MAT_REUSE_MATRIX) { 598ccb205f8SBarry Smith PetscInt n_cols,n_rows; 599ccb205f8SBarry Smith C = *B; 6005f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetSize(C,&n_rows,&n_cols)); 6012c71b3e2SJacob Faibussowitsch PetscCheckFalse(n_rows != nrows || n_cols != ncols,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Reused submatrix wrong size"); 6025f80ce2aSJacob Faibussowitsch CHKERRQ(MatZeroEntries(C)); 603ccb205f8SBarry Smith } else { 6045f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreate(PetscObjectComm((PetscObject)A),&C)); 6055f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE)); 6066e63c7a1SBarry Smith if (A->symmetric) { 6075f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetType(C,MATSEQSBAIJ)); 6086e63c7a1SBarry Smith } else { 6095f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetType(C,MATSEQAIJ)); 6106e63c7a1SBarry Smith } 6115f80ce2aSJacob Faibussowitsch CHKERRQ(MatSeqAIJSetPreallocation(C,0,ailen)); 6125f80ce2aSJacob Faibussowitsch CHKERRQ(MatSeqSBAIJSetPreallocation(C,1,0,ailen)); 613ccb205f8SBarry Smith } 614ccb205f8SBarry Smith c = (Mat_SeqAIJ*)C->data; 615ccb205f8SBarry Smith 616ccb205f8SBarry Smith /* loop over rows inserting into submatrix */ 617ccb205f8SBarry Smith a_new = c->a; 618ccb205f8SBarry Smith j_new = c->j; 619ccb205f8SBarry Smith i_new = c->i; 620ccb205f8SBarry Smith 621ccb205f8SBarry Smith for (i=0; i<nrows; i++) { 622ccb205f8SBarry Smith lensi = ailen[i]; 623ccb205f8SBarry Smith for (k=0; k<lensi; k++) { 624ccb205f8SBarry Smith *j_new++ = *aj++; 6255f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetValue(*aa++,first,first,a_new++)); 626ccb205f8SBarry Smith } 627ccb205f8SBarry Smith i_new[i+1] = i_new[i] + lensi; 628ccb205f8SBarry Smith c->ilen[i] = lensi; 629ccb205f8SBarry Smith } 630ccb205f8SBarry Smith 6315f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY)); 6325f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY)); 633ccb205f8SBarry Smith *B = C; 634ccb205f8SBarry Smith PetscFunctionReturn(0); 635ccb205f8SBarry Smith } 636ccb205f8SBarry Smith 63781f0254dSBarry Smith static PetscErrorCode MatAssemblyEnd_BlockMat(Mat A,MatAssemblyType mode) 638421e10b8SBarry Smith { 639421e10b8SBarry Smith Mat_BlockMat *a = (Mat_BlockMat*)A->data; 640421e10b8SBarry Smith PetscInt fshift = 0,i,j,*ai = a->i,*aj = a->j,*imax = a->imax; 641ccb205f8SBarry Smith PetscInt m = a->mbs,*ip,N,*ailen = a->ilen,rmax = 0; 642421e10b8SBarry Smith Mat *aa = a->a,*ap; 643421e10b8SBarry Smith 644421e10b8SBarry Smith PetscFunctionBegin; 645421e10b8SBarry Smith if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0); 646421e10b8SBarry Smith 647421e10b8SBarry Smith if (m) rmax = ailen[0]; /* determine row with most nonzeros */ 648421e10b8SBarry Smith for (i=1; i<m; i++) { 649421e10b8SBarry Smith /* move each row back by the amount of empty slots (fshift) before it*/ 650421e10b8SBarry Smith fshift += imax[i-1] - ailen[i-1]; 651421e10b8SBarry Smith rmax = PetscMax(rmax,ailen[i]); 652421e10b8SBarry Smith if (fshift) { 653421e10b8SBarry Smith ip = aj + ai[i]; 654421e10b8SBarry Smith ap = aa + ai[i]; 655421e10b8SBarry Smith N = ailen[i]; 656421e10b8SBarry Smith for (j=0; j<N; j++) { 657421e10b8SBarry Smith ip[j-fshift] = ip[j]; 658421e10b8SBarry Smith ap[j-fshift] = ap[j]; 659421e10b8SBarry Smith } 660421e10b8SBarry Smith } 661421e10b8SBarry Smith ai[i] = ai[i-1] + ailen[i-1]; 662421e10b8SBarry Smith } 663421e10b8SBarry Smith if (m) { 664421e10b8SBarry Smith fshift += imax[m-1] - ailen[m-1]; 665421e10b8SBarry Smith ai[m] = ai[m-1] + ailen[m-1]; 666421e10b8SBarry Smith } 667421e10b8SBarry Smith /* reset ilen and imax for each row */ 668421e10b8SBarry Smith for (i=0; i<m; i++) { 669421e10b8SBarry Smith ailen[i] = imax[i] = ai[i+1] - ai[i]; 670421e10b8SBarry Smith } 671421e10b8SBarry Smith a->nz = ai[m]; 672ccb205f8SBarry Smith for (i=0; i<a->nz; i++) { 6736bdcaf15SBarry Smith PetscAssert(aa[i],PETSC_COMM_SELF,PETSC_ERR_PLIB,"Null matrix at location %" PetscInt_FMT " column %" PetscInt_FMT " nz %" PetscInt_FMT,i,aj[i],a->nz); 6745f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(aa[i],MAT_FINAL_ASSEMBLY)); 6755f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(aa[i],MAT_FINAL_ASSEMBLY)); 676ccb205f8SBarry Smith } 6775f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo(A,"Matrix size: %" PetscInt_FMT " X %" PetscInt_FMT "; storage space: %" PetscInt_FMT " unneeded,%" PetscInt_FMT " used\n",m,A->cmap->n/A->cmap->bs,fshift,a->nz)); 6785f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo(A,"Number of mallocs during MatSetValues() is %" PetscInt_FMT "\n",a->reallocs)); 6795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo(A,"Maximum nonzeros in any row is %" PetscInt_FMT "\n",rmax)); 6802205254eSKarl Rupp 6818e58a170SBarry Smith A->info.mallocs += a->reallocs; 682421e10b8SBarry Smith a->reallocs = 0; 683421e10b8SBarry Smith A->info.nz_unneeded = (double)fshift; 684421e10b8SBarry Smith a->rmax = rmax; 6855f80ce2aSJacob Faibussowitsch CHKERRQ(MatMarkDiagonal_BlockMat(A)); 686421e10b8SBarry Smith PetscFunctionReturn(0); 687421e10b8SBarry Smith } 688421e10b8SBarry Smith 68981f0254dSBarry Smith static PetscErrorCode MatSetOption_BlockMat(Mat A,MatOption opt,PetscBool flg) 690290bbb0aSBarry Smith { 691290bbb0aSBarry Smith PetscFunctionBegin; 6924e0d8c25SBarry Smith if (opt == MAT_SYMMETRIC && flg) { 69341f059aeSBarry Smith A->ops->sor = MatSOR_BlockMat_Symmetric; 694290bbb0aSBarry Smith A->ops->mult = MatMult_BlockMat_Symmetric; 695290bbb0aSBarry Smith } else { 6965f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo(A,"Unused matrix option %s\n",MatOptions[opt])); 697290bbb0aSBarry Smith } 698290bbb0aSBarry Smith PetscFunctionReturn(0); 699290bbb0aSBarry Smith } 700290bbb0aSBarry Smith 7013964eb88SJed Brown static struct _MatOps MatOps_Values = {MatSetValues_BlockMat, 702f4259b30SLisandro Dalcin NULL, 703f4259b30SLisandro Dalcin NULL, 704421e10b8SBarry Smith MatMult_BlockMat, 705421e10b8SBarry Smith /* 4*/ MatMultAdd_BlockMat, 706421e10b8SBarry Smith MatMultTranspose_BlockMat, 707421e10b8SBarry Smith MatMultTransposeAdd_BlockMat, 708f4259b30SLisandro Dalcin NULL, 709f4259b30SLisandro Dalcin NULL, 710f4259b30SLisandro Dalcin NULL, 711f4259b30SLisandro Dalcin /* 10*/ NULL, 712f4259b30SLisandro Dalcin NULL, 713f4259b30SLisandro Dalcin NULL, 71441f059aeSBarry Smith MatSOR_BlockMat, 715f4259b30SLisandro Dalcin NULL, 716f4259b30SLisandro Dalcin /* 15*/ NULL, 717f4259b30SLisandro Dalcin NULL, 718f4259b30SLisandro Dalcin NULL, 719f4259b30SLisandro Dalcin NULL, 720f4259b30SLisandro Dalcin NULL, 721f4259b30SLisandro Dalcin /* 20*/ NULL, 722421e10b8SBarry Smith MatAssemblyEnd_BlockMat, 723290bbb0aSBarry Smith MatSetOption_BlockMat, 724f4259b30SLisandro Dalcin NULL, 725f4259b30SLisandro Dalcin /* 24*/ NULL, 726f4259b30SLisandro Dalcin NULL, 727f4259b30SLisandro Dalcin NULL, 728f4259b30SLisandro Dalcin NULL, 729f4259b30SLisandro Dalcin NULL, 730f4259b30SLisandro Dalcin /* 29*/ NULL, 731f4259b30SLisandro Dalcin NULL, 732f4259b30SLisandro Dalcin NULL, 733f4259b30SLisandro Dalcin NULL, 734f4259b30SLisandro Dalcin NULL, 735f4259b30SLisandro Dalcin /* 34*/ NULL, 736f4259b30SLisandro Dalcin NULL, 737f4259b30SLisandro Dalcin NULL, 738f4259b30SLisandro Dalcin NULL, 739f4259b30SLisandro Dalcin NULL, 740f4259b30SLisandro Dalcin /* 39*/ NULL, 741f4259b30SLisandro Dalcin NULL, 742f4259b30SLisandro Dalcin NULL, 743f4259b30SLisandro Dalcin NULL, 744f4259b30SLisandro Dalcin NULL, 745f4259b30SLisandro Dalcin /* 44*/ NULL, 746f4259b30SLisandro Dalcin NULL, 7477d68702bSBarry Smith MatShift_Basic, 748f4259b30SLisandro Dalcin NULL, 749f4259b30SLisandro Dalcin NULL, 750f4259b30SLisandro Dalcin /* 49*/ NULL, 751f4259b30SLisandro Dalcin NULL, 752f4259b30SLisandro Dalcin NULL, 753f4259b30SLisandro Dalcin NULL, 754f4259b30SLisandro Dalcin NULL, 755f4259b30SLisandro Dalcin /* 54*/ NULL, 756f4259b30SLisandro Dalcin NULL, 757f4259b30SLisandro Dalcin NULL, 758f4259b30SLisandro Dalcin NULL, 759f4259b30SLisandro Dalcin NULL, 7607dae84e0SHong Zhang /* 59*/ MatCreateSubMatrix_BlockMat, 761421e10b8SBarry Smith MatDestroy_BlockMat, 762ccb205f8SBarry Smith MatView_BlockMat, 763f4259b30SLisandro Dalcin NULL, 764f4259b30SLisandro Dalcin NULL, 765f4259b30SLisandro Dalcin /* 64*/ NULL, 766f4259b30SLisandro Dalcin NULL, 767f4259b30SLisandro Dalcin NULL, 768f4259b30SLisandro Dalcin NULL, 769f4259b30SLisandro Dalcin NULL, 770f4259b30SLisandro Dalcin /* 69*/ NULL, 771f4259b30SLisandro Dalcin NULL, 772f4259b30SLisandro Dalcin NULL, 773f4259b30SLisandro Dalcin NULL, 774f4259b30SLisandro Dalcin NULL, 775f4259b30SLisandro Dalcin /* 74*/ NULL, 776f4259b30SLisandro Dalcin NULL, 777f4259b30SLisandro Dalcin NULL, 778f4259b30SLisandro Dalcin NULL, 779f4259b30SLisandro Dalcin NULL, 780f4259b30SLisandro Dalcin /* 79*/ NULL, 781f4259b30SLisandro Dalcin NULL, 782f4259b30SLisandro Dalcin NULL, 783f4259b30SLisandro Dalcin NULL, 7845bba2384SShri Abhyankar MatLoad_BlockMat, 785f4259b30SLisandro Dalcin /* 84*/ NULL, 786f4259b30SLisandro Dalcin NULL, 787f4259b30SLisandro Dalcin NULL, 788f4259b30SLisandro Dalcin NULL, 789f4259b30SLisandro Dalcin NULL, 790f4259b30SLisandro Dalcin /* 89*/ NULL, 791f4259b30SLisandro Dalcin NULL, 792f4259b30SLisandro Dalcin NULL, 793f4259b30SLisandro Dalcin NULL, 794f4259b30SLisandro Dalcin NULL, 795f4259b30SLisandro Dalcin /* 94*/ NULL, 796f4259b30SLisandro Dalcin NULL, 797f4259b30SLisandro Dalcin NULL, 798f4259b30SLisandro Dalcin NULL, 799f4259b30SLisandro Dalcin NULL, 800f4259b30SLisandro Dalcin /* 99*/ NULL, 801f4259b30SLisandro Dalcin NULL, 802f4259b30SLisandro Dalcin NULL, 803f4259b30SLisandro Dalcin NULL, 804f4259b30SLisandro Dalcin NULL, 805f4259b30SLisandro Dalcin /*104*/ NULL, 806f4259b30SLisandro Dalcin NULL, 807f4259b30SLisandro Dalcin NULL, 808f4259b30SLisandro Dalcin NULL, 809f4259b30SLisandro Dalcin NULL, 810f4259b30SLisandro Dalcin /*109*/ NULL, 811f4259b30SLisandro Dalcin NULL, 812f4259b30SLisandro Dalcin NULL, 813f4259b30SLisandro Dalcin NULL, 814f4259b30SLisandro Dalcin NULL, 815f4259b30SLisandro Dalcin /*114*/ NULL, 816f4259b30SLisandro Dalcin NULL, 817f4259b30SLisandro Dalcin NULL, 818f4259b30SLisandro Dalcin NULL, 819f4259b30SLisandro Dalcin NULL, 820f4259b30SLisandro Dalcin /*119*/ NULL, 821f4259b30SLisandro Dalcin NULL, 822f4259b30SLisandro Dalcin NULL, 823f4259b30SLisandro Dalcin NULL, 824f4259b30SLisandro Dalcin NULL, 825f4259b30SLisandro Dalcin /*124*/ NULL, 826f4259b30SLisandro Dalcin NULL, 827f4259b30SLisandro Dalcin NULL, 828f4259b30SLisandro Dalcin NULL, 829f4259b30SLisandro Dalcin NULL, 830f4259b30SLisandro Dalcin /*129*/ NULL, 831f4259b30SLisandro Dalcin NULL, 832f4259b30SLisandro Dalcin NULL, 833f4259b30SLisandro Dalcin NULL, 834f4259b30SLisandro Dalcin NULL, 835f4259b30SLisandro Dalcin /*134*/ NULL, 836f4259b30SLisandro Dalcin NULL, 837f4259b30SLisandro Dalcin NULL, 838f4259b30SLisandro Dalcin NULL, 839f4259b30SLisandro Dalcin NULL, 840f4259b30SLisandro Dalcin /*139*/ NULL, 841f4259b30SLisandro Dalcin NULL, 842d70f29a3SPierre Jolivet NULL, 843d70f29a3SPierre Jolivet NULL, 844d70f29a3SPierre Jolivet NULL, 845d70f29a3SPierre Jolivet /*144*/ NULL, 846d70f29a3SPierre Jolivet NULL, 847d70f29a3SPierre Jolivet NULL, 848f4259b30SLisandro Dalcin NULL 849a5973382SShri Abhyankar }; 850421e10b8SBarry Smith 8518cdf2d9bSBarry Smith /*@C 8528cdf2d9bSBarry Smith MatBlockMatSetPreallocation - For good matrix assembly performance 8538cdf2d9bSBarry Smith the user should preallocate the matrix storage by setting the parameter nz 8548cdf2d9bSBarry Smith (or the array nnz). By setting these parameters accurately, performance 8558cdf2d9bSBarry Smith during matrix assembly can be increased by more than a factor of 50. 8568cdf2d9bSBarry Smith 857d083f849SBarry Smith Collective 8588cdf2d9bSBarry Smith 8598cdf2d9bSBarry Smith Input Parameters: 8608cdf2d9bSBarry Smith + B - The matrix 8618cdf2d9bSBarry Smith . bs - size of each block in matrix 8628cdf2d9bSBarry Smith . nz - number of nonzeros per block row (same for all rows) 8638cdf2d9bSBarry Smith - nnz - array containing the number of nonzeros in the various block rows 8640298fd71SBarry Smith (possibly different for each row) or NULL 8658cdf2d9bSBarry Smith 8668cdf2d9bSBarry Smith Notes: 8678cdf2d9bSBarry Smith If nnz is given then nz is ignored 8688cdf2d9bSBarry Smith 8698cdf2d9bSBarry Smith Specify the preallocated storage with either nz or nnz (not both). 8700298fd71SBarry Smith Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory 8718cdf2d9bSBarry Smith allocation. For large problems you MUST preallocate memory or you 8728cdf2d9bSBarry Smith will get TERRIBLE performance, see the users' manual chapter on matrices. 8738cdf2d9bSBarry Smith 8748cdf2d9bSBarry Smith Level: intermediate 8758cdf2d9bSBarry Smith 8768cdf2d9bSBarry Smith .seealso: MatCreate(), MatCreateBlockMat(), MatSetValues() 8778cdf2d9bSBarry Smith 8788cdf2d9bSBarry Smith @*/ 8797087cfbeSBarry Smith PetscErrorCode MatBlockMatSetPreallocation(Mat B,PetscInt bs,PetscInt nz,const PetscInt nnz[]) 8808cdf2d9bSBarry Smith { 8818cdf2d9bSBarry Smith PetscFunctionBegin; 8825f80ce2aSJacob Faibussowitsch CHKERRQ(PetscTryMethod(B,"MatBlockMatSetPreallocation_C",(Mat,PetscInt,PetscInt,const PetscInt[]),(B,bs,nz,nnz))); 8838cdf2d9bSBarry Smith PetscFunctionReturn(0); 8848cdf2d9bSBarry Smith } 8858cdf2d9bSBarry Smith 88681f0254dSBarry Smith static PetscErrorCode MatBlockMatSetPreallocation_BlockMat(Mat A,PetscInt bs,PetscInt nz,PetscInt *nnz) 8878cdf2d9bSBarry Smith { 8888cdf2d9bSBarry Smith Mat_BlockMat *bmat = (Mat_BlockMat*)A->data; 8898cdf2d9bSBarry Smith PetscInt i; 8908cdf2d9bSBarry Smith 8918cdf2d9bSBarry Smith PetscFunctionBegin; 8925f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutSetBlockSize(A->rmap,bs)); 8935f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutSetBlockSize(A->cmap,bs)); 8945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutSetUp(A->rmap)); 8955f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutSetUp(A->cmap)); 8965f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutGetBlockSize(A->rmap,&bs)); 89734ef9618SShri Abhyankar 8988cdf2d9bSBarry Smith if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5; 8992c71b3e2SJacob Faibussowitsch PetscCheckFalse(nz < 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %" PetscInt_FMT,nz); 9008cdf2d9bSBarry Smith if (nnz) { 901d0f46423SBarry Smith for (i=0; i<A->rmap->n/bs; i++) { 9022c71b3e2SJacob Faibussowitsch PetscCheckFalse(nnz[i] < 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be less than 0: local row %" PetscInt_FMT " value %" PetscInt_FMT,i,nnz[i]); 9032c71b3e2SJacob Faibussowitsch PetscCheckFalse(nnz[i] > A->cmap->n/bs,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be greater than row length: local row %" PetscInt_FMT " value %" PetscInt_FMT " rowlength %" PetscInt_FMT,i,nnz[i],A->cmap->n/bs); 9048cdf2d9bSBarry Smith } 9058cdf2d9bSBarry Smith } 906d0f46423SBarry Smith bmat->mbs = A->rmap->n/bs; 9078cdf2d9bSBarry Smith 9085f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreateSeqWithArray(PETSC_COMM_SELF,1,bs,NULL,&bmat->right)); 9095f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreateSeqWithArray(PETSC_COMM_SELF,1,bs,NULL,&bmat->middle)); 9105f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreateSeq(PETSC_COMM_SELF,bs,&bmat->left)); 9118cdf2d9bSBarry Smith 9122ee49352SLisandro Dalcin if (!bmat->imax) { 9135f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc2(A->rmap->n,&bmat->imax,A->rmap->n,&bmat->ilen)); 9145f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogObjectMemory((PetscObject)A,2*A->rmap->n*sizeof(PetscInt))); 9152ee49352SLisandro Dalcin } 916c0aa6a63SJacob Faibussowitsch if (PetscLikely(nnz)) { 9178cdf2d9bSBarry Smith nz = 0; 918d0f46423SBarry Smith for (i=0; i<A->rmap->n/A->rmap->bs; i++) { 9198cdf2d9bSBarry Smith bmat->imax[i] = nnz[i]; 9208cdf2d9bSBarry Smith nz += nnz[i]; 9218cdf2d9bSBarry Smith } 922f23aa3ddSBarry Smith } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Currently requires block row by row preallocation"); 9238cdf2d9bSBarry Smith 9248cdf2d9bSBarry Smith /* bmat->ilen will count nonzeros in each row so far. */ 9255f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArrayzero(bmat->ilen,bmat->mbs)); 9268cdf2d9bSBarry Smith 9278cdf2d9bSBarry Smith /* allocate the matrix space */ 9285f80ce2aSJacob Faibussowitsch CHKERRQ(MatSeqXAIJFreeAIJ(A,(PetscScalar**)&bmat->a,&bmat->j,&bmat->i)); 9295f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc3(nz,&bmat->a,nz,&bmat->j,A->rmap->n+1,&bmat->i)); 9305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogObjectMemory((PetscObject)A,(A->rmap->n+1)*sizeof(PetscInt)+nz*(sizeof(PetscScalar)+sizeof(PetscInt)))); 9318cdf2d9bSBarry Smith bmat->i[0] = 0; 9328cdf2d9bSBarry Smith for (i=1; i<bmat->mbs+1; i++) { 9338cdf2d9bSBarry Smith bmat->i[i] = bmat->i[i-1] + bmat->imax[i-1]; 9348cdf2d9bSBarry Smith } 9358cdf2d9bSBarry Smith bmat->singlemalloc = PETSC_TRUE; 9368cdf2d9bSBarry Smith bmat->free_a = PETSC_TRUE; 9378cdf2d9bSBarry Smith bmat->free_ij = PETSC_TRUE; 9388cdf2d9bSBarry Smith 9398cdf2d9bSBarry Smith bmat->nz = 0; 9408cdf2d9bSBarry Smith bmat->maxnz = nz; 9418cdf2d9bSBarry Smith A->info.nz_unneeded = (double)bmat->maxnz; 9425f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetOption(A,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE)); 9438cdf2d9bSBarry Smith PetscFunctionReturn(0); 9448cdf2d9bSBarry Smith } 9458cdf2d9bSBarry Smith 946421e10b8SBarry Smith /*MC 947421e10b8SBarry Smith MATBLOCKMAT - A matrix that is defined by a set of Mat's that represents a sparse block matrix 948421e10b8SBarry Smith consisting of (usually) sparse blocks. 949421e10b8SBarry Smith 950421e10b8SBarry Smith Level: advanced 951421e10b8SBarry Smith 952421e10b8SBarry Smith .seealso: MatCreateBlockMat() 953421e10b8SBarry Smith 954421e10b8SBarry Smith M*/ 955421e10b8SBarry Smith 9568cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_BlockMat(Mat A) 957421e10b8SBarry Smith { 958421e10b8SBarry Smith Mat_BlockMat *b; 959421e10b8SBarry Smith 960421e10b8SBarry Smith PetscFunctionBegin; 9615f80ce2aSJacob Faibussowitsch CHKERRQ(PetscNewLog(A,&b)); 962421e10b8SBarry Smith A->data = (void*)b; 9635f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps))); 964421e10b8SBarry Smith 965421e10b8SBarry Smith A->assembled = PETSC_TRUE; 966421e10b8SBarry Smith A->preallocated = PETSC_FALSE; 9675f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectChangeTypeName((PetscObject)A,MATBLOCKMAT)); 968290bbb0aSBarry Smith 9695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatBlockMatSetPreallocation_C",MatBlockMatSetPreallocation_BlockMat)); 970421e10b8SBarry Smith PetscFunctionReturn(0); 971421e10b8SBarry Smith } 972421e10b8SBarry Smith 973421e10b8SBarry Smith /*@C 974bbd3f336SJed Brown MatCreateBlockMat - Creates a new matrix in which each block contains a uniform-size sequential Mat object 975421e10b8SBarry Smith 976d083f849SBarry Smith Collective 977421e10b8SBarry Smith 978421e10b8SBarry Smith Input Parameters: 979421e10b8SBarry Smith + comm - MPI communicator 980421e10b8SBarry Smith . m - number of rows 981421e10b8SBarry Smith . n - number of columns 9828cdf2d9bSBarry Smith . bs - size of each submatrix 9838cdf2d9bSBarry Smith . nz - expected maximum number of nonzero blocks in row (use PETSC_DEFAULT if not known) 9840298fd71SBarry Smith - nnz - expected number of nonzers per block row if known (use NULL otherwise) 985421e10b8SBarry Smith 986421e10b8SBarry Smith Output Parameter: 987421e10b8SBarry Smith . A - the matrix 988421e10b8SBarry Smith 989421e10b8SBarry Smith Level: intermediate 990421e10b8SBarry Smith 99195452b02SPatrick Sanan Notes: 99295452b02SPatrick Sanan Matrices of this type are nominally-sparse matrices in which each "entry" is a Mat object. Each Mat must 993bbd3f336SJed Brown have the same size and be sequential. The local and global sizes must be compatible with this decomposition. 994bbd3f336SJed Brown 995bbd3f336SJed Brown For matrices containing parallel submatrices and variable block sizes, see MATNEST. 996421e10b8SBarry Smith 997bbd3f336SJed Brown .seealso: MATBLOCKMAT, MatCreateNest() 998421e10b8SBarry Smith @*/ 9997087cfbeSBarry Smith PetscErrorCode MatCreateBlockMat(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt bs,PetscInt nz,PetscInt *nnz, Mat *A) 1000421e10b8SBarry Smith { 1001421e10b8SBarry Smith PetscFunctionBegin; 10025f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreate(comm,A)); 10035f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetSizes(*A,m,n,PETSC_DETERMINE,PETSC_DETERMINE)); 10045f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetType(*A,MATBLOCKMAT)); 10055f80ce2aSJacob Faibussowitsch CHKERRQ(MatBlockMatSetPreallocation(*A,bs,nz,nnz)); 1006421e10b8SBarry Smith PetscFunctionReturn(0); 1007421e10b8SBarry Smith } 1008