xref: /petsc/src/mat/impls/blockmat/seq/blockmat.c (revision bf0cc55543cd83e035744be2f77202b216d1436e)
1421e10b8SBarry Smith 
2421e10b8SBarry Smith /*
3421e10b8SBarry Smith    This provides a matrix that consists of Mats
4421e10b8SBarry Smith */
5421e10b8SBarry Smith 
6c6db04a5SJed Brown #include <private/matimpl.h>              /*I "petscmat.h" I*/
7c6db04a5SJed Brown #include <../src/mat/impls/baij/seq/baij.h>    /* use the common AIJ data-structure */
8c6db04a5SJed Brown #include <petscksp.h>
9421e10b8SBarry Smith 
10421e10b8SBarry Smith typedef struct {
11421e10b8SBarry Smith   SEQAIJHEADER(Mat);
12421e10b8SBarry Smith   SEQBAIJHEADER;
13ccb205f8SBarry Smith   Mat               *diags;
14421e10b8SBarry Smith 
156e63c7a1SBarry Smith   Vec               left,right,middle,workb;   /* dummy vectors to perform local parts of product */
16421e10b8SBarry Smith } Mat_BlockMat;
17421e10b8SBarry Smith 
187087cfbeSBarry Smith extern PetscErrorCode  MatBlockMatSetPreallocation(Mat,PetscInt,PetscInt,const PetscInt*);
19a5973382SShri Abhyankar 
20421e10b8SBarry Smith #undef __FUNCT__
2141f059aeSBarry Smith #define __FUNCT__ "MatSOR_BlockMat_Symmetric"
2241f059aeSBarry Smith PetscErrorCode MatSOR_BlockMat_Symmetric(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx)
23290bbb0aSBarry Smith {
24290bbb0aSBarry Smith   Mat_BlockMat       *a = (Mat_BlockMat*)A->data;
25290bbb0aSBarry Smith   PetscScalar        *x;
26290bbb0aSBarry Smith   const Mat          *v = a->a;
27290bbb0aSBarry Smith   const PetscScalar  *b;
28290bbb0aSBarry Smith   PetscErrorCode     ierr;
29d0f46423SBarry Smith   PetscInt           n = A->cmap->n,i,mbs = n/A->rmap->bs,j,bs = A->rmap->bs;
30290bbb0aSBarry Smith   const PetscInt     *idx;
31290bbb0aSBarry Smith   IS                 row,col;
32290bbb0aSBarry Smith   MatFactorInfo      info;
336e63c7a1SBarry Smith   Vec                left = a->left,right = a->right, middle = a->middle;
34290bbb0aSBarry Smith   Mat                *diag;
35290bbb0aSBarry Smith 
36290bbb0aSBarry Smith   PetscFunctionBegin;
37290bbb0aSBarry Smith   its = its*lits;
38e32f2f54SBarry 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);
39e32f2f54SBarry Smith   if (flag & SOR_EISENSTAT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support yet for Eisenstat");
40e32f2f54SBarry Smith   if (omega != 1.0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support yet for omega not equal to 1.0");
41e32f2f54SBarry Smith   if (fshift) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support yet for fshift");
42290bbb0aSBarry Smith   if ((flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) && !(flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP))
43e32f2f54SBarry Smith     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot do backward sweep without forward sweep");
44290bbb0aSBarry Smith 
45290bbb0aSBarry Smith   if (!a->diags) {
46290bbb0aSBarry Smith     ierr = PetscMalloc(mbs*sizeof(Mat),&a->diags);CHKERRQ(ierr);
47290bbb0aSBarry Smith     ierr = MatFactorInfoInitialize(&info);CHKERRQ(ierr);
48290bbb0aSBarry Smith     for (i=0; i<mbs; i++) {
492692d6eeSBarry Smith       ierr = MatGetOrdering(a->a[a->diag[i]], MATORDERINGND,&row,&col);CHKERRQ(ierr);
50719d5645SBarry Smith       ierr = MatCholeskyFactorSymbolic(a->diags[i],a->a[a->diag[i]],row,&info);CHKERRQ(ierr);
51719d5645SBarry Smith       ierr = MatCholeskyFactorNumeric(a->diags[i],a->a[a->diag[i]],&info);CHKERRQ(ierr);
526bf464f9SBarry Smith       ierr = ISDestroy(&row);CHKERRQ(ierr);
536bf464f9SBarry Smith       ierr = ISDestroy(&col);CHKERRQ(ierr);
54290bbb0aSBarry Smith     }
556e63c7a1SBarry Smith     ierr = VecDuplicate(bb,&a->workb);CHKERRQ(ierr);
56290bbb0aSBarry Smith   }
57290bbb0aSBarry Smith   diag    = a->diags;
58290bbb0aSBarry Smith 
59290bbb0aSBarry Smith   ierr = VecSet(xx,0.0);CHKERRQ(ierr);
60290bbb0aSBarry Smith   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
61290bbb0aSBarry Smith   /* copy right hand side because it must be modified during iteration */
626e63c7a1SBarry Smith   ierr = VecCopy(bb,a->workb);CHKERRQ(ierr);
633649974fSBarry Smith   ierr = VecGetArrayRead(a->workb,&b);CHKERRQ(ierr);
64290bbb0aSBarry Smith 
6541f059aeSBarry Smith   /* need to add code for when initial guess is zero, see MatSOR_SeqAIJ */
66290bbb0aSBarry Smith   while (its--) {
67290bbb0aSBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){
68290bbb0aSBarry Smith 
69290bbb0aSBarry Smith       for (i=0; i<mbs; i++) {
706e63c7a1SBarry Smith         n    = a->i[i+1] - a->i[i] - 1;
716e63c7a1SBarry Smith         idx  = a->j + a->i[i] + 1;
726e63c7a1SBarry Smith         v    = a->a + a->i[i] + 1;
73290bbb0aSBarry Smith 
74290bbb0aSBarry Smith         ierr = VecSet(left,0.0);CHKERRQ(ierr);
75290bbb0aSBarry Smith         for (j=0; j<n; j++) {
76290bbb0aSBarry Smith           ierr = VecPlaceArray(right,x + idx[j]*bs);CHKERRQ(ierr);
77290bbb0aSBarry Smith           ierr = MatMultAdd(v[j],right,left,left);CHKERRQ(ierr);
78290bbb0aSBarry Smith           ierr = VecResetArray(right);CHKERRQ(ierr);
79290bbb0aSBarry Smith         }
80290bbb0aSBarry Smith         ierr = VecPlaceArray(right,b + i*bs);CHKERRQ(ierr);
81290bbb0aSBarry Smith         ierr = VecAYPX(left,-1.0,right);CHKERRQ(ierr);
82290bbb0aSBarry Smith         ierr = VecResetArray(right);CHKERRQ(ierr);
83290bbb0aSBarry Smith 
84290bbb0aSBarry Smith         ierr = VecPlaceArray(right,x + i*bs);CHKERRQ(ierr);
85290bbb0aSBarry Smith         ierr = MatSolve(diag[i],left,right);CHKERRQ(ierr);
866e63c7a1SBarry Smith 
8741f059aeSBarry Smith         /* now adjust right hand side, see MatSOR_SeqSBAIJ */
886e63c7a1SBarry Smith         for (j=0; j<n; j++) {
896e63c7a1SBarry Smith           ierr = MatMultTranspose(v[j],right,left);CHKERRQ(ierr);
906e63c7a1SBarry Smith           ierr = VecPlaceArray(middle,b + idx[j]*bs);CHKERRQ(ierr);
916e63c7a1SBarry Smith           ierr = VecAXPY(middle,-1.0,left);CHKERRQ(ierr);
926e63c7a1SBarry Smith           ierr = VecResetArray(middle);CHKERRQ(ierr);
936e63c7a1SBarry Smith         }
94290bbb0aSBarry Smith         ierr = VecResetArray(right);CHKERRQ(ierr);
956e63c7a1SBarry Smith 
96290bbb0aSBarry Smith       }
97290bbb0aSBarry Smith     }
98290bbb0aSBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){
99290bbb0aSBarry Smith 
100290bbb0aSBarry Smith       for (i=mbs-1; i>=0; i--) {
1016e63c7a1SBarry Smith         n    = a->i[i+1] - a->i[i] - 1;
1026e63c7a1SBarry Smith         idx  = a->j + a->i[i] + 1;
1036e63c7a1SBarry Smith         v    = a->a + a->i[i] + 1;
104290bbb0aSBarry Smith 
105290bbb0aSBarry Smith         ierr = VecSet(left,0.0);CHKERRQ(ierr);
106290bbb0aSBarry Smith         for (j=0; j<n; j++) {
107290bbb0aSBarry Smith           ierr = VecPlaceArray(right,x + idx[j]*bs);CHKERRQ(ierr);
108290bbb0aSBarry Smith           ierr = MatMultAdd(v[j],right,left,left);CHKERRQ(ierr);
109290bbb0aSBarry Smith           ierr = VecResetArray(right);CHKERRQ(ierr);
110290bbb0aSBarry Smith         }
111290bbb0aSBarry Smith         ierr = VecPlaceArray(right,b + i*bs);CHKERRQ(ierr);
112290bbb0aSBarry Smith         ierr = VecAYPX(left,-1.0,right);CHKERRQ(ierr);
113290bbb0aSBarry Smith         ierr = VecResetArray(right);CHKERRQ(ierr);
114290bbb0aSBarry Smith 
115290bbb0aSBarry Smith         ierr = VecPlaceArray(right,x + i*bs);CHKERRQ(ierr);
116290bbb0aSBarry Smith         ierr = MatSolve(diag[i],left,right);CHKERRQ(ierr);
117290bbb0aSBarry Smith         ierr = VecResetArray(right);CHKERRQ(ierr);
118290bbb0aSBarry Smith 
119290bbb0aSBarry Smith       }
120290bbb0aSBarry Smith     }
121290bbb0aSBarry Smith   }
122290bbb0aSBarry Smith   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
1233649974fSBarry Smith   ierr = VecRestoreArrayRead(a->workb,&b);CHKERRQ(ierr);
124290bbb0aSBarry Smith   PetscFunctionReturn(0);
125290bbb0aSBarry Smith }
126290bbb0aSBarry Smith 
127290bbb0aSBarry Smith #undef __FUNCT__
12841f059aeSBarry Smith #define __FUNCT__ "MatSOR_BlockMat"
12941f059aeSBarry Smith PetscErrorCode MatSOR_BlockMat(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx)
130ccb205f8SBarry Smith {
131ccb205f8SBarry Smith   Mat_BlockMat       *a = (Mat_BlockMat*)A->data;
132ccb205f8SBarry Smith   PetscScalar        *x;
133ccb205f8SBarry Smith   const Mat          *v = a->a;
134ccb205f8SBarry Smith   const PetscScalar  *b;
135ccb205f8SBarry Smith   PetscErrorCode     ierr;
136d0f46423SBarry Smith   PetscInt           n = A->cmap->n,i,mbs = n/A->rmap->bs,j,bs = A->rmap->bs;
137ccb205f8SBarry Smith   const PetscInt     *idx;
138ccb205f8SBarry Smith   IS                 row,col;
139ccb205f8SBarry Smith   MatFactorInfo      info;
140ccb205f8SBarry Smith   Vec                left = a->left,right = a->right;
141ccb205f8SBarry Smith   Mat                *diag;
142ccb205f8SBarry Smith 
143ccb205f8SBarry Smith   PetscFunctionBegin;
144ccb205f8SBarry Smith   its = its*lits;
145e32f2f54SBarry 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);
146e32f2f54SBarry Smith   if (flag & SOR_EISENSTAT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support yet for Eisenstat");
147e32f2f54SBarry Smith   if (omega != 1.0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support yet for omega not equal to 1.0");
148e32f2f54SBarry Smith   if (fshift) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support yet for fshift");
149ccb205f8SBarry Smith 
150ccb205f8SBarry Smith   if (!a->diags) {
151ccb205f8SBarry Smith     ierr = PetscMalloc(mbs*sizeof(Mat),&a->diags);CHKERRQ(ierr);
152ccb205f8SBarry Smith     ierr = MatFactorInfoInitialize(&info);CHKERRQ(ierr);
153ccb205f8SBarry Smith     for (i=0; i<mbs; i++) {
1542692d6eeSBarry Smith       ierr = MatGetOrdering(a->a[a->diag[i]], MATORDERINGND,&row,&col);CHKERRQ(ierr);
155719d5645SBarry Smith       ierr = MatLUFactorSymbolic(a->diags[i],a->a[a->diag[i]],row,col,&info);CHKERRQ(ierr);
156719d5645SBarry Smith       ierr = MatLUFactorNumeric(a->diags[i],a->a[a->diag[i]],&info);CHKERRQ(ierr);
1576bf464f9SBarry Smith       ierr = ISDestroy(&row);CHKERRQ(ierr);
1586bf464f9SBarry Smith       ierr = ISDestroy(&col);CHKERRQ(ierr);
159ccb205f8SBarry Smith     }
160ccb205f8SBarry Smith   }
161ccb205f8SBarry Smith   diag = a->diags;
162ccb205f8SBarry Smith 
163ccb205f8SBarry Smith   ierr = VecSet(xx,0.0);CHKERRQ(ierr);
164ccb205f8SBarry Smith   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
1653649974fSBarry Smith   ierr = VecGetArrayRead(bb,&b);CHKERRQ(ierr);
166ccb205f8SBarry Smith 
16741f059aeSBarry Smith   /* need to add code for when initial guess is zero, see MatSOR_SeqAIJ */
168ccb205f8SBarry Smith   while (its--) {
169ccb205f8SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){
170ccb205f8SBarry Smith 
171ccb205f8SBarry Smith       for (i=0; i<mbs; i++) {
172ccb205f8SBarry Smith         n    = a->i[i+1] - a->i[i];
173ccb205f8SBarry Smith         idx  = a->j + a->i[i];
174ccb205f8SBarry Smith         v    = a->a + a->i[i];
175ccb205f8SBarry Smith 
176ccb205f8SBarry Smith         ierr = VecSet(left,0.0);CHKERRQ(ierr);
177ccb205f8SBarry Smith         for (j=0; j<n; j++) {
178ccb205f8SBarry Smith           if (idx[j] != i) {
179ccb205f8SBarry Smith             ierr = VecPlaceArray(right,x + idx[j]*bs);CHKERRQ(ierr);
180ccb205f8SBarry Smith             ierr = MatMultAdd(v[j],right,left,left);CHKERRQ(ierr);
181ccb205f8SBarry Smith             ierr = VecResetArray(right);CHKERRQ(ierr);
182ccb205f8SBarry Smith           }
183ccb205f8SBarry Smith         }
184ccb205f8SBarry Smith         ierr = VecPlaceArray(right,b + i*bs);CHKERRQ(ierr);
185ccb205f8SBarry Smith         ierr = VecAYPX(left,-1.0,right);CHKERRQ(ierr);
186ccb205f8SBarry Smith         ierr = VecResetArray(right);CHKERRQ(ierr);
187ccb205f8SBarry Smith 
188ccb205f8SBarry Smith         ierr = VecPlaceArray(right,x + i*bs);CHKERRQ(ierr);
189ccb205f8SBarry Smith         ierr = MatSolve(diag[i],left,right);CHKERRQ(ierr);
190ccb205f8SBarry Smith         ierr = VecResetArray(right);CHKERRQ(ierr);
191ccb205f8SBarry Smith       }
192ccb205f8SBarry Smith     }
193ccb205f8SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){
194ccb205f8SBarry Smith 
195ccb205f8SBarry Smith       for (i=mbs-1; i>=0; i--) {
196ccb205f8SBarry Smith         n    = a->i[i+1] - a->i[i];
197ccb205f8SBarry Smith         idx  = a->j + a->i[i];
198ccb205f8SBarry Smith         v    = a->a + a->i[i];
199ccb205f8SBarry Smith 
200ccb205f8SBarry Smith         ierr = VecSet(left,0.0);CHKERRQ(ierr);
201ccb205f8SBarry Smith         for (j=0; j<n; j++) {
202ccb205f8SBarry Smith           if (idx[j] != i) {
203ccb205f8SBarry Smith             ierr = VecPlaceArray(right,x + idx[j]*bs);CHKERRQ(ierr);
204ccb205f8SBarry Smith             ierr = MatMultAdd(v[j],right,left,left);CHKERRQ(ierr);
205ccb205f8SBarry Smith             ierr = VecResetArray(right);CHKERRQ(ierr);
206ccb205f8SBarry Smith           }
207ccb205f8SBarry Smith         }
208ccb205f8SBarry Smith         ierr = VecPlaceArray(right,b + i*bs);CHKERRQ(ierr);
209ccb205f8SBarry Smith         ierr = VecAYPX(left,-1.0,right);CHKERRQ(ierr);
210ccb205f8SBarry Smith         ierr = VecResetArray(right);CHKERRQ(ierr);
211ccb205f8SBarry Smith 
212ccb205f8SBarry Smith         ierr = VecPlaceArray(right,x + i*bs);CHKERRQ(ierr);
213ccb205f8SBarry Smith         ierr = MatSolve(diag[i],left,right);CHKERRQ(ierr);
214ccb205f8SBarry Smith         ierr = VecResetArray(right);CHKERRQ(ierr);
215ccb205f8SBarry Smith 
216ccb205f8SBarry Smith       }
217ccb205f8SBarry Smith     }
218ccb205f8SBarry Smith   }
219ccb205f8SBarry Smith   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
2203649974fSBarry Smith   ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
221ccb205f8SBarry Smith   PetscFunctionReturn(0);
222ccb205f8SBarry Smith }
223ccb205f8SBarry Smith 
224ccb205f8SBarry Smith #undef __FUNCT__
225421e10b8SBarry Smith #define __FUNCT__ "MatSetValues_BlockMat"
226421e10b8SBarry Smith PetscErrorCode MatSetValues_BlockMat(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
227421e10b8SBarry Smith {
228421e10b8SBarry Smith   Mat_BlockMat   *a = (Mat_BlockMat*)A->data;
229421e10b8SBarry Smith   PetscInt       *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N,lastcol = -1;
230421e10b8SBarry Smith   PetscInt       *imax=a->imax,*ai=a->i,*ailen=a->ilen;
231d0f46423SBarry Smith   PetscInt       *aj=a->j,nonew=a->nonew,bs=A->rmap->bs,brow,bcol;
232421e10b8SBarry Smith   PetscErrorCode ierr;
233421e10b8SBarry Smith   PetscInt       ridx,cidx;
234ace3abfcSBarry Smith   PetscBool      roworiented=a->roworiented;
235421e10b8SBarry Smith   MatScalar      value;
236421e10b8SBarry Smith   Mat            *ap,*aa = a->a;
237421e10b8SBarry Smith 
238421e10b8SBarry Smith   PetscFunctionBegin;
23971fd2e92SBarry Smith   if (v) PetscValidScalarPointer(v,6);
240421e10b8SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
241421e10b8SBarry Smith     row  = im[k];
242421e10b8SBarry Smith     brow = row/bs;
243421e10b8SBarry Smith     if (row < 0) continue;
244421e10b8SBarry Smith #if defined(PETSC_USE_DEBUG)
245e32f2f54SBarry 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);
246421e10b8SBarry Smith #endif
247421e10b8SBarry Smith     rp   = aj + ai[brow];
248421e10b8SBarry Smith     ap   = aa + ai[brow];
249421e10b8SBarry Smith     rmax = imax[brow];
250421e10b8SBarry Smith     nrow = ailen[brow];
251421e10b8SBarry Smith     low  = 0;
252421e10b8SBarry Smith     high = nrow;
253421e10b8SBarry Smith     for (l=0; l<n; l++) { /* loop over added columns */
254421e10b8SBarry Smith       if (in[l] < 0) continue;
255421e10b8SBarry Smith #if defined(PETSC_USE_DEBUG)
256e32f2f54SBarry 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);
257421e10b8SBarry Smith #endif
258421e10b8SBarry Smith       col = in[l]; bcol = col/bs;
2596e63c7a1SBarry Smith       if (A->symmetric && brow > bcol) continue;
260421e10b8SBarry Smith       ridx = row % bs; cidx = col % bs;
261421e10b8SBarry Smith       if (roworiented) {
262421e10b8SBarry Smith         value = v[l + k*n];
263421e10b8SBarry Smith       } else {
264421e10b8SBarry Smith         value = v[k + l*m];
265421e10b8SBarry Smith       }
266421e10b8SBarry Smith       if (col <= lastcol) low = 0; else high = nrow;
267421e10b8SBarry Smith       lastcol = col;
268421e10b8SBarry Smith       while (high-low > 7) {
269421e10b8SBarry Smith         t = (low+high)/2;
270421e10b8SBarry Smith         if (rp[t] > bcol) high = t;
271421e10b8SBarry Smith         else              low  = t;
272421e10b8SBarry Smith       }
273421e10b8SBarry Smith       for (i=low; i<high; i++) {
274421e10b8SBarry Smith         if (rp[i] > bcol) break;
275421e10b8SBarry Smith         if (rp[i] == bcol) {
276421e10b8SBarry Smith           goto noinsert1;
277421e10b8SBarry Smith         }
278421e10b8SBarry Smith       }
279421e10b8SBarry Smith       if (nonew == 1) goto noinsert1;
280e32f2f54SBarry Smith       if (nonew == -1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero (%D, %D) in the matrix", row, col);
281fef13f97SBarry Smith       MatSeqXAIJReallocateAIJ(A,a->mbs,1,nrow,brow,bcol,rmax,aa,ai,aj,rp,ap,imax,nonew,Mat);
282421e10b8SBarry Smith       N = nrow++ - 1; high++;
283421e10b8SBarry Smith       /* shift up all the later entries in this row */
284421e10b8SBarry Smith       for (ii=N; ii>=i; ii--) {
285421e10b8SBarry Smith         rp[ii+1] = rp[ii];
286421e10b8SBarry Smith         ap[ii+1] = ap[ii];
287421e10b8SBarry Smith       }
288421e10b8SBarry Smith       if (N>=i) ap[i] = 0;
289421e10b8SBarry Smith       rp[i]           = bcol;
290421e10b8SBarry Smith       a->nz++;
291421e10b8SBarry Smith       noinsert1:;
292421e10b8SBarry Smith       if (!*(ap+i)) {
2936e63c7a1SBarry Smith         ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,bs,bs,0,0,ap+i);CHKERRQ(ierr);
294b0223207SBarry Smith       }
295421e10b8SBarry Smith       ierr = MatSetValues(ap[i],1,&ridx,1,&cidx,&value,is);CHKERRQ(ierr);
296421e10b8SBarry Smith       low = i;
297421e10b8SBarry Smith     }
298421e10b8SBarry Smith     ailen[brow] = nrow;
299421e10b8SBarry Smith   }
300421e10b8SBarry Smith   A->same_nonzero = PETSC_FALSE;
301421e10b8SBarry Smith   PetscFunctionReturn(0);
302421e10b8SBarry Smith }
303421e10b8SBarry Smith 
304421e10b8SBarry Smith #undef __FUNCT__
3055bba2384SShri Abhyankar #define __FUNCT__ "MatLoad_BlockMat"
306112444f4SShri Abhyankar PetscErrorCode MatLoad_BlockMat(Mat newmat, PetscViewer viewer)
307a5973382SShri Abhyankar {
308a5973382SShri Abhyankar   PetscErrorCode    ierr;
309a5973382SShri Abhyankar   Mat               tmpA;
310a5973382SShri Abhyankar   PetscInt          i,j,m,n,bs = 1,ncols,*lens,currentcol,mbs,**ii,*ilens,nextcol,*llens,cnt = 0;
311a5973382SShri Abhyankar   const PetscInt    *cols;
312a5973382SShri Abhyankar   const PetscScalar *values;
313ace3abfcSBarry Smith   PetscBool         flg = PETSC_FALSE,notdone;
314a5973382SShri Abhyankar   Mat_SeqAIJ        *a;
315a5973382SShri Abhyankar   Mat_BlockMat      *amat;
316a5973382SShri Abhyankar 
317a5973382SShri Abhyankar   PetscFunctionBegin;
318a5973382SShri Abhyankar   ierr = MatCreate(PETSC_COMM_SELF,&tmpA);CHKERRQ(ierr);
319a5973382SShri Abhyankar   ierr = MatSetType(tmpA,MATSEQAIJ);CHKERRQ(ierr);
320112444f4SShri Abhyankar   ierr = MatLoad_SeqAIJ(tmpA,viewer);CHKERRQ(ierr);
321a5973382SShri Abhyankar 
322a5973382SShri Abhyankar   ierr = MatGetLocalSize(tmpA,&m,&n);CHKERRQ(ierr);
323a5973382SShri Abhyankar   ierr = PetscOptionsBegin(PETSC_COMM_SELF,PETSC_NULL,"Options for loading BlockMat matrix 1","Mat");CHKERRQ(ierr);
324a5973382SShri Abhyankar   ierr = PetscOptionsInt("-matload_block_size","Set the blocksize used to store the matrix","MatLoad",bs,&bs,PETSC_NULL);CHKERRQ(ierr);
325acfcf0e5SJed Brown   ierr = PetscOptionsBool("-matload_symmetric","Store the matrix as symmetric","MatLoad",flg,&flg,PETSC_NULL);CHKERRQ(ierr);
326a5973382SShri Abhyankar   ierr = PetscOptionsEnd();CHKERRQ(ierr);
327a5973382SShri Abhyankar 
328a5973382SShri Abhyankar   /* Determine number of nonzero blocks for each block row */
329a5973382SShri Abhyankar   a    = (Mat_SeqAIJ*) tmpA->data;
330a5973382SShri Abhyankar   mbs  = m/bs;
331a5973382SShri Abhyankar   ierr = PetscMalloc3(mbs,PetscInt,&lens,bs,PetscInt*,&ii,bs,PetscInt,&ilens);CHKERRQ(ierr);
332a5973382SShri Abhyankar   ierr = PetscMemzero(lens,mbs*sizeof(PetscInt));CHKERRQ(ierr);
333a5973382SShri Abhyankar 
334a5973382SShri Abhyankar   for (i=0; i<mbs; i++) {
335a5973382SShri Abhyankar     for (j=0; j<bs; j++) {
336a5973382SShri Abhyankar       ii[j]         = a->j + a->i[i*bs + j];
337a5973382SShri Abhyankar       ilens[j]      = a->i[i*bs + j + 1] - a->i[i*bs + j];
338a5973382SShri Abhyankar     }
339a5973382SShri Abhyankar 
340a5973382SShri Abhyankar     currentcol = -1;
341a5973382SShri Abhyankar     notdone = PETSC_TRUE;
342a5973382SShri Abhyankar     while (PETSC_TRUE) {
343a5973382SShri Abhyankar       notdone = PETSC_FALSE;
344a5973382SShri Abhyankar       nextcol = 1000000000;
345a5973382SShri Abhyankar       for (j=0; j<bs; j++) {
346a5973382SShri Abhyankar         while ((ilens[j] > 0 && ii[j][0]/bs <= currentcol)) {
347a5973382SShri Abhyankar           ii[j]++;
348a5973382SShri Abhyankar           ilens[j]--;
349a5973382SShri Abhyankar         }
350a5973382SShri Abhyankar         if (ilens[j] > 0) {
351a5973382SShri Abhyankar           notdone = PETSC_TRUE;
352a5973382SShri Abhyankar           nextcol = PetscMin(nextcol,ii[j][0]/bs);
353a5973382SShri Abhyankar         }
354a5973382SShri Abhyankar       }
355a5973382SShri Abhyankar       if (!notdone) break;
356a5973382SShri Abhyankar       if (!flg || (nextcol >= i)) lens[i]++;
357a5973382SShri Abhyankar       currentcol = nextcol;
358a5973382SShri Abhyankar     }
359a5973382SShri Abhyankar   }
360a5973382SShri Abhyankar 
361a5973382SShri Abhyankar   if (newmat->rmap->n < 0 && newmat->rmap->N < 0 && newmat->cmap->n < 0 && newmat->cmap->N < 0) {
362a5973382SShri Abhyankar     ierr = MatSetSizes(newmat,m,n,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
363a5973382SShri Abhyankar   }
364a5973382SShri Abhyankar   ierr = MatBlockMatSetPreallocation(newmat,bs,0,lens);CHKERRQ(ierr);
365a5973382SShri Abhyankar   if (flg) {
366a5973382SShri Abhyankar     ierr = MatSetOption(newmat,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
367a5973382SShri Abhyankar   }
368a5973382SShri Abhyankar   amat = (Mat_BlockMat*)(newmat)->data;
369a5973382SShri Abhyankar 
370a5973382SShri Abhyankar   /* preallocate the submatrices */
371a5973382SShri Abhyankar   ierr = PetscMalloc(bs*sizeof(PetscInt),&llens);CHKERRQ(ierr);
372a5973382SShri Abhyankar   for (i=0; i<mbs; i++) { /* loops for block rows */
373a5973382SShri Abhyankar     for (j=0; j<bs; j++) {
374a5973382SShri Abhyankar       ii[j]         = a->j + a->i[i*bs + j];
375a5973382SShri Abhyankar       ilens[j]      = a->i[i*bs + j + 1] - a->i[i*bs + j];
376a5973382SShri Abhyankar     }
377a5973382SShri Abhyankar 
378a5973382SShri Abhyankar     currentcol = 1000000000;
379a5973382SShri Abhyankar     for (j=0; j<bs; j++) { /* loop over rows in block finding first nonzero block */
380a5973382SShri Abhyankar       if (ilens[j] > 0) {
381a5973382SShri Abhyankar 	currentcol = PetscMin(currentcol,ii[j][0]/bs);
382a5973382SShri Abhyankar       }
383a5973382SShri Abhyankar     }
384a5973382SShri Abhyankar 
385a5973382SShri Abhyankar     notdone = PETSC_TRUE;
386a5973382SShri Abhyankar     while (PETSC_TRUE) {  /* loops over blocks in block row */
387a5973382SShri Abhyankar 
388a5973382SShri Abhyankar       notdone = PETSC_FALSE;
389a5973382SShri Abhyankar       nextcol = 1000000000;
390a5973382SShri Abhyankar       ierr = PetscMemzero(llens,bs*sizeof(PetscInt));CHKERRQ(ierr);
391a5973382SShri Abhyankar       for (j=0; j<bs; j++) { /* loop over rows in block */
392a5973382SShri Abhyankar         while ((ilens[j] > 0 && ii[j][0]/bs <= currentcol)) { /* loop over columns in row */
393a5973382SShri Abhyankar           ii[j]++;
394a5973382SShri Abhyankar           ilens[j]--;
395a5973382SShri Abhyankar           llens[j]++;
396a5973382SShri Abhyankar         }
397a5973382SShri Abhyankar         if (ilens[j] > 0) {
398a5973382SShri Abhyankar           notdone = PETSC_TRUE;
399a5973382SShri Abhyankar           nextcol = PetscMin(nextcol,ii[j][0]/bs);
400a5973382SShri Abhyankar         }
401a5973382SShri Abhyankar       }
402a5973382SShri Abhyankar       if (cnt >= amat->maxnz) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Number of blocks found greater than expected %D",cnt);
403a5973382SShri Abhyankar       if (!flg || currentcol >= i) {
404a5973382SShri Abhyankar         amat->j[cnt] = currentcol;
405a5973382SShri Abhyankar         ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,bs,bs,0,llens,amat->a+cnt++);CHKERRQ(ierr);
406a5973382SShri Abhyankar       }
407a5973382SShri Abhyankar 
408a5973382SShri Abhyankar       if (!notdone) break;
409a5973382SShri Abhyankar       currentcol = nextcol;
410a5973382SShri Abhyankar     }
411a5973382SShri Abhyankar     amat->ilen[i] = lens[i];
412a5973382SShri Abhyankar   }
413a5973382SShri Abhyankar   CHKMEMQ;
414a5973382SShri Abhyankar 
415a5973382SShri Abhyankar   ierr = PetscFree3(lens,ii,ilens);CHKERRQ(ierr);
416a5973382SShri Abhyankar   ierr = PetscFree(llens);CHKERRQ(ierr);
417a5973382SShri Abhyankar 
418a5973382SShri Abhyankar   /* copy over the matrix, one row at a time */
419a5973382SShri Abhyankar   for (i=0; i<m; i++) {
420a5973382SShri Abhyankar     ierr = MatGetRow(tmpA,i,&ncols,&cols,&values);CHKERRQ(ierr);
421a5973382SShri Abhyankar     ierr = MatSetValues(newmat,1,&i,ncols,cols,values,INSERT_VALUES);CHKERRQ(ierr);
422a5973382SShri Abhyankar     ierr = MatRestoreRow(tmpA,i,&ncols,&cols,&values);CHKERRQ(ierr);
423a5973382SShri Abhyankar   }
424a5973382SShri Abhyankar   ierr = MatAssemblyBegin(newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
425a5973382SShri Abhyankar   ierr = MatAssemblyEnd(newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
426a5973382SShri Abhyankar   PetscFunctionReturn(0);
427a5973382SShri Abhyankar }
428a5973382SShri Abhyankar 
429a5973382SShri Abhyankar #undef __FUNCT__
430ccb205f8SBarry Smith #define __FUNCT__ "MatView_BlockMat"
431ccb205f8SBarry Smith PetscErrorCode MatView_BlockMat(Mat A,PetscViewer viewer)
432ccb205f8SBarry Smith {
43364075487SBarry Smith   Mat_BlockMat      *a = (Mat_BlockMat*)A->data;
434ccb205f8SBarry Smith   PetscErrorCode    ierr;
435ccb205f8SBarry Smith   const char        *name;
436ccb205f8SBarry Smith   PetscViewerFormat format;
437ccb205f8SBarry Smith 
438ccb205f8SBarry Smith   PetscFunctionBegin;
439ccb205f8SBarry Smith   ierr = PetscObjectGetName((PetscObject)A,&name);CHKERRQ(ierr);
440ccb205f8SBarry Smith   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
441ccb205f8SBarry Smith   if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO) {
442ccb205f8SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Nonzero block matrices = %D \n",a->nz);CHKERRQ(ierr);
44364075487SBarry Smith     if (A->symmetric) {
4448c1ad04dSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"Only upper triangular part of symmetric matrix is stored\n");CHKERRQ(ierr);
44564075487SBarry Smith     }
446ccb205f8SBarry Smith   }
447ccb205f8SBarry Smith   PetscFunctionReturn(0);
448ccb205f8SBarry Smith }
449421e10b8SBarry Smith 
450421e10b8SBarry Smith #undef __FUNCT__
451421e10b8SBarry Smith #define __FUNCT__ "MatDestroy_BlockMat"
452421e10b8SBarry Smith PetscErrorCode MatDestroy_BlockMat(Mat mat)
453421e10b8SBarry Smith {
454421e10b8SBarry Smith   PetscErrorCode ierr;
455421e10b8SBarry Smith   Mat_BlockMat   *bmat = (Mat_BlockMat*)mat->data;
456ccb205f8SBarry Smith   PetscInt       i;
457421e10b8SBarry Smith 
458421e10b8SBarry Smith   PetscFunctionBegin;
4596bf464f9SBarry Smith   ierr = VecDestroy(&bmat->right);CHKERRQ(ierr);
4606bf464f9SBarry Smith   ierr = VecDestroy(&bmat->left);CHKERRQ(ierr);
4616bf464f9SBarry Smith   ierr = VecDestroy(&bmat->middle);CHKERRQ(ierr);
4626bf464f9SBarry Smith   ierr = VecDestroy(&bmat->workb);CHKERRQ(ierr);
463ccb205f8SBarry Smith   if (bmat->diags) {
464d0f46423SBarry Smith     for (i=0; i<mat->rmap->n/mat->rmap->bs; i++) {
4656bf464f9SBarry Smith       ierr = MatDestroy(&bmat->diags[i]);CHKERRQ(ierr);
466ccb205f8SBarry Smith     }
467ccb205f8SBarry Smith   }
468ccb205f8SBarry Smith   if (bmat->a) {
469ccb205f8SBarry Smith     for (i=0; i<bmat->nz; i++) {
4706bf464f9SBarry Smith       ierr = MatDestroy(&bmat->a[i]);CHKERRQ(ierr);
471ccb205f8SBarry Smith     }
472ccb205f8SBarry Smith   }
473ccb205f8SBarry Smith   ierr = MatSeqXAIJFreeAIJ(mat,(PetscScalar**)&bmat->a,&bmat->j,&bmat->i);CHKERRQ(ierr);
474*bf0cc555SLisandro Dalcin   ierr = PetscFree(mat->data);CHKERRQ(ierr);
475421e10b8SBarry Smith   PetscFunctionReturn(0);
476421e10b8SBarry Smith }
477421e10b8SBarry Smith 
478421e10b8SBarry Smith #undef __FUNCT__
479421e10b8SBarry Smith #define __FUNCT__ "MatMult_BlockMat"
480421e10b8SBarry Smith PetscErrorCode MatMult_BlockMat(Mat A,Vec x,Vec y)
481421e10b8SBarry Smith {
482421e10b8SBarry Smith   Mat_BlockMat   *bmat = (Mat_BlockMat*)A->data;
483421e10b8SBarry Smith   PetscErrorCode ierr;
484421e10b8SBarry Smith   PetscScalar    *xx,*yy;
485d0f46423SBarry Smith   PetscInt       *aj,i,*ii,jrow,m = A->rmap->n/A->rmap->bs,bs = A->rmap->bs,n,j;
486421e10b8SBarry Smith   Mat            *aa;
487421e10b8SBarry Smith 
488421e10b8SBarry Smith   PetscFunctionBegin;
489ccb205f8SBarry Smith   CHKMEMQ;
490421e10b8SBarry Smith   /*
491421e10b8SBarry Smith      Standard CSR multiply except each entry is a Mat
492421e10b8SBarry Smith   */
493421e10b8SBarry Smith   ierr = VecGetArray(x,&xx);CHKERRQ(ierr);
494ccb205f8SBarry Smith 
495421e10b8SBarry Smith   ierr = VecSet(y,0.0);CHKERRQ(ierr);
496421e10b8SBarry Smith   ierr = VecGetArray(y,&yy);CHKERRQ(ierr);
497421e10b8SBarry Smith   aj  = bmat->j;
498421e10b8SBarry Smith   aa  = bmat->a;
499421e10b8SBarry Smith   ii  = bmat->i;
500421e10b8SBarry Smith   for (i=0; i<m; i++) {
501421e10b8SBarry Smith     jrow = ii[i];
502ccb205f8SBarry Smith     ierr = VecPlaceArray(bmat->left,yy + bs*i);CHKERRQ(ierr);
503421e10b8SBarry Smith     n    = ii[i+1] - jrow;
504421e10b8SBarry Smith     for (j=0; j<n; j++) {
505421e10b8SBarry Smith       ierr = VecPlaceArray(bmat->right,xx + bs*aj[jrow]);CHKERRQ(ierr);
506ccb205f8SBarry Smith       ierr = MatMultAdd(aa[jrow],bmat->right,bmat->left,bmat->left);CHKERRQ(ierr);
507421e10b8SBarry Smith       ierr = VecResetArray(bmat->right);CHKERRQ(ierr);
508421e10b8SBarry Smith       jrow++;
509421e10b8SBarry Smith     }
510421e10b8SBarry Smith     ierr = VecResetArray(bmat->left);CHKERRQ(ierr);
511421e10b8SBarry Smith   }
512421e10b8SBarry Smith   ierr = VecRestoreArray(x,&xx);CHKERRQ(ierr);
513421e10b8SBarry Smith   ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr);
514ccb205f8SBarry Smith   CHKMEMQ;
515421e10b8SBarry Smith   PetscFunctionReturn(0);
516421e10b8SBarry Smith }
517421e10b8SBarry Smith 
518421e10b8SBarry Smith #undef __FUNCT__
519290bbb0aSBarry Smith #define __FUNCT__ "MatMult_BlockMat_Symmetric"
520290bbb0aSBarry Smith PetscErrorCode MatMult_BlockMat_Symmetric(Mat A,Vec x,Vec y)
521290bbb0aSBarry Smith {
522290bbb0aSBarry Smith   Mat_BlockMat   *bmat = (Mat_BlockMat*)A->data;
523290bbb0aSBarry Smith   PetscErrorCode ierr;
524290bbb0aSBarry Smith   PetscScalar    *xx,*yy;
525d0f46423SBarry Smith   PetscInt       *aj,i,*ii,jrow,m = A->rmap->n/A->rmap->bs,bs = A->rmap->bs,n,j;
526290bbb0aSBarry Smith   Mat            *aa;
527290bbb0aSBarry Smith 
528290bbb0aSBarry Smith   PetscFunctionBegin;
529290bbb0aSBarry Smith   CHKMEMQ;
530290bbb0aSBarry Smith   /*
531290bbb0aSBarry Smith      Standard CSR multiply except each entry is a Mat
532290bbb0aSBarry Smith   */
533290bbb0aSBarry Smith   ierr = VecGetArray(x,&xx);CHKERRQ(ierr);
534290bbb0aSBarry Smith 
535290bbb0aSBarry Smith   ierr = VecSet(y,0.0);CHKERRQ(ierr);
536290bbb0aSBarry Smith   ierr = VecGetArray(y,&yy);CHKERRQ(ierr);
537290bbb0aSBarry Smith   aj  = bmat->j;
538290bbb0aSBarry Smith   aa  = bmat->a;
539290bbb0aSBarry Smith   ii  = bmat->i;
540290bbb0aSBarry Smith   for (i=0; i<m; i++) {
541290bbb0aSBarry Smith     jrow = ii[i];
542290bbb0aSBarry Smith     n    = ii[i+1] - jrow;
543290bbb0aSBarry Smith     ierr = VecPlaceArray(bmat->left,yy + bs*i);CHKERRQ(ierr);
544290bbb0aSBarry Smith     ierr = VecPlaceArray(bmat->middle,xx + bs*i);CHKERRQ(ierr);
545290bbb0aSBarry Smith     /* if we ALWAYS required a diagonal entry then could remove this if test */
546290bbb0aSBarry Smith     if (aj[jrow] == i) {
547290bbb0aSBarry Smith       ierr = VecPlaceArray(bmat->right,xx + bs*aj[jrow]);CHKERRQ(ierr);
548290bbb0aSBarry Smith       ierr = MatMultAdd(aa[jrow],bmat->right,bmat->left,bmat->left);CHKERRQ(ierr);
549290bbb0aSBarry Smith       ierr = VecResetArray(bmat->right);CHKERRQ(ierr);
550290bbb0aSBarry Smith       jrow++;
551290bbb0aSBarry Smith       n--;
552290bbb0aSBarry Smith     }
553290bbb0aSBarry Smith     for (j=0; j<n; j++) {
554290bbb0aSBarry Smith       ierr = VecPlaceArray(bmat->right,xx + bs*aj[jrow]);CHKERRQ(ierr);            /* upper triangular part */
555290bbb0aSBarry Smith       ierr = MatMultAdd(aa[jrow],bmat->right,bmat->left,bmat->left);CHKERRQ(ierr);
556290bbb0aSBarry Smith       ierr = VecResetArray(bmat->right);CHKERRQ(ierr);
557290bbb0aSBarry Smith 
558290bbb0aSBarry Smith       ierr = VecPlaceArray(bmat->right,yy + bs*aj[jrow]);CHKERRQ(ierr);            /* lower triangular part */
559290bbb0aSBarry Smith       ierr = MatMultTransposeAdd(aa[jrow],bmat->middle,bmat->right,bmat->right);CHKERRQ(ierr);
560290bbb0aSBarry Smith       ierr = VecResetArray(bmat->right);CHKERRQ(ierr);
561290bbb0aSBarry Smith       jrow++;
562290bbb0aSBarry Smith     }
563290bbb0aSBarry Smith     ierr = VecResetArray(bmat->left);CHKERRQ(ierr);
564290bbb0aSBarry Smith     ierr = VecResetArray(bmat->middle);CHKERRQ(ierr);
565290bbb0aSBarry Smith   }
566290bbb0aSBarry Smith   ierr = VecRestoreArray(x,&xx);CHKERRQ(ierr);
567290bbb0aSBarry Smith   ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr);
568290bbb0aSBarry Smith   CHKMEMQ;
569290bbb0aSBarry Smith   PetscFunctionReturn(0);
570290bbb0aSBarry Smith }
571290bbb0aSBarry Smith 
572290bbb0aSBarry Smith #undef __FUNCT__
573421e10b8SBarry Smith #define __FUNCT__ "MatMultAdd_BlockMat"
574421e10b8SBarry Smith PetscErrorCode MatMultAdd_BlockMat(Mat A,Vec x,Vec y,Vec z)
575421e10b8SBarry Smith {
576421e10b8SBarry Smith   PetscFunctionBegin;
577421e10b8SBarry Smith   PetscFunctionReturn(0);
578421e10b8SBarry Smith }
579421e10b8SBarry Smith 
580421e10b8SBarry Smith #undef __FUNCT__
581421e10b8SBarry Smith #define __FUNCT__ "MatMultTranspose_BlockMat"
582421e10b8SBarry Smith PetscErrorCode MatMultTranspose_BlockMat(Mat A,Vec x,Vec y)
583421e10b8SBarry Smith {
584421e10b8SBarry Smith   PetscFunctionBegin;
585421e10b8SBarry Smith   PetscFunctionReturn(0);
586421e10b8SBarry Smith }
587421e10b8SBarry Smith 
588421e10b8SBarry Smith #undef __FUNCT__
589421e10b8SBarry Smith #define __FUNCT__ "MatMultTransposeAdd_BlockMat"
590421e10b8SBarry Smith PetscErrorCode MatMultTransposeAdd_BlockMat(Mat A,Vec x,Vec y,Vec z)
591421e10b8SBarry Smith {
592421e10b8SBarry Smith   PetscFunctionBegin;
593421e10b8SBarry Smith   PetscFunctionReturn(0);
594421e10b8SBarry Smith }
595421e10b8SBarry Smith 
596ccb205f8SBarry Smith /*
597ccb205f8SBarry Smith      Adds diagonal pointers to sparse matrix structure.
598ccb205f8SBarry Smith */
599ccb205f8SBarry Smith #undef __FUNCT__
600ccb205f8SBarry Smith #define __FUNCT__ "MatMarkDiagonal_BlockMat"
601ccb205f8SBarry Smith PetscErrorCode MatMarkDiagonal_BlockMat(Mat A)
602ccb205f8SBarry Smith {
603ccb205f8SBarry Smith   Mat_BlockMat   *a = (Mat_BlockMat*)A->data;
604ccb205f8SBarry Smith   PetscErrorCode ierr;
605d0f46423SBarry Smith   PetscInt       i,j,mbs = A->rmap->n/A->rmap->bs;
606ccb205f8SBarry Smith 
607ccb205f8SBarry Smith   PetscFunctionBegin;
608ccb205f8SBarry Smith   if (!a->diag) {
609ccb205f8SBarry Smith     ierr = PetscMalloc(mbs*sizeof(PetscInt),&a->diag);CHKERRQ(ierr);
610ccb205f8SBarry Smith   }
611ccb205f8SBarry Smith   for (i=0; i<mbs; i++) {
612ccb205f8SBarry Smith     a->diag[i] = a->i[i+1];
613ccb205f8SBarry Smith     for (j=a->i[i]; j<a->i[i+1]; j++) {
614ccb205f8SBarry Smith       if (a->j[j] == i) {
615ccb205f8SBarry Smith         a->diag[i] = j;
616ccb205f8SBarry Smith         break;
617ccb205f8SBarry Smith       }
618ccb205f8SBarry Smith     }
619ccb205f8SBarry Smith   }
620ccb205f8SBarry Smith   PetscFunctionReturn(0);
621ccb205f8SBarry Smith }
622ccb205f8SBarry Smith 
623ccb205f8SBarry Smith #undef __FUNCT__
624ccb205f8SBarry Smith #define __FUNCT__ "MatGetSubMatrix_BlockMat"
6254aa3045dSJed Brown PetscErrorCode MatGetSubMatrix_BlockMat(Mat A,IS isrow,IS iscol,MatReuse scall,Mat *B)
626ccb205f8SBarry Smith {
627ccb205f8SBarry Smith   Mat_BlockMat   *a = (Mat_BlockMat*)A->data;
628ccb205f8SBarry Smith   Mat_SeqAIJ     *c;
629ccb205f8SBarry Smith   PetscErrorCode ierr;
630ccb205f8SBarry Smith   PetscInt       i,k,first,step,lensi,nrows,ncols;
631d2a212eaSBarry Smith   PetscInt       *j_new,*i_new,*aj = a->j,*ailen = a->ilen;
6321620fd73SBarry Smith   PetscScalar    *a_new;
633ccb205f8SBarry Smith   Mat            C,*aa = a->a;
634ace3abfcSBarry Smith   PetscBool      stride,equal;
635ccb205f8SBarry Smith 
636ccb205f8SBarry Smith   PetscFunctionBegin;
637ccb205f8SBarry Smith   ierr = ISEqual(isrow,iscol,&equal);CHKERRQ(ierr);
638e32f2f54SBarry Smith   if (!equal) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only for idential column and row indices");
6390dbe5b1eSSatish Balay   ierr = PetscTypeCompare((PetscObject)iscol,ISSTRIDE,&stride);CHKERRQ(ierr);
640e32f2f54SBarry Smith   if (!stride) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only for stride indices");
641ccb205f8SBarry Smith   ierr = ISStrideGetInfo(iscol,&first,&step);CHKERRQ(ierr);
642e32f2f54SBarry Smith   if (step != A->rmap->bs) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Can only select one entry from each block");
643ccb205f8SBarry Smith 
644ccb205f8SBarry Smith   ierr = ISGetLocalSize(isrow,&nrows);CHKERRQ(ierr);
645ccb205f8SBarry Smith   ncols = nrows;
646ccb205f8SBarry Smith 
647ccb205f8SBarry Smith   /* create submatrix */
648ccb205f8SBarry Smith   if (scall == MAT_REUSE_MATRIX) {
649ccb205f8SBarry Smith     PetscInt n_cols,n_rows;
650ccb205f8SBarry Smith     C = *B;
651ccb205f8SBarry Smith     ierr = MatGetSize(C,&n_rows,&n_cols);CHKERRQ(ierr);
652e32f2f54SBarry Smith     if (n_rows != nrows || n_cols != ncols) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Reused submatrix wrong size");
653ccb205f8SBarry Smith     ierr = MatZeroEntries(C);CHKERRQ(ierr);
654ccb205f8SBarry Smith   } else {
6557adad957SLisandro Dalcin     ierr = MatCreate(((PetscObject)A)->comm,&C);CHKERRQ(ierr);
656ccb205f8SBarry Smith     ierr = MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
6576e63c7a1SBarry Smith     if (A->symmetric) {
6586e63c7a1SBarry Smith       ierr = MatSetType(C,MATSEQSBAIJ);CHKERRQ(ierr);
6596e63c7a1SBarry Smith     } else {
660ccb205f8SBarry Smith       ierr = MatSetType(C,MATSEQAIJ);CHKERRQ(ierr);
6616e63c7a1SBarry Smith     }
6626e63c7a1SBarry Smith     ierr = MatSeqAIJSetPreallocation(C,0,ailen);CHKERRQ(ierr);
6636e63c7a1SBarry Smith     ierr = MatSeqSBAIJSetPreallocation(C,1,0,ailen);CHKERRQ(ierr);
664ccb205f8SBarry Smith   }
665ccb205f8SBarry Smith   c = (Mat_SeqAIJ*)C->data;
666ccb205f8SBarry Smith 
667ccb205f8SBarry Smith   /* loop over rows inserting into submatrix */
668ccb205f8SBarry Smith   a_new    = c->a;
669ccb205f8SBarry Smith   j_new    = c->j;
670ccb205f8SBarry Smith   i_new    = c->i;
671ccb205f8SBarry Smith 
672ccb205f8SBarry Smith   for (i=0; i<nrows; i++) {
673ccb205f8SBarry Smith     lensi = ailen[i];
674ccb205f8SBarry Smith     for (k=0; k<lensi; k++) {
675ccb205f8SBarry Smith       *j_new++ = *aj++;
6761620fd73SBarry Smith       ierr     = MatGetValue(*aa++,first,first,a_new++);CHKERRQ(ierr);
677ccb205f8SBarry Smith     }
678ccb205f8SBarry Smith     i_new[i+1]  = i_new[i] + lensi;
679ccb205f8SBarry Smith     c->ilen[i]  = lensi;
680ccb205f8SBarry Smith   }
681ccb205f8SBarry Smith 
682ccb205f8SBarry Smith   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
683ccb205f8SBarry Smith   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
684ccb205f8SBarry Smith   *B = C;
685ccb205f8SBarry Smith   PetscFunctionReturn(0);
686ccb205f8SBarry Smith }
687ccb205f8SBarry Smith 
688421e10b8SBarry Smith #undef __FUNCT__
689421e10b8SBarry Smith #define __FUNCT__ "MatAssemblyEnd_BlockMat"
690421e10b8SBarry Smith PetscErrorCode MatAssemblyEnd_BlockMat(Mat A,MatAssemblyType mode)
691421e10b8SBarry Smith {
692421e10b8SBarry Smith   Mat_BlockMat   *a = (Mat_BlockMat*)A->data;
693421e10b8SBarry Smith   PetscErrorCode ierr;
694421e10b8SBarry Smith   PetscInt       fshift = 0,i,j,*ai = a->i,*aj = a->j,*imax = a->imax;
695ccb205f8SBarry Smith   PetscInt       m = a->mbs,*ip,N,*ailen = a->ilen,rmax = 0;
696421e10b8SBarry Smith   Mat            *aa = a->a,*ap;
697421e10b8SBarry Smith 
698421e10b8SBarry Smith   PetscFunctionBegin;
699421e10b8SBarry Smith   if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0);
700421e10b8SBarry Smith 
701421e10b8SBarry Smith   if (m) rmax = ailen[0]; /* determine row with most nonzeros */
702421e10b8SBarry Smith   for (i=1; i<m; i++) {
703421e10b8SBarry Smith     /* move each row back by the amount of empty slots (fshift) before it*/
704421e10b8SBarry Smith     fshift += imax[i-1] - ailen[i-1];
705421e10b8SBarry Smith     rmax   = PetscMax(rmax,ailen[i]);
706421e10b8SBarry Smith     if (fshift) {
707421e10b8SBarry Smith       ip = aj + ai[i] ;
708421e10b8SBarry Smith       ap = aa + ai[i] ;
709421e10b8SBarry Smith       N  = ailen[i];
710421e10b8SBarry Smith       for (j=0; j<N; j++) {
711421e10b8SBarry Smith         ip[j-fshift] = ip[j];
712421e10b8SBarry Smith         ap[j-fshift] = ap[j];
713421e10b8SBarry Smith       }
714421e10b8SBarry Smith     }
715421e10b8SBarry Smith     ai[i] = ai[i-1] + ailen[i-1];
716421e10b8SBarry Smith   }
717421e10b8SBarry Smith   if (m) {
718421e10b8SBarry Smith     fshift += imax[m-1] - ailen[m-1];
719421e10b8SBarry Smith     ai[m]  = ai[m-1] + ailen[m-1];
720421e10b8SBarry Smith   }
721421e10b8SBarry Smith   /* reset ilen and imax for each row */
722421e10b8SBarry Smith   for (i=0; i<m; i++) {
723421e10b8SBarry Smith     ailen[i] = imax[i] = ai[i+1] - ai[i];
724421e10b8SBarry Smith   }
725421e10b8SBarry Smith   a->nz = ai[m];
726ccb205f8SBarry Smith   for (i=0; i<a->nz; i++) {
727ccb205f8SBarry Smith #if defined(PETSC_USE_DEBUG)
728e32f2f54SBarry 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);
729ccb205f8SBarry Smith #endif
730ccb205f8SBarry Smith     ierr = MatAssemblyBegin(aa[i],MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
731ccb205f8SBarry Smith     ierr = MatAssemblyEnd(aa[i],MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
732ccb205f8SBarry Smith   }
733ccb205f8SBarry Smith   CHKMEMQ;
734d0f46423SBarry 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);
735421e10b8SBarry Smith   ierr = PetscInfo1(A,"Number of mallocs during MatSetValues() is %D\n",a->reallocs);CHKERRQ(ierr);
736421e10b8SBarry Smith   ierr = PetscInfo1(A,"Maximum nonzeros in any row is %D\n",rmax);CHKERRQ(ierr);
7378e58a170SBarry Smith   A->info.mallocs     += a->reallocs;
738421e10b8SBarry Smith   a->reallocs          = 0;
739421e10b8SBarry Smith   A->info.nz_unneeded  = (double)fshift;
740421e10b8SBarry Smith   a->rmax              = rmax;
741421e10b8SBarry Smith 
742421e10b8SBarry Smith   A->same_nonzero = PETSC_TRUE;
743ccb205f8SBarry Smith   ierr = MatMarkDiagonal_BlockMat(A);CHKERRQ(ierr);
744421e10b8SBarry Smith   PetscFunctionReturn(0);
745421e10b8SBarry Smith }
746421e10b8SBarry Smith 
747290bbb0aSBarry Smith #undef __FUNCT__
748290bbb0aSBarry Smith #define __FUNCT__ "MatSetOption_BlockMat"
749ace3abfcSBarry Smith PetscErrorCode MatSetOption_BlockMat(Mat A,MatOption opt,PetscBool  flg)
750290bbb0aSBarry Smith {
751290bbb0aSBarry Smith   PetscFunctionBegin;
7524e0d8c25SBarry Smith   if (opt == MAT_SYMMETRIC && flg) {
75341f059aeSBarry Smith     A->ops->sor = MatSOR_BlockMat_Symmetric;
754290bbb0aSBarry Smith     A->ops->mult  = MatMult_BlockMat_Symmetric;
755290bbb0aSBarry Smith   } else {
756290bbb0aSBarry Smith     PetscInfo1(A,"Unused matrix option %s\n",MatOptions[opt]);
757290bbb0aSBarry Smith   }
758290bbb0aSBarry Smith   PetscFunctionReturn(0);
759290bbb0aSBarry Smith }
760290bbb0aSBarry Smith 
761290bbb0aSBarry Smith 
762421e10b8SBarry Smith static struct _MatOps MatOps_Values = {MatSetValues_BlockMat,
763421e10b8SBarry Smith        0,
764421e10b8SBarry Smith        0,
765421e10b8SBarry Smith        MatMult_BlockMat,
766421e10b8SBarry Smith /* 4*/ MatMultAdd_BlockMat,
767421e10b8SBarry Smith        MatMultTranspose_BlockMat,
768421e10b8SBarry Smith        MatMultTransposeAdd_BlockMat,
769421e10b8SBarry Smith        0,
770421e10b8SBarry Smith        0,
771421e10b8SBarry Smith        0,
772421e10b8SBarry Smith /*10*/ 0,
773421e10b8SBarry Smith        0,
774421e10b8SBarry Smith        0,
77541f059aeSBarry Smith        MatSOR_BlockMat,
776421e10b8SBarry Smith        0,
777421e10b8SBarry Smith /*15*/ 0,
778421e10b8SBarry Smith        0,
779421e10b8SBarry Smith        0,
780421e10b8SBarry Smith        0,
781421e10b8SBarry Smith        0,
782421e10b8SBarry Smith /*20*/ 0,
783421e10b8SBarry Smith        MatAssemblyEnd_BlockMat,
784290bbb0aSBarry Smith        MatSetOption_BlockMat,
785421e10b8SBarry Smith        0,
786d519adbfSMatthew Knepley /*24*/ 0,
787421e10b8SBarry Smith        0,
788421e10b8SBarry Smith        0,
789421e10b8SBarry Smith        0,
790421e10b8SBarry Smith        0,
791d519adbfSMatthew Knepley /*29*/ 0,
792421e10b8SBarry Smith        0,
793421e10b8SBarry Smith        0,
794421e10b8SBarry Smith        0,
795421e10b8SBarry Smith        0,
796d519adbfSMatthew Knepley /*34*/ 0,
797421e10b8SBarry Smith        0,
798421e10b8SBarry Smith        0,
799421e10b8SBarry Smith        0,
800421e10b8SBarry Smith        0,
801d519adbfSMatthew Knepley /*39*/ 0,
802421e10b8SBarry Smith        0,
803421e10b8SBarry Smith        0,
804421e10b8SBarry Smith        0,
805421e10b8SBarry Smith        0,
806d519adbfSMatthew Knepley /*44*/ 0,
807421e10b8SBarry Smith        0,
808421e10b8SBarry Smith        0,
809421e10b8SBarry Smith        0,
810421e10b8SBarry Smith        0,
811d519adbfSMatthew Knepley /*49*/ 0,
812421e10b8SBarry Smith        0,
813421e10b8SBarry Smith        0,
814421e10b8SBarry Smith        0,
815421e10b8SBarry Smith        0,
816d519adbfSMatthew Knepley /*54*/ 0,
817421e10b8SBarry Smith        0,
818421e10b8SBarry Smith        0,
819421e10b8SBarry Smith        0,
820421e10b8SBarry Smith        0,
821d519adbfSMatthew Knepley /*59*/ MatGetSubMatrix_BlockMat,
822421e10b8SBarry Smith        MatDestroy_BlockMat,
823ccb205f8SBarry Smith        MatView_BlockMat,
824421e10b8SBarry Smith        0,
825421e10b8SBarry Smith        0,
826d519adbfSMatthew Knepley /*64*/ 0,
827421e10b8SBarry Smith        0,
828421e10b8SBarry Smith        0,
829421e10b8SBarry Smith        0,
830421e10b8SBarry Smith        0,
831d519adbfSMatthew Knepley /*69*/ 0,
832421e10b8SBarry Smith        0,
833421e10b8SBarry Smith        0,
834421e10b8SBarry Smith        0,
835421e10b8SBarry Smith        0,
836d519adbfSMatthew Knepley /*74*/ 0,
837421e10b8SBarry Smith        0,
838421e10b8SBarry Smith        0,
839421e10b8SBarry Smith        0,
840421e10b8SBarry Smith        0,
841d519adbfSMatthew Knepley /*79*/ 0,
842421e10b8SBarry Smith        0,
843421e10b8SBarry Smith        0,
844421e10b8SBarry Smith        0,
8455bba2384SShri Abhyankar        MatLoad_BlockMat,
846d519adbfSMatthew Knepley /*84*/ 0,
847421e10b8SBarry Smith        0,
848421e10b8SBarry Smith        0,
849421e10b8SBarry Smith        0,
850421e10b8SBarry Smith        0,
851d519adbfSMatthew Knepley /*89*/ 0,
852421e10b8SBarry Smith        0,
853421e10b8SBarry Smith        0,
854421e10b8SBarry Smith        0,
855421e10b8SBarry Smith        0,
856d519adbfSMatthew Knepley /*94*/ 0,
857421e10b8SBarry Smith        0,
858421e10b8SBarry Smith        0,
859a5973382SShri Abhyankar        0,
860a5973382SShri Abhyankar        0,
861a5973382SShri Abhyankar /*99*/ 0,
862a5973382SShri Abhyankar        0,
863a5973382SShri Abhyankar        0,
864a5973382SShri Abhyankar        0,
865a5973382SShri Abhyankar        0,
866a5973382SShri Abhyankar /*104*/0,
867a5973382SShri Abhyankar        0,
868a5973382SShri Abhyankar        0,
869a5973382SShri Abhyankar        0,
870a5973382SShri Abhyankar        0,
871a5973382SShri Abhyankar /*109*/0,
872a5973382SShri Abhyankar        0,
873a5973382SShri Abhyankar        0,
874a5973382SShri Abhyankar        0,
875a5973382SShri Abhyankar        0,
876a5973382SShri Abhyankar /*114*/0,
877a5973382SShri Abhyankar        0,
878a5973382SShri Abhyankar        0,
879a5973382SShri Abhyankar        0,
880a5973382SShri Abhyankar        0,
881a5973382SShri Abhyankar /*119*/0,
882a5973382SShri Abhyankar        0,
883a5973382SShri Abhyankar        0,
8845bba2384SShri Abhyankar        0
885a5973382SShri Abhyankar };
886421e10b8SBarry Smith 
8878cdf2d9bSBarry Smith #undef __FUNCT__
8888cdf2d9bSBarry Smith #define __FUNCT__ "MatBlockMatSetPreallocation"
8898cdf2d9bSBarry Smith /*@C
8908cdf2d9bSBarry Smith    MatBlockMatSetPreallocation - For good matrix assembly performance
8918cdf2d9bSBarry Smith    the user should preallocate the matrix storage by setting the parameter nz
8928cdf2d9bSBarry Smith    (or the array nnz).  By setting these parameters accurately, performance
8938cdf2d9bSBarry Smith    during matrix assembly can be increased by more than a factor of 50.
8948cdf2d9bSBarry Smith 
8958cdf2d9bSBarry Smith    Collective on MPI_Comm
8968cdf2d9bSBarry Smith 
8978cdf2d9bSBarry Smith    Input Parameters:
8988cdf2d9bSBarry Smith +  B - The matrix
8998cdf2d9bSBarry Smith .  bs - size of each block in matrix
9008cdf2d9bSBarry Smith .  nz - number of nonzeros per block row (same for all rows)
9018cdf2d9bSBarry Smith -  nnz - array containing the number of nonzeros in the various block rows
9028cdf2d9bSBarry Smith          (possibly different for each row) or PETSC_NULL
9038cdf2d9bSBarry Smith 
9048cdf2d9bSBarry Smith    Notes:
9058cdf2d9bSBarry Smith      If nnz is given then nz is ignored
9068cdf2d9bSBarry Smith 
9078cdf2d9bSBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
9088cdf2d9bSBarry Smith    Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory
9098cdf2d9bSBarry Smith    allocation.  For large problems you MUST preallocate memory or you
9108cdf2d9bSBarry Smith    will get TERRIBLE performance, see the users' manual chapter on matrices.
9118cdf2d9bSBarry Smith 
9128cdf2d9bSBarry Smith    Level: intermediate
9138cdf2d9bSBarry Smith 
9148cdf2d9bSBarry Smith .seealso: MatCreate(), MatCreateBlockMat(), MatSetValues()
9158cdf2d9bSBarry Smith 
9168cdf2d9bSBarry Smith @*/
9177087cfbeSBarry Smith PetscErrorCode  MatBlockMatSetPreallocation(Mat B,PetscInt bs,PetscInt nz,const PetscInt nnz[])
9188cdf2d9bSBarry Smith {
9194ac538c5SBarry Smith   PetscErrorCode ierr;
9208cdf2d9bSBarry Smith 
9218cdf2d9bSBarry Smith   PetscFunctionBegin;
9224ac538c5SBarry Smith   ierr = PetscTryMethod(B,"MatBlockMatSetPreallocation_C",(Mat,PetscInt,PetscInt,const PetscInt[]),(B,bs,nz,nnz));CHKERRQ(ierr);
9238cdf2d9bSBarry Smith   PetscFunctionReturn(0);
9248cdf2d9bSBarry Smith }
9258cdf2d9bSBarry Smith 
9268cdf2d9bSBarry Smith EXTERN_C_BEGIN
9278cdf2d9bSBarry Smith #undef __FUNCT__
9288cdf2d9bSBarry Smith #define __FUNCT__ "MatBlockMatSetPreallocation_BlockMat"
9297087cfbeSBarry Smith PetscErrorCode  MatBlockMatSetPreallocation_BlockMat(Mat A,PetscInt bs,PetscInt nz,PetscInt *nnz)
9308cdf2d9bSBarry Smith {
9318cdf2d9bSBarry Smith   Mat_BlockMat   *bmat = (Mat_BlockMat*)A->data;
9328cdf2d9bSBarry Smith   PetscErrorCode ierr;
9338cdf2d9bSBarry Smith   PetscInt       i;
9348cdf2d9bSBarry Smith 
9358cdf2d9bSBarry Smith   PetscFunctionBegin;
93634ef9618SShri Abhyankar   ierr = PetscLayoutSetBlockSize(A->rmap,1);CHKERRQ(ierr);
93734ef9618SShri Abhyankar   ierr = PetscLayoutSetBlockSize(A->cmap,1);CHKERRQ(ierr);
93834ef9618SShri Abhyankar   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
93934ef9618SShri Abhyankar   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
94034ef9618SShri Abhyankar 
94165e19b50SBarry Smith   if (bs < 1) SETERRQ1(((PetscObject)A)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Block size given %D must be great than zero",bs);
942e32f2f54SBarry 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);
943e32f2f54SBarry 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);
9448cdf2d9bSBarry Smith   if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
945e32f2f54SBarry Smith   if (nz < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %d",nz);
9468cdf2d9bSBarry Smith   if (nnz) {
947d0f46423SBarry Smith     for (i=0; i<A->rmap->n/bs; i++) {
948e32f2f54SBarry 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]);
949e32f2f54SBarry 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);
9508cdf2d9bSBarry Smith     }
9518cdf2d9bSBarry Smith   }
952d0f46423SBarry Smith   A->rmap->bs = A->cmap->bs = bs;
953d0f46423SBarry Smith   bmat->mbs  = A->rmap->n/bs;
9548cdf2d9bSBarry Smith 
9558cdf2d9bSBarry Smith   ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,bs,PETSC_NULL,&bmat->right);CHKERRQ(ierr);
9568cdf2d9bSBarry Smith   ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,bs,PETSC_NULL,&bmat->middle);CHKERRQ(ierr);
9578cdf2d9bSBarry Smith   ierr = VecCreateSeq(PETSC_COMM_SELF,bs,&bmat->left);CHKERRQ(ierr);
9588cdf2d9bSBarry Smith 
9592ee49352SLisandro Dalcin   if (!bmat->imax) {
960d0f46423SBarry Smith     ierr = PetscMalloc2(A->rmap->n,PetscInt,&bmat->imax,A->rmap->n,PetscInt,&bmat->ilen);CHKERRQ(ierr);
961d0f46423SBarry Smith     ierr = PetscLogObjectMemory(A,2*A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
9622ee49352SLisandro Dalcin   }
9638cdf2d9bSBarry Smith   if (nnz) {
9648cdf2d9bSBarry Smith     nz = 0;
965d0f46423SBarry Smith     for (i=0; i<A->rmap->n/A->rmap->bs; i++) {
9668cdf2d9bSBarry Smith       bmat->imax[i] = nnz[i];
9678cdf2d9bSBarry Smith       nz           += nnz[i];
9688cdf2d9bSBarry Smith     }
9698cdf2d9bSBarry Smith   } else {
970e32f2f54SBarry Smith     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Currently requires block row by row preallocation");
9718cdf2d9bSBarry Smith   }
9728cdf2d9bSBarry Smith 
9738cdf2d9bSBarry Smith   /* bmat->ilen will count nonzeros in each row so far. */
9748cdf2d9bSBarry Smith   for (i=0; i<bmat->mbs; i++) { bmat->ilen[i] = 0;}
9758cdf2d9bSBarry Smith 
9768cdf2d9bSBarry Smith   /* allocate the matrix space */
9772ee49352SLisandro Dalcin   ierr = MatSeqXAIJFreeAIJ(A,(PetscScalar**)&bmat->a,&bmat->j,&bmat->i);CHKERRQ(ierr);
978d0f46423SBarry Smith   ierr = PetscMalloc3(nz,Mat,&bmat->a,nz,PetscInt,&bmat->j,A->rmap->n+1,PetscInt,&bmat->i);CHKERRQ(ierr);
979d0f46423SBarry Smith   ierr = PetscLogObjectMemory(A,(A->rmap->n+1)*sizeof(PetscInt)+nz*(sizeof(PetscScalar)+sizeof(PetscInt)));CHKERRQ(ierr);
9808cdf2d9bSBarry Smith   bmat->i[0] = 0;
9818cdf2d9bSBarry Smith   for (i=1; i<bmat->mbs+1; i++) {
9828cdf2d9bSBarry Smith     bmat->i[i] = bmat->i[i-1] + bmat->imax[i-1];
9838cdf2d9bSBarry Smith   }
9848cdf2d9bSBarry Smith   bmat->singlemalloc = PETSC_TRUE;
9858cdf2d9bSBarry Smith   bmat->free_a       = PETSC_TRUE;
9868cdf2d9bSBarry Smith   bmat->free_ij      = PETSC_TRUE;
9878cdf2d9bSBarry Smith 
9888cdf2d9bSBarry Smith   bmat->nz                = 0;
9898cdf2d9bSBarry Smith   bmat->maxnz             = nz;
9908cdf2d9bSBarry Smith   A->info.nz_unneeded  = (double)bmat->maxnz;
9918cdf2d9bSBarry Smith 
9928cdf2d9bSBarry Smith   PetscFunctionReturn(0);
9938cdf2d9bSBarry Smith }
9948cdf2d9bSBarry Smith EXTERN_C_END
9958cdf2d9bSBarry Smith 
996421e10b8SBarry Smith /*MC
997421e10b8SBarry Smith    MATBLOCKMAT - A matrix that is defined by a set of Mat's that represents a sparse block matrix
998421e10b8SBarry Smith                  consisting of (usually) sparse blocks.
999421e10b8SBarry Smith 
1000421e10b8SBarry Smith   Level: advanced
1001421e10b8SBarry Smith 
1002421e10b8SBarry Smith .seealso: MatCreateBlockMat()
1003421e10b8SBarry Smith 
1004421e10b8SBarry Smith M*/
1005421e10b8SBarry Smith 
1006421e10b8SBarry Smith EXTERN_C_BEGIN
1007421e10b8SBarry Smith #undef __FUNCT__
1008421e10b8SBarry Smith #define __FUNCT__ "MatCreate_BlockMat"
10097087cfbeSBarry Smith PetscErrorCode  MatCreate_BlockMat(Mat A)
1010421e10b8SBarry Smith {
1011421e10b8SBarry Smith   Mat_BlockMat   *b;
1012421e10b8SBarry Smith   PetscErrorCode ierr;
1013421e10b8SBarry Smith 
1014421e10b8SBarry Smith   PetscFunctionBegin;
101538f2d2fdSLisandro Dalcin   ierr = PetscNewLog(A,Mat_BlockMat,&b);CHKERRQ(ierr);
1016421e10b8SBarry Smith   A->data = (void*)b;
101738f2d2fdSLisandro Dalcin   ierr = PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
1018421e10b8SBarry Smith 
1019421e10b8SBarry Smith   A->assembled     = PETSC_TRUE;
1020421e10b8SBarry Smith   A->preallocated  = PETSC_FALSE;
1021421e10b8SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)A,MATBLOCKMAT);CHKERRQ(ierr);
1022290bbb0aSBarry Smith 
10238cdf2d9bSBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatBlockMatSetPreallocation_C",
10248cdf2d9bSBarry Smith                                      "MatBlockMatSetPreallocation_BlockMat",
10258cdf2d9bSBarry Smith                                       MatBlockMatSetPreallocation_BlockMat);CHKERRQ(ierr);
10268cdf2d9bSBarry Smith 
1027421e10b8SBarry Smith   PetscFunctionReturn(0);
1028421e10b8SBarry Smith }
1029421e10b8SBarry Smith EXTERN_C_END
1030421e10b8SBarry Smith 
1031421e10b8SBarry Smith #undef __FUNCT__
1032421e10b8SBarry Smith #define __FUNCT__ "MatCreateBlockMat"
1033421e10b8SBarry Smith /*@C
1034421e10b8SBarry Smith    MatCreateBlockMat - Creates a new matrix based sparse Mat storage
1035421e10b8SBarry Smith 
1036421e10b8SBarry Smith   Collective on MPI_Comm
1037421e10b8SBarry Smith 
1038421e10b8SBarry Smith    Input Parameters:
1039421e10b8SBarry Smith +  comm - MPI communicator
1040421e10b8SBarry Smith .  m - number of rows
1041421e10b8SBarry Smith .  n  - number of columns
10428cdf2d9bSBarry Smith .  bs - size of each submatrix
10438cdf2d9bSBarry Smith .  nz  - expected maximum number of nonzero blocks in row (use PETSC_DEFAULT if not known)
10448cdf2d9bSBarry Smith -  nnz - expected number of nonzers per block row if known (use PETSC_NULL otherwise)
1045421e10b8SBarry Smith 
1046421e10b8SBarry Smith 
1047421e10b8SBarry Smith    Output Parameter:
1048421e10b8SBarry Smith .  A - the matrix
1049421e10b8SBarry Smith 
1050421e10b8SBarry Smith    Level: intermediate
1051421e10b8SBarry Smith 
1052421e10b8SBarry Smith    PETSc requires that matrices and vectors being used for certain
1053421e10b8SBarry Smith    operations are partitioned accordingly.  For example, when
1054421e10b8SBarry Smith    creating a bmat matrix, A, that supports parallel matrix-vector
1055421e10b8SBarry Smith    products using MatMult(A,x,y) the user should set the number
1056421e10b8SBarry Smith    of local matrix rows to be the number of local elements of the
1057421e10b8SBarry Smith    corresponding result vector, y. Note that this is information is
1058421e10b8SBarry Smith    required for use of the matrix interface routines, even though
1059421e10b8SBarry Smith    the bmat matrix may not actually be physically partitioned.
1060421e10b8SBarry Smith    For example,
1061421e10b8SBarry Smith 
1062421e10b8SBarry Smith .keywords: matrix, bmat, create
1063421e10b8SBarry Smith 
1064421e10b8SBarry Smith .seealso: MATBLOCKMAT
1065421e10b8SBarry Smith @*/
10667087cfbeSBarry Smith PetscErrorCode  MatCreateBlockMat(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt bs,PetscInt nz,PetscInt *nnz, Mat *A)
1067421e10b8SBarry Smith {
1068421e10b8SBarry Smith   PetscErrorCode ierr;
1069421e10b8SBarry Smith 
1070421e10b8SBarry Smith   PetscFunctionBegin;
1071421e10b8SBarry Smith   ierr = MatCreate(comm,A);CHKERRQ(ierr);
1072421e10b8SBarry Smith   ierr = MatSetSizes(*A,m,n,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
1073421e10b8SBarry Smith   ierr = MatSetType(*A,MATBLOCKMAT);CHKERRQ(ierr);
10748cdf2d9bSBarry Smith   ierr = MatBlockMatSetPreallocation(*A,bs,nz,nnz);CHKERRQ(ierr);
1075421e10b8SBarry Smith   PetscFunctionReturn(0);
1076421e10b8SBarry Smith }
1077421e10b8SBarry Smith 
1078421e10b8SBarry Smith 
1079421e10b8SBarry Smith 
1080