xref: /petsc/src/mat/impls/blockmat/seq/blockmat.c (revision 8cdf2d9bd607131c51052d6a01f20bc8fd4d7d21)
1421e10b8SBarry Smith #define PETSCMAT_DLL
2421e10b8SBarry Smith 
3421e10b8SBarry Smith /*
4421e10b8SBarry Smith    This provides a matrix that consists of Mats
5421e10b8SBarry Smith */
6421e10b8SBarry Smith 
7421e10b8SBarry Smith #include "src/mat/matimpl.h"              /*I "petscmat.h" I*/
8421e10b8SBarry Smith #include "src/mat/impls/baij/seq/baij.h"    /* use the common AIJ data-structure */
9ccb205f8SBarry Smith #include "petscksp.h"
10421e10b8SBarry Smith 
11421e10b8SBarry Smith #define CHUNKSIZE   15
12421e10b8SBarry Smith 
13421e10b8SBarry Smith typedef struct {
14421e10b8SBarry Smith   SEQAIJHEADER(Mat);
15421e10b8SBarry Smith   SEQBAIJHEADER;
16ccb205f8SBarry Smith   Mat               *diags;
17421e10b8SBarry Smith 
186e63c7a1SBarry Smith   Vec               left,right,middle,workb;   /* dummy vectors to perform local parts of product */
19421e10b8SBarry Smith } Mat_BlockMat;
20421e10b8SBarry Smith 
21421e10b8SBarry Smith #undef __FUNCT__
22290bbb0aSBarry Smith #define __FUNCT__ "MatRelax_BlockMat_Symmetric"
23290bbb0aSBarry Smith PetscErrorCode MatRelax_BlockMat_Symmetric(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx)
24290bbb0aSBarry Smith {
25290bbb0aSBarry Smith   Mat_BlockMat       *a = (Mat_BlockMat*)A->data;
26290bbb0aSBarry Smith   PetscScalar        *x;
27290bbb0aSBarry Smith   const Mat          *v = a->a;
28290bbb0aSBarry Smith   const PetscScalar  *b;
29290bbb0aSBarry Smith   PetscErrorCode     ierr;
30290bbb0aSBarry Smith   PetscInt           n = A->cmap.n,i,mbs = n/A->rmap.bs,j,bs = A->rmap.bs;
31290bbb0aSBarry Smith   const PetscInt     *idx;
32290bbb0aSBarry Smith   IS                 row,col;
33290bbb0aSBarry Smith   MatFactorInfo      info;
346e63c7a1SBarry Smith   Vec                left = a->left,right = a->right, middle = a->middle;
35290bbb0aSBarry Smith   Mat                *diag;
36290bbb0aSBarry Smith 
37290bbb0aSBarry Smith   PetscFunctionBegin;
38290bbb0aSBarry Smith   its = its*lits;
39290bbb0aSBarry Smith   if (its <= 0) SETERRQ2(PETSC_ERR_ARG_WRONG,"Relaxation requires global its %D and local its %D both positive",its,lits);
40290bbb0aSBarry Smith   if (flag & SOR_EISENSTAT) SETERRQ(PETSC_ERR_SUP,"No support yet for Eisenstat");
41290bbb0aSBarry Smith   if (omega != 1.0) SETERRQ(PETSC_ERR_SUP,"No support yet for omega not equal to 1.0");
42290bbb0aSBarry Smith   if (fshift) SETERRQ(PETSC_ERR_SUP,"No support yet for fshift");
43290bbb0aSBarry Smith   if ((flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) && !(flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP))
44290bbb0aSBarry Smith     SETERRQ(PETSC_ERR_SUP,"Cannot do backward sweep without forward sweep");
45290bbb0aSBarry Smith 
46290bbb0aSBarry Smith   if (!a->diags) {
47290bbb0aSBarry Smith     ierr = PetscMalloc(mbs*sizeof(Mat),&a->diags);CHKERRQ(ierr);
48290bbb0aSBarry Smith     ierr = MatFactorInfoInitialize(&info);CHKERRQ(ierr);
49290bbb0aSBarry Smith     for (i=0; i<mbs; i++) {
50290bbb0aSBarry Smith       ierr = MatGetOrdering(a->a[a->diag[i]], MATORDERING_ND,&row,&col);CHKERRQ(ierr);
516e63c7a1SBarry Smith       ierr = MatCholeskyFactorSymbolic(a->a[a->diag[i]],row,&info,a->diags+i);CHKERRQ(ierr);
526e63c7a1SBarry Smith       ierr = MatCholeskyFactorNumeric(a->a[a->diag[i]],&info,a->diags+i);CHKERRQ(ierr);
53290bbb0aSBarry Smith       ierr = ISDestroy(row);CHKERRQ(ierr);
54290bbb0aSBarry Smith       ierr = ISDestroy(col);CHKERRQ(ierr);
55290bbb0aSBarry Smith     }
566e63c7a1SBarry Smith     ierr = VecDuplicate(bb,&a->workb);CHKERRQ(ierr);
57290bbb0aSBarry Smith   }
58290bbb0aSBarry Smith   diag    = a->diags;
59290bbb0aSBarry Smith 
60290bbb0aSBarry Smith   ierr = VecSet(xx,0.0);CHKERRQ(ierr);
61290bbb0aSBarry Smith   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
62290bbb0aSBarry Smith   /* copy right hand side because it must be modified during iteration */
636e63c7a1SBarry Smith   ierr = VecCopy(bb,a->workb);CHKERRQ(ierr);
646e63c7a1SBarry Smith   ierr = VecGetArray(a->workb,(PetscScalar**)&b);CHKERRQ(ierr);
65290bbb0aSBarry Smith 
66290bbb0aSBarry Smith   /* need to add code for when initial guess is zero, see MatRelax_SeqAIJ */
67290bbb0aSBarry Smith   while (its--) {
68290bbb0aSBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){
69290bbb0aSBarry Smith 
70290bbb0aSBarry Smith       for (i=0; i<mbs; i++) {
716e63c7a1SBarry Smith         n    = a->i[i+1] - a->i[i] - 1;
726e63c7a1SBarry Smith         idx  = a->j + a->i[i] + 1;
736e63c7a1SBarry Smith         v    = a->a + a->i[i] + 1;
74290bbb0aSBarry Smith 
75290bbb0aSBarry Smith         ierr = VecSet(left,0.0);CHKERRQ(ierr);
76290bbb0aSBarry Smith         for (j=0; j<n; j++) {
77290bbb0aSBarry Smith           ierr = VecPlaceArray(right,x + idx[j]*bs);CHKERRQ(ierr);
78290bbb0aSBarry Smith           ierr = MatMultAdd(v[j],right,left,left);CHKERRQ(ierr);
79290bbb0aSBarry Smith           ierr = VecResetArray(right);CHKERRQ(ierr);
80290bbb0aSBarry Smith         }
81290bbb0aSBarry Smith         ierr = VecPlaceArray(right,b + i*bs);CHKERRQ(ierr);
82290bbb0aSBarry Smith         ierr = VecAYPX(left,-1.0,right);CHKERRQ(ierr);
83290bbb0aSBarry Smith         ierr = VecResetArray(right);CHKERRQ(ierr);
84290bbb0aSBarry Smith 
85290bbb0aSBarry Smith         ierr = VecPlaceArray(right,x + i*bs);CHKERRQ(ierr);
86290bbb0aSBarry Smith         ierr = MatSolve(diag[i],left,right);CHKERRQ(ierr);
876e63c7a1SBarry Smith 
886e63c7a1SBarry Smith         /* now adjust right hand side, see MatRelax_SeqSBAIJ */
896e63c7a1SBarry Smith         for (j=0; j<n; j++) {
906e63c7a1SBarry Smith           ierr = MatMultTranspose(v[j],right,left);CHKERRQ(ierr);
916e63c7a1SBarry Smith           ierr = VecPlaceArray(middle,b + idx[j]*bs);CHKERRQ(ierr);
926e63c7a1SBarry Smith           ierr = VecAXPY(middle,-1.0,left);CHKERRQ(ierr);
936e63c7a1SBarry Smith           ierr = VecResetArray(middle);CHKERRQ(ierr);
946e63c7a1SBarry Smith         }
95290bbb0aSBarry Smith         ierr = VecResetArray(right);CHKERRQ(ierr);
966e63c7a1SBarry Smith 
97290bbb0aSBarry Smith       }
98290bbb0aSBarry Smith     }
99290bbb0aSBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){
100290bbb0aSBarry Smith 
101290bbb0aSBarry Smith       for (i=mbs-1; i>=0; i--) {
1026e63c7a1SBarry Smith         n    = a->i[i+1] - a->i[i] - 1;
1036e63c7a1SBarry Smith         idx  = a->j + a->i[i] + 1;
1046e63c7a1SBarry Smith         v    = a->a + a->i[i] + 1;
105290bbb0aSBarry Smith 
106290bbb0aSBarry Smith         ierr = VecSet(left,0.0);CHKERRQ(ierr);
107290bbb0aSBarry Smith         for (j=0; j<n; j++) {
108290bbb0aSBarry Smith           ierr = VecPlaceArray(right,x + idx[j]*bs);CHKERRQ(ierr);
109290bbb0aSBarry Smith           ierr = MatMultAdd(v[j],right,left,left);CHKERRQ(ierr);
110290bbb0aSBarry Smith           ierr = VecResetArray(right);CHKERRQ(ierr);
111290bbb0aSBarry Smith         }
112290bbb0aSBarry Smith         ierr = VecPlaceArray(right,b + i*bs);CHKERRQ(ierr);
113290bbb0aSBarry Smith         ierr = VecAYPX(left,-1.0,right);CHKERRQ(ierr);
114290bbb0aSBarry Smith         ierr = VecResetArray(right);CHKERRQ(ierr);
115290bbb0aSBarry Smith 
116290bbb0aSBarry Smith         ierr = VecPlaceArray(right,x + i*bs);CHKERRQ(ierr);
117290bbb0aSBarry Smith         ierr = MatSolve(diag[i],left,right);CHKERRQ(ierr);
118290bbb0aSBarry Smith         ierr = VecResetArray(right);CHKERRQ(ierr);
119290bbb0aSBarry Smith 
120290bbb0aSBarry Smith       }
121290bbb0aSBarry Smith     }
122290bbb0aSBarry Smith   }
123290bbb0aSBarry Smith   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
1246e63c7a1SBarry Smith   ierr = VecRestoreArray(a->workb,(PetscScalar**)&b);CHKERRQ(ierr);
125290bbb0aSBarry Smith   PetscFunctionReturn(0);
126290bbb0aSBarry Smith }
127290bbb0aSBarry Smith 
128290bbb0aSBarry Smith #undef __FUNCT__
129ccb205f8SBarry Smith #define __FUNCT__ "MatRelax_BlockMat"
130ccb205f8SBarry Smith PetscErrorCode MatRelax_BlockMat(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx)
131ccb205f8SBarry Smith {
132ccb205f8SBarry Smith   Mat_BlockMat       *a = (Mat_BlockMat*)A->data;
133ccb205f8SBarry Smith   PetscScalar        *x;
134ccb205f8SBarry Smith   const Mat          *v = a->a;
135ccb205f8SBarry Smith   const PetscScalar  *b;
136ccb205f8SBarry Smith   PetscErrorCode     ierr;
137ccb205f8SBarry Smith   PetscInt           n = A->cmap.n,i,mbs = n/A->rmap.bs,j,bs = A->rmap.bs;
138ccb205f8SBarry Smith   const PetscInt     *idx;
139ccb205f8SBarry Smith   IS                 row,col;
140ccb205f8SBarry Smith   MatFactorInfo      info;
141ccb205f8SBarry Smith   Vec                left = a->left,right = a->right;
142ccb205f8SBarry Smith   Mat                *diag;
143ccb205f8SBarry Smith 
144ccb205f8SBarry Smith   PetscFunctionBegin;
145ccb205f8SBarry Smith   its = its*lits;
146ccb205f8SBarry Smith   if (its <= 0) SETERRQ2(PETSC_ERR_ARG_WRONG,"Relaxation requires global its %D and local its %D both positive",its,lits);
147ccb205f8SBarry Smith   if (flag & SOR_EISENSTAT) SETERRQ(PETSC_ERR_SUP,"No support yet for Eisenstat");
148ccb205f8SBarry Smith   if (omega != 1.0) SETERRQ(PETSC_ERR_SUP,"No support yet for omega not equal to 1.0");
149ccb205f8SBarry Smith   if (fshift) SETERRQ(PETSC_ERR_SUP,"No support yet for fshift");
150ccb205f8SBarry Smith 
151ccb205f8SBarry Smith   if (!a->diags) {
152ccb205f8SBarry Smith     ierr = PetscMalloc(mbs*sizeof(Mat),&a->diags);CHKERRQ(ierr);
153ccb205f8SBarry Smith     ierr = MatFactorInfoInitialize(&info);CHKERRQ(ierr);
154ccb205f8SBarry Smith     for (i=0; i<mbs; i++) {
155ccb205f8SBarry Smith       ierr = MatGetOrdering(a->a[a->diag[i]], MATORDERING_ND,&row,&col);CHKERRQ(ierr);
156ccb205f8SBarry Smith       ierr = MatLUFactorSymbolic(a->a[a->diag[i]],row,col,&info,a->diags+i);CHKERRQ(ierr);
157ccb205f8SBarry Smith       ierr = MatLUFactorNumeric(a->a[a->diag[i]],&info,a->diags+i);CHKERRQ(ierr);
158ccb205f8SBarry Smith       ierr = ISDestroy(row);CHKERRQ(ierr);
159ccb205f8SBarry Smith       ierr = ISDestroy(col);CHKERRQ(ierr);
160ccb205f8SBarry Smith     }
161ccb205f8SBarry Smith   }
162ccb205f8SBarry Smith   diag = a->diags;
163ccb205f8SBarry Smith 
164ccb205f8SBarry Smith   ierr = VecSet(xx,0.0);CHKERRQ(ierr);
165ccb205f8SBarry Smith   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
166ccb205f8SBarry Smith   ierr = VecGetArray(bb,(PetscScalar**)&b);CHKERRQ(ierr);
167ccb205f8SBarry Smith 
168ccb205f8SBarry Smith   /* need to add code for when initial guess is zero, see MatRelax_SeqAIJ */
169ccb205f8SBarry Smith   while (its--) {
170ccb205f8SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){
171ccb205f8SBarry Smith 
172ccb205f8SBarry Smith       for (i=0; i<mbs; i++) {
173ccb205f8SBarry Smith         n    = a->i[i+1] - a->i[i];
174ccb205f8SBarry Smith         idx  = a->j + a->i[i];
175ccb205f8SBarry Smith         v    = a->a + a->i[i];
176ccb205f8SBarry Smith 
177ccb205f8SBarry Smith         ierr = VecSet(left,0.0);CHKERRQ(ierr);
178ccb205f8SBarry Smith         for (j=0; j<n; j++) {
179ccb205f8SBarry Smith           if (idx[j] != i) {
180ccb205f8SBarry Smith             ierr = VecPlaceArray(right,x + idx[j]*bs);CHKERRQ(ierr);
181ccb205f8SBarry Smith             ierr = MatMultAdd(v[j],right,left,left);CHKERRQ(ierr);
182ccb205f8SBarry Smith             ierr = VecResetArray(right);CHKERRQ(ierr);
183ccb205f8SBarry Smith           }
184ccb205f8SBarry Smith         }
185ccb205f8SBarry Smith         ierr = VecPlaceArray(right,b + i*bs);CHKERRQ(ierr);
186ccb205f8SBarry Smith         ierr = VecAYPX(left,-1.0,right);CHKERRQ(ierr);
187ccb205f8SBarry Smith         ierr = VecResetArray(right);CHKERRQ(ierr);
188ccb205f8SBarry Smith 
189ccb205f8SBarry Smith         ierr = VecPlaceArray(right,x + i*bs);CHKERRQ(ierr);
190ccb205f8SBarry Smith         ierr = MatSolve(diag[i],left,right);CHKERRQ(ierr);
191ccb205f8SBarry Smith         ierr = VecResetArray(right);CHKERRQ(ierr);
192ccb205f8SBarry Smith       }
193ccb205f8SBarry Smith     }
194ccb205f8SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){
195ccb205f8SBarry Smith 
196ccb205f8SBarry Smith       for (i=mbs-1; i>=0; i--) {
197ccb205f8SBarry Smith         n    = a->i[i+1] - a->i[i];
198ccb205f8SBarry Smith         idx  = a->j + a->i[i];
199ccb205f8SBarry Smith         v    = a->a + a->i[i];
200ccb205f8SBarry Smith 
201ccb205f8SBarry Smith         ierr = VecSet(left,0.0);CHKERRQ(ierr);
202ccb205f8SBarry Smith         for (j=0; j<n; j++) {
203ccb205f8SBarry Smith           if (idx[j] != i) {
204ccb205f8SBarry Smith             ierr = VecPlaceArray(right,x + idx[j]*bs);CHKERRQ(ierr);
205ccb205f8SBarry Smith             ierr = MatMultAdd(v[j],right,left,left);CHKERRQ(ierr);
206ccb205f8SBarry Smith             ierr = VecResetArray(right);CHKERRQ(ierr);
207ccb205f8SBarry Smith           }
208ccb205f8SBarry Smith         }
209ccb205f8SBarry Smith         ierr = VecPlaceArray(right,b + i*bs);CHKERRQ(ierr);
210ccb205f8SBarry Smith         ierr = VecAYPX(left,-1.0,right);CHKERRQ(ierr);
211ccb205f8SBarry Smith         ierr = VecResetArray(right);CHKERRQ(ierr);
212ccb205f8SBarry Smith 
213ccb205f8SBarry Smith         ierr = VecPlaceArray(right,x + i*bs);CHKERRQ(ierr);
214ccb205f8SBarry Smith         ierr = MatSolve(diag[i],left,right);CHKERRQ(ierr);
215ccb205f8SBarry Smith         ierr = VecResetArray(right);CHKERRQ(ierr);
216ccb205f8SBarry Smith 
217ccb205f8SBarry Smith       }
218ccb205f8SBarry Smith     }
219ccb205f8SBarry Smith   }
220ccb205f8SBarry Smith   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
221ccb205f8SBarry Smith   ierr = VecRestoreArray(bb,(PetscScalar**)&b);CHKERRQ(ierr);
222ccb205f8SBarry Smith   PetscFunctionReturn(0);
223ccb205f8SBarry Smith }
224ccb205f8SBarry Smith 
225ccb205f8SBarry Smith #undef __FUNCT__
226421e10b8SBarry Smith #define __FUNCT__ "MatSetValues_BlockMat"
227421e10b8SBarry Smith PetscErrorCode MatSetValues_BlockMat(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
228421e10b8SBarry Smith {
229421e10b8SBarry Smith   Mat_BlockMat   *a = (Mat_BlockMat*)A->data;
230421e10b8SBarry Smith   PetscInt       *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N,lastcol = -1;
231421e10b8SBarry Smith   PetscInt       *imax=a->imax,*ai=a->i,*ailen=a->ilen;
232421e10b8SBarry Smith   PetscInt       *aj=a->j,nonew=a->nonew,bs=A->rmap.bs,brow,bcol;
233421e10b8SBarry Smith   PetscErrorCode ierr;
234421e10b8SBarry Smith   PetscInt       ridx,cidx;
235421e10b8SBarry Smith   PetscTruth     roworiented=a->roworiented;
236421e10b8SBarry Smith   MatScalar      value;
237421e10b8SBarry Smith   Mat            *ap,*aa = a->a;
238421e10b8SBarry Smith 
239421e10b8SBarry Smith   PetscFunctionBegin;
240421e10b8SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
241421e10b8SBarry Smith     row  = im[k];
242421e10b8SBarry Smith     brow = row/bs;
243421e10b8SBarry Smith     if (row < 0) continue;
244421e10b8SBarry Smith #if defined(PETSC_USE_DEBUG)
245421e10b8SBarry Smith     if (row >= A->rmap.N) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",row,A->rmap.N-1);
246421e10b8SBarry Smith #endif
247421e10b8SBarry Smith     rp   = aj + ai[brow];
248421e10b8SBarry Smith     ap   = aa + ai[brow];
249421e10b8SBarry Smith     rmax = imax[brow];
250421e10b8SBarry Smith     nrow = ailen[brow];
251421e10b8SBarry Smith     low  = 0;
252421e10b8SBarry Smith     high = nrow;
253421e10b8SBarry Smith     for (l=0; l<n; l++) { /* loop over added columns */
254421e10b8SBarry Smith       if (in[l] < 0) continue;
255421e10b8SBarry Smith #if defined(PETSC_USE_DEBUG)
256421e10b8SBarry Smith       if (in[l] >= A->cmap.n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",in[l],A->cmap.n-1);
257421e10b8SBarry Smith #endif
258421e10b8SBarry Smith       col = in[l]; bcol = col/bs;
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) {
276ccb205f8SBarry Smith 	  /*          printf("row %d col %d found i %d\n",brow,bcol,i);*/
277421e10b8SBarry Smith           goto noinsert1;
278421e10b8SBarry Smith         }
279421e10b8SBarry Smith       }
280421e10b8SBarry Smith       if (nonew == 1) goto noinsert1;
281421e10b8SBarry Smith       if (nonew == -1) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero (%D, %D) in the matrix", row, col);
282421e10b8SBarry Smith       MatSeqXAIJReallocateAIJ(A,a->mbs,1,nrow,brow,bcol,rmax,aa,ai,aj,rp,ap,imax,nonew,Mat);
283421e10b8SBarry Smith       N = nrow++ - 1; high++;
284421e10b8SBarry Smith       /* shift up all the later entries in this row */
285ccb205f8SBarry Smith       /*      printf("N %d i %d\n",N,i);*/
286421e10b8SBarry Smith       for (ii=N; ii>=i; ii--) {
287421e10b8SBarry Smith         rp[ii+1] = rp[ii];
288421e10b8SBarry Smith         ap[ii+1] = ap[ii];
289421e10b8SBarry Smith       }
290421e10b8SBarry Smith       if (N>=i) ap[i] = 0;
291421e10b8SBarry Smith       rp[i]           = bcol;
292421e10b8SBarry Smith       a->nz++;
293421e10b8SBarry Smith       noinsert1:;
294421e10b8SBarry Smith       if (!*(ap+i)) {
295ccb205f8SBarry Smith 	/*        printf("create matrix at i %d rw %d col %d\n",i,brow,bcol);*/
296b0223207SBarry Smith         if (A->symmetric && brow == bcol) {
2976e63c7a1SBarry Smith           /* don't use SBAIJ since want to reorder in sparse factorization */
2986e63c7a1SBarry Smith           ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,bs,bs,0,0,ap+i);CHKERRQ(ierr);
299b0223207SBarry Smith         } else {
300421e10b8SBarry Smith           ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,bs,bs,0,0,ap+i);CHKERRQ(ierr);
301421e10b8SBarry Smith         }
302b0223207SBarry Smith       }
303ccb205f8SBarry Smith       /*      printf("numerical value at i %d row %d col %d cidx %d ridx %d value %g\n",i,brow,bcol,cidx,ridx,value);*/
304421e10b8SBarry Smith       ierr = MatSetValues(ap[i],1,&ridx,1,&cidx,&value,is);CHKERRQ(ierr);
305421e10b8SBarry Smith       low = i;
306421e10b8SBarry Smith     }
307ccb205f8SBarry Smith     /*    printf("nrow for row %d %d\n",nrow,brow);*/
308421e10b8SBarry Smith     ailen[brow] = nrow;
309421e10b8SBarry Smith   }
310421e10b8SBarry Smith   A->same_nonzero = PETSC_FALSE;
311421e10b8SBarry Smith   PetscFunctionReturn(0);
312421e10b8SBarry Smith }
313421e10b8SBarry Smith 
314421e10b8SBarry Smith #undef __FUNCT__
315421e10b8SBarry Smith #define __FUNCT__ "MatLoad_BlockMat"
316421e10b8SBarry Smith PetscErrorCode MatLoad_BlockMat(PetscViewer viewer, MatType type,Mat *A)
317421e10b8SBarry Smith {
318421e10b8SBarry Smith   PetscErrorCode    ierr;
319421e10b8SBarry Smith   Mat               tmpA;
320*8cdf2d9bSBarry Smith   PetscInt          i,j,m,n,bs = 1,ncols,*lens,currentcol,mbs,**ii,*ilens,nextcol;
321421e10b8SBarry Smith   const PetscInt    *cols;
322421e10b8SBarry Smith   const PetscScalar *values;
323*8cdf2d9bSBarry Smith   PetscTruth        flg,notdone;
324*8cdf2d9bSBarry Smith   Mat_SeqAIJ        *a;
325421e10b8SBarry Smith 
326421e10b8SBarry Smith   PetscFunctionBegin;
327421e10b8SBarry Smith   ierr = MatLoad_SeqAIJ(viewer,MATSEQAIJ,&tmpA);CHKERRQ(ierr);
328421e10b8SBarry Smith 
329421e10b8SBarry Smith   ierr = MatGetLocalSize(tmpA,&m,&n);CHKERRQ(ierr);
33077925062SSatish Balay   ierr = PetscOptionsBegin(PETSC_COMM_SELF,PETSC_NULL,"Options for loading BlockMat matrix 1","Mat");CHKERRQ(ierr);
331421e10b8SBarry Smith     ierr = PetscOptionsInt("-matload_block_size","Set the blocksize used to store the matrix","MatLoad",bs,&bs,PETSC_NULL);CHKERRQ(ierr);
332290bbb0aSBarry Smith     ierr = PetscOptionsName("-matload_symmetric","Store the matrix as symmetric","MatLoad",&flg);CHKERRQ(ierr);
333*8cdf2d9bSBarry Smith   ierr = PetscOptionsEnd();CHKERRQ(ierr);
334*8cdf2d9bSBarry Smith 
335*8cdf2d9bSBarry Smith   a    = (Mat_SeqAIJ*) tmpA->data;
336*8cdf2d9bSBarry Smith   mbs  = m/bs;
337*8cdf2d9bSBarry Smith   ierr = PetscMalloc3(mbs,PetscInt,&lens,bs,PetscInt,&ii,bs,PetscInt,&ilens);CHKERRQ(ierr);
338*8cdf2d9bSBarry Smith   ierr = PetscMemzero(lens,mbs*sizeof(PetscInt));CHKERRQ(ierr);
339*8cdf2d9bSBarry Smith 
340*8cdf2d9bSBarry Smith   for (i=0; i<mbs; i++) {
341*8cdf2d9bSBarry Smith     for (j=0; j<bs; j++) {
342*8cdf2d9bSBarry Smith       currentcol    = -1;
343*8cdf2d9bSBarry Smith       CHKMEMQ;
344*8cdf2d9bSBarry Smith       ii[j]         = a->j + a->i[i*bs + j];
345*8cdf2d9bSBarry Smith       CHKMEMQ;
346*8cdf2d9bSBarry Smith       ilens[j]      = a->i[i*bs + j + 1] - a->i[i*bs + j];
347*8cdf2d9bSBarry Smith       CHKMEMQ;
348*8cdf2d9bSBarry Smith       /*      printf("j %d length %d\n",j,ilens[j]);*/
349*8cdf2d9bSBarry Smith     }
350*8cdf2d9bSBarry Smith     notdone = PETSC_TRUE;
351*8cdf2d9bSBarry Smith     while (PETSC_TRUE) {
352*8cdf2d9bSBarry Smith       notdone = PETSC_FALSE;
353*8cdf2d9bSBarry Smith       nextcol = 1000000000;
354*8cdf2d9bSBarry Smith       for (j=0; j<bs; j++) {
355*8cdf2d9bSBarry Smith 	/*	printf("loop j %d length %d\n",j,ilens[j]); */
356*8cdf2d9bSBarry Smith         while ((ii[j][0]/bs <= currentcol && ilens[j] > 0) || (flg && ii[j][0]/bs < i)) {
357*8cdf2d9bSBarry Smith           ii[j]++;
358*8cdf2d9bSBarry Smith       CHKMEMQ;
359*8cdf2d9bSBarry Smith           ilens[j]--;
360*8cdf2d9bSBarry Smith       CHKMEMQ;
361*8cdf2d9bSBarry Smith         }
362*8cdf2d9bSBarry Smith         if (ilens[j] > 0) {
363*8cdf2d9bSBarry Smith           notdone = PETSC_TRUE;
364*8cdf2d9bSBarry Smith           nextcol = PetscMin(nextcol,ii[j][0]/bs);
365*8cdf2d9bSBarry Smith         }
366*8cdf2d9bSBarry Smith       }
367*8cdf2d9bSBarry Smith       if (!notdone) break;
368*8cdf2d9bSBarry Smith       currentcol = nextcol;
369*8cdf2d9bSBarry Smith       CHKMEMQ;
370*8cdf2d9bSBarry Smith       lens[i]++;
371*8cdf2d9bSBarry Smith       CHKMEMQ;
372*8cdf2d9bSBarry Smith     }
373*8cdf2d9bSBarry Smith     /*    printf("len of i %d %d\n",i,lens[i]);*/
374*8cdf2d9bSBarry Smith   }
375*8cdf2d9bSBarry Smith       CHKMEMQ;
376*8cdf2d9bSBarry Smith 
377*8cdf2d9bSBarry Smith   ierr = MatCreateBlockMat(PETSC_COMM_SELF,m,n,bs,0,lens,A);CHKERRQ(ierr);
378*8cdf2d9bSBarry Smith   ierr = PetscFree3(lens,ii,ilens);CHKERRQ(ierr);
379290bbb0aSBarry Smith   if (flg) {
380290bbb0aSBarry Smith     ierr = MatSetOption(*A,MAT_SYMMETRIC);CHKERRQ(ierr);
381290bbb0aSBarry Smith   }
382421e10b8SBarry Smith   for (i=0; i<m; i++) {
383421e10b8SBarry Smith     ierr = MatGetRow(tmpA,i,&ncols,&cols,&values);CHKERRQ(ierr);
384421e10b8SBarry Smith     ierr = MatSetValues(*A,1,&i,ncols,cols,values,INSERT_VALUES);CHKERRQ(ierr);
385ccb205f8SBarry Smith     ierr = MatRestoreRow(tmpA,i,&ncols,&cols,&values);CHKERRQ(ierr);
386421e10b8SBarry Smith   }
387421e10b8SBarry Smith   ierr = MatAssemblyBegin(*A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
388421e10b8SBarry Smith   ierr = MatAssemblyEnd(*A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
389421e10b8SBarry Smith   PetscFunctionReturn(0);
390421e10b8SBarry Smith }
391421e10b8SBarry Smith 
392ccb205f8SBarry Smith #undef __FUNCT__
393ccb205f8SBarry Smith #define __FUNCT__ "MatView_BlockMat"
394ccb205f8SBarry Smith PetscErrorCode MatView_BlockMat(Mat A,PetscViewer viewer)
395ccb205f8SBarry Smith {
396ccb205f8SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
397ccb205f8SBarry Smith   PetscErrorCode    ierr;
398ccb205f8SBarry Smith   const char        *name;
399ccb205f8SBarry Smith   PetscViewerFormat format;
400ccb205f8SBarry Smith 
401ccb205f8SBarry Smith   PetscFunctionBegin;
402ccb205f8SBarry Smith   ierr = PetscObjectGetName((PetscObject)A,&name);CHKERRQ(ierr);
403ccb205f8SBarry Smith   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
404ccb205f8SBarry Smith   if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO) {
405ccb205f8SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Nonzero block matrices = %D \n",a->nz);CHKERRQ(ierr);
406ccb205f8SBarry Smith   }
407ccb205f8SBarry Smith   PetscFunctionReturn(0);
408ccb205f8SBarry Smith }
409421e10b8SBarry Smith 
410421e10b8SBarry Smith #undef __FUNCT__
411421e10b8SBarry Smith #define __FUNCT__ "MatDestroy_BlockMat"
412421e10b8SBarry Smith PetscErrorCode MatDestroy_BlockMat(Mat mat)
413421e10b8SBarry Smith {
414421e10b8SBarry Smith   PetscErrorCode ierr;
415421e10b8SBarry Smith   Mat_BlockMat   *bmat = (Mat_BlockMat*)mat->data;
416ccb205f8SBarry Smith   PetscInt       i;
417421e10b8SBarry Smith 
418421e10b8SBarry Smith   PetscFunctionBegin;
419421e10b8SBarry Smith   if (bmat->right) {
420421e10b8SBarry Smith     ierr = VecDestroy(bmat->right);CHKERRQ(ierr);
421421e10b8SBarry Smith   }
422421e10b8SBarry Smith   if (bmat->left) {
423421e10b8SBarry Smith     ierr = VecDestroy(bmat->left);CHKERRQ(ierr);
424421e10b8SBarry Smith   }
425290bbb0aSBarry Smith   if (bmat->middle) {
426290bbb0aSBarry Smith     ierr = VecDestroy(bmat->middle);CHKERRQ(ierr);
427290bbb0aSBarry Smith   }
4286e63c7a1SBarry Smith   if (bmat->workb) {
4296e63c7a1SBarry Smith     ierr = VecDestroy(bmat->workb);CHKERRQ(ierr);
4306e63c7a1SBarry Smith   }
431ccb205f8SBarry Smith   if (bmat->diags) {
432ccb205f8SBarry Smith     for (i=0; i<mat->rmap.n/mat->rmap.bs; i++) {
433ccb205f8SBarry Smith       if (bmat->diags[i]) {ierr = MatDestroy(bmat->diags[i]);CHKERRQ(ierr);}
434ccb205f8SBarry Smith     }
435ccb205f8SBarry Smith   }
436ccb205f8SBarry Smith   if (bmat->a) {
437ccb205f8SBarry Smith     for (i=0; i<bmat->nz; i++) {
438ccb205f8SBarry Smith       if (bmat->a[i]) {ierr = MatDestroy(bmat->a[i]);CHKERRQ(ierr);}
439ccb205f8SBarry Smith     }
440ccb205f8SBarry Smith   }
441ccb205f8SBarry Smith   ierr = MatSeqXAIJFreeAIJ(mat,(PetscScalar**)&bmat->a,&bmat->j,&bmat->i);CHKERRQ(ierr);
442421e10b8SBarry Smith   ierr = PetscFree(bmat);CHKERRQ(ierr);
443421e10b8SBarry Smith   PetscFunctionReturn(0);
444421e10b8SBarry Smith }
445421e10b8SBarry Smith 
446421e10b8SBarry Smith #undef __FUNCT__
447421e10b8SBarry Smith #define __FUNCT__ "MatMult_BlockMat"
448421e10b8SBarry Smith PetscErrorCode MatMult_BlockMat(Mat A,Vec x,Vec y)
449421e10b8SBarry Smith {
450421e10b8SBarry Smith   Mat_BlockMat   *bmat = (Mat_BlockMat*)A->data;
451421e10b8SBarry Smith   PetscErrorCode ierr;
452421e10b8SBarry Smith   PetscScalar    *xx,*yy;
453421e10b8SBarry Smith   PetscInt       *aj,i,*ii,jrow,m = A->rmap.n/A->rmap.bs,bs = A->rmap.bs,n,j;
454421e10b8SBarry Smith   Mat            *aa;
455421e10b8SBarry Smith 
456421e10b8SBarry Smith   PetscFunctionBegin;
457ccb205f8SBarry Smith   CHKMEMQ;
458421e10b8SBarry Smith   /*
459421e10b8SBarry Smith      Standard CSR multiply except each entry is a Mat
460421e10b8SBarry Smith   */
461421e10b8SBarry Smith   ierr = VecGetArray(x,&xx);CHKERRQ(ierr);
462ccb205f8SBarry Smith 
463421e10b8SBarry Smith   ierr = VecSet(y,0.0);CHKERRQ(ierr);
464421e10b8SBarry Smith   ierr = VecGetArray(y,&yy);CHKERRQ(ierr);
465421e10b8SBarry Smith   aj  = bmat->j;
466421e10b8SBarry Smith   aa  = bmat->a;
467421e10b8SBarry Smith   ii  = bmat->i;
468421e10b8SBarry Smith   for (i=0; i<m; i++) {
469421e10b8SBarry Smith     jrow = ii[i];
470ccb205f8SBarry Smith     ierr = VecPlaceArray(bmat->left,yy + bs*i);CHKERRQ(ierr);
471421e10b8SBarry Smith     n    = ii[i+1] - jrow;
472421e10b8SBarry Smith     for (j=0; j<n; j++) {
473421e10b8SBarry Smith       ierr = VecPlaceArray(bmat->right,xx + bs*aj[jrow]);CHKERRQ(ierr);
474ccb205f8SBarry Smith       ierr = MatMultAdd(aa[jrow],bmat->right,bmat->left,bmat->left);CHKERRQ(ierr);
475421e10b8SBarry Smith       ierr = VecResetArray(bmat->right);CHKERRQ(ierr);
476421e10b8SBarry Smith       jrow++;
477421e10b8SBarry Smith     }
478421e10b8SBarry Smith     ierr = VecResetArray(bmat->left);CHKERRQ(ierr);
479421e10b8SBarry Smith   }
480421e10b8SBarry Smith   ierr = VecRestoreArray(x,&xx);CHKERRQ(ierr);
481421e10b8SBarry Smith   ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr);
482ccb205f8SBarry Smith   CHKMEMQ;
483421e10b8SBarry Smith   PetscFunctionReturn(0);
484421e10b8SBarry Smith }
485421e10b8SBarry Smith 
486421e10b8SBarry Smith #undef __FUNCT__
487290bbb0aSBarry Smith #define __FUNCT__ "MatMult_BlockMat_Symmetric"
488290bbb0aSBarry Smith PetscErrorCode MatMult_BlockMat_Symmetric(Mat A,Vec x,Vec y)
489290bbb0aSBarry Smith {
490290bbb0aSBarry Smith   Mat_BlockMat   *bmat = (Mat_BlockMat*)A->data;
491290bbb0aSBarry Smith   PetscErrorCode ierr;
492290bbb0aSBarry Smith   PetscScalar    *xx,*yy;
493290bbb0aSBarry Smith   PetscInt       *aj,i,*ii,jrow,m = A->rmap.n/A->rmap.bs,bs = A->rmap.bs,n,j;
494290bbb0aSBarry Smith   Mat            *aa;
495290bbb0aSBarry Smith 
496290bbb0aSBarry Smith   PetscFunctionBegin;
497290bbb0aSBarry Smith   CHKMEMQ;
498290bbb0aSBarry Smith   /*
499290bbb0aSBarry Smith      Standard CSR multiply except each entry is a Mat
500290bbb0aSBarry Smith   */
501290bbb0aSBarry Smith   ierr = VecGetArray(x,&xx);CHKERRQ(ierr);
502290bbb0aSBarry Smith 
503290bbb0aSBarry Smith   ierr = VecSet(y,0.0);CHKERRQ(ierr);
504290bbb0aSBarry Smith   ierr = VecGetArray(y,&yy);CHKERRQ(ierr);
505290bbb0aSBarry Smith   aj  = bmat->j;
506290bbb0aSBarry Smith   aa  = bmat->a;
507290bbb0aSBarry Smith   ii  = bmat->i;
508290bbb0aSBarry Smith   for (i=0; i<m; i++) {
509290bbb0aSBarry Smith     jrow = ii[i];
510290bbb0aSBarry Smith     n    = ii[i+1] - jrow;
511290bbb0aSBarry Smith     ierr = VecPlaceArray(bmat->left,yy + bs*i);CHKERRQ(ierr);
512290bbb0aSBarry Smith     ierr = VecPlaceArray(bmat->middle,xx + bs*i);CHKERRQ(ierr);
513290bbb0aSBarry Smith     /* if we ALWAYS required a diagonal entry then could remove this if test */
514290bbb0aSBarry Smith     if (aj[jrow] == i) {
515290bbb0aSBarry Smith       ierr = VecPlaceArray(bmat->right,xx + bs*aj[jrow]);CHKERRQ(ierr);
516290bbb0aSBarry Smith       ierr = MatMultAdd(aa[jrow],bmat->right,bmat->left,bmat->left);CHKERRQ(ierr);
517290bbb0aSBarry Smith       ierr = VecResetArray(bmat->right);CHKERRQ(ierr);
518290bbb0aSBarry Smith       jrow++;
519290bbb0aSBarry Smith       n--;
520290bbb0aSBarry Smith     }
521290bbb0aSBarry Smith     for (j=0; j<n; j++) {
522290bbb0aSBarry Smith       ierr = VecPlaceArray(bmat->right,xx + bs*aj[jrow]);CHKERRQ(ierr);            /* upper triangular part */
523290bbb0aSBarry Smith       ierr = MatMultAdd(aa[jrow],bmat->right,bmat->left,bmat->left);CHKERRQ(ierr);
524290bbb0aSBarry Smith       ierr = VecResetArray(bmat->right);CHKERRQ(ierr);
525290bbb0aSBarry Smith 
526290bbb0aSBarry Smith       ierr = VecPlaceArray(bmat->right,yy + bs*aj[jrow]);CHKERRQ(ierr);            /* lower triangular part */
527290bbb0aSBarry Smith       ierr = MatMultTransposeAdd(aa[jrow],bmat->middle,bmat->right,bmat->right);CHKERRQ(ierr);
528290bbb0aSBarry Smith       ierr = VecResetArray(bmat->right);CHKERRQ(ierr);
529290bbb0aSBarry Smith       jrow++;
530290bbb0aSBarry Smith     }
531290bbb0aSBarry Smith     ierr = VecResetArray(bmat->left);CHKERRQ(ierr);
532290bbb0aSBarry Smith     ierr = VecResetArray(bmat->middle);CHKERRQ(ierr);
533290bbb0aSBarry Smith   }
534290bbb0aSBarry Smith   ierr = VecRestoreArray(x,&xx);CHKERRQ(ierr);
535290bbb0aSBarry Smith   ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr);
536290bbb0aSBarry Smith   CHKMEMQ;
537290bbb0aSBarry Smith   PetscFunctionReturn(0);
538290bbb0aSBarry Smith }
539290bbb0aSBarry Smith 
540290bbb0aSBarry Smith #undef __FUNCT__
541421e10b8SBarry Smith #define __FUNCT__ "MatMultAdd_BlockMat"
542421e10b8SBarry Smith PetscErrorCode MatMultAdd_BlockMat(Mat A,Vec x,Vec y,Vec z)
543421e10b8SBarry Smith {
544421e10b8SBarry Smith   PetscFunctionBegin;
545421e10b8SBarry Smith   PetscFunctionReturn(0);
546421e10b8SBarry Smith }
547421e10b8SBarry Smith 
548421e10b8SBarry Smith #undef __FUNCT__
549421e10b8SBarry Smith #define __FUNCT__ "MatMultTranspose_BlockMat"
550421e10b8SBarry Smith PetscErrorCode MatMultTranspose_BlockMat(Mat A,Vec x,Vec y)
551421e10b8SBarry Smith {
552421e10b8SBarry Smith   PetscFunctionBegin;
553421e10b8SBarry Smith   PetscFunctionReturn(0);
554421e10b8SBarry Smith }
555421e10b8SBarry Smith 
556421e10b8SBarry Smith #undef __FUNCT__
557421e10b8SBarry Smith #define __FUNCT__ "MatMultTransposeAdd_BlockMat"
558421e10b8SBarry Smith PetscErrorCode MatMultTransposeAdd_BlockMat(Mat A,Vec x,Vec y,Vec z)
559421e10b8SBarry Smith {
560421e10b8SBarry Smith   PetscFunctionBegin;
561421e10b8SBarry Smith   PetscFunctionReturn(0);
562421e10b8SBarry Smith }
563421e10b8SBarry Smith 
564ccb205f8SBarry Smith /*
565ccb205f8SBarry Smith      Adds diagonal pointers to sparse matrix structure.
566ccb205f8SBarry Smith */
567ccb205f8SBarry Smith #undef __FUNCT__
568ccb205f8SBarry Smith #define __FUNCT__ "MatMarkDiagonal_BlockMat"
569ccb205f8SBarry Smith PetscErrorCode MatMarkDiagonal_BlockMat(Mat A)
570ccb205f8SBarry Smith {
571ccb205f8SBarry Smith   Mat_BlockMat   *a = (Mat_BlockMat*)A->data;
572ccb205f8SBarry Smith   PetscErrorCode ierr;
573ccb205f8SBarry Smith   PetscInt       i,j,mbs = A->rmap.n/A->rmap.bs;
574ccb205f8SBarry Smith 
575ccb205f8SBarry Smith   PetscFunctionBegin;
576ccb205f8SBarry Smith   if (!a->diag) {
577ccb205f8SBarry Smith     ierr = PetscMalloc(mbs*sizeof(PetscInt),&a->diag);CHKERRQ(ierr);
578ccb205f8SBarry Smith   }
579ccb205f8SBarry Smith   for (i=0; i<mbs; i++) {
580ccb205f8SBarry Smith     a->diag[i] = a->i[i+1];
581ccb205f8SBarry Smith     for (j=a->i[i]; j<a->i[i+1]; j++) {
582ccb205f8SBarry Smith       if (a->j[j] == i) {
583ccb205f8SBarry Smith         a->diag[i] = j;
584ccb205f8SBarry Smith         break;
585ccb205f8SBarry Smith       }
586ccb205f8SBarry Smith     }
587ccb205f8SBarry Smith   }
588ccb205f8SBarry Smith   PetscFunctionReturn(0);
589ccb205f8SBarry Smith }
590ccb205f8SBarry Smith 
591ccb205f8SBarry Smith #undef __FUNCT__
592ccb205f8SBarry Smith #define __FUNCT__ "MatGetSubMatrix_BlockMat"
593ccb205f8SBarry Smith PetscErrorCode MatGetSubMatrix_BlockMat(Mat A,IS isrow,IS iscol,PetscInt csize,MatReuse scall,Mat *B)
594ccb205f8SBarry Smith {
595ccb205f8SBarry Smith   Mat_BlockMat   *a = (Mat_BlockMat*)A->data;
596ccb205f8SBarry Smith   Mat_SeqAIJ     *c;
597ccb205f8SBarry Smith   PetscErrorCode ierr;
598ccb205f8SBarry Smith   PetscInt       i,k,first,step,lensi,nrows,ncols;
599ccb205f8SBarry Smith   PetscInt       *j_new,*i_new,*aj = a->j,*ai = a->i,ii,*ailen = a->ilen;
600ccb205f8SBarry Smith   PetscScalar    *a_new,value;
601ccb205f8SBarry Smith   Mat            C,*aa = a->a;
602ccb205f8SBarry Smith   PetscTruth     stride,equal;
603ccb205f8SBarry Smith 
604ccb205f8SBarry Smith   PetscFunctionBegin;
605ccb205f8SBarry Smith   ierr = ISEqual(isrow,iscol,&equal);CHKERRQ(ierr);
606ccb205f8SBarry Smith   if (!equal) SETERRQ(PETSC_ERR_SUP,"Only for idential column and row indices");
607ccb205f8SBarry Smith   ierr = ISStride(iscol,&stride);CHKERRQ(ierr);
608ccb205f8SBarry Smith   if (!stride) SETERRQ(PETSC_ERR_SUP,"Only for stride indices");
609ccb205f8SBarry Smith   ierr = ISStrideGetInfo(iscol,&first,&step);CHKERRQ(ierr);
610ccb205f8SBarry Smith   if (step != A->rmap.bs) SETERRQ(PETSC_ERR_SUP,"Can only select one entry from each block");
611ccb205f8SBarry Smith 
612ccb205f8SBarry Smith   ierr = ISGetLocalSize(isrow,&nrows);CHKERRQ(ierr);
613ccb205f8SBarry Smith   ncols = nrows;
614ccb205f8SBarry Smith 
615ccb205f8SBarry Smith   /* create submatrix */
616ccb205f8SBarry Smith   if (scall == MAT_REUSE_MATRIX) {
617ccb205f8SBarry Smith     PetscInt n_cols,n_rows;
618ccb205f8SBarry Smith     C = *B;
619ccb205f8SBarry Smith     ierr = MatGetSize(C,&n_rows,&n_cols);CHKERRQ(ierr);
620ccb205f8SBarry Smith     if (n_rows != nrows || n_cols != ncols) SETERRQ(PETSC_ERR_ARG_SIZ,"Reused submatrix wrong size");
621ccb205f8SBarry Smith     ierr = MatZeroEntries(C);CHKERRQ(ierr);
622ccb205f8SBarry Smith   } else {
623ccb205f8SBarry Smith     ierr = MatCreate(A->comm,&C);CHKERRQ(ierr);
624ccb205f8SBarry Smith     ierr = MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
6256e63c7a1SBarry Smith     if (A->symmetric) {
6266e63c7a1SBarry Smith       ierr = MatSetType(C,MATSEQSBAIJ);CHKERRQ(ierr);
6276e63c7a1SBarry Smith     } else {
628ccb205f8SBarry Smith       ierr = MatSetType(C,MATSEQAIJ);CHKERRQ(ierr);
6296e63c7a1SBarry Smith     }
6306e63c7a1SBarry Smith     ierr = MatSeqAIJSetPreallocation(C,0,ailen);CHKERRQ(ierr);
6316e63c7a1SBarry Smith     ierr = MatSeqSBAIJSetPreallocation(C,1,0,ailen);CHKERRQ(ierr);
632ccb205f8SBarry Smith   }
633ccb205f8SBarry Smith   c = (Mat_SeqAIJ*)C->data;
634ccb205f8SBarry Smith 
635ccb205f8SBarry Smith   /* loop over rows inserting into submatrix */
636ccb205f8SBarry Smith   a_new    = c->a;
637ccb205f8SBarry Smith   j_new    = c->j;
638ccb205f8SBarry Smith   i_new    = c->i;
639ccb205f8SBarry Smith 
640ccb205f8SBarry Smith   for (i=0; i<nrows; i++) {
641ccb205f8SBarry Smith     ii    = ai[i];
642ccb205f8SBarry Smith     lensi = ailen[i];
643ccb205f8SBarry Smith     for (k=0; k<lensi; k++) {
644ccb205f8SBarry Smith       *j_new++ = *aj++;
645ccb205f8SBarry Smith       ierr     = MatGetValue(*aa++,first,first,value);CHKERRQ(ierr);
646ccb205f8SBarry Smith       *a_new++ = value;
647ccb205f8SBarry Smith     }
648ccb205f8SBarry Smith     i_new[i+1]  = i_new[i] + lensi;
649ccb205f8SBarry Smith     c->ilen[i]  = lensi;
650ccb205f8SBarry Smith   }
651ccb205f8SBarry Smith 
652ccb205f8SBarry Smith   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
653ccb205f8SBarry Smith   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
654ccb205f8SBarry Smith   *B = C;
655ccb205f8SBarry Smith   PetscFunctionReturn(0);
656ccb205f8SBarry Smith }
657ccb205f8SBarry Smith 
658421e10b8SBarry Smith #undef __FUNCT__
659421e10b8SBarry Smith #define __FUNCT__ "MatAssemblyEnd_BlockMat"
660421e10b8SBarry Smith PetscErrorCode MatAssemblyEnd_BlockMat(Mat A,MatAssemblyType mode)
661421e10b8SBarry Smith {
662421e10b8SBarry Smith   Mat_BlockMat   *a = (Mat_BlockMat*)A->data;
663421e10b8SBarry Smith   PetscErrorCode ierr;
664421e10b8SBarry Smith   PetscInt       fshift = 0,i,j,*ai = a->i,*aj = a->j,*imax = a->imax;
665ccb205f8SBarry Smith   PetscInt       m = a->mbs,*ip,N,*ailen = a->ilen,rmax = 0;
666421e10b8SBarry Smith   Mat            *aa = a->a,*ap;
667421e10b8SBarry Smith 
668421e10b8SBarry Smith   PetscFunctionBegin;
669421e10b8SBarry Smith   if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0);
670421e10b8SBarry Smith 
671421e10b8SBarry Smith   if (m) rmax = ailen[0]; /* determine row with most nonzeros */
672421e10b8SBarry Smith   for (i=1; i<m; i++) {
673421e10b8SBarry Smith     /* move each row back by the amount of empty slots (fshift) before it*/
674421e10b8SBarry Smith     fshift += imax[i-1] - ailen[i-1];
675421e10b8SBarry Smith     rmax   = PetscMax(rmax,ailen[i]);
676421e10b8SBarry Smith     if (fshift) {
677421e10b8SBarry Smith       ip = aj + ai[i] ;
678421e10b8SBarry Smith       ap = aa + ai[i] ;
679421e10b8SBarry Smith       N  = ailen[i];
680421e10b8SBarry Smith       for (j=0; j<N; j++) {
681421e10b8SBarry Smith         ip[j-fshift] = ip[j];
682421e10b8SBarry Smith         ap[j-fshift] = ap[j];
683421e10b8SBarry Smith       }
684421e10b8SBarry Smith     }
685421e10b8SBarry Smith     ai[i] = ai[i-1] + ailen[i-1];
686421e10b8SBarry Smith   }
687421e10b8SBarry Smith   if (m) {
688421e10b8SBarry Smith     fshift += imax[m-1] - ailen[m-1];
689421e10b8SBarry Smith     ai[m]  = ai[m-1] + ailen[m-1];
690421e10b8SBarry Smith   }
691421e10b8SBarry Smith   /* reset ilen and imax for each row */
692421e10b8SBarry Smith   for (i=0; i<m; i++) {
693421e10b8SBarry Smith     ailen[i] = imax[i] = ai[i+1] - ai[i];
694421e10b8SBarry Smith   }
695421e10b8SBarry Smith   a->nz = ai[m];
696ccb205f8SBarry Smith   for (i=0; i<a->nz; i++) {
697ccb205f8SBarry Smith #if defined(PETSC_USE_DEBUG)
698ccb205f8SBarry Smith     if (!aa[i]) SETERRQ3(PETSC_ERR_PLIB,"Null matrix at location %D column %D nz %D",i,aj[i],a->nz);
699ccb205f8SBarry Smith #endif
700ccb205f8SBarry Smith     ierr = MatAssemblyBegin(aa[i],MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
701ccb205f8SBarry Smith     ierr = MatAssemblyEnd(aa[i],MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
702ccb205f8SBarry Smith   }
703ccb205f8SBarry Smith   CHKMEMQ;
704*8cdf2d9bSBarry 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);
705421e10b8SBarry Smith   ierr = PetscInfo1(A,"Number of mallocs during MatSetValues() is %D\n",a->reallocs);CHKERRQ(ierr);
706421e10b8SBarry Smith   ierr = PetscInfo1(A,"Maximum nonzeros in any row is %D\n",rmax);CHKERRQ(ierr);
707421e10b8SBarry Smith   a->reallocs          = 0;
708421e10b8SBarry Smith   A->info.nz_unneeded  = (double)fshift;
709421e10b8SBarry Smith   a->rmax              = rmax;
710421e10b8SBarry Smith 
711421e10b8SBarry Smith   A->same_nonzero = PETSC_TRUE;
712ccb205f8SBarry Smith   ierr = MatMarkDiagonal_BlockMat(A);CHKERRQ(ierr);
713421e10b8SBarry Smith   PetscFunctionReturn(0);
714421e10b8SBarry Smith }
715421e10b8SBarry Smith 
716290bbb0aSBarry Smith #undef __FUNCT__
717290bbb0aSBarry Smith #define __FUNCT__ "MatSetOption_BlockMat"
718290bbb0aSBarry Smith PetscErrorCode MatSetOption_BlockMat(Mat A,MatOption opt)
719290bbb0aSBarry Smith {
720290bbb0aSBarry Smith   PetscFunctionBegin;
721290bbb0aSBarry Smith   if (opt == MAT_SYMMETRIC) {
722290bbb0aSBarry Smith     A->ops->relax = MatRelax_BlockMat_Symmetric;
723290bbb0aSBarry Smith     A->ops->mult  = MatMult_BlockMat_Symmetric;
724290bbb0aSBarry Smith   } else {
725290bbb0aSBarry Smith     PetscInfo1(A,"Unused matrix option %s\n",MatOptions[opt]);
726290bbb0aSBarry Smith   }
727290bbb0aSBarry Smith   PetscFunctionReturn(0);
728290bbb0aSBarry Smith }
729290bbb0aSBarry Smith 
730290bbb0aSBarry Smith 
731421e10b8SBarry Smith static struct _MatOps MatOps_Values = {MatSetValues_BlockMat,
732421e10b8SBarry Smith        0,
733421e10b8SBarry Smith        0,
734421e10b8SBarry Smith        MatMult_BlockMat,
735421e10b8SBarry Smith /* 4*/ MatMultAdd_BlockMat,
736421e10b8SBarry Smith        MatMultTranspose_BlockMat,
737421e10b8SBarry Smith        MatMultTransposeAdd_BlockMat,
738421e10b8SBarry Smith        0,
739421e10b8SBarry Smith        0,
740421e10b8SBarry Smith        0,
741421e10b8SBarry Smith /*10*/ 0,
742421e10b8SBarry Smith        0,
743421e10b8SBarry Smith        0,
744ccb205f8SBarry Smith        MatRelax_BlockMat,
745421e10b8SBarry Smith        0,
746421e10b8SBarry Smith /*15*/ 0,
747421e10b8SBarry Smith        0,
748421e10b8SBarry Smith        0,
749421e10b8SBarry Smith        0,
750421e10b8SBarry Smith        0,
751421e10b8SBarry Smith /*20*/ 0,
752421e10b8SBarry Smith        MatAssemblyEnd_BlockMat,
753421e10b8SBarry Smith        0,
754290bbb0aSBarry Smith        MatSetOption_BlockMat,
755421e10b8SBarry Smith        0,
756421e10b8SBarry Smith /*25*/ 0,
757421e10b8SBarry Smith        0,
758421e10b8SBarry Smith        0,
759421e10b8SBarry Smith        0,
760421e10b8SBarry Smith        0,
761421e10b8SBarry Smith /*30*/ 0,
762421e10b8SBarry Smith        0,
763421e10b8SBarry Smith        0,
764421e10b8SBarry Smith        0,
765421e10b8SBarry Smith        0,
766421e10b8SBarry Smith /*35*/ 0,
767421e10b8SBarry Smith        0,
768421e10b8SBarry Smith        0,
769421e10b8SBarry Smith        0,
770421e10b8SBarry Smith        0,
771421e10b8SBarry Smith /*40*/ 0,
772421e10b8SBarry Smith        0,
773421e10b8SBarry Smith        0,
774421e10b8SBarry Smith        0,
775421e10b8SBarry Smith        0,
776421e10b8SBarry Smith /*45*/ 0,
777421e10b8SBarry Smith        0,
778421e10b8SBarry Smith        0,
779421e10b8SBarry Smith        0,
780421e10b8SBarry Smith        0,
781*8cdf2d9bSBarry Smith /*50*/ 0,
782421e10b8SBarry Smith        0,
783421e10b8SBarry Smith        0,
784421e10b8SBarry Smith        0,
785421e10b8SBarry Smith        0,
786421e10b8SBarry Smith /*55*/ 0,
787421e10b8SBarry Smith        0,
788421e10b8SBarry Smith        0,
789421e10b8SBarry Smith        0,
790421e10b8SBarry Smith        0,
791ccb205f8SBarry Smith /*60*/ MatGetSubMatrix_BlockMat,
792421e10b8SBarry Smith        MatDestroy_BlockMat,
793ccb205f8SBarry Smith        MatView_BlockMat,
794421e10b8SBarry Smith        0,
795421e10b8SBarry Smith        0,
796421e10b8SBarry Smith /*65*/ 0,
797421e10b8SBarry Smith        0,
798421e10b8SBarry Smith        0,
799421e10b8SBarry Smith        0,
800421e10b8SBarry Smith        0,
801421e10b8SBarry Smith /*70*/ 0,
802421e10b8SBarry Smith        0,
803421e10b8SBarry Smith        0,
804421e10b8SBarry Smith        0,
805421e10b8SBarry Smith        0,
806421e10b8SBarry Smith /*75*/ 0,
807421e10b8SBarry Smith        0,
808421e10b8SBarry Smith        0,
809421e10b8SBarry Smith        0,
810421e10b8SBarry Smith        0,
811421e10b8SBarry Smith /*80*/ 0,
812421e10b8SBarry Smith        0,
813421e10b8SBarry Smith        0,
814421e10b8SBarry Smith        0,
815421e10b8SBarry Smith        MatLoad_BlockMat,
816421e10b8SBarry Smith /*85*/ 0,
817421e10b8SBarry Smith        0,
818421e10b8SBarry Smith        0,
819421e10b8SBarry Smith        0,
820421e10b8SBarry Smith        0,
821421e10b8SBarry Smith /*90*/ 0,
822421e10b8SBarry Smith        0,
823421e10b8SBarry Smith        0,
824421e10b8SBarry Smith        0,
825421e10b8SBarry Smith        0,
826421e10b8SBarry Smith /*95*/ 0,
827421e10b8SBarry Smith        0,
828421e10b8SBarry Smith        0,
829421e10b8SBarry Smith        0};
830421e10b8SBarry Smith 
831*8cdf2d9bSBarry Smith #undef __FUNCT__
832*8cdf2d9bSBarry Smith #define __FUNCT__ "MatBlockMatSetPreallocation"
833*8cdf2d9bSBarry Smith /*@C
834*8cdf2d9bSBarry Smith    MatBlockMatSetPreallocation - For good matrix assembly performance
835*8cdf2d9bSBarry Smith    the user should preallocate the matrix storage by setting the parameter nz
836*8cdf2d9bSBarry Smith    (or the array nnz).  By setting these parameters accurately, performance
837*8cdf2d9bSBarry Smith    during matrix assembly can be increased by more than a factor of 50.
838*8cdf2d9bSBarry Smith 
839*8cdf2d9bSBarry Smith    Collective on MPI_Comm
840*8cdf2d9bSBarry Smith 
841*8cdf2d9bSBarry Smith    Input Parameters:
842*8cdf2d9bSBarry Smith +  B - The matrix
843*8cdf2d9bSBarry Smith .  bs - size of each block in matrix
844*8cdf2d9bSBarry Smith .  nz - number of nonzeros per block row (same for all rows)
845*8cdf2d9bSBarry Smith -  nnz - array containing the number of nonzeros in the various block rows
846*8cdf2d9bSBarry Smith          (possibly different for each row) or PETSC_NULL
847*8cdf2d9bSBarry Smith 
848*8cdf2d9bSBarry Smith    Notes:
849*8cdf2d9bSBarry Smith      If nnz is given then nz is ignored
850*8cdf2d9bSBarry Smith 
851*8cdf2d9bSBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
852*8cdf2d9bSBarry Smith    Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory
853*8cdf2d9bSBarry Smith    allocation.  For large problems you MUST preallocate memory or you
854*8cdf2d9bSBarry Smith    will get TERRIBLE performance, see the users' manual chapter on matrices.
855*8cdf2d9bSBarry Smith 
856*8cdf2d9bSBarry Smith    Level: intermediate
857*8cdf2d9bSBarry Smith 
858*8cdf2d9bSBarry Smith .seealso: MatCreate(), MatCreateBlockMat(), MatSetValues()
859*8cdf2d9bSBarry Smith 
860*8cdf2d9bSBarry Smith @*/
861*8cdf2d9bSBarry Smith PetscErrorCode PETSCMAT_DLLEXPORT MatBlockMatSetPreallocation(Mat B,PetscInt bs,PetscInt nz,const PetscInt nnz[])
862*8cdf2d9bSBarry Smith {
863*8cdf2d9bSBarry Smith   PetscErrorCode ierr,(*f)(Mat,PetscInt,PetscInt,const PetscInt[]);
864*8cdf2d9bSBarry Smith 
865*8cdf2d9bSBarry Smith   PetscFunctionBegin;
866*8cdf2d9bSBarry Smith   ierr = PetscObjectQueryFunction((PetscObject)B,"MatBlockMatSetPreallocation_C",(void (**)(void))&f);CHKERRQ(ierr);
867*8cdf2d9bSBarry Smith   if (f) {
868*8cdf2d9bSBarry Smith     ierr = (*f)(B,bs,nz,nnz);CHKERRQ(ierr);
869*8cdf2d9bSBarry Smith   }
870*8cdf2d9bSBarry Smith   PetscFunctionReturn(0);
871*8cdf2d9bSBarry Smith }
872*8cdf2d9bSBarry Smith 
873*8cdf2d9bSBarry Smith EXTERN_C_BEGIN
874*8cdf2d9bSBarry Smith #undef __FUNCT__
875*8cdf2d9bSBarry Smith #define __FUNCT__ "MatBlockMatSetPreallocation_BlockMat"
876*8cdf2d9bSBarry Smith PetscErrorCode PETSCMAT_DLLEXPORT MatBlockMatSetPreallocation_BlockMat(Mat A,PetscInt bs,PetscInt nz,PetscInt *nnz)
877*8cdf2d9bSBarry Smith {
878*8cdf2d9bSBarry Smith   Mat_BlockMat   *bmat = (Mat_BlockMat*)A->data;
879*8cdf2d9bSBarry Smith   PetscErrorCode ierr;
880*8cdf2d9bSBarry Smith   PetscInt       i;
881*8cdf2d9bSBarry Smith 
882*8cdf2d9bSBarry Smith   PetscFunctionBegin;
883*8cdf2d9bSBarry Smith   if (bs < 1) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Block size given %D must be great than zero",bs);
884*8cdf2d9bSBarry Smith   if (A->rmap.n % bs) SETERRQ2(PETSC_ERR_ARG_INCOMP,"Blocksize %D does not divide number of rows %D",bs,A->rmap.n);
885*8cdf2d9bSBarry Smith   if (A->cmap.n % bs) SETERRQ2(PETSC_ERR_ARG_INCOMP,"Blocksize %D does not divide number of columns %D",bs,A->cmap.n);
886*8cdf2d9bSBarry Smith   if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
887*8cdf2d9bSBarry Smith   if (nz < 0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %d",nz);
888*8cdf2d9bSBarry Smith   if (nnz) {
889*8cdf2d9bSBarry Smith     for (i=0; i<A->rmap.n/bs; i++) {
890*8cdf2d9bSBarry Smith       if (nnz[i] < 0) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be less than 0: local row %d value %d",i,nnz[i]);
891*8cdf2d9bSBarry Smith       if (nnz[i] > A->cmap.n/bs) SETERRQ3(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);
892*8cdf2d9bSBarry Smith     }
893*8cdf2d9bSBarry Smith   }
894*8cdf2d9bSBarry Smith   A->rmap.bs = A->cmap.bs = bs;
895*8cdf2d9bSBarry Smith   bmat->mbs  = A->rmap.n/bs;
896*8cdf2d9bSBarry Smith 
897*8cdf2d9bSBarry Smith   printf("A->rmap.n%d %d\n",A->rmap.n, bs);
898*8cdf2d9bSBarry Smith   ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,bs,PETSC_NULL,&bmat->right);CHKERRQ(ierr);
899*8cdf2d9bSBarry Smith   ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,bs,PETSC_NULL,&bmat->middle);CHKERRQ(ierr);
900*8cdf2d9bSBarry Smith   ierr = VecCreateSeq(PETSC_COMM_SELF,bs,&bmat->left);CHKERRQ(ierr);
901*8cdf2d9bSBarry Smith 
902*8cdf2d9bSBarry Smith   ierr = PetscMalloc2(A->rmap.n,PetscInt,&bmat->imax,A->rmap.n,PetscInt,&bmat->ilen);CHKERRQ(ierr);
903*8cdf2d9bSBarry Smith   if (nnz) {
904*8cdf2d9bSBarry Smith     nz = 0;
905*8cdf2d9bSBarry Smith     for (i=0; i<A->rmap.n/A->rmap.bs; i++) {
906*8cdf2d9bSBarry Smith       bmat->imax[i] = nnz[i];
907*8cdf2d9bSBarry Smith       nz           += nnz[i];
908*8cdf2d9bSBarry Smith     }
909*8cdf2d9bSBarry Smith   } else {
910*8cdf2d9bSBarry Smith     SETERRQ(PETSC_ERR_SUP,"Currently requires block row by row preallocation");
911*8cdf2d9bSBarry Smith   }
912*8cdf2d9bSBarry Smith 
913*8cdf2d9bSBarry Smith   /* bmat->ilen will count nonzeros in each row so far. */
914*8cdf2d9bSBarry Smith   for (i=0; i<bmat->mbs; i++) { bmat->ilen[i] = 0;}
915*8cdf2d9bSBarry Smith 
916*8cdf2d9bSBarry Smith   /* allocate the matrix space */
917*8cdf2d9bSBarry Smith   ierr = PetscMalloc3(nz,Mat,&bmat->a,nz,PetscInt,&bmat->j,A->rmap.n+1,PetscInt,&bmat->i);CHKERRQ(ierr);
918*8cdf2d9bSBarry Smith   bmat->i[0] = 0;
919*8cdf2d9bSBarry Smith   for (i=1; i<bmat->mbs+1; i++) {
920*8cdf2d9bSBarry Smith     bmat->i[i] = bmat->i[i-1] + bmat->imax[i-1];
921*8cdf2d9bSBarry Smith   }
922*8cdf2d9bSBarry Smith   bmat->singlemalloc = PETSC_TRUE;
923*8cdf2d9bSBarry Smith   bmat->free_a       = PETSC_TRUE;
924*8cdf2d9bSBarry Smith   bmat->free_ij      = PETSC_TRUE;
925*8cdf2d9bSBarry Smith 
926*8cdf2d9bSBarry Smith   bmat->nz                = 0;
927*8cdf2d9bSBarry Smith   bmat->maxnz             = nz;
928*8cdf2d9bSBarry Smith   A->info.nz_unneeded  = (double)bmat->maxnz;
929*8cdf2d9bSBarry Smith 
930*8cdf2d9bSBarry Smith   PetscFunctionReturn(0);
931*8cdf2d9bSBarry Smith }
932*8cdf2d9bSBarry Smith EXTERN_C_END
933*8cdf2d9bSBarry Smith 
934421e10b8SBarry Smith /*MC
935421e10b8SBarry Smith    MATBLOCKMAT - A matrix that is defined by a set of Mat's that represents a sparse block matrix
936421e10b8SBarry Smith                  consisting of (usually) sparse blocks.
937421e10b8SBarry Smith 
938421e10b8SBarry Smith   Level: advanced
939421e10b8SBarry Smith 
940421e10b8SBarry Smith .seealso: MatCreateBlockMat()
941421e10b8SBarry Smith 
942421e10b8SBarry Smith M*/
943421e10b8SBarry Smith 
944421e10b8SBarry Smith EXTERN_C_BEGIN
945421e10b8SBarry Smith #undef __FUNCT__
946421e10b8SBarry Smith #define __FUNCT__ "MatCreate_BlockMat"
947421e10b8SBarry Smith PetscErrorCode PETSCMAT_DLLEXPORT MatCreate_BlockMat(Mat A)
948421e10b8SBarry Smith {
949421e10b8SBarry Smith   Mat_BlockMat   *b;
950421e10b8SBarry Smith   PetscErrorCode ierr;
951421e10b8SBarry Smith 
952421e10b8SBarry Smith   PetscFunctionBegin;
953421e10b8SBarry Smith   ierr = PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
954421e10b8SBarry Smith   ierr = PetscNew(Mat_BlockMat,&b);CHKERRQ(ierr);
955421e10b8SBarry Smith 
956421e10b8SBarry Smith   A->data = (void*)b;
957421e10b8SBarry Smith 
958421e10b8SBarry Smith   ierr = PetscMapInitialize(A->comm,&A->rmap);CHKERRQ(ierr);
959421e10b8SBarry Smith   ierr = PetscMapInitialize(A->comm,&A->cmap);CHKERRQ(ierr);
960421e10b8SBarry Smith 
961421e10b8SBarry Smith   A->assembled     = PETSC_TRUE;
962421e10b8SBarry Smith   A->preallocated  = PETSC_FALSE;
963421e10b8SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)A,MATBLOCKMAT);CHKERRQ(ierr);
964290bbb0aSBarry Smith 
965290bbb0aSBarry Smith   ierr = PetscOptionsBegin(A->comm,A->prefix,"Matrix Option","Mat");CHKERRQ(ierr);
966290bbb0aSBarry Smith   ierr = PetscOptionsEnd();
967290bbb0aSBarry Smith 
968*8cdf2d9bSBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatBlockMatSetPreallocation_C",
969*8cdf2d9bSBarry Smith                                      "MatBlockMatSetPreallocation_BlockMat",
970*8cdf2d9bSBarry Smith                                       MatBlockMatSetPreallocation_BlockMat);CHKERRQ(ierr);
971*8cdf2d9bSBarry Smith 
972421e10b8SBarry Smith   PetscFunctionReturn(0);
973421e10b8SBarry Smith }
974421e10b8SBarry Smith EXTERN_C_END
975421e10b8SBarry Smith 
976421e10b8SBarry Smith #undef __FUNCT__
977421e10b8SBarry Smith #define __FUNCT__ "MatCreateBlockMat"
978421e10b8SBarry Smith /*@C
979421e10b8SBarry Smith    MatCreateBlockMat - Creates a new matrix based sparse Mat storage
980421e10b8SBarry Smith 
981421e10b8SBarry Smith   Collective on MPI_Comm
982421e10b8SBarry Smith 
983421e10b8SBarry Smith    Input Parameters:
984421e10b8SBarry Smith +  comm - MPI communicator
985421e10b8SBarry Smith .  m - number of rows
986421e10b8SBarry Smith .  n  - number of columns
987*8cdf2d9bSBarry Smith .  bs - size of each submatrix
988*8cdf2d9bSBarry Smith .  nz  - expected maximum number of nonzero blocks in row (use PETSC_DEFAULT if not known)
989*8cdf2d9bSBarry Smith -  nnz - expected number of nonzers per block row if known (use PETSC_NULL otherwise)
990421e10b8SBarry Smith 
991421e10b8SBarry Smith 
992421e10b8SBarry Smith    Output Parameter:
993421e10b8SBarry Smith .  A - the matrix
994421e10b8SBarry Smith 
995421e10b8SBarry Smith    Level: intermediate
996421e10b8SBarry Smith 
997421e10b8SBarry Smith    PETSc requires that matrices and vectors being used for certain
998421e10b8SBarry Smith    operations are partitioned accordingly.  For example, when
999421e10b8SBarry Smith    creating a bmat matrix, A, that supports parallel matrix-vector
1000421e10b8SBarry Smith    products using MatMult(A,x,y) the user should set the number
1001421e10b8SBarry Smith    of local matrix rows to be the number of local elements of the
1002421e10b8SBarry Smith    corresponding result vector, y. Note that this is information is
1003421e10b8SBarry Smith    required for use of the matrix interface routines, even though
1004421e10b8SBarry Smith    the bmat matrix may not actually be physically partitioned.
1005421e10b8SBarry Smith    For example,
1006421e10b8SBarry Smith 
1007421e10b8SBarry Smith .keywords: matrix, bmat, create
1008421e10b8SBarry Smith 
1009421e10b8SBarry Smith .seealso: MATBLOCKMAT
1010421e10b8SBarry Smith @*/
1011*8cdf2d9bSBarry Smith PetscErrorCode PETSCMAT_DLLEXPORT MatCreateBlockMat(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt bs,PetscInt nz,PetscInt *nnz, Mat *A)
1012421e10b8SBarry Smith {
1013421e10b8SBarry Smith   PetscErrorCode ierr;
1014421e10b8SBarry Smith 
1015421e10b8SBarry Smith   PetscFunctionBegin;
1016421e10b8SBarry Smith   ierr = MatCreate(comm,A);CHKERRQ(ierr);
1017421e10b8SBarry Smith   ierr = MatSetSizes(*A,m,n,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
1018421e10b8SBarry Smith   ierr = MatSetType(*A,MATBLOCKMAT);CHKERRQ(ierr);
1019*8cdf2d9bSBarry Smith   ierr = MatBlockMatSetPreallocation(*A,bs,nz,nnz);CHKERRQ(ierr);
1020421e10b8SBarry Smith   PetscFunctionReturn(0);
1021421e10b8SBarry Smith }
1022421e10b8SBarry Smith 
1023421e10b8SBarry Smith 
1024421e10b8SBarry Smith 
1025