xref: /petsc/src/mat/impls/blockmat/seq/blockmat.c (revision b45d2f2cb7e031d9c0de5873eca80614ca7b863b)
1421e10b8SBarry Smith 
2421e10b8SBarry Smith /*
3421e10b8SBarry Smith    This provides a matrix that consists of Mats
4421e10b8SBarry Smith */
5421e10b8SBarry Smith 
6*b45d2f2cSJed Brown #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 
177087cfbeSBarry Smith extern PetscErrorCode  MatBlockMatSetPreallocation(Mat,PetscInt,PetscInt,const PetscInt*);
18a5973382SShri Abhyankar 
19421e10b8SBarry Smith #undef __FUNCT__
2041f059aeSBarry Smith #define __FUNCT__ "MatSOR_BlockMat_Symmetric"
2141f059aeSBarry Smith PetscErrorCode MatSOR_BlockMat_Symmetric(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx)
22290bbb0aSBarry Smith {
23290bbb0aSBarry Smith   Mat_BlockMat       *a = (Mat_BlockMat*)A->data;
24290bbb0aSBarry Smith   PetscScalar        *x;
25290bbb0aSBarry Smith   const Mat          *v = a->a;
26290bbb0aSBarry Smith   const PetscScalar  *b;
27290bbb0aSBarry Smith   PetscErrorCode     ierr;
28d0f46423SBarry Smith   PetscInt           n = A->cmap->n,i,mbs = n/A->rmap->bs,j,bs = A->rmap->bs;
29290bbb0aSBarry Smith   const PetscInt     *idx;
30290bbb0aSBarry Smith   IS                 row,col;
31290bbb0aSBarry Smith   MatFactorInfo      info;
326e63c7a1SBarry Smith   Vec                left = a->left,right = a->right, middle = a->middle;
33290bbb0aSBarry Smith   Mat                *diag;
34290bbb0aSBarry Smith 
35290bbb0aSBarry Smith   PetscFunctionBegin;
36290bbb0aSBarry Smith   its = its*lits;
37e32f2f54SBarry Smith   if (its <= 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Relaxation requires global its %D and local its %D both positive",its,lits);
38e32f2f54SBarry Smith   if (flag & SOR_EISENSTAT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support yet for Eisenstat");
39e32f2f54SBarry Smith   if (omega != 1.0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support yet for omega not equal to 1.0");
40e32f2f54SBarry Smith   if (fshift) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support yet for fshift");
41290bbb0aSBarry Smith   if ((flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) && !(flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP))
42e32f2f54SBarry Smith     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot do backward sweep without forward sweep");
43290bbb0aSBarry Smith 
44290bbb0aSBarry Smith   if (!a->diags) {
45290bbb0aSBarry Smith     ierr = PetscMalloc(mbs*sizeof(Mat),&a->diags);CHKERRQ(ierr);
46290bbb0aSBarry Smith     ierr = MatFactorInfoInitialize(&info);CHKERRQ(ierr);
47290bbb0aSBarry Smith     for (i=0; i<mbs; i++) {
482692d6eeSBarry Smith       ierr = MatGetOrdering(a->a[a->diag[i]], MATORDERINGND,&row,&col);CHKERRQ(ierr);
49719d5645SBarry Smith       ierr = MatCholeskyFactorSymbolic(a->diags[i],a->a[a->diag[i]],row,&info);CHKERRQ(ierr);
50719d5645SBarry Smith       ierr = MatCholeskyFactorNumeric(a->diags[i],a->a[a->diag[i]],&info);CHKERRQ(ierr);
516bf464f9SBarry Smith       ierr = ISDestroy(&row);CHKERRQ(ierr);
526bf464f9SBarry Smith       ierr = ISDestroy(&col);CHKERRQ(ierr);
53290bbb0aSBarry Smith     }
546e63c7a1SBarry Smith     ierr = VecDuplicate(bb,&a->workb);CHKERRQ(ierr);
55290bbb0aSBarry Smith   }
56290bbb0aSBarry Smith   diag    = a->diags;
57290bbb0aSBarry Smith 
58290bbb0aSBarry Smith   ierr = VecSet(xx,0.0);CHKERRQ(ierr);
59290bbb0aSBarry Smith   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
60290bbb0aSBarry Smith   /* copy right hand side because it must be modified during iteration */
616e63c7a1SBarry Smith   ierr = VecCopy(bb,a->workb);CHKERRQ(ierr);
623649974fSBarry Smith   ierr = VecGetArrayRead(a->workb,&b);CHKERRQ(ierr);
63290bbb0aSBarry Smith 
6441f059aeSBarry Smith   /* need to add code for when initial guess is zero, see MatSOR_SeqAIJ */
65290bbb0aSBarry Smith   while (its--) {
66290bbb0aSBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){
67290bbb0aSBarry Smith 
68290bbb0aSBarry Smith       for (i=0; i<mbs; i++) {
696e63c7a1SBarry Smith         n    = a->i[i+1] - a->i[i] - 1;
706e63c7a1SBarry Smith         idx  = a->j + a->i[i] + 1;
716e63c7a1SBarry Smith         v    = a->a + a->i[i] + 1;
72290bbb0aSBarry Smith 
73290bbb0aSBarry Smith         ierr = VecSet(left,0.0);CHKERRQ(ierr);
74290bbb0aSBarry Smith         for (j=0; j<n; j++) {
75290bbb0aSBarry Smith           ierr = VecPlaceArray(right,x + idx[j]*bs);CHKERRQ(ierr);
76290bbb0aSBarry Smith           ierr = MatMultAdd(v[j],right,left,left);CHKERRQ(ierr);
77290bbb0aSBarry Smith           ierr = VecResetArray(right);CHKERRQ(ierr);
78290bbb0aSBarry Smith         }
79290bbb0aSBarry Smith         ierr = VecPlaceArray(right,b + i*bs);CHKERRQ(ierr);
80290bbb0aSBarry Smith         ierr = VecAYPX(left,-1.0,right);CHKERRQ(ierr);
81290bbb0aSBarry Smith         ierr = VecResetArray(right);CHKERRQ(ierr);
82290bbb0aSBarry Smith 
83290bbb0aSBarry Smith         ierr = VecPlaceArray(right,x + i*bs);CHKERRQ(ierr);
84290bbb0aSBarry Smith         ierr = MatSolve(diag[i],left,right);CHKERRQ(ierr);
856e63c7a1SBarry Smith 
8641f059aeSBarry Smith         /* now adjust right hand side, see MatSOR_SeqSBAIJ */
876e63c7a1SBarry Smith         for (j=0; j<n; j++) {
886e63c7a1SBarry Smith           ierr = MatMultTranspose(v[j],right,left);CHKERRQ(ierr);
896e63c7a1SBarry Smith           ierr = VecPlaceArray(middle,b + idx[j]*bs);CHKERRQ(ierr);
906e63c7a1SBarry Smith           ierr = VecAXPY(middle,-1.0,left);CHKERRQ(ierr);
916e63c7a1SBarry Smith           ierr = VecResetArray(middle);CHKERRQ(ierr);
926e63c7a1SBarry Smith         }
93290bbb0aSBarry Smith         ierr = VecResetArray(right);CHKERRQ(ierr);
946e63c7a1SBarry Smith 
95290bbb0aSBarry Smith       }
96290bbb0aSBarry Smith     }
97290bbb0aSBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){
98290bbb0aSBarry Smith 
99290bbb0aSBarry Smith       for (i=mbs-1; i>=0; i--) {
1006e63c7a1SBarry Smith         n    = a->i[i+1] - a->i[i] - 1;
1016e63c7a1SBarry Smith         idx  = a->j + a->i[i] + 1;
1026e63c7a1SBarry Smith         v    = a->a + a->i[i] + 1;
103290bbb0aSBarry Smith 
104290bbb0aSBarry Smith         ierr = VecSet(left,0.0);CHKERRQ(ierr);
105290bbb0aSBarry Smith         for (j=0; j<n; j++) {
106290bbb0aSBarry Smith           ierr = VecPlaceArray(right,x + idx[j]*bs);CHKERRQ(ierr);
107290bbb0aSBarry Smith           ierr = MatMultAdd(v[j],right,left,left);CHKERRQ(ierr);
108290bbb0aSBarry Smith           ierr = VecResetArray(right);CHKERRQ(ierr);
109290bbb0aSBarry Smith         }
110290bbb0aSBarry Smith         ierr = VecPlaceArray(right,b + i*bs);CHKERRQ(ierr);
111290bbb0aSBarry Smith         ierr = VecAYPX(left,-1.0,right);CHKERRQ(ierr);
112290bbb0aSBarry Smith         ierr = VecResetArray(right);CHKERRQ(ierr);
113290bbb0aSBarry Smith 
114290bbb0aSBarry Smith         ierr = VecPlaceArray(right,x + i*bs);CHKERRQ(ierr);
115290bbb0aSBarry Smith         ierr = MatSolve(diag[i],left,right);CHKERRQ(ierr);
116290bbb0aSBarry Smith         ierr = VecResetArray(right);CHKERRQ(ierr);
117290bbb0aSBarry Smith 
118290bbb0aSBarry Smith       }
119290bbb0aSBarry Smith     }
120290bbb0aSBarry Smith   }
121290bbb0aSBarry Smith   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
1223649974fSBarry Smith   ierr = VecRestoreArrayRead(a->workb,&b);CHKERRQ(ierr);
123290bbb0aSBarry Smith   PetscFunctionReturn(0);
124290bbb0aSBarry Smith }
125290bbb0aSBarry Smith 
126290bbb0aSBarry Smith #undef __FUNCT__
12741f059aeSBarry Smith #define __FUNCT__ "MatSOR_BlockMat"
12841f059aeSBarry Smith PetscErrorCode MatSOR_BlockMat(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx)
129ccb205f8SBarry Smith {
130ccb205f8SBarry Smith   Mat_BlockMat       *a = (Mat_BlockMat*)A->data;
131ccb205f8SBarry Smith   PetscScalar        *x;
132ccb205f8SBarry Smith   const Mat          *v = a->a;
133ccb205f8SBarry Smith   const PetscScalar  *b;
134ccb205f8SBarry Smith   PetscErrorCode     ierr;
135d0f46423SBarry Smith   PetscInt           n = A->cmap->n,i,mbs = n/A->rmap->bs,j,bs = A->rmap->bs;
136ccb205f8SBarry Smith   const PetscInt     *idx;
137ccb205f8SBarry Smith   IS                 row,col;
138ccb205f8SBarry Smith   MatFactorInfo      info;
139ccb205f8SBarry Smith   Vec                left = a->left,right = a->right;
140ccb205f8SBarry Smith   Mat                *diag;
141ccb205f8SBarry Smith 
142ccb205f8SBarry Smith   PetscFunctionBegin;
143ccb205f8SBarry Smith   its = its*lits;
144e32f2f54SBarry Smith   if (its <= 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Relaxation requires global its %D and local its %D both positive",its,lits);
145e32f2f54SBarry Smith   if (flag & SOR_EISENSTAT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support yet for Eisenstat");
146e32f2f54SBarry Smith   if (omega != 1.0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support yet for omega not equal to 1.0");
147e32f2f54SBarry Smith   if (fshift) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support yet for fshift");
148ccb205f8SBarry Smith 
149ccb205f8SBarry Smith   if (!a->diags) {
150ccb205f8SBarry Smith     ierr = PetscMalloc(mbs*sizeof(Mat),&a->diags);CHKERRQ(ierr);
151ccb205f8SBarry Smith     ierr = MatFactorInfoInitialize(&info);CHKERRQ(ierr);
152ccb205f8SBarry Smith     for (i=0; i<mbs; i++) {
1532692d6eeSBarry Smith       ierr = MatGetOrdering(a->a[a->diag[i]], MATORDERINGND,&row,&col);CHKERRQ(ierr);
154719d5645SBarry Smith       ierr = MatLUFactorSymbolic(a->diags[i],a->a[a->diag[i]],row,col,&info);CHKERRQ(ierr);
155719d5645SBarry Smith       ierr = MatLUFactorNumeric(a->diags[i],a->a[a->diag[i]],&info);CHKERRQ(ierr);
1566bf464f9SBarry Smith       ierr = ISDestroy(&row);CHKERRQ(ierr);
1576bf464f9SBarry Smith       ierr = ISDestroy(&col);CHKERRQ(ierr);
158ccb205f8SBarry Smith     }
159ccb205f8SBarry Smith   }
160ccb205f8SBarry Smith   diag = a->diags;
161ccb205f8SBarry Smith 
162ccb205f8SBarry Smith   ierr = VecSet(xx,0.0);CHKERRQ(ierr);
163ccb205f8SBarry Smith   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
1643649974fSBarry Smith   ierr = VecGetArrayRead(bb,&b);CHKERRQ(ierr);
165ccb205f8SBarry Smith 
16641f059aeSBarry Smith   /* need to add code for when initial guess is zero, see MatSOR_SeqAIJ */
167ccb205f8SBarry Smith   while (its--) {
168ccb205f8SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){
169ccb205f8SBarry Smith 
170ccb205f8SBarry Smith       for (i=0; i<mbs; i++) {
171ccb205f8SBarry Smith         n    = a->i[i+1] - a->i[i];
172ccb205f8SBarry Smith         idx  = a->j + a->i[i];
173ccb205f8SBarry Smith         v    = a->a + a->i[i];
174ccb205f8SBarry Smith 
175ccb205f8SBarry Smith         ierr = VecSet(left,0.0);CHKERRQ(ierr);
176ccb205f8SBarry Smith         for (j=0; j<n; j++) {
177ccb205f8SBarry Smith           if (idx[j] != i) {
178ccb205f8SBarry Smith             ierr = VecPlaceArray(right,x + idx[j]*bs);CHKERRQ(ierr);
179ccb205f8SBarry Smith             ierr = MatMultAdd(v[j],right,left,left);CHKERRQ(ierr);
180ccb205f8SBarry Smith             ierr = VecResetArray(right);CHKERRQ(ierr);
181ccb205f8SBarry Smith           }
182ccb205f8SBarry Smith         }
183ccb205f8SBarry Smith         ierr = VecPlaceArray(right,b + i*bs);CHKERRQ(ierr);
184ccb205f8SBarry Smith         ierr = VecAYPX(left,-1.0,right);CHKERRQ(ierr);
185ccb205f8SBarry Smith         ierr = VecResetArray(right);CHKERRQ(ierr);
186ccb205f8SBarry Smith 
187ccb205f8SBarry Smith         ierr = VecPlaceArray(right,x + i*bs);CHKERRQ(ierr);
188ccb205f8SBarry Smith         ierr = MatSolve(diag[i],left,right);CHKERRQ(ierr);
189ccb205f8SBarry Smith         ierr = VecResetArray(right);CHKERRQ(ierr);
190ccb205f8SBarry Smith       }
191ccb205f8SBarry Smith     }
192ccb205f8SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){
193ccb205f8SBarry Smith 
194ccb205f8SBarry Smith       for (i=mbs-1; i>=0; i--) {
195ccb205f8SBarry Smith         n    = a->i[i+1] - a->i[i];
196ccb205f8SBarry Smith         idx  = a->j + a->i[i];
197ccb205f8SBarry Smith         v    = a->a + a->i[i];
198ccb205f8SBarry Smith 
199ccb205f8SBarry Smith         ierr = VecSet(left,0.0);CHKERRQ(ierr);
200ccb205f8SBarry Smith         for (j=0; j<n; j++) {
201ccb205f8SBarry Smith           if (idx[j] != i) {
202ccb205f8SBarry Smith             ierr = VecPlaceArray(right,x + idx[j]*bs);CHKERRQ(ierr);
203ccb205f8SBarry Smith             ierr = MatMultAdd(v[j],right,left,left);CHKERRQ(ierr);
204ccb205f8SBarry Smith             ierr = VecResetArray(right);CHKERRQ(ierr);
205ccb205f8SBarry Smith           }
206ccb205f8SBarry Smith         }
207ccb205f8SBarry Smith         ierr = VecPlaceArray(right,b + i*bs);CHKERRQ(ierr);
208ccb205f8SBarry Smith         ierr = VecAYPX(left,-1.0,right);CHKERRQ(ierr);
209ccb205f8SBarry Smith         ierr = VecResetArray(right);CHKERRQ(ierr);
210ccb205f8SBarry Smith 
211ccb205f8SBarry Smith         ierr = VecPlaceArray(right,x + i*bs);CHKERRQ(ierr);
212ccb205f8SBarry Smith         ierr = MatSolve(diag[i],left,right);CHKERRQ(ierr);
213ccb205f8SBarry Smith         ierr = VecResetArray(right);CHKERRQ(ierr);
214ccb205f8SBarry Smith 
215ccb205f8SBarry Smith       }
216ccb205f8SBarry Smith     }
217ccb205f8SBarry Smith   }
218ccb205f8SBarry Smith   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
2193649974fSBarry Smith   ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
220ccb205f8SBarry Smith   PetscFunctionReturn(0);
221ccb205f8SBarry Smith }
222ccb205f8SBarry Smith 
223ccb205f8SBarry Smith #undef __FUNCT__
224421e10b8SBarry Smith #define __FUNCT__ "MatSetValues_BlockMat"
225421e10b8SBarry Smith PetscErrorCode MatSetValues_BlockMat(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
226421e10b8SBarry Smith {
227421e10b8SBarry Smith   Mat_BlockMat   *a = (Mat_BlockMat*)A->data;
228421e10b8SBarry Smith   PetscInt       *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N,lastcol = -1;
229421e10b8SBarry Smith   PetscInt       *imax=a->imax,*ai=a->i,*ailen=a->ilen;
230d0f46423SBarry Smith   PetscInt       *aj=a->j,nonew=a->nonew,bs=A->rmap->bs,brow,bcol;
231421e10b8SBarry Smith   PetscErrorCode ierr;
232421e10b8SBarry Smith   PetscInt       ridx,cidx;
233ace3abfcSBarry Smith   PetscBool      roworiented=a->roworiented;
234421e10b8SBarry Smith   MatScalar      value;
235421e10b8SBarry Smith   Mat            *ap,*aa = a->a;
236421e10b8SBarry Smith 
237421e10b8SBarry Smith   PetscFunctionBegin;
23871fd2e92SBarry Smith   if (v) PetscValidScalarPointer(v,6);
239421e10b8SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
240421e10b8SBarry Smith     row  = im[k];
241421e10b8SBarry Smith     brow = row/bs;
242421e10b8SBarry Smith     if (row < 0) continue;
243421e10b8SBarry Smith #if defined(PETSC_USE_DEBUG)
244e32f2f54SBarry Smith     if (row >= A->rmap->N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",row,A->rmap->N-1);
245421e10b8SBarry Smith #endif
246421e10b8SBarry Smith     rp   = aj + ai[brow];
247421e10b8SBarry Smith     ap   = aa + ai[brow];
248421e10b8SBarry Smith     rmax = imax[brow];
249421e10b8SBarry Smith     nrow = ailen[brow];
250421e10b8SBarry Smith     low  = 0;
251421e10b8SBarry Smith     high = nrow;
252421e10b8SBarry Smith     for (l=0; l<n; l++) { /* loop over added columns */
253421e10b8SBarry Smith       if (in[l] < 0) continue;
254421e10b8SBarry Smith #if defined(PETSC_USE_DEBUG)
255e32f2f54SBarry Smith       if (in[l] >= A->cmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",in[l],A->cmap->n-1);
256421e10b8SBarry Smith #endif
257421e10b8SBarry Smith       col = in[l]; bcol = col/bs;
2586e63c7a1SBarry Smith       if (A->symmetric && brow > bcol) continue;
259421e10b8SBarry Smith       ridx = row % bs; cidx = col % bs;
260421e10b8SBarry Smith       if (roworiented) {
261421e10b8SBarry Smith         value = v[l + k*n];
262421e10b8SBarry Smith       } else {
263421e10b8SBarry Smith         value = v[k + l*m];
264421e10b8SBarry Smith       }
265421e10b8SBarry Smith       if (col <= lastcol) low = 0; else high = nrow;
266421e10b8SBarry Smith       lastcol = col;
267421e10b8SBarry Smith       while (high-low > 7) {
268421e10b8SBarry Smith         t = (low+high)/2;
269421e10b8SBarry Smith         if (rp[t] > bcol) high = t;
270421e10b8SBarry Smith         else              low  = t;
271421e10b8SBarry Smith       }
272421e10b8SBarry Smith       for (i=low; i<high; i++) {
273421e10b8SBarry Smith         if (rp[i] > bcol) break;
274421e10b8SBarry Smith         if (rp[i] == bcol) {
275421e10b8SBarry Smith           goto noinsert1;
276421e10b8SBarry Smith         }
277421e10b8SBarry Smith       }
278421e10b8SBarry Smith       if (nonew == 1) goto noinsert1;
279e32f2f54SBarry Smith       if (nonew == -1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero (%D, %D) in the matrix", row, col);
280fef13f97SBarry Smith       MatSeqXAIJReallocateAIJ(A,a->mbs,1,nrow,brow,bcol,rmax,aa,ai,aj,rp,ap,imax,nonew,Mat);
281421e10b8SBarry Smith       N = nrow++ - 1; high++;
282421e10b8SBarry Smith       /* shift up all the later entries in this row */
283421e10b8SBarry Smith       for (ii=N; ii>=i; ii--) {
284421e10b8SBarry Smith         rp[ii+1] = rp[ii];
285421e10b8SBarry Smith         ap[ii+1] = ap[ii];
286421e10b8SBarry Smith       }
287421e10b8SBarry Smith       if (N>=i) ap[i] = 0;
288421e10b8SBarry Smith       rp[i]           = bcol;
289421e10b8SBarry Smith       a->nz++;
290421e10b8SBarry Smith       noinsert1:;
291421e10b8SBarry Smith       if (!*(ap+i)) {
2926e63c7a1SBarry Smith         ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,bs,bs,0,0,ap+i);CHKERRQ(ierr);
293b0223207SBarry Smith       }
294421e10b8SBarry Smith       ierr = MatSetValues(ap[i],1,&ridx,1,&cidx,&value,is);CHKERRQ(ierr);
295421e10b8SBarry Smith       low = i;
296421e10b8SBarry Smith     }
297421e10b8SBarry Smith     ailen[brow] = nrow;
298421e10b8SBarry Smith   }
299421e10b8SBarry Smith   A->same_nonzero = PETSC_FALSE;
300421e10b8SBarry Smith   PetscFunctionReturn(0);
301421e10b8SBarry Smith }
302421e10b8SBarry Smith 
303421e10b8SBarry Smith #undef __FUNCT__
3045bba2384SShri Abhyankar #define __FUNCT__ "MatLoad_BlockMat"
305112444f4SShri Abhyankar PetscErrorCode MatLoad_BlockMat(Mat newmat, PetscViewer viewer)
306a5973382SShri Abhyankar {
307a5973382SShri Abhyankar   PetscErrorCode    ierr;
308a5973382SShri Abhyankar   Mat               tmpA;
309a5973382SShri Abhyankar   PetscInt          i,j,m,n,bs = 1,ncols,*lens,currentcol,mbs,**ii,*ilens,nextcol,*llens,cnt = 0;
310a5973382SShri Abhyankar   const PetscInt    *cols;
311a5973382SShri Abhyankar   const PetscScalar *values;
312ace3abfcSBarry Smith   PetscBool         flg = PETSC_FALSE,notdone;
313a5973382SShri Abhyankar   Mat_SeqAIJ        *a;
314a5973382SShri Abhyankar   Mat_BlockMat      *amat;
315a5973382SShri Abhyankar 
316a5973382SShri Abhyankar   PetscFunctionBegin;
317a5973382SShri Abhyankar   ierr = MatCreate(PETSC_COMM_SELF,&tmpA);CHKERRQ(ierr);
318a5973382SShri Abhyankar   ierr = MatSetType(tmpA,MATSEQAIJ);CHKERRQ(ierr);
319112444f4SShri Abhyankar   ierr = MatLoad_SeqAIJ(tmpA,viewer);CHKERRQ(ierr);
320a5973382SShri Abhyankar 
321a5973382SShri Abhyankar   ierr = MatGetLocalSize(tmpA,&m,&n);CHKERRQ(ierr);
322a5973382SShri Abhyankar   ierr = PetscOptionsBegin(PETSC_COMM_SELF,PETSC_NULL,"Options for loading BlockMat matrix 1","Mat");CHKERRQ(ierr);
323a5973382SShri Abhyankar   ierr = PetscOptionsInt("-matload_block_size","Set the blocksize used to store the matrix","MatLoad",bs,&bs,PETSC_NULL);CHKERRQ(ierr);
324acfcf0e5SJed Brown   ierr = PetscOptionsBool("-matload_symmetric","Store the matrix as symmetric","MatLoad",flg,&flg,PETSC_NULL);CHKERRQ(ierr);
325a5973382SShri Abhyankar   ierr = PetscOptionsEnd();CHKERRQ(ierr);
326a5973382SShri Abhyankar 
327a5973382SShri Abhyankar   /* Determine number of nonzero blocks for each block row */
328a5973382SShri Abhyankar   a    = (Mat_SeqAIJ*) tmpA->data;
329a5973382SShri Abhyankar   mbs  = m/bs;
330a5973382SShri Abhyankar   ierr = PetscMalloc3(mbs,PetscInt,&lens,bs,PetscInt*,&ii,bs,PetscInt,&ilens);CHKERRQ(ierr);
331a5973382SShri Abhyankar   ierr = PetscMemzero(lens,mbs*sizeof(PetscInt));CHKERRQ(ierr);
332a5973382SShri Abhyankar 
333a5973382SShri Abhyankar   for (i=0; i<mbs; i++) {
334a5973382SShri Abhyankar     for (j=0; j<bs; j++) {
335a5973382SShri Abhyankar       ii[j]         = a->j + a->i[i*bs + j];
336a5973382SShri Abhyankar       ilens[j]      = a->i[i*bs + j + 1] - a->i[i*bs + j];
337a5973382SShri Abhyankar     }
338a5973382SShri Abhyankar 
339a5973382SShri Abhyankar     currentcol = -1;
340a5973382SShri Abhyankar     notdone = PETSC_TRUE;
341a5973382SShri Abhyankar     while (PETSC_TRUE) {
342a5973382SShri Abhyankar       notdone = PETSC_FALSE;
343a5973382SShri Abhyankar       nextcol = 1000000000;
344a5973382SShri Abhyankar       for (j=0; j<bs; j++) {
345a5973382SShri Abhyankar         while ((ilens[j] > 0 && ii[j][0]/bs <= currentcol)) {
346a5973382SShri Abhyankar           ii[j]++;
347a5973382SShri Abhyankar           ilens[j]--;
348a5973382SShri Abhyankar         }
349a5973382SShri Abhyankar         if (ilens[j] > 0) {
350a5973382SShri Abhyankar           notdone = PETSC_TRUE;
351a5973382SShri Abhyankar           nextcol = PetscMin(nextcol,ii[j][0]/bs);
352a5973382SShri Abhyankar         }
353a5973382SShri Abhyankar       }
354a5973382SShri Abhyankar       if (!notdone) break;
355a5973382SShri Abhyankar       if (!flg || (nextcol >= i)) lens[i]++;
356a5973382SShri Abhyankar       currentcol = nextcol;
357a5973382SShri Abhyankar     }
358a5973382SShri Abhyankar   }
359a5973382SShri Abhyankar 
360a5973382SShri Abhyankar   if (newmat->rmap->n < 0 && newmat->rmap->N < 0 && newmat->cmap->n < 0 && newmat->cmap->N < 0) {
361a5973382SShri Abhyankar     ierr = MatSetSizes(newmat,m,n,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
362a5973382SShri Abhyankar   }
363a5973382SShri Abhyankar   ierr = MatBlockMatSetPreallocation(newmat,bs,0,lens);CHKERRQ(ierr);
364a5973382SShri Abhyankar   if (flg) {
365a5973382SShri Abhyankar     ierr = MatSetOption(newmat,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
366a5973382SShri Abhyankar   }
367a5973382SShri Abhyankar   amat = (Mat_BlockMat*)(newmat)->data;
368a5973382SShri Abhyankar 
369a5973382SShri Abhyankar   /* preallocate the submatrices */
370a5973382SShri Abhyankar   ierr = PetscMalloc(bs*sizeof(PetscInt),&llens);CHKERRQ(ierr);
371a5973382SShri Abhyankar   for (i=0; i<mbs; i++) { /* loops for block rows */
372a5973382SShri Abhyankar     for (j=0; j<bs; j++) {
373a5973382SShri Abhyankar       ii[j]         = a->j + a->i[i*bs + j];
374a5973382SShri Abhyankar       ilens[j]      = a->i[i*bs + j + 1] - a->i[i*bs + j];
375a5973382SShri Abhyankar     }
376a5973382SShri Abhyankar 
377a5973382SShri Abhyankar     currentcol = 1000000000;
378a5973382SShri Abhyankar     for (j=0; j<bs; j++) { /* loop over rows in block finding first nonzero block */
379a5973382SShri Abhyankar       if (ilens[j] > 0) {
380a5973382SShri Abhyankar 	currentcol = PetscMin(currentcol,ii[j][0]/bs);
381a5973382SShri Abhyankar       }
382a5973382SShri Abhyankar     }
383a5973382SShri Abhyankar 
384a5973382SShri Abhyankar     notdone = PETSC_TRUE;
385a5973382SShri Abhyankar     while (PETSC_TRUE) {  /* loops over blocks in block row */
386a5973382SShri Abhyankar 
387a5973382SShri Abhyankar       notdone = PETSC_FALSE;
388a5973382SShri Abhyankar       nextcol = 1000000000;
389a5973382SShri Abhyankar       ierr = PetscMemzero(llens,bs*sizeof(PetscInt));CHKERRQ(ierr);
390a5973382SShri Abhyankar       for (j=0; j<bs; j++) { /* loop over rows in block */
391a5973382SShri Abhyankar         while ((ilens[j] > 0 && ii[j][0]/bs <= currentcol)) { /* loop over columns in row */
392a5973382SShri Abhyankar           ii[j]++;
393a5973382SShri Abhyankar           ilens[j]--;
394a5973382SShri Abhyankar           llens[j]++;
395a5973382SShri Abhyankar         }
396a5973382SShri Abhyankar         if (ilens[j] > 0) {
397a5973382SShri Abhyankar           notdone = PETSC_TRUE;
398a5973382SShri Abhyankar           nextcol = PetscMin(nextcol,ii[j][0]/bs);
399a5973382SShri Abhyankar         }
400a5973382SShri Abhyankar       }
401a5973382SShri Abhyankar       if (cnt >= amat->maxnz) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Number of blocks found greater than expected %D",cnt);
402a5973382SShri Abhyankar       if (!flg || currentcol >= i) {
403a5973382SShri Abhyankar         amat->j[cnt] = currentcol;
404a5973382SShri Abhyankar         ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,bs,bs,0,llens,amat->a+cnt++);CHKERRQ(ierr);
405a5973382SShri Abhyankar       }
406a5973382SShri Abhyankar 
407a5973382SShri Abhyankar       if (!notdone) break;
408a5973382SShri Abhyankar       currentcol = nextcol;
409a5973382SShri Abhyankar     }
410a5973382SShri Abhyankar     amat->ilen[i] = lens[i];
411a5973382SShri Abhyankar   }
412a5973382SShri Abhyankar   CHKMEMQ;
413a5973382SShri Abhyankar 
414a5973382SShri Abhyankar   ierr = PetscFree3(lens,ii,ilens);CHKERRQ(ierr);
415a5973382SShri Abhyankar   ierr = PetscFree(llens);CHKERRQ(ierr);
416a5973382SShri Abhyankar 
417a5973382SShri Abhyankar   /* copy over the matrix, one row at a time */
418a5973382SShri Abhyankar   for (i=0; i<m; i++) {
419a5973382SShri Abhyankar     ierr = MatGetRow(tmpA,i,&ncols,&cols,&values);CHKERRQ(ierr);
420a5973382SShri Abhyankar     ierr = MatSetValues(newmat,1,&i,ncols,cols,values,INSERT_VALUES);CHKERRQ(ierr);
421a5973382SShri Abhyankar     ierr = MatRestoreRow(tmpA,i,&ncols,&cols,&values);CHKERRQ(ierr);
422a5973382SShri Abhyankar   }
423a5973382SShri Abhyankar   ierr = MatAssemblyBegin(newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
424a5973382SShri Abhyankar   ierr = MatAssemblyEnd(newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
425a5973382SShri Abhyankar   PetscFunctionReturn(0);
426a5973382SShri Abhyankar }
427a5973382SShri Abhyankar 
428a5973382SShri Abhyankar #undef __FUNCT__
429ccb205f8SBarry Smith #define __FUNCT__ "MatView_BlockMat"
430ccb205f8SBarry Smith PetscErrorCode MatView_BlockMat(Mat A,PetscViewer viewer)
431ccb205f8SBarry Smith {
43264075487SBarry Smith   Mat_BlockMat      *a = (Mat_BlockMat*)A->data;
433ccb205f8SBarry Smith   PetscErrorCode    ierr;
434ccb205f8SBarry Smith   const char        *name;
435ccb205f8SBarry Smith   PetscViewerFormat format;
436ccb205f8SBarry Smith 
437ccb205f8SBarry Smith   PetscFunctionBegin;
438ccb205f8SBarry Smith   ierr = PetscObjectGetName((PetscObject)A,&name);CHKERRQ(ierr);
439ccb205f8SBarry Smith   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
440ccb205f8SBarry Smith   if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO) {
441ccb205f8SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Nonzero block matrices = %D \n",a->nz);CHKERRQ(ierr);
44264075487SBarry Smith     if (A->symmetric) {
4438c1ad04dSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"Only upper triangular part of symmetric matrix is stored\n");CHKERRQ(ierr);
44464075487SBarry Smith     }
445ccb205f8SBarry Smith   }
446ccb205f8SBarry Smith   PetscFunctionReturn(0);
447ccb205f8SBarry Smith }
448421e10b8SBarry Smith 
449421e10b8SBarry Smith #undef __FUNCT__
450421e10b8SBarry Smith #define __FUNCT__ "MatDestroy_BlockMat"
451421e10b8SBarry Smith PetscErrorCode MatDestroy_BlockMat(Mat mat)
452421e10b8SBarry Smith {
453421e10b8SBarry Smith   PetscErrorCode ierr;
454421e10b8SBarry Smith   Mat_BlockMat   *bmat = (Mat_BlockMat*)mat->data;
455ccb205f8SBarry Smith   PetscInt       i;
456421e10b8SBarry Smith 
457421e10b8SBarry Smith   PetscFunctionBegin;
4586bf464f9SBarry Smith   ierr = VecDestroy(&bmat->right);CHKERRQ(ierr);
4596bf464f9SBarry Smith   ierr = VecDestroy(&bmat->left);CHKERRQ(ierr);
4606bf464f9SBarry Smith   ierr = VecDestroy(&bmat->middle);CHKERRQ(ierr);
4616bf464f9SBarry Smith   ierr = VecDestroy(&bmat->workb);CHKERRQ(ierr);
462ccb205f8SBarry Smith   if (bmat->diags) {
463d0f46423SBarry Smith     for (i=0; i<mat->rmap->n/mat->rmap->bs; i++) {
4646bf464f9SBarry Smith       ierr = MatDestroy(&bmat->diags[i]);CHKERRQ(ierr);
465ccb205f8SBarry Smith     }
466ccb205f8SBarry Smith   }
467ccb205f8SBarry Smith   if (bmat->a) {
468ccb205f8SBarry Smith     for (i=0; i<bmat->nz; i++) {
4696bf464f9SBarry Smith       ierr = MatDestroy(&bmat->a[i]);CHKERRQ(ierr);
470ccb205f8SBarry Smith     }
471ccb205f8SBarry Smith   }
472ccb205f8SBarry Smith   ierr = MatSeqXAIJFreeAIJ(mat,(PetscScalar**)&bmat->a,&bmat->j,&bmat->i);CHKERRQ(ierr);
473bf0cc555SLisandro Dalcin   ierr = PetscFree(mat->data);CHKERRQ(ierr);
474421e10b8SBarry Smith   PetscFunctionReturn(0);
475421e10b8SBarry Smith }
476421e10b8SBarry Smith 
477421e10b8SBarry Smith #undef __FUNCT__
478421e10b8SBarry Smith #define __FUNCT__ "MatMult_BlockMat"
479421e10b8SBarry Smith PetscErrorCode MatMult_BlockMat(Mat A,Vec x,Vec y)
480421e10b8SBarry Smith {
481421e10b8SBarry Smith   Mat_BlockMat   *bmat = (Mat_BlockMat*)A->data;
482421e10b8SBarry Smith   PetscErrorCode ierr;
483421e10b8SBarry Smith   PetscScalar    *xx,*yy;
484d0f46423SBarry Smith   PetscInt       *aj,i,*ii,jrow,m = A->rmap->n/A->rmap->bs,bs = A->rmap->bs,n,j;
485421e10b8SBarry Smith   Mat            *aa;
486421e10b8SBarry Smith 
487421e10b8SBarry Smith   PetscFunctionBegin;
488ccb205f8SBarry Smith   CHKMEMQ;
489421e10b8SBarry Smith   /*
490421e10b8SBarry Smith      Standard CSR multiply except each entry is a Mat
491421e10b8SBarry Smith   */
492421e10b8SBarry Smith   ierr = VecGetArray(x,&xx);CHKERRQ(ierr);
493ccb205f8SBarry Smith 
494421e10b8SBarry Smith   ierr = VecSet(y,0.0);CHKERRQ(ierr);
495421e10b8SBarry Smith   ierr = VecGetArray(y,&yy);CHKERRQ(ierr);
496421e10b8SBarry Smith   aj  = bmat->j;
497421e10b8SBarry Smith   aa  = bmat->a;
498421e10b8SBarry Smith   ii  = bmat->i;
499421e10b8SBarry Smith   for (i=0; i<m; i++) {
500421e10b8SBarry Smith     jrow = ii[i];
501ccb205f8SBarry Smith     ierr = VecPlaceArray(bmat->left,yy + bs*i);CHKERRQ(ierr);
502421e10b8SBarry Smith     n    = ii[i+1] - jrow;
503421e10b8SBarry Smith     for (j=0; j<n; j++) {
504421e10b8SBarry Smith       ierr = VecPlaceArray(bmat->right,xx + bs*aj[jrow]);CHKERRQ(ierr);
505ccb205f8SBarry Smith       ierr = MatMultAdd(aa[jrow],bmat->right,bmat->left,bmat->left);CHKERRQ(ierr);
506421e10b8SBarry Smith       ierr = VecResetArray(bmat->right);CHKERRQ(ierr);
507421e10b8SBarry Smith       jrow++;
508421e10b8SBarry Smith     }
509421e10b8SBarry Smith     ierr = VecResetArray(bmat->left);CHKERRQ(ierr);
510421e10b8SBarry Smith   }
511421e10b8SBarry Smith   ierr = VecRestoreArray(x,&xx);CHKERRQ(ierr);
512421e10b8SBarry Smith   ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr);
513ccb205f8SBarry Smith   CHKMEMQ;
514421e10b8SBarry Smith   PetscFunctionReturn(0);
515421e10b8SBarry Smith }
516421e10b8SBarry Smith 
517421e10b8SBarry Smith #undef __FUNCT__
518290bbb0aSBarry Smith #define __FUNCT__ "MatMult_BlockMat_Symmetric"
519290bbb0aSBarry Smith PetscErrorCode MatMult_BlockMat_Symmetric(Mat A,Vec x,Vec y)
520290bbb0aSBarry Smith {
521290bbb0aSBarry Smith   Mat_BlockMat   *bmat = (Mat_BlockMat*)A->data;
522290bbb0aSBarry Smith   PetscErrorCode ierr;
523290bbb0aSBarry Smith   PetscScalar    *xx,*yy;
524d0f46423SBarry Smith   PetscInt       *aj,i,*ii,jrow,m = A->rmap->n/A->rmap->bs,bs = A->rmap->bs,n,j;
525290bbb0aSBarry Smith   Mat            *aa;
526290bbb0aSBarry Smith 
527290bbb0aSBarry Smith   PetscFunctionBegin;
528290bbb0aSBarry Smith   CHKMEMQ;
529290bbb0aSBarry Smith   /*
530290bbb0aSBarry Smith      Standard CSR multiply except each entry is a Mat
531290bbb0aSBarry Smith   */
532290bbb0aSBarry Smith   ierr = VecGetArray(x,&xx);CHKERRQ(ierr);
533290bbb0aSBarry Smith 
534290bbb0aSBarry Smith   ierr = VecSet(y,0.0);CHKERRQ(ierr);
535290bbb0aSBarry Smith   ierr = VecGetArray(y,&yy);CHKERRQ(ierr);
536290bbb0aSBarry Smith   aj  = bmat->j;
537290bbb0aSBarry Smith   aa  = bmat->a;
538290bbb0aSBarry Smith   ii  = bmat->i;
539290bbb0aSBarry Smith   for (i=0; i<m; i++) {
540290bbb0aSBarry Smith     jrow = ii[i];
541290bbb0aSBarry Smith     n    = ii[i+1] - jrow;
542290bbb0aSBarry Smith     ierr = VecPlaceArray(bmat->left,yy + bs*i);CHKERRQ(ierr);
543290bbb0aSBarry Smith     ierr = VecPlaceArray(bmat->middle,xx + bs*i);CHKERRQ(ierr);
544290bbb0aSBarry Smith     /* if we ALWAYS required a diagonal entry then could remove this if test */
545290bbb0aSBarry Smith     if (aj[jrow] == i) {
546290bbb0aSBarry Smith       ierr = VecPlaceArray(bmat->right,xx + bs*aj[jrow]);CHKERRQ(ierr);
547290bbb0aSBarry Smith       ierr = MatMultAdd(aa[jrow],bmat->right,bmat->left,bmat->left);CHKERRQ(ierr);
548290bbb0aSBarry Smith       ierr = VecResetArray(bmat->right);CHKERRQ(ierr);
549290bbb0aSBarry Smith       jrow++;
550290bbb0aSBarry Smith       n--;
551290bbb0aSBarry Smith     }
552290bbb0aSBarry Smith     for (j=0; j<n; j++) {
553290bbb0aSBarry Smith       ierr = VecPlaceArray(bmat->right,xx + bs*aj[jrow]);CHKERRQ(ierr);            /* upper triangular part */
554290bbb0aSBarry Smith       ierr = MatMultAdd(aa[jrow],bmat->right,bmat->left,bmat->left);CHKERRQ(ierr);
555290bbb0aSBarry Smith       ierr = VecResetArray(bmat->right);CHKERRQ(ierr);
556290bbb0aSBarry Smith 
557290bbb0aSBarry Smith       ierr = VecPlaceArray(bmat->right,yy + bs*aj[jrow]);CHKERRQ(ierr);            /* lower triangular part */
558290bbb0aSBarry Smith       ierr = MatMultTransposeAdd(aa[jrow],bmat->middle,bmat->right,bmat->right);CHKERRQ(ierr);
559290bbb0aSBarry Smith       ierr = VecResetArray(bmat->right);CHKERRQ(ierr);
560290bbb0aSBarry Smith       jrow++;
561290bbb0aSBarry Smith     }
562290bbb0aSBarry Smith     ierr = VecResetArray(bmat->left);CHKERRQ(ierr);
563290bbb0aSBarry Smith     ierr = VecResetArray(bmat->middle);CHKERRQ(ierr);
564290bbb0aSBarry Smith   }
565290bbb0aSBarry Smith   ierr = VecRestoreArray(x,&xx);CHKERRQ(ierr);
566290bbb0aSBarry Smith   ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr);
567290bbb0aSBarry Smith   CHKMEMQ;
568290bbb0aSBarry Smith   PetscFunctionReturn(0);
569290bbb0aSBarry Smith }
570290bbb0aSBarry Smith 
571290bbb0aSBarry Smith #undef __FUNCT__
572421e10b8SBarry Smith #define __FUNCT__ "MatMultAdd_BlockMat"
573421e10b8SBarry Smith PetscErrorCode MatMultAdd_BlockMat(Mat A,Vec x,Vec y,Vec z)
574421e10b8SBarry Smith {
575421e10b8SBarry Smith   PetscFunctionBegin;
576421e10b8SBarry Smith   PetscFunctionReturn(0);
577421e10b8SBarry Smith }
578421e10b8SBarry Smith 
579421e10b8SBarry Smith #undef __FUNCT__
580421e10b8SBarry Smith #define __FUNCT__ "MatMultTranspose_BlockMat"
581421e10b8SBarry Smith PetscErrorCode MatMultTranspose_BlockMat(Mat A,Vec x,Vec y)
582421e10b8SBarry Smith {
583421e10b8SBarry Smith   PetscFunctionBegin;
584421e10b8SBarry Smith   PetscFunctionReturn(0);
585421e10b8SBarry Smith }
586421e10b8SBarry Smith 
587421e10b8SBarry Smith #undef __FUNCT__
588421e10b8SBarry Smith #define __FUNCT__ "MatMultTransposeAdd_BlockMat"
589421e10b8SBarry Smith PetscErrorCode MatMultTransposeAdd_BlockMat(Mat A,Vec x,Vec y,Vec z)
590421e10b8SBarry Smith {
591421e10b8SBarry Smith   PetscFunctionBegin;
592421e10b8SBarry Smith   PetscFunctionReturn(0);
593421e10b8SBarry Smith }
594421e10b8SBarry Smith 
595ccb205f8SBarry Smith /*
596ccb205f8SBarry Smith      Adds diagonal pointers to sparse matrix structure.
597ccb205f8SBarry Smith */
598ccb205f8SBarry Smith #undef __FUNCT__
599ccb205f8SBarry Smith #define __FUNCT__ "MatMarkDiagonal_BlockMat"
600ccb205f8SBarry Smith PetscErrorCode MatMarkDiagonal_BlockMat(Mat A)
601ccb205f8SBarry Smith {
602ccb205f8SBarry Smith   Mat_BlockMat   *a = (Mat_BlockMat*)A->data;
603ccb205f8SBarry Smith   PetscErrorCode ierr;
604d0f46423SBarry Smith   PetscInt       i,j,mbs = A->rmap->n/A->rmap->bs;
605ccb205f8SBarry Smith 
606ccb205f8SBarry Smith   PetscFunctionBegin;
607ccb205f8SBarry Smith   if (!a->diag) {
608ccb205f8SBarry Smith     ierr = PetscMalloc(mbs*sizeof(PetscInt),&a->diag);CHKERRQ(ierr);
609ccb205f8SBarry Smith   }
610ccb205f8SBarry Smith   for (i=0; i<mbs; i++) {
611ccb205f8SBarry Smith     a->diag[i] = a->i[i+1];
612ccb205f8SBarry Smith     for (j=a->i[i]; j<a->i[i+1]; j++) {
613ccb205f8SBarry Smith       if (a->j[j] == i) {
614ccb205f8SBarry Smith         a->diag[i] = j;
615ccb205f8SBarry Smith         break;
616ccb205f8SBarry Smith       }
617ccb205f8SBarry Smith     }
618ccb205f8SBarry Smith   }
619ccb205f8SBarry Smith   PetscFunctionReturn(0);
620ccb205f8SBarry Smith }
621ccb205f8SBarry Smith 
622ccb205f8SBarry Smith #undef __FUNCT__
623ccb205f8SBarry Smith #define __FUNCT__ "MatGetSubMatrix_BlockMat"
6244aa3045dSJed Brown PetscErrorCode MatGetSubMatrix_BlockMat(Mat A,IS isrow,IS iscol,MatReuse scall,Mat *B)
625ccb205f8SBarry Smith {
626ccb205f8SBarry Smith   Mat_BlockMat   *a = (Mat_BlockMat*)A->data;
627ccb205f8SBarry Smith   Mat_SeqAIJ     *c;
628ccb205f8SBarry Smith   PetscErrorCode ierr;
629ccb205f8SBarry Smith   PetscInt       i,k,first,step,lensi,nrows,ncols;
630d2a212eaSBarry Smith   PetscInt       *j_new,*i_new,*aj = a->j,*ailen = a->ilen;
6311620fd73SBarry Smith   PetscScalar    *a_new;
632ccb205f8SBarry Smith   Mat            C,*aa = a->a;
633ace3abfcSBarry Smith   PetscBool      stride,equal;
634ccb205f8SBarry Smith 
635ccb205f8SBarry Smith   PetscFunctionBegin;
636ccb205f8SBarry Smith   ierr = ISEqual(isrow,iscol,&equal);CHKERRQ(ierr);
637e32f2f54SBarry Smith   if (!equal) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only for idential column and row indices");
6380dbe5b1eSSatish Balay   ierr = PetscTypeCompare((PetscObject)iscol,ISSTRIDE,&stride);CHKERRQ(ierr);
639e32f2f54SBarry Smith   if (!stride) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only for stride indices");
640ccb205f8SBarry Smith   ierr = ISStrideGetInfo(iscol,&first,&step);CHKERRQ(ierr);
641e32f2f54SBarry Smith   if (step != A->rmap->bs) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Can only select one entry from each block");
642ccb205f8SBarry Smith 
643ccb205f8SBarry Smith   ierr = ISGetLocalSize(isrow,&nrows);CHKERRQ(ierr);
644ccb205f8SBarry Smith   ncols = nrows;
645ccb205f8SBarry Smith 
646ccb205f8SBarry Smith   /* create submatrix */
647ccb205f8SBarry Smith   if (scall == MAT_REUSE_MATRIX) {
648ccb205f8SBarry Smith     PetscInt n_cols,n_rows;
649ccb205f8SBarry Smith     C = *B;
650ccb205f8SBarry Smith     ierr = MatGetSize(C,&n_rows,&n_cols);CHKERRQ(ierr);
651e32f2f54SBarry Smith     if (n_rows != nrows || n_cols != ncols) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Reused submatrix wrong size");
652ccb205f8SBarry Smith     ierr = MatZeroEntries(C);CHKERRQ(ierr);
653ccb205f8SBarry Smith   } else {
6547adad957SLisandro Dalcin     ierr = MatCreate(((PetscObject)A)->comm,&C);CHKERRQ(ierr);
655ccb205f8SBarry Smith     ierr = MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
6566e63c7a1SBarry Smith     if (A->symmetric) {
6576e63c7a1SBarry Smith       ierr = MatSetType(C,MATSEQSBAIJ);CHKERRQ(ierr);
6586e63c7a1SBarry Smith     } else {
659ccb205f8SBarry Smith       ierr = MatSetType(C,MATSEQAIJ);CHKERRQ(ierr);
6606e63c7a1SBarry Smith     }
6616e63c7a1SBarry Smith     ierr = MatSeqAIJSetPreallocation(C,0,ailen);CHKERRQ(ierr);
6626e63c7a1SBarry Smith     ierr = MatSeqSBAIJSetPreallocation(C,1,0,ailen);CHKERRQ(ierr);
663ccb205f8SBarry Smith   }
664ccb205f8SBarry Smith   c = (Mat_SeqAIJ*)C->data;
665ccb205f8SBarry Smith 
666ccb205f8SBarry Smith   /* loop over rows inserting into submatrix */
667ccb205f8SBarry Smith   a_new    = c->a;
668ccb205f8SBarry Smith   j_new    = c->j;
669ccb205f8SBarry Smith   i_new    = c->i;
670ccb205f8SBarry Smith 
671ccb205f8SBarry Smith   for (i=0; i<nrows; i++) {
672ccb205f8SBarry Smith     lensi = ailen[i];
673ccb205f8SBarry Smith     for (k=0; k<lensi; k++) {
674ccb205f8SBarry Smith       *j_new++ = *aj++;
6751620fd73SBarry Smith       ierr     = MatGetValue(*aa++,first,first,a_new++);CHKERRQ(ierr);
676ccb205f8SBarry Smith     }
677ccb205f8SBarry Smith     i_new[i+1]  = i_new[i] + lensi;
678ccb205f8SBarry Smith     c->ilen[i]  = lensi;
679ccb205f8SBarry Smith   }
680ccb205f8SBarry Smith 
681ccb205f8SBarry Smith   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
682ccb205f8SBarry Smith   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
683ccb205f8SBarry Smith   *B = C;
684ccb205f8SBarry Smith   PetscFunctionReturn(0);
685ccb205f8SBarry Smith }
686ccb205f8SBarry Smith 
687421e10b8SBarry Smith #undef __FUNCT__
688421e10b8SBarry Smith #define __FUNCT__ "MatAssemblyEnd_BlockMat"
689421e10b8SBarry Smith PetscErrorCode MatAssemblyEnd_BlockMat(Mat A,MatAssemblyType mode)
690421e10b8SBarry Smith {
691421e10b8SBarry Smith   Mat_BlockMat   *a = (Mat_BlockMat*)A->data;
692421e10b8SBarry Smith   PetscErrorCode ierr;
693421e10b8SBarry Smith   PetscInt       fshift = 0,i,j,*ai = a->i,*aj = a->j,*imax = a->imax;
694ccb205f8SBarry Smith   PetscInt       m = a->mbs,*ip,N,*ailen = a->ilen,rmax = 0;
695421e10b8SBarry Smith   Mat            *aa = a->a,*ap;
696421e10b8SBarry Smith 
697421e10b8SBarry Smith   PetscFunctionBegin;
698421e10b8SBarry Smith   if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0);
699421e10b8SBarry Smith 
700421e10b8SBarry Smith   if (m) rmax = ailen[0]; /* determine row with most nonzeros */
701421e10b8SBarry Smith   for (i=1; i<m; i++) {
702421e10b8SBarry Smith     /* move each row back by the amount of empty slots (fshift) before it*/
703421e10b8SBarry Smith     fshift += imax[i-1] - ailen[i-1];
704421e10b8SBarry Smith     rmax   = PetscMax(rmax,ailen[i]);
705421e10b8SBarry Smith     if (fshift) {
706421e10b8SBarry Smith       ip = aj + ai[i] ;
707421e10b8SBarry Smith       ap = aa + ai[i] ;
708421e10b8SBarry Smith       N  = ailen[i];
709421e10b8SBarry Smith       for (j=0; j<N; j++) {
710421e10b8SBarry Smith         ip[j-fshift] = ip[j];
711421e10b8SBarry Smith         ap[j-fshift] = ap[j];
712421e10b8SBarry Smith       }
713421e10b8SBarry Smith     }
714421e10b8SBarry Smith     ai[i] = ai[i-1] + ailen[i-1];
715421e10b8SBarry Smith   }
716421e10b8SBarry Smith   if (m) {
717421e10b8SBarry Smith     fshift += imax[m-1] - ailen[m-1];
718421e10b8SBarry Smith     ai[m]  = ai[m-1] + ailen[m-1];
719421e10b8SBarry Smith   }
720421e10b8SBarry Smith   /* reset ilen and imax for each row */
721421e10b8SBarry Smith   for (i=0; i<m; i++) {
722421e10b8SBarry Smith     ailen[i] = imax[i] = ai[i+1] - ai[i];
723421e10b8SBarry Smith   }
724421e10b8SBarry Smith   a->nz = ai[m];
725ccb205f8SBarry Smith   for (i=0; i<a->nz; i++) {
726ccb205f8SBarry Smith #if defined(PETSC_USE_DEBUG)
727e32f2f54SBarry Smith     if (!aa[i]) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Null matrix at location %D column %D nz %D",i,aj[i],a->nz);
728ccb205f8SBarry Smith #endif
729ccb205f8SBarry Smith     ierr = MatAssemblyBegin(aa[i],MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
730ccb205f8SBarry Smith     ierr = MatAssemblyEnd(aa[i],MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
731ccb205f8SBarry Smith   }
732ccb205f8SBarry Smith   CHKMEMQ;
733d0f46423SBarry Smith   ierr = PetscInfo4(A,"Matrix size: %D X %D; storage space: %D unneeded,%D used\n",m,A->cmap->n/A->cmap->bs,fshift,a->nz);CHKERRQ(ierr);
734421e10b8SBarry Smith   ierr = PetscInfo1(A,"Number of mallocs during MatSetValues() is %D\n",a->reallocs);CHKERRQ(ierr);
735421e10b8SBarry Smith   ierr = PetscInfo1(A,"Maximum nonzeros in any row is %D\n",rmax);CHKERRQ(ierr);
7368e58a170SBarry Smith   A->info.mallocs     += a->reallocs;
737421e10b8SBarry Smith   a->reallocs          = 0;
738421e10b8SBarry Smith   A->info.nz_unneeded  = (double)fshift;
739421e10b8SBarry Smith   a->rmax              = rmax;
740421e10b8SBarry Smith 
741421e10b8SBarry Smith   A->same_nonzero = PETSC_TRUE;
742ccb205f8SBarry Smith   ierr = MatMarkDiagonal_BlockMat(A);CHKERRQ(ierr);
743421e10b8SBarry Smith   PetscFunctionReturn(0);
744421e10b8SBarry Smith }
745421e10b8SBarry Smith 
746290bbb0aSBarry Smith #undef __FUNCT__
747290bbb0aSBarry Smith #define __FUNCT__ "MatSetOption_BlockMat"
748ace3abfcSBarry Smith PetscErrorCode MatSetOption_BlockMat(Mat A,MatOption opt,PetscBool  flg)
749290bbb0aSBarry Smith {
750290bbb0aSBarry Smith   PetscFunctionBegin;
7514e0d8c25SBarry Smith   if (opt == MAT_SYMMETRIC && flg) {
75241f059aeSBarry Smith     A->ops->sor = MatSOR_BlockMat_Symmetric;
753290bbb0aSBarry Smith     A->ops->mult  = MatMult_BlockMat_Symmetric;
754290bbb0aSBarry Smith   } else {
755290bbb0aSBarry Smith     PetscInfo1(A,"Unused matrix option %s\n",MatOptions[opt]);
756290bbb0aSBarry Smith   }
757290bbb0aSBarry Smith   PetscFunctionReturn(0);
758290bbb0aSBarry Smith }
759290bbb0aSBarry Smith 
760290bbb0aSBarry Smith 
761421e10b8SBarry Smith static struct _MatOps MatOps_Values = {MatSetValues_BlockMat,
762421e10b8SBarry Smith        0,
763421e10b8SBarry Smith        0,
764421e10b8SBarry Smith        MatMult_BlockMat,
765421e10b8SBarry Smith /* 4*/ MatMultAdd_BlockMat,
766421e10b8SBarry Smith        MatMultTranspose_BlockMat,
767421e10b8SBarry Smith        MatMultTransposeAdd_BlockMat,
768421e10b8SBarry Smith        0,
769421e10b8SBarry Smith        0,
770421e10b8SBarry Smith        0,
771421e10b8SBarry Smith /*10*/ 0,
772421e10b8SBarry Smith        0,
773421e10b8SBarry Smith        0,
77441f059aeSBarry Smith        MatSOR_BlockMat,
775421e10b8SBarry Smith        0,
776421e10b8SBarry Smith /*15*/ 0,
777421e10b8SBarry Smith        0,
778421e10b8SBarry Smith        0,
779421e10b8SBarry Smith        0,
780421e10b8SBarry Smith        0,
781421e10b8SBarry Smith /*20*/ 0,
782421e10b8SBarry Smith        MatAssemblyEnd_BlockMat,
783290bbb0aSBarry Smith        MatSetOption_BlockMat,
784421e10b8SBarry Smith        0,
785d519adbfSMatthew Knepley /*24*/ 0,
786421e10b8SBarry Smith        0,
787421e10b8SBarry Smith        0,
788421e10b8SBarry Smith        0,
789421e10b8SBarry Smith        0,
790d519adbfSMatthew Knepley /*29*/ 0,
791421e10b8SBarry Smith        0,
792421e10b8SBarry Smith        0,
793421e10b8SBarry Smith        0,
794421e10b8SBarry Smith        0,
795d519adbfSMatthew Knepley /*34*/ 0,
796421e10b8SBarry Smith        0,
797421e10b8SBarry Smith        0,
798421e10b8SBarry Smith        0,
799421e10b8SBarry Smith        0,
800d519adbfSMatthew Knepley /*39*/ 0,
801421e10b8SBarry Smith        0,
802421e10b8SBarry Smith        0,
803421e10b8SBarry Smith        0,
804421e10b8SBarry Smith        0,
805d519adbfSMatthew Knepley /*44*/ 0,
806421e10b8SBarry Smith        0,
807421e10b8SBarry Smith        0,
808421e10b8SBarry Smith        0,
809421e10b8SBarry Smith        0,
810d519adbfSMatthew Knepley /*49*/ 0,
811421e10b8SBarry Smith        0,
812421e10b8SBarry Smith        0,
813421e10b8SBarry Smith        0,
814421e10b8SBarry Smith        0,
815d519adbfSMatthew Knepley /*54*/ 0,
816421e10b8SBarry Smith        0,
817421e10b8SBarry Smith        0,
818421e10b8SBarry Smith        0,
819421e10b8SBarry Smith        0,
820d519adbfSMatthew Knepley /*59*/ MatGetSubMatrix_BlockMat,
821421e10b8SBarry Smith        MatDestroy_BlockMat,
822ccb205f8SBarry Smith        MatView_BlockMat,
823421e10b8SBarry Smith        0,
824421e10b8SBarry Smith        0,
825d519adbfSMatthew Knepley /*64*/ 0,
826421e10b8SBarry Smith        0,
827421e10b8SBarry Smith        0,
828421e10b8SBarry Smith        0,
829421e10b8SBarry Smith        0,
830d519adbfSMatthew Knepley /*69*/ 0,
831421e10b8SBarry Smith        0,
832421e10b8SBarry Smith        0,
833421e10b8SBarry Smith        0,
834421e10b8SBarry Smith        0,
835d519adbfSMatthew Knepley /*74*/ 0,
836421e10b8SBarry Smith        0,
837421e10b8SBarry Smith        0,
838421e10b8SBarry Smith        0,
839421e10b8SBarry Smith        0,
840d519adbfSMatthew Knepley /*79*/ 0,
841421e10b8SBarry Smith        0,
842421e10b8SBarry Smith        0,
843421e10b8SBarry Smith        0,
8445bba2384SShri Abhyankar        MatLoad_BlockMat,
845d519adbfSMatthew Knepley /*84*/ 0,
846421e10b8SBarry Smith        0,
847421e10b8SBarry Smith        0,
848421e10b8SBarry Smith        0,
849421e10b8SBarry Smith        0,
850d519adbfSMatthew Knepley /*89*/ 0,
851421e10b8SBarry Smith        0,
852421e10b8SBarry Smith        0,
853421e10b8SBarry Smith        0,
854421e10b8SBarry Smith        0,
855d519adbfSMatthew Knepley /*94*/ 0,
856421e10b8SBarry Smith        0,
857421e10b8SBarry Smith        0,
858a5973382SShri Abhyankar        0,
859a5973382SShri Abhyankar        0,
860a5973382SShri Abhyankar /*99*/ 0,
861a5973382SShri Abhyankar        0,
862a5973382SShri Abhyankar        0,
863a5973382SShri Abhyankar        0,
864a5973382SShri Abhyankar        0,
865a5973382SShri Abhyankar /*104*/0,
866a5973382SShri Abhyankar        0,
867a5973382SShri Abhyankar        0,
868a5973382SShri Abhyankar        0,
869a5973382SShri Abhyankar        0,
870a5973382SShri Abhyankar /*109*/0,
871a5973382SShri Abhyankar        0,
872a5973382SShri Abhyankar        0,
873a5973382SShri Abhyankar        0,
874a5973382SShri Abhyankar        0,
875a5973382SShri Abhyankar /*114*/0,
876a5973382SShri Abhyankar        0,
877a5973382SShri Abhyankar        0,
878a5973382SShri Abhyankar        0,
879a5973382SShri Abhyankar        0,
880a5973382SShri Abhyankar /*119*/0,
881a5973382SShri Abhyankar        0,
882a5973382SShri Abhyankar        0,
8835bba2384SShri Abhyankar        0
884a5973382SShri Abhyankar };
885421e10b8SBarry Smith 
8868cdf2d9bSBarry Smith #undef __FUNCT__
8878cdf2d9bSBarry Smith #define __FUNCT__ "MatBlockMatSetPreallocation"
8888cdf2d9bSBarry Smith /*@C
8898cdf2d9bSBarry Smith    MatBlockMatSetPreallocation - For good matrix assembly performance
8908cdf2d9bSBarry Smith    the user should preallocate the matrix storage by setting the parameter nz
8918cdf2d9bSBarry Smith    (or the array nnz).  By setting these parameters accurately, performance
8928cdf2d9bSBarry Smith    during matrix assembly can be increased by more than a factor of 50.
8938cdf2d9bSBarry Smith 
8948cdf2d9bSBarry Smith    Collective on MPI_Comm
8958cdf2d9bSBarry Smith 
8968cdf2d9bSBarry Smith    Input Parameters:
8978cdf2d9bSBarry Smith +  B - The matrix
8988cdf2d9bSBarry Smith .  bs - size of each block in matrix
8998cdf2d9bSBarry Smith .  nz - number of nonzeros per block row (same for all rows)
9008cdf2d9bSBarry Smith -  nnz - array containing the number of nonzeros in the various block rows
9018cdf2d9bSBarry Smith          (possibly different for each row) or PETSC_NULL
9028cdf2d9bSBarry Smith 
9038cdf2d9bSBarry Smith    Notes:
9048cdf2d9bSBarry Smith      If nnz is given then nz is ignored
9058cdf2d9bSBarry Smith 
9068cdf2d9bSBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
9078cdf2d9bSBarry Smith    Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory
9088cdf2d9bSBarry Smith    allocation.  For large problems you MUST preallocate memory or you
9098cdf2d9bSBarry Smith    will get TERRIBLE performance, see the users' manual chapter on matrices.
9108cdf2d9bSBarry Smith 
9118cdf2d9bSBarry Smith    Level: intermediate
9128cdf2d9bSBarry Smith 
9138cdf2d9bSBarry Smith .seealso: MatCreate(), MatCreateBlockMat(), MatSetValues()
9148cdf2d9bSBarry Smith 
9158cdf2d9bSBarry Smith @*/
9167087cfbeSBarry Smith PetscErrorCode  MatBlockMatSetPreallocation(Mat B,PetscInt bs,PetscInt nz,const PetscInt nnz[])
9178cdf2d9bSBarry Smith {
9184ac538c5SBarry Smith   PetscErrorCode ierr;
9198cdf2d9bSBarry Smith 
9208cdf2d9bSBarry Smith   PetscFunctionBegin;
9214ac538c5SBarry Smith   ierr = PetscTryMethod(B,"MatBlockMatSetPreallocation_C",(Mat,PetscInt,PetscInt,const PetscInt[]),(B,bs,nz,nnz));CHKERRQ(ierr);
9228cdf2d9bSBarry Smith   PetscFunctionReturn(0);
9238cdf2d9bSBarry Smith }
9248cdf2d9bSBarry Smith 
9258cdf2d9bSBarry Smith EXTERN_C_BEGIN
9268cdf2d9bSBarry Smith #undef __FUNCT__
9278cdf2d9bSBarry Smith #define __FUNCT__ "MatBlockMatSetPreallocation_BlockMat"
9287087cfbeSBarry Smith PetscErrorCode  MatBlockMatSetPreallocation_BlockMat(Mat A,PetscInt bs,PetscInt nz,PetscInt *nnz)
9298cdf2d9bSBarry Smith {
9308cdf2d9bSBarry Smith   Mat_BlockMat   *bmat = (Mat_BlockMat*)A->data;
9318cdf2d9bSBarry Smith   PetscErrorCode ierr;
9328cdf2d9bSBarry Smith   PetscInt       i;
9338cdf2d9bSBarry Smith 
9348cdf2d9bSBarry Smith   PetscFunctionBegin;
93534ef9618SShri Abhyankar   ierr = PetscLayoutSetBlockSize(A->rmap,1);CHKERRQ(ierr);
93634ef9618SShri Abhyankar   ierr = PetscLayoutSetBlockSize(A->cmap,1);CHKERRQ(ierr);
93734ef9618SShri Abhyankar   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
93834ef9618SShri Abhyankar   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
93934ef9618SShri Abhyankar 
94065e19b50SBarry Smith   if (bs < 1) SETERRQ1(((PetscObject)A)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Block size given %D must be great than zero",bs);
941e32f2f54SBarry Smith   if (A->rmap->n % bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Blocksize %D does not divide number of rows %D",bs,A->rmap->n);
942e32f2f54SBarry Smith   if (A->cmap->n % bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Blocksize %D does not divide number of columns %D",bs,A->cmap->n);
9438cdf2d9bSBarry Smith   if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
944e32f2f54SBarry Smith   if (nz < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %d",nz);
9458cdf2d9bSBarry Smith   if (nnz) {
946d0f46423SBarry Smith     for (i=0; i<A->rmap->n/bs; i++) {
947e32f2f54SBarry Smith       if (nnz[i] < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be less than 0: local row %d value %d",i,nnz[i]);
948e32f2f54SBarry Smith       if (nnz[i] > A->cmap->n/bs) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be greater than row length: local row %d value %d rowlength %d",i,nnz[i],A->cmap->n/bs);
9498cdf2d9bSBarry Smith     }
9508cdf2d9bSBarry Smith   }
951d0f46423SBarry Smith   A->rmap->bs = A->cmap->bs = bs;
952d0f46423SBarry Smith   bmat->mbs  = A->rmap->n/bs;
9538cdf2d9bSBarry Smith 
9548cdf2d9bSBarry Smith   ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,bs,PETSC_NULL,&bmat->right);CHKERRQ(ierr);
9558cdf2d9bSBarry Smith   ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,bs,PETSC_NULL,&bmat->middle);CHKERRQ(ierr);
9568cdf2d9bSBarry Smith   ierr = VecCreateSeq(PETSC_COMM_SELF,bs,&bmat->left);CHKERRQ(ierr);
9578cdf2d9bSBarry Smith 
9582ee49352SLisandro Dalcin   if (!bmat->imax) {
959d0f46423SBarry Smith     ierr = PetscMalloc2(A->rmap->n,PetscInt,&bmat->imax,A->rmap->n,PetscInt,&bmat->ilen);CHKERRQ(ierr);
960d0f46423SBarry Smith     ierr = PetscLogObjectMemory(A,2*A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
9612ee49352SLisandro Dalcin   }
9628cdf2d9bSBarry Smith   if (nnz) {
9638cdf2d9bSBarry Smith     nz = 0;
964d0f46423SBarry Smith     for (i=0; i<A->rmap->n/A->rmap->bs; i++) {
9658cdf2d9bSBarry Smith       bmat->imax[i] = nnz[i];
9668cdf2d9bSBarry Smith       nz           += nnz[i];
9678cdf2d9bSBarry Smith     }
9688cdf2d9bSBarry Smith   } else {
969e32f2f54SBarry Smith     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Currently requires block row by row preallocation");
9708cdf2d9bSBarry Smith   }
9718cdf2d9bSBarry Smith 
9728cdf2d9bSBarry Smith   /* bmat->ilen will count nonzeros in each row so far. */
9738cdf2d9bSBarry Smith   for (i=0; i<bmat->mbs; i++) { bmat->ilen[i] = 0;}
9748cdf2d9bSBarry Smith 
9758cdf2d9bSBarry Smith   /* allocate the matrix space */
9762ee49352SLisandro Dalcin   ierr = MatSeqXAIJFreeAIJ(A,(PetscScalar**)&bmat->a,&bmat->j,&bmat->i);CHKERRQ(ierr);
977d0f46423SBarry Smith   ierr = PetscMalloc3(nz,Mat,&bmat->a,nz,PetscInt,&bmat->j,A->rmap->n+1,PetscInt,&bmat->i);CHKERRQ(ierr);
978d0f46423SBarry Smith   ierr = PetscLogObjectMemory(A,(A->rmap->n+1)*sizeof(PetscInt)+nz*(sizeof(PetscScalar)+sizeof(PetscInt)));CHKERRQ(ierr);
9798cdf2d9bSBarry Smith   bmat->i[0] = 0;
9808cdf2d9bSBarry Smith   for (i=1; i<bmat->mbs+1; i++) {
9818cdf2d9bSBarry Smith     bmat->i[i] = bmat->i[i-1] + bmat->imax[i-1];
9828cdf2d9bSBarry Smith   }
9838cdf2d9bSBarry Smith   bmat->singlemalloc = PETSC_TRUE;
9848cdf2d9bSBarry Smith   bmat->free_a       = PETSC_TRUE;
9858cdf2d9bSBarry Smith   bmat->free_ij      = PETSC_TRUE;
9868cdf2d9bSBarry Smith 
9878cdf2d9bSBarry Smith   bmat->nz                = 0;
9888cdf2d9bSBarry Smith   bmat->maxnz             = nz;
9898cdf2d9bSBarry Smith   A->info.nz_unneeded  = (double)bmat->maxnz;
9907827cd58SJed Brown   ierr = MatSetOption(A,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
9918cdf2d9bSBarry Smith   PetscFunctionReturn(0);
9928cdf2d9bSBarry Smith }
9938cdf2d9bSBarry Smith EXTERN_C_END
9948cdf2d9bSBarry Smith 
995421e10b8SBarry Smith /*MC
996421e10b8SBarry Smith    MATBLOCKMAT - A matrix that is defined by a set of Mat's that represents a sparse block matrix
997421e10b8SBarry Smith                  consisting of (usually) sparse blocks.
998421e10b8SBarry Smith 
999421e10b8SBarry Smith   Level: advanced
1000421e10b8SBarry Smith 
1001421e10b8SBarry Smith .seealso: MatCreateBlockMat()
1002421e10b8SBarry Smith 
1003421e10b8SBarry Smith M*/
1004421e10b8SBarry Smith 
1005421e10b8SBarry Smith EXTERN_C_BEGIN
1006421e10b8SBarry Smith #undef __FUNCT__
1007421e10b8SBarry Smith #define __FUNCT__ "MatCreate_BlockMat"
10087087cfbeSBarry Smith PetscErrorCode  MatCreate_BlockMat(Mat A)
1009421e10b8SBarry Smith {
1010421e10b8SBarry Smith   Mat_BlockMat   *b;
1011421e10b8SBarry Smith   PetscErrorCode ierr;
1012421e10b8SBarry Smith 
1013421e10b8SBarry Smith   PetscFunctionBegin;
101438f2d2fdSLisandro Dalcin   ierr = PetscNewLog(A,Mat_BlockMat,&b);CHKERRQ(ierr);
1015421e10b8SBarry Smith   A->data = (void*)b;
101638f2d2fdSLisandro Dalcin   ierr = PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
1017421e10b8SBarry Smith 
1018421e10b8SBarry Smith   A->assembled     = PETSC_TRUE;
1019421e10b8SBarry Smith   A->preallocated  = PETSC_FALSE;
1020421e10b8SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)A,MATBLOCKMAT);CHKERRQ(ierr);
1021290bbb0aSBarry Smith 
10228cdf2d9bSBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatBlockMatSetPreallocation_C",
10238cdf2d9bSBarry Smith                                      "MatBlockMatSetPreallocation_BlockMat",
10248cdf2d9bSBarry Smith                                       MatBlockMatSetPreallocation_BlockMat);CHKERRQ(ierr);
10258cdf2d9bSBarry Smith 
1026421e10b8SBarry Smith   PetscFunctionReturn(0);
1027421e10b8SBarry Smith }
1028421e10b8SBarry Smith EXTERN_C_END
1029421e10b8SBarry Smith 
1030421e10b8SBarry Smith #undef __FUNCT__
1031421e10b8SBarry Smith #define __FUNCT__ "MatCreateBlockMat"
1032421e10b8SBarry Smith /*@C
1033421e10b8SBarry Smith    MatCreateBlockMat - Creates a new matrix based sparse Mat storage
1034421e10b8SBarry Smith 
1035421e10b8SBarry Smith   Collective on MPI_Comm
1036421e10b8SBarry Smith 
1037421e10b8SBarry Smith    Input Parameters:
1038421e10b8SBarry Smith +  comm - MPI communicator
1039421e10b8SBarry Smith .  m - number of rows
1040421e10b8SBarry Smith .  n  - number of columns
10418cdf2d9bSBarry Smith .  bs - size of each submatrix
10428cdf2d9bSBarry Smith .  nz  - expected maximum number of nonzero blocks in row (use PETSC_DEFAULT if not known)
10438cdf2d9bSBarry Smith -  nnz - expected number of nonzers per block row if known (use PETSC_NULL otherwise)
1044421e10b8SBarry Smith 
1045421e10b8SBarry Smith 
1046421e10b8SBarry Smith    Output Parameter:
1047421e10b8SBarry Smith .  A - the matrix
1048421e10b8SBarry Smith 
1049421e10b8SBarry Smith    Level: intermediate
1050421e10b8SBarry Smith 
1051421e10b8SBarry Smith    PETSc requires that matrices and vectors being used for certain
1052421e10b8SBarry Smith    operations are partitioned accordingly.  For example, when
1053421e10b8SBarry Smith    creating a bmat matrix, A, that supports parallel matrix-vector
1054421e10b8SBarry Smith    products using MatMult(A,x,y) the user should set the number
1055421e10b8SBarry Smith    of local matrix rows to be the number of local elements of the
1056421e10b8SBarry Smith    corresponding result vector, y. Note that this is information is
1057421e10b8SBarry Smith    required for use of the matrix interface routines, even though
1058421e10b8SBarry Smith    the bmat matrix may not actually be physically partitioned.
1059421e10b8SBarry Smith    For example,
1060421e10b8SBarry Smith 
1061421e10b8SBarry Smith .keywords: matrix, bmat, create
1062421e10b8SBarry Smith 
1063421e10b8SBarry Smith .seealso: MATBLOCKMAT
1064421e10b8SBarry Smith @*/
10657087cfbeSBarry Smith PetscErrorCode  MatCreateBlockMat(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt bs,PetscInt nz,PetscInt *nnz, Mat *A)
1066421e10b8SBarry Smith {
1067421e10b8SBarry Smith   PetscErrorCode ierr;
1068421e10b8SBarry Smith 
1069421e10b8SBarry Smith   PetscFunctionBegin;
1070421e10b8SBarry Smith   ierr = MatCreate(comm,A);CHKERRQ(ierr);
1071421e10b8SBarry Smith   ierr = MatSetSizes(*A,m,n,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
1072421e10b8SBarry Smith   ierr = MatSetType(*A,MATBLOCKMAT);CHKERRQ(ierr);
10738cdf2d9bSBarry Smith   ierr = MatBlockMatSetPreallocation(*A,bs,nz,nnz);CHKERRQ(ierr);
1074421e10b8SBarry Smith   PetscFunctionReturn(0);
1075421e10b8SBarry Smith }
1076421e10b8SBarry Smith 
1077421e10b8SBarry Smith 
1078421e10b8SBarry Smith 
1079