xref: /petsc/src/mat/impls/blockmat/seq/blockmat.c (revision a59733823807b501c0f15d871a909cf4da023a69)
1421e10b8SBarry Smith #define PETSCMAT_DLL
2421e10b8SBarry Smith 
3421e10b8SBarry Smith /*
4421e10b8SBarry Smith    This provides a matrix that consists of Mats
5421e10b8SBarry Smith */
6421e10b8SBarry Smith 
77c4f633dSBarry Smith #include "private/matimpl.h"              /*I "petscmat.h" I*/
87c4f633dSBarry Smith #include "../src/mat/impls/baij/seq/baij.h"    /* use the common AIJ data-structure */
9ccb205f8SBarry Smith #include "petscksp.h"
10421e10b8SBarry Smith 
11421e10b8SBarry Smith typedef struct {
12421e10b8SBarry Smith   SEQAIJHEADER(Mat);
13421e10b8SBarry Smith   SEQBAIJHEADER;
14ccb205f8SBarry Smith   Mat               *diags;
15421e10b8SBarry Smith 
166e63c7a1SBarry Smith   Vec               left,right,middle,workb;   /* dummy vectors to perform local parts of product */
17421e10b8SBarry Smith } Mat_BlockMat;
18421e10b8SBarry Smith 
19*a5973382SShri Abhyankar EXTERN PetscErrorCode PETSCMAT_DLLEXPORT MatBlockMatSetPreallocation(Mat,PetscInt,PetscInt,const PetscInt*);
20*a5973382SShri Abhyankar 
21421e10b8SBarry Smith #undef __FUNCT__
2241f059aeSBarry Smith #define __FUNCT__ "MatSOR_BlockMat_Symmetric"
2341f059aeSBarry Smith PetscErrorCode MatSOR_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;
30d0f46423SBarry 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;
39e32f2f54SBarry 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);
40e32f2f54SBarry Smith   if (flag & SOR_EISENSTAT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support yet for Eisenstat");
41e32f2f54SBarry Smith   if (omega != 1.0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support yet for omega not equal to 1.0");
42e32f2f54SBarry Smith   if (fshift) SETERRQ(PETSC_COMM_SELF,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))
44e32f2f54SBarry Smith     SETERRQ(PETSC_COMM_SELF,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++) {
502692d6eeSBarry Smith       ierr = MatGetOrdering(a->a[a->diag[i]], MATORDERINGND,&row,&col);CHKERRQ(ierr);
51719d5645SBarry Smith       ierr = MatCholeskyFactorSymbolic(a->diags[i],a->a[a->diag[i]],row,&info);CHKERRQ(ierr);
52719d5645SBarry Smith       ierr = MatCholeskyFactorNumeric(a->diags[i],a->a[a->diag[i]],&info);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);
643649974fSBarry Smith   ierr = VecGetArrayRead(a->workb,&b);CHKERRQ(ierr);
65290bbb0aSBarry Smith 
6641f059aeSBarry Smith   /* need to add code for when initial guess is zero, see MatSOR_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 
8841f059aeSBarry Smith         /* now adjust right hand side, see MatSOR_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);
1243649974fSBarry Smith   ierr = VecRestoreArrayRead(a->workb,&b);CHKERRQ(ierr);
125290bbb0aSBarry Smith   PetscFunctionReturn(0);
126290bbb0aSBarry Smith }
127290bbb0aSBarry Smith 
128290bbb0aSBarry Smith #undef __FUNCT__
12941f059aeSBarry Smith #define __FUNCT__ "MatSOR_BlockMat"
13041f059aeSBarry Smith PetscErrorCode MatSOR_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;
137d0f46423SBarry 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;
146e32f2f54SBarry 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);
147e32f2f54SBarry Smith   if (flag & SOR_EISENSTAT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support yet for Eisenstat");
148e32f2f54SBarry Smith   if (omega != 1.0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support yet for omega not equal to 1.0");
149e32f2f54SBarry Smith   if (fshift) SETERRQ(PETSC_COMM_SELF,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++) {
1552692d6eeSBarry Smith       ierr = MatGetOrdering(a->a[a->diag[i]], MATORDERINGND,&row,&col);CHKERRQ(ierr);
156719d5645SBarry Smith       ierr = MatLUFactorSymbolic(a->diags[i],a->a[a->diag[i]],row,col,&info);CHKERRQ(ierr);
157719d5645SBarry Smith       ierr = MatLUFactorNumeric(a->diags[i],a->a[a->diag[i]],&info);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);
1663649974fSBarry Smith   ierr = VecGetArrayRead(bb,&b);CHKERRQ(ierr);
167ccb205f8SBarry Smith 
16841f059aeSBarry Smith   /* need to add code for when initial guess is zero, see MatSOR_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);
2213649974fSBarry Smith   ierr = VecRestoreArrayRead(bb,&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;
232d0f46423SBarry 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;
24071fd2e92SBarry Smith   if (v) PetscValidScalarPointer(v,6);
241421e10b8SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
242421e10b8SBarry Smith     row  = im[k];
243421e10b8SBarry Smith     brow = row/bs;
244421e10b8SBarry Smith     if (row < 0) continue;
245421e10b8SBarry Smith #if defined(PETSC_USE_DEBUG)
246e32f2f54SBarry 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);
247421e10b8SBarry Smith #endif
248421e10b8SBarry Smith     rp   = aj + ai[brow];
249421e10b8SBarry Smith     ap   = aa + ai[brow];
250421e10b8SBarry Smith     rmax = imax[brow];
251421e10b8SBarry Smith     nrow = ailen[brow];
252421e10b8SBarry Smith     low  = 0;
253421e10b8SBarry Smith     high = nrow;
254421e10b8SBarry Smith     for (l=0; l<n; l++) { /* loop over added columns */
255421e10b8SBarry Smith       if (in[l] < 0) continue;
256421e10b8SBarry Smith #if defined(PETSC_USE_DEBUG)
257e32f2f54SBarry 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);
258421e10b8SBarry Smith #endif
259421e10b8SBarry Smith       col = in[l]; bcol = col/bs;
2606e63c7a1SBarry Smith       if (A->symmetric && brow > bcol) continue;
261421e10b8SBarry Smith       ridx = row % bs; cidx = col % bs;
262421e10b8SBarry Smith       if (roworiented) {
263421e10b8SBarry Smith         value = v[l + k*n];
264421e10b8SBarry Smith       } else {
265421e10b8SBarry Smith         value = v[k + l*m];
266421e10b8SBarry Smith       }
267421e10b8SBarry Smith       if (col <= lastcol) low = 0; else high = nrow;
268421e10b8SBarry Smith       lastcol = col;
269421e10b8SBarry Smith       while (high-low > 7) {
270421e10b8SBarry Smith         t = (low+high)/2;
271421e10b8SBarry Smith         if (rp[t] > bcol) high = t;
272421e10b8SBarry Smith         else              low  = t;
273421e10b8SBarry Smith       }
274421e10b8SBarry Smith       for (i=low; i<high; i++) {
275421e10b8SBarry Smith         if (rp[i] > bcol) break;
276421e10b8SBarry Smith         if (rp[i] == bcol) {
277421e10b8SBarry Smith           goto noinsert1;
278421e10b8SBarry Smith         }
279421e10b8SBarry Smith       }
280421e10b8SBarry Smith       if (nonew == 1) goto noinsert1;
281e32f2f54SBarry Smith       if (nonew == -1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero (%D, %D) in the matrix", row, col);
282fef13f97SBarry 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 */
285421e10b8SBarry Smith       for (ii=N; ii>=i; ii--) {
286421e10b8SBarry Smith         rp[ii+1] = rp[ii];
287421e10b8SBarry Smith         ap[ii+1] = ap[ii];
288421e10b8SBarry Smith       }
289421e10b8SBarry Smith       if (N>=i) ap[i] = 0;
290421e10b8SBarry Smith       rp[i]           = bcol;
291421e10b8SBarry Smith       a->nz++;
292421e10b8SBarry Smith       noinsert1:;
293421e10b8SBarry Smith       if (!*(ap+i)) {
2946e63c7a1SBarry Smith         ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,bs,bs,0,0,ap+i);CHKERRQ(ierr);
295b0223207SBarry Smith       }
296421e10b8SBarry Smith       ierr = MatSetValues(ap[i],1,&ridx,1,&cidx,&value,is);CHKERRQ(ierr);
297421e10b8SBarry Smith       low = i;
298421e10b8SBarry Smith     }
299421e10b8SBarry Smith     ailen[brow] = nrow;
300421e10b8SBarry Smith   }
301421e10b8SBarry Smith   A->same_nonzero = PETSC_FALSE;
302421e10b8SBarry Smith   PetscFunctionReturn(0);
303421e10b8SBarry Smith }
304421e10b8SBarry Smith 
305421e10b8SBarry Smith #undef __FUNCT__
306421e10b8SBarry Smith #define __FUNCT__ "MatLoad_BlockMat"
307a313700dSBarry Smith PetscErrorCode MatLoad_BlockMat(PetscViewer viewer, const MatType type,Mat *A)
308421e10b8SBarry Smith {
309421e10b8SBarry Smith   PetscErrorCode    ierr;
310421e10b8SBarry Smith   Mat               tmpA;
311a0e1a203SBarry Smith   PetscInt          i,j,m,n,bs = 1,ncols,*lens,currentcol,mbs,**ii,*ilens,nextcol,*llens,cnt = 0;
312421e10b8SBarry Smith   const PetscInt    *cols;
313421e10b8SBarry Smith   const PetscScalar *values;
31490d69ab7SBarry Smith   PetscTruth        flg = PETSC_FALSE,notdone;
3158cdf2d9bSBarry Smith   Mat_SeqAIJ        *a;
316a0e1a203SBarry Smith   Mat_BlockMat      *amat;
317421e10b8SBarry Smith 
318421e10b8SBarry Smith   PetscFunctionBegin;
319421e10b8SBarry Smith   ierr = MatLoad_SeqAIJ(viewer,MATSEQAIJ,&tmpA);CHKERRQ(ierr);
320421e10b8SBarry Smith 
321421e10b8SBarry Smith   ierr = MatGetLocalSize(tmpA,&m,&n);CHKERRQ(ierr);
32277925062SSatish Balay   ierr = PetscOptionsBegin(PETSC_COMM_SELF,PETSC_NULL,"Options for loading BlockMat matrix 1","Mat");CHKERRQ(ierr);
323421e10b8SBarry Smith     ierr = PetscOptionsInt("-matload_block_size","Set the blocksize used to store the matrix","MatLoad",bs,&bs,PETSC_NULL);CHKERRQ(ierr);
32490d69ab7SBarry Smith     ierr = PetscOptionsTruth("-matload_symmetric","Store the matrix as symmetric","MatLoad",flg,&flg,PETSC_NULL);CHKERRQ(ierr);
3258cdf2d9bSBarry Smith   ierr = PetscOptionsEnd();CHKERRQ(ierr);
3268cdf2d9bSBarry Smith 
327a0e1a203SBarry Smith   /* Determine number of nonzero blocks for each block row */
3288cdf2d9bSBarry Smith   a    = (Mat_SeqAIJ*) tmpA->data;
3298cdf2d9bSBarry Smith   mbs  = m/bs;
3301b453117SMatthew Knepley   ierr = PetscMalloc3(mbs,PetscInt,&lens,bs,PetscInt*,&ii,bs,PetscInt,&ilens);CHKERRQ(ierr);
3318cdf2d9bSBarry Smith   ierr = PetscMemzero(lens,mbs*sizeof(PetscInt));CHKERRQ(ierr);
3328cdf2d9bSBarry Smith 
3338cdf2d9bSBarry Smith   for (i=0; i<mbs; i++) {
3348cdf2d9bSBarry Smith     for (j=0; j<bs; j++) {
3358cdf2d9bSBarry Smith       ii[j]         = a->j + a->i[i*bs + j];
3368cdf2d9bSBarry Smith       ilens[j]      = a->i[i*bs + j + 1] - a->i[i*bs + j];
3378cdf2d9bSBarry Smith     }
338a0e1a203SBarry Smith 
339a0e1a203SBarry Smith     currentcol = -1;
3408cdf2d9bSBarry Smith     notdone = PETSC_TRUE;
3418cdf2d9bSBarry Smith     while (PETSC_TRUE) {
3428cdf2d9bSBarry Smith       notdone = PETSC_FALSE;
3438cdf2d9bSBarry Smith       nextcol = 1000000000;
3448cdf2d9bSBarry Smith       for (j=0; j<bs; j++) {
345a0e1a203SBarry Smith         while ((ilens[j] > 0 && ii[j][0]/bs <= currentcol)) {
3468cdf2d9bSBarry Smith           ii[j]++;
3478cdf2d9bSBarry Smith           ilens[j]--;
3488cdf2d9bSBarry Smith         }
3498cdf2d9bSBarry Smith         if (ilens[j] > 0) {
3508cdf2d9bSBarry Smith           notdone = PETSC_TRUE;
3518cdf2d9bSBarry Smith           nextcol = PetscMin(nextcol,ii[j][0]/bs);
3528cdf2d9bSBarry Smith         }
3538cdf2d9bSBarry Smith       }
3548cdf2d9bSBarry Smith       if (!notdone) break;
355a0e1a203SBarry Smith       if (!flg || (nextcol >= i)) lens[i]++;
3568cdf2d9bSBarry Smith       currentcol = nextcol;
3578cdf2d9bSBarry Smith     }
3588cdf2d9bSBarry Smith   }
3598cdf2d9bSBarry Smith 
3608cdf2d9bSBarry Smith   ierr = MatCreateBlockMat(PETSC_COMM_SELF,m,n,bs,0,lens,A);CHKERRQ(ierr);
361290bbb0aSBarry Smith   if (flg) {
3624e0d8c25SBarry Smith     ierr = MatSetOption(*A,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
363290bbb0aSBarry Smith   }
364a0e1a203SBarry Smith   amat = (Mat_BlockMat*)(*A)->data;
365a0e1a203SBarry Smith 
366a0e1a203SBarry Smith   /* preallocate the submatrices */
367a0e1a203SBarry Smith   ierr = PetscMalloc(bs*sizeof(PetscInt),&llens);CHKERRQ(ierr);
368a0e1a203SBarry Smith   for (i=0; i<mbs; i++) { /* loops for block rows */
369a0e1a203SBarry Smith     for (j=0; j<bs; j++) {
370a0e1a203SBarry Smith       ii[j]         = a->j + a->i[i*bs + j];
371a0e1a203SBarry Smith       ilens[j]      = a->i[i*bs + j + 1] - a->i[i*bs + j];
372a0e1a203SBarry Smith     }
373a0e1a203SBarry Smith 
374a0e1a203SBarry Smith     currentcol = 1000000000;
375a0e1a203SBarry Smith     for (j=0; j<bs; j++) { /* loop over rows in block finding first nonzero block */
376a0e1a203SBarry Smith       if (ilens[j] > 0) {
377a0e1a203SBarry Smith 	currentcol = PetscMin(currentcol,ii[j][0]/bs);
378a0e1a203SBarry Smith       }
379a0e1a203SBarry Smith     }
380a0e1a203SBarry Smith 
381a0e1a203SBarry Smith     notdone = PETSC_TRUE;
382a0e1a203SBarry Smith     while (PETSC_TRUE) {  /* loops over blocks in block row */
383a0e1a203SBarry Smith 
384a0e1a203SBarry Smith       notdone = PETSC_FALSE;
385a0e1a203SBarry Smith       nextcol = 1000000000;
386a0e1a203SBarry Smith       ierr = PetscMemzero(llens,bs*sizeof(PetscInt));CHKERRQ(ierr);
387a0e1a203SBarry Smith       for (j=0; j<bs; j++) { /* loop over rows in block */
388a0e1a203SBarry Smith         while ((ilens[j] > 0 && ii[j][0]/bs <= currentcol)) { /* loop over columns in row */
389a0e1a203SBarry Smith           ii[j]++;
390a0e1a203SBarry Smith           ilens[j]--;
391a0e1a203SBarry Smith           llens[j]++;
392a0e1a203SBarry Smith         }
393a0e1a203SBarry Smith         if (ilens[j] > 0) {
394a0e1a203SBarry Smith           notdone = PETSC_TRUE;
395a0e1a203SBarry Smith           nextcol = PetscMin(nextcol,ii[j][0]/bs);
396a0e1a203SBarry Smith         }
397a0e1a203SBarry Smith       }
398e32f2f54SBarry Smith       if (cnt >= amat->maxnz) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Number of blocks found greater than expected %D",cnt);
399a0e1a203SBarry Smith       if (!flg || currentcol >= i) {
400a0e1a203SBarry Smith         amat->j[cnt] = currentcol;
401a0e1a203SBarry Smith         ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,bs,bs,0,llens,amat->a+cnt++);CHKERRQ(ierr);
402a0e1a203SBarry Smith       }
403a0e1a203SBarry Smith 
404a0e1a203SBarry Smith       if (!notdone) break;
405a0e1a203SBarry Smith       currentcol = nextcol;
406a0e1a203SBarry Smith     }
407a0e1a203SBarry Smith     amat->ilen[i] = lens[i];
408a0e1a203SBarry Smith   }
409a0e1a203SBarry Smith   CHKMEMQ;
410a0e1a203SBarry Smith 
411a0e1a203SBarry Smith   ierr = PetscFree3(lens,ii,ilens);CHKERRQ(ierr);
412a0e1a203SBarry Smith   ierr = PetscFree(llens);CHKERRQ(ierr);
413a0e1a203SBarry Smith 
414a0e1a203SBarry Smith   /* copy over the matrix, one row at a time */
415421e10b8SBarry Smith   for (i=0; i<m; i++) {
416421e10b8SBarry Smith     ierr = MatGetRow(tmpA,i,&ncols,&cols,&values);CHKERRQ(ierr);
417421e10b8SBarry Smith     ierr = MatSetValues(*A,1,&i,ncols,cols,values,INSERT_VALUES);CHKERRQ(ierr);
418ccb205f8SBarry Smith     ierr = MatRestoreRow(tmpA,i,&ncols,&cols,&values);CHKERRQ(ierr);
419421e10b8SBarry Smith   }
420421e10b8SBarry Smith   ierr = MatAssemblyBegin(*A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
421421e10b8SBarry Smith   ierr = MatAssemblyEnd(*A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
422421e10b8SBarry Smith   PetscFunctionReturn(0);
423421e10b8SBarry Smith }
424421e10b8SBarry Smith 
425ccb205f8SBarry Smith #undef __FUNCT__
426*a5973382SShri Abhyankar #define __FUNCT__ "MatLoadnew_BlockMat"
427*a5973382SShri Abhyankar PetscErrorCode MatLoadnew_BlockMat(PetscViewer viewer, Mat newmat)
428*a5973382SShri Abhyankar {
429*a5973382SShri Abhyankar   PetscErrorCode    ierr;
430*a5973382SShri Abhyankar   Mat               tmpA;
431*a5973382SShri Abhyankar   PetscInt          i,j,m,n,bs = 1,ncols,*lens,currentcol,mbs,**ii,*ilens,nextcol,*llens,cnt = 0;
432*a5973382SShri Abhyankar   const PetscInt    *cols;
433*a5973382SShri Abhyankar   const PetscScalar *values;
434*a5973382SShri Abhyankar   PetscTruth        flg = PETSC_FALSE,notdone;
435*a5973382SShri Abhyankar   Mat_SeqAIJ        *a;
436*a5973382SShri Abhyankar   Mat_BlockMat      *amat;
437*a5973382SShri Abhyankar 
438*a5973382SShri Abhyankar   PetscFunctionBegin;
439*a5973382SShri Abhyankar   ierr = MatCreate(PETSC_COMM_SELF,&tmpA);CHKERRQ(ierr);
440*a5973382SShri Abhyankar   ierr = MatSetType(tmpA,MATSEQAIJ);CHKERRQ(ierr);
441*a5973382SShri Abhyankar   ierr = MatLoadnew_SeqAIJ(viewer,tmpA);CHKERRQ(ierr);
442*a5973382SShri Abhyankar 
443*a5973382SShri Abhyankar   ierr = MatGetLocalSize(tmpA,&m,&n);CHKERRQ(ierr);
444*a5973382SShri Abhyankar   ierr = PetscOptionsBegin(PETSC_COMM_SELF,PETSC_NULL,"Options for loading BlockMat matrix 1","Mat");CHKERRQ(ierr);
445*a5973382SShri Abhyankar   ierr = PetscOptionsInt("-matload_block_size","Set the blocksize used to store the matrix","MatLoad",bs,&bs,PETSC_NULL);CHKERRQ(ierr);
446*a5973382SShri Abhyankar   ierr = PetscOptionsTruth("-matload_symmetric","Store the matrix as symmetric","MatLoad",flg,&flg,PETSC_NULL);CHKERRQ(ierr);
447*a5973382SShri Abhyankar   ierr = PetscOptionsEnd();CHKERRQ(ierr);
448*a5973382SShri Abhyankar 
449*a5973382SShri Abhyankar   /* Determine number of nonzero blocks for each block row */
450*a5973382SShri Abhyankar   a    = (Mat_SeqAIJ*) tmpA->data;
451*a5973382SShri Abhyankar   mbs  = m/bs;
452*a5973382SShri Abhyankar   ierr = PetscMalloc3(mbs,PetscInt,&lens,bs,PetscInt*,&ii,bs,PetscInt,&ilens);CHKERRQ(ierr);
453*a5973382SShri Abhyankar   ierr = PetscMemzero(lens,mbs*sizeof(PetscInt));CHKERRQ(ierr);
454*a5973382SShri Abhyankar 
455*a5973382SShri Abhyankar   for (i=0; i<mbs; i++) {
456*a5973382SShri Abhyankar     for (j=0; j<bs; j++) {
457*a5973382SShri Abhyankar       ii[j]         = a->j + a->i[i*bs + j];
458*a5973382SShri Abhyankar       ilens[j]      = a->i[i*bs + j + 1] - a->i[i*bs + j];
459*a5973382SShri Abhyankar     }
460*a5973382SShri Abhyankar 
461*a5973382SShri Abhyankar     currentcol = -1;
462*a5973382SShri Abhyankar     notdone = PETSC_TRUE;
463*a5973382SShri Abhyankar     while (PETSC_TRUE) {
464*a5973382SShri Abhyankar       notdone = PETSC_FALSE;
465*a5973382SShri Abhyankar       nextcol = 1000000000;
466*a5973382SShri Abhyankar       for (j=0; j<bs; j++) {
467*a5973382SShri Abhyankar         while ((ilens[j] > 0 && ii[j][0]/bs <= currentcol)) {
468*a5973382SShri Abhyankar           ii[j]++;
469*a5973382SShri Abhyankar           ilens[j]--;
470*a5973382SShri Abhyankar         }
471*a5973382SShri Abhyankar         if (ilens[j] > 0) {
472*a5973382SShri Abhyankar           notdone = PETSC_TRUE;
473*a5973382SShri Abhyankar           nextcol = PetscMin(nextcol,ii[j][0]/bs);
474*a5973382SShri Abhyankar         }
475*a5973382SShri Abhyankar       }
476*a5973382SShri Abhyankar       if (!notdone) break;
477*a5973382SShri Abhyankar       if (!flg || (nextcol >= i)) lens[i]++;
478*a5973382SShri Abhyankar       currentcol = nextcol;
479*a5973382SShri Abhyankar     }
480*a5973382SShri Abhyankar   }
481*a5973382SShri Abhyankar 
482*a5973382SShri Abhyankar   if (newmat->rmap->n < 0 && newmat->rmap->N < 0 && newmat->cmap->n < 0 && newmat->cmap->N < 0) {
483*a5973382SShri Abhyankar     ierr = MatSetSizes(newmat,m,n,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
484*a5973382SShri Abhyankar   }
485*a5973382SShri Abhyankar   ierr = MatBlockMatSetPreallocation(newmat,bs,0,lens);CHKERRQ(ierr);
486*a5973382SShri Abhyankar   if (flg) {
487*a5973382SShri Abhyankar     ierr = MatSetOption(newmat,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
488*a5973382SShri Abhyankar   }
489*a5973382SShri Abhyankar   amat = (Mat_BlockMat*)(newmat)->data;
490*a5973382SShri Abhyankar 
491*a5973382SShri Abhyankar   /* preallocate the submatrices */
492*a5973382SShri Abhyankar   ierr = PetscMalloc(bs*sizeof(PetscInt),&llens);CHKERRQ(ierr);
493*a5973382SShri Abhyankar   for (i=0; i<mbs; i++) { /* loops for block rows */
494*a5973382SShri Abhyankar     for (j=0; j<bs; j++) {
495*a5973382SShri Abhyankar       ii[j]         = a->j + a->i[i*bs + j];
496*a5973382SShri Abhyankar       ilens[j]      = a->i[i*bs + j + 1] - a->i[i*bs + j];
497*a5973382SShri Abhyankar     }
498*a5973382SShri Abhyankar 
499*a5973382SShri Abhyankar     currentcol = 1000000000;
500*a5973382SShri Abhyankar     for (j=0; j<bs; j++) { /* loop over rows in block finding first nonzero block */
501*a5973382SShri Abhyankar       if (ilens[j] > 0) {
502*a5973382SShri Abhyankar 	currentcol = PetscMin(currentcol,ii[j][0]/bs);
503*a5973382SShri Abhyankar       }
504*a5973382SShri Abhyankar     }
505*a5973382SShri Abhyankar 
506*a5973382SShri Abhyankar     notdone = PETSC_TRUE;
507*a5973382SShri Abhyankar     while (PETSC_TRUE) {  /* loops over blocks in block row */
508*a5973382SShri Abhyankar 
509*a5973382SShri Abhyankar       notdone = PETSC_FALSE;
510*a5973382SShri Abhyankar       nextcol = 1000000000;
511*a5973382SShri Abhyankar       ierr = PetscMemzero(llens,bs*sizeof(PetscInt));CHKERRQ(ierr);
512*a5973382SShri Abhyankar       for (j=0; j<bs; j++) { /* loop over rows in block */
513*a5973382SShri Abhyankar         while ((ilens[j] > 0 && ii[j][0]/bs <= currentcol)) { /* loop over columns in row */
514*a5973382SShri Abhyankar           ii[j]++;
515*a5973382SShri Abhyankar           ilens[j]--;
516*a5973382SShri Abhyankar           llens[j]++;
517*a5973382SShri Abhyankar         }
518*a5973382SShri Abhyankar         if (ilens[j] > 0) {
519*a5973382SShri Abhyankar           notdone = PETSC_TRUE;
520*a5973382SShri Abhyankar           nextcol = PetscMin(nextcol,ii[j][0]/bs);
521*a5973382SShri Abhyankar         }
522*a5973382SShri Abhyankar       }
523*a5973382SShri Abhyankar       if (cnt >= amat->maxnz) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Number of blocks found greater than expected %D",cnt);
524*a5973382SShri Abhyankar       if (!flg || currentcol >= i) {
525*a5973382SShri Abhyankar         amat->j[cnt] = currentcol;
526*a5973382SShri Abhyankar         ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,bs,bs,0,llens,amat->a+cnt++);CHKERRQ(ierr);
527*a5973382SShri Abhyankar       }
528*a5973382SShri Abhyankar 
529*a5973382SShri Abhyankar       if (!notdone) break;
530*a5973382SShri Abhyankar       currentcol = nextcol;
531*a5973382SShri Abhyankar     }
532*a5973382SShri Abhyankar     amat->ilen[i] = lens[i];
533*a5973382SShri Abhyankar   }
534*a5973382SShri Abhyankar   CHKMEMQ;
535*a5973382SShri Abhyankar 
536*a5973382SShri Abhyankar   ierr = PetscFree3(lens,ii,ilens);CHKERRQ(ierr);
537*a5973382SShri Abhyankar   ierr = PetscFree(llens);CHKERRQ(ierr);
538*a5973382SShri Abhyankar 
539*a5973382SShri Abhyankar   /* copy over the matrix, one row at a time */
540*a5973382SShri Abhyankar   for (i=0; i<m; i++) {
541*a5973382SShri Abhyankar     ierr = MatGetRow(tmpA,i,&ncols,&cols,&values);CHKERRQ(ierr);
542*a5973382SShri Abhyankar     ierr = MatSetValues(newmat,1,&i,ncols,cols,values,INSERT_VALUES);CHKERRQ(ierr);
543*a5973382SShri Abhyankar     ierr = MatRestoreRow(tmpA,i,&ncols,&cols,&values);CHKERRQ(ierr);
544*a5973382SShri Abhyankar   }
545*a5973382SShri Abhyankar   ierr = MatAssemblyBegin(newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
546*a5973382SShri Abhyankar   ierr = MatAssemblyEnd(newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
547*a5973382SShri Abhyankar   PetscFunctionReturn(0);
548*a5973382SShri Abhyankar }
549*a5973382SShri Abhyankar 
550*a5973382SShri Abhyankar #undef __FUNCT__
551ccb205f8SBarry Smith #define __FUNCT__ "MatView_BlockMat"
552ccb205f8SBarry Smith PetscErrorCode MatView_BlockMat(Mat A,PetscViewer viewer)
553ccb205f8SBarry Smith {
55464075487SBarry Smith   Mat_BlockMat      *a = (Mat_BlockMat*)A->data;
555ccb205f8SBarry Smith   PetscErrorCode    ierr;
556ccb205f8SBarry Smith   const char        *name;
557ccb205f8SBarry Smith   PetscViewerFormat format;
558ccb205f8SBarry Smith 
559ccb205f8SBarry Smith   PetscFunctionBegin;
560ccb205f8SBarry Smith   ierr = PetscObjectGetName((PetscObject)A,&name);CHKERRQ(ierr);
561ccb205f8SBarry Smith   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
562ccb205f8SBarry Smith   if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO) {
563ccb205f8SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Nonzero block matrices = %D \n",a->nz);CHKERRQ(ierr);
56464075487SBarry Smith     if (A->symmetric) {
5658c1ad04dSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"Only upper triangular part of symmetric matrix is stored\n");CHKERRQ(ierr);
56664075487SBarry Smith     }
567ccb205f8SBarry Smith   }
568ccb205f8SBarry Smith   PetscFunctionReturn(0);
569ccb205f8SBarry Smith }
570421e10b8SBarry Smith 
571421e10b8SBarry Smith #undef __FUNCT__
572421e10b8SBarry Smith #define __FUNCT__ "MatDestroy_BlockMat"
573421e10b8SBarry Smith PetscErrorCode MatDestroy_BlockMat(Mat mat)
574421e10b8SBarry Smith {
575421e10b8SBarry Smith   PetscErrorCode ierr;
576421e10b8SBarry Smith   Mat_BlockMat   *bmat = (Mat_BlockMat*)mat->data;
577ccb205f8SBarry Smith   PetscInt       i;
578421e10b8SBarry Smith 
579421e10b8SBarry Smith   PetscFunctionBegin;
580421e10b8SBarry Smith   if (bmat->right) {
581421e10b8SBarry Smith     ierr = VecDestroy(bmat->right);CHKERRQ(ierr);
582421e10b8SBarry Smith   }
583421e10b8SBarry Smith   if (bmat->left) {
584421e10b8SBarry Smith     ierr = VecDestroy(bmat->left);CHKERRQ(ierr);
585421e10b8SBarry Smith   }
586290bbb0aSBarry Smith   if (bmat->middle) {
587290bbb0aSBarry Smith     ierr = VecDestroy(bmat->middle);CHKERRQ(ierr);
588290bbb0aSBarry Smith   }
5896e63c7a1SBarry Smith   if (bmat->workb) {
5906e63c7a1SBarry Smith     ierr = VecDestroy(bmat->workb);CHKERRQ(ierr);
5916e63c7a1SBarry Smith   }
592ccb205f8SBarry Smith   if (bmat->diags) {
593d0f46423SBarry Smith     for (i=0; i<mat->rmap->n/mat->rmap->bs; i++) {
594ccb205f8SBarry Smith       if (bmat->diags[i]) {ierr = MatDestroy(bmat->diags[i]);CHKERRQ(ierr);}
595ccb205f8SBarry Smith     }
596ccb205f8SBarry Smith   }
597ccb205f8SBarry Smith   if (bmat->a) {
598ccb205f8SBarry Smith     for (i=0; i<bmat->nz; i++) {
599ccb205f8SBarry Smith       if (bmat->a[i]) {ierr = MatDestroy(bmat->a[i]);CHKERRQ(ierr);}
600ccb205f8SBarry Smith     }
601ccb205f8SBarry Smith   }
602ccb205f8SBarry Smith   ierr = MatSeqXAIJFreeAIJ(mat,(PetscScalar**)&bmat->a,&bmat->j,&bmat->i);CHKERRQ(ierr);
603421e10b8SBarry Smith   ierr = PetscFree(bmat);CHKERRQ(ierr);
604421e10b8SBarry Smith   PetscFunctionReturn(0);
605421e10b8SBarry Smith }
606421e10b8SBarry Smith 
607421e10b8SBarry Smith #undef __FUNCT__
608421e10b8SBarry Smith #define __FUNCT__ "MatMult_BlockMat"
609421e10b8SBarry Smith PetscErrorCode MatMult_BlockMat(Mat A,Vec x,Vec y)
610421e10b8SBarry Smith {
611421e10b8SBarry Smith   Mat_BlockMat   *bmat = (Mat_BlockMat*)A->data;
612421e10b8SBarry Smith   PetscErrorCode ierr;
613421e10b8SBarry Smith   PetscScalar    *xx,*yy;
614d0f46423SBarry Smith   PetscInt       *aj,i,*ii,jrow,m = A->rmap->n/A->rmap->bs,bs = A->rmap->bs,n,j;
615421e10b8SBarry Smith   Mat            *aa;
616421e10b8SBarry Smith 
617421e10b8SBarry Smith   PetscFunctionBegin;
618ccb205f8SBarry Smith   CHKMEMQ;
619421e10b8SBarry Smith   /*
620421e10b8SBarry Smith      Standard CSR multiply except each entry is a Mat
621421e10b8SBarry Smith   */
622421e10b8SBarry Smith   ierr = VecGetArray(x,&xx);CHKERRQ(ierr);
623ccb205f8SBarry Smith 
624421e10b8SBarry Smith   ierr = VecSet(y,0.0);CHKERRQ(ierr);
625421e10b8SBarry Smith   ierr = VecGetArray(y,&yy);CHKERRQ(ierr);
626421e10b8SBarry Smith   aj  = bmat->j;
627421e10b8SBarry Smith   aa  = bmat->a;
628421e10b8SBarry Smith   ii  = bmat->i;
629421e10b8SBarry Smith   for (i=0; i<m; i++) {
630421e10b8SBarry Smith     jrow = ii[i];
631ccb205f8SBarry Smith     ierr = VecPlaceArray(bmat->left,yy + bs*i);CHKERRQ(ierr);
632421e10b8SBarry Smith     n    = ii[i+1] - jrow;
633421e10b8SBarry Smith     for (j=0; j<n; j++) {
634421e10b8SBarry Smith       ierr = VecPlaceArray(bmat->right,xx + bs*aj[jrow]);CHKERRQ(ierr);
635ccb205f8SBarry Smith       ierr = MatMultAdd(aa[jrow],bmat->right,bmat->left,bmat->left);CHKERRQ(ierr);
636421e10b8SBarry Smith       ierr = VecResetArray(bmat->right);CHKERRQ(ierr);
637421e10b8SBarry Smith       jrow++;
638421e10b8SBarry Smith     }
639421e10b8SBarry Smith     ierr = VecResetArray(bmat->left);CHKERRQ(ierr);
640421e10b8SBarry Smith   }
641421e10b8SBarry Smith   ierr = VecRestoreArray(x,&xx);CHKERRQ(ierr);
642421e10b8SBarry Smith   ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr);
643ccb205f8SBarry Smith   CHKMEMQ;
644421e10b8SBarry Smith   PetscFunctionReturn(0);
645421e10b8SBarry Smith }
646421e10b8SBarry Smith 
647421e10b8SBarry Smith #undef __FUNCT__
648290bbb0aSBarry Smith #define __FUNCT__ "MatMult_BlockMat_Symmetric"
649290bbb0aSBarry Smith PetscErrorCode MatMult_BlockMat_Symmetric(Mat A,Vec x,Vec y)
650290bbb0aSBarry Smith {
651290bbb0aSBarry Smith   Mat_BlockMat   *bmat = (Mat_BlockMat*)A->data;
652290bbb0aSBarry Smith   PetscErrorCode ierr;
653290bbb0aSBarry Smith   PetscScalar    *xx,*yy;
654d0f46423SBarry Smith   PetscInt       *aj,i,*ii,jrow,m = A->rmap->n/A->rmap->bs,bs = A->rmap->bs,n,j;
655290bbb0aSBarry Smith   Mat            *aa;
656290bbb0aSBarry Smith 
657290bbb0aSBarry Smith   PetscFunctionBegin;
658290bbb0aSBarry Smith   CHKMEMQ;
659290bbb0aSBarry Smith   /*
660290bbb0aSBarry Smith      Standard CSR multiply except each entry is a Mat
661290bbb0aSBarry Smith   */
662290bbb0aSBarry Smith   ierr = VecGetArray(x,&xx);CHKERRQ(ierr);
663290bbb0aSBarry Smith 
664290bbb0aSBarry Smith   ierr = VecSet(y,0.0);CHKERRQ(ierr);
665290bbb0aSBarry Smith   ierr = VecGetArray(y,&yy);CHKERRQ(ierr);
666290bbb0aSBarry Smith   aj  = bmat->j;
667290bbb0aSBarry Smith   aa  = bmat->a;
668290bbb0aSBarry Smith   ii  = bmat->i;
669290bbb0aSBarry Smith   for (i=0; i<m; i++) {
670290bbb0aSBarry Smith     jrow = ii[i];
671290bbb0aSBarry Smith     n    = ii[i+1] - jrow;
672290bbb0aSBarry Smith     ierr = VecPlaceArray(bmat->left,yy + bs*i);CHKERRQ(ierr);
673290bbb0aSBarry Smith     ierr = VecPlaceArray(bmat->middle,xx + bs*i);CHKERRQ(ierr);
674290bbb0aSBarry Smith     /* if we ALWAYS required a diagonal entry then could remove this if test */
675290bbb0aSBarry Smith     if (aj[jrow] == i) {
676290bbb0aSBarry Smith       ierr = VecPlaceArray(bmat->right,xx + bs*aj[jrow]);CHKERRQ(ierr);
677290bbb0aSBarry Smith       ierr = MatMultAdd(aa[jrow],bmat->right,bmat->left,bmat->left);CHKERRQ(ierr);
678290bbb0aSBarry Smith       ierr = VecResetArray(bmat->right);CHKERRQ(ierr);
679290bbb0aSBarry Smith       jrow++;
680290bbb0aSBarry Smith       n--;
681290bbb0aSBarry Smith     }
682290bbb0aSBarry Smith     for (j=0; j<n; j++) {
683290bbb0aSBarry Smith       ierr = VecPlaceArray(bmat->right,xx + bs*aj[jrow]);CHKERRQ(ierr);            /* upper triangular part */
684290bbb0aSBarry Smith       ierr = MatMultAdd(aa[jrow],bmat->right,bmat->left,bmat->left);CHKERRQ(ierr);
685290bbb0aSBarry Smith       ierr = VecResetArray(bmat->right);CHKERRQ(ierr);
686290bbb0aSBarry Smith 
687290bbb0aSBarry Smith       ierr = VecPlaceArray(bmat->right,yy + bs*aj[jrow]);CHKERRQ(ierr);            /* lower triangular part */
688290bbb0aSBarry Smith       ierr = MatMultTransposeAdd(aa[jrow],bmat->middle,bmat->right,bmat->right);CHKERRQ(ierr);
689290bbb0aSBarry Smith       ierr = VecResetArray(bmat->right);CHKERRQ(ierr);
690290bbb0aSBarry Smith       jrow++;
691290bbb0aSBarry Smith     }
692290bbb0aSBarry Smith     ierr = VecResetArray(bmat->left);CHKERRQ(ierr);
693290bbb0aSBarry Smith     ierr = VecResetArray(bmat->middle);CHKERRQ(ierr);
694290bbb0aSBarry Smith   }
695290bbb0aSBarry Smith   ierr = VecRestoreArray(x,&xx);CHKERRQ(ierr);
696290bbb0aSBarry Smith   ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr);
697290bbb0aSBarry Smith   CHKMEMQ;
698290bbb0aSBarry Smith   PetscFunctionReturn(0);
699290bbb0aSBarry Smith }
700290bbb0aSBarry Smith 
701290bbb0aSBarry Smith #undef __FUNCT__
702421e10b8SBarry Smith #define __FUNCT__ "MatMultAdd_BlockMat"
703421e10b8SBarry Smith PetscErrorCode MatMultAdd_BlockMat(Mat A,Vec x,Vec y,Vec z)
704421e10b8SBarry Smith {
705421e10b8SBarry Smith   PetscFunctionBegin;
706421e10b8SBarry Smith   PetscFunctionReturn(0);
707421e10b8SBarry Smith }
708421e10b8SBarry Smith 
709421e10b8SBarry Smith #undef __FUNCT__
710421e10b8SBarry Smith #define __FUNCT__ "MatMultTranspose_BlockMat"
711421e10b8SBarry Smith PetscErrorCode MatMultTranspose_BlockMat(Mat A,Vec x,Vec y)
712421e10b8SBarry Smith {
713421e10b8SBarry Smith   PetscFunctionBegin;
714421e10b8SBarry Smith   PetscFunctionReturn(0);
715421e10b8SBarry Smith }
716421e10b8SBarry Smith 
717421e10b8SBarry Smith #undef __FUNCT__
718421e10b8SBarry Smith #define __FUNCT__ "MatMultTransposeAdd_BlockMat"
719421e10b8SBarry Smith PetscErrorCode MatMultTransposeAdd_BlockMat(Mat A,Vec x,Vec y,Vec z)
720421e10b8SBarry Smith {
721421e10b8SBarry Smith   PetscFunctionBegin;
722421e10b8SBarry Smith   PetscFunctionReturn(0);
723421e10b8SBarry Smith }
724421e10b8SBarry Smith 
725ccb205f8SBarry Smith /*
726ccb205f8SBarry Smith      Adds diagonal pointers to sparse matrix structure.
727ccb205f8SBarry Smith */
728ccb205f8SBarry Smith #undef __FUNCT__
729ccb205f8SBarry Smith #define __FUNCT__ "MatMarkDiagonal_BlockMat"
730ccb205f8SBarry Smith PetscErrorCode MatMarkDiagonal_BlockMat(Mat A)
731ccb205f8SBarry Smith {
732ccb205f8SBarry Smith   Mat_BlockMat   *a = (Mat_BlockMat*)A->data;
733ccb205f8SBarry Smith   PetscErrorCode ierr;
734d0f46423SBarry Smith   PetscInt       i,j,mbs = A->rmap->n/A->rmap->bs;
735ccb205f8SBarry Smith 
736ccb205f8SBarry Smith   PetscFunctionBegin;
737ccb205f8SBarry Smith   if (!a->diag) {
738ccb205f8SBarry Smith     ierr = PetscMalloc(mbs*sizeof(PetscInt),&a->diag);CHKERRQ(ierr);
739ccb205f8SBarry Smith   }
740ccb205f8SBarry Smith   for (i=0; i<mbs; i++) {
741ccb205f8SBarry Smith     a->diag[i] = a->i[i+1];
742ccb205f8SBarry Smith     for (j=a->i[i]; j<a->i[i+1]; j++) {
743ccb205f8SBarry Smith       if (a->j[j] == i) {
744ccb205f8SBarry Smith         a->diag[i] = j;
745ccb205f8SBarry Smith         break;
746ccb205f8SBarry Smith       }
747ccb205f8SBarry Smith     }
748ccb205f8SBarry Smith   }
749ccb205f8SBarry Smith   PetscFunctionReturn(0);
750ccb205f8SBarry Smith }
751ccb205f8SBarry Smith 
752ccb205f8SBarry Smith #undef __FUNCT__
753ccb205f8SBarry Smith #define __FUNCT__ "MatGetSubMatrix_BlockMat"
7544aa3045dSJed Brown PetscErrorCode MatGetSubMatrix_BlockMat(Mat A,IS isrow,IS iscol,MatReuse scall,Mat *B)
755ccb205f8SBarry Smith {
756ccb205f8SBarry Smith   Mat_BlockMat   *a = (Mat_BlockMat*)A->data;
757ccb205f8SBarry Smith   Mat_SeqAIJ     *c;
758ccb205f8SBarry Smith   PetscErrorCode ierr;
759ccb205f8SBarry Smith   PetscInt       i,k,first,step,lensi,nrows,ncols;
760d2a212eaSBarry Smith   PetscInt       *j_new,*i_new,*aj = a->j,*ailen = a->ilen;
7611620fd73SBarry Smith   PetscScalar    *a_new;
762ccb205f8SBarry Smith   Mat            C,*aa = a->a;
763ccb205f8SBarry Smith   PetscTruth     stride,equal;
764ccb205f8SBarry Smith 
765ccb205f8SBarry Smith   PetscFunctionBegin;
766ccb205f8SBarry Smith   ierr = ISEqual(isrow,iscol,&equal);CHKERRQ(ierr);
767e32f2f54SBarry Smith   if (!equal) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only for idential column and row indices");
768ccb205f8SBarry Smith   ierr = ISStride(iscol,&stride);CHKERRQ(ierr);
769e32f2f54SBarry Smith   if (!stride) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only for stride indices");
770ccb205f8SBarry Smith   ierr = ISStrideGetInfo(iscol,&first,&step);CHKERRQ(ierr);
771e32f2f54SBarry Smith   if (step != A->rmap->bs) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Can only select one entry from each block");
772ccb205f8SBarry Smith 
773ccb205f8SBarry Smith   ierr = ISGetLocalSize(isrow,&nrows);CHKERRQ(ierr);
774ccb205f8SBarry Smith   ncols = nrows;
775ccb205f8SBarry Smith 
776ccb205f8SBarry Smith   /* create submatrix */
777ccb205f8SBarry Smith   if (scall == MAT_REUSE_MATRIX) {
778ccb205f8SBarry Smith     PetscInt n_cols,n_rows;
779ccb205f8SBarry Smith     C = *B;
780ccb205f8SBarry Smith     ierr = MatGetSize(C,&n_rows,&n_cols);CHKERRQ(ierr);
781e32f2f54SBarry Smith     if (n_rows != nrows || n_cols != ncols) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Reused submatrix wrong size");
782ccb205f8SBarry Smith     ierr = MatZeroEntries(C);CHKERRQ(ierr);
783ccb205f8SBarry Smith   } else {
7847adad957SLisandro Dalcin     ierr = MatCreate(((PetscObject)A)->comm,&C);CHKERRQ(ierr);
785ccb205f8SBarry Smith     ierr = MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
7866e63c7a1SBarry Smith     if (A->symmetric) {
7876e63c7a1SBarry Smith       ierr = MatSetType(C,MATSEQSBAIJ);CHKERRQ(ierr);
7886e63c7a1SBarry Smith     } else {
789ccb205f8SBarry Smith       ierr = MatSetType(C,MATSEQAIJ);CHKERRQ(ierr);
7906e63c7a1SBarry Smith     }
7916e63c7a1SBarry Smith     ierr = MatSeqAIJSetPreallocation(C,0,ailen);CHKERRQ(ierr);
7926e63c7a1SBarry Smith     ierr = MatSeqSBAIJSetPreallocation(C,1,0,ailen);CHKERRQ(ierr);
793ccb205f8SBarry Smith   }
794ccb205f8SBarry Smith   c = (Mat_SeqAIJ*)C->data;
795ccb205f8SBarry Smith 
796ccb205f8SBarry Smith   /* loop over rows inserting into submatrix */
797ccb205f8SBarry Smith   a_new    = c->a;
798ccb205f8SBarry Smith   j_new    = c->j;
799ccb205f8SBarry Smith   i_new    = c->i;
800ccb205f8SBarry Smith 
801ccb205f8SBarry Smith   for (i=0; i<nrows; i++) {
802ccb205f8SBarry Smith     lensi = ailen[i];
803ccb205f8SBarry Smith     for (k=0; k<lensi; k++) {
804ccb205f8SBarry Smith       *j_new++ = *aj++;
8051620fd73SBarry Smith       ierr     = MatGetValue(*aa++,first,first,a_new++);CHKERRQ(ierr);
806ccb205f8SBarry Smith     }
807ccb205f8SBarry Smith     i_new[i+1]  = i_new[i] + lensi;
808ccb205f8SBarry Smith     c->ilen[i]  = lensi;
809ccb205f8SBarry Smith   }
810ccb205f8SBarry Smith 
811ccb205f8SBarry Smith   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
812ccb205f8SBarry Smith   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
813ccb205f8SBarry Smith   *B = C;
814ccb205f8SBarry Smith   PetscFunctionReturn(0);
815ccb205f8SBarry Smith }
816ccb205f8SBarry Smith 
817421e10b8SBarry Smith #undef __FUNCT__
818421e10b8SBarry Smith #define __FUNCT__ "MatAssemblyEnd_BlockMat"
819421e10b8SBarry Smith PetscErrorCode MatAssemblyEnd_BlockMat(Mat A,MatAssemblyType mode)
820421e10b8SBarry Smith {
821421e10b8SBarry Smith   Mat_BlockMat   *a = (Mat_BlockMat*)A->data;
822421e10b8SBarry Smith   PetscErrorCode ierr;
823421e10b8SBarry Smith   PetscInt       fshift = 0,i,j,*ai = a->i,*aj = a->j,*imax = a->imax;
824ccb205f8SBarry Smith   PetscInt       m = a->mbs,*ip,N,*ailen = a->ilen,rmax = 0;
825421e10b8SBarry Smith   Mat            *aa = a->a,*ap;
826421e10b8SBarry Smith 
827421e10b8SBarry Smith   PetscFunctionBegin;
828421e10b8SBarry Smith   if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0);
829421e10b8SBarry Smith 
830421e10b8SBarry Smith   if (m) rmax = ailen[0]; /* determine row with most nonzeros */
831421e10b8SBarry Smith   for (i=1; i<m; i++) {
832421e10b8SBarry Smith     /* move each row back by the amount of empty slots (fshift) before it*/
833421e10b8SBarry Smith     fshift += imax[i-1] - ailen[i-1];
834421e10b8SBarry Smith     rmax   = PetscMax(rmax,ailen[i]);
835421e10b8SBarry Smith     if (fshift) {
836421e10b8SBarry Smith       ip = aj + ai[i] ;
837421e10b8SBarry Smith       ap = aa + ai[i] ;
838421e10b8SBarry Smith       N  = ailen[i];
839421e10b8SBarry Smith       for (j=0; j<N; j++) {
840421e10b8SBarry Smith         ip[j-fshift] = ip[j];
841421e10b8SBarry Smith         ap[j-fshift] = ap[j];
842421e10b8SBarry Smith       }
843421e10b8SBarry Smith     }
844421e10b8SBarry Smith     ai[i] = ai[i-1] + ailen[i-1];
845421e10b8SBarry Smith   }
846421e10b8SBarry Smith   if (m) {
847421e10b8SBarry Smith     fshift += imax[m-1] - ailen[m-1];
848421e10b8SBarry Smith     ai[m]  = ai[m-1] + ailen[m-1];
849421e10b8SBarry Smith   }
850421e10b8SBarry Smith   /* reset ilen and imax for each row */
851421e10b8SBarry Smith   for (i=0; i<m; i++) {
852421e10b8SBarry Smith     ailen[i] = imax[i] = ai[i+1] - ai[i];
853421e10b8SBarry Smith   }
854421e10b8SBarry Smith   a->nz = ai[m];
855ccb205f8SBarry Smith   for (i=0; i<a->nz; i++) {
856ccb205f8SBarry Smith #if defined(PETSC_USE_DEBUG)
857e32f2f54SBarry 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);
858ccb205f8SBarry Smith #endif
859ccb205f8SBarry Smith     ierr = MatAssemblyBegin(aa[i],MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
860ccb205f8SBarry Smith     ierr = MatAssemblyEnd(aa[i],MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
861ccb205f8SBarry Smith   }
862ccb205f8SBarry Smith   CHKMEMQ;
863d0f46423SBarry 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);
864421e10b8SBarry Smith   ierr = PetscInfo1(A,"Number of mallocs during MatSetValues() is %D\n",a->reallocs);CHKERRQ(ierr);
865421e10b8SBarry Smith   ierr = PetscInfo1(A,"Maximum nonzeros in any row is %D\n",rmax);CHKERRQ(ierr);
8668e58a170SBarry Smith   A->info.mallocs     += a->reallocs;
867421e10b8SBarry Smith   a->reallocs          = 0;
868421e10b8SBarry Smith   A->info.nz_unneeded  = (double)fshift;
869421e10b8SBarry Smith   a->rmax              = rmax;
870421e10b8SBarry Smith 
871421e10b8SBarry Smith   A->same_nonzero = PETSC_TRUE;
872ccb205f8SBarry Smith   ierr = MatMarkDiagonal_BlockMat(A);CHKERRQ(ierr);
873421e10b8SBarry Smith   PetscFunctionReturn(0);
874421e10b8SBarry Smith }
875421e10b8SBarry Smith 
876290bbb0aSBarry Smith #undef __FUNCT__
877290bbb0aSBarry Smith #define __FUNCT__ "MatSetOption_BlockMat"
8784e0d8c25SBarry Smith PetscErrorCode MatSetOption_BlockMat(Mat A,MatOption opt,PetscTruth flg)
879290bbb0aSBarry Smith {
880290bbb0aSBarry Smith   PetscFunctionBegin;
8814e0d8c25SBarry Smith   if (opt == MAT_SYMMETRIC && flg) {
88241f059aeSBarry Smith     A->ops->sor = MatSOR_BlockMat_Symmetric;
883290bbb0aSBarry Smith     A->ops->mult  = MatMult_BlockMat_Symmetric;
884290bbb0aSBarry Smith   } else {
885290bbb0aSBarry Smith     PetscInfo1(A,"Unused matrix option %s\n",MatOptions[opt]);
886290bbb0aSBarry Smith   }
887290bbb0aSBarry Smith   PetscFunctionReturn(0);
888290bbb0aSBarry Smith }
889290bbb0aSBarry Smith 
890290bbb0aSBarry Smith 
891421e10b8SBarry Smith static struct _MatOps MatOps_Values = {MatSetValues_BlockMat,
892421e10b8SBarry Smith        0,
893421e10b8SBarry Smith        0,
894421e10b8SBarry Smith        MatMult_BlockMat,
895421e10b8SBarry Smith /* 4*/ MatMultAdd_BlockMat,
896421e10b8SBarry Smith        MatMultTranspose_BlockMat,
897421e10b8SBarry Smith        MatMultTransposeAdd_BlockMat,
898421e10b8SBarry Smith        0,
899421e10b8SBarry Smith        0,
900421e10b8SBarry Smith        0,
901421e10b8SBarry Smith /*10*/ 0,
902421e10b8SBarry Smith        0,
903421e10b8SBarry Smith        0,
90441f059aeSBarry Smith        MatSOR_BlockMat,
905421e10b8SBarry Smith        0,
906421e10b8SBarry Smith /*15*/ 0,
907421e10b8SBarry Smith        0,
908421e10b8SBarry Smith        0,
909421e10b8SBarry Smith        0,
910421e10b8SBarry Smith        0,
911421e10b8SBarry Smith /*20*/ 0,
912421e10b8SBarry Smith        MatAssemblyEnd_BlockMat,
913290bbb0aSBarry Smith        MatSetOption_BlockMat,
914421e10b8SBarry Smith        0,
915d519adbfSMatthew Knepley /*24*/ 0,
916421e10b8SBarry Smith        0,
917421e10b8SBarry Smith        0,
918421e10b8SBarry Smith        0,
919421e10b8SBarry Smith        0,
920d519adbfSMatthew Knepley /*29*/ 0,
921421e10b8SBarry Smith        0,
922421e10b8SBarry Smith        0,
923421e10b8SBarry Smith        0,
924421e10b8SBarry Smith        0,
925d519adbfSMatthew Knepley /*34*/ 0,
926421e10b8SBarry Smith        0,
927421e10b8SBarry Smith        0,
928421e10b8SBarry Smith        0,
929421e10b8SBarry Smith        0,
930d519adbfSMatthew Knepley /*39*/ 0,
931421e10b8SBarry Smith        0,
932421e10b8SBarry Smith        0,
933421e10b8SBarry Smith        0,
934421e10b8SBarry Smith        0,
935d519adbfSMatthew Knepley /*44*/ 0,
936421e10b8SBarry Smith        0,
937421e10b8SBarry Smith        0,
938421e10b8SBarry Smith        0,
939421e10b8SBarry Smith        0,
940d519adbfSMatthew Knepley /*49*/ 0,
941421e10b8SBarry Smith        0,
942421e10b8SBarry Smith        0,
943421e10b8SBarry Smith        0,
944421e10b8SBarry Smith        0,
945d519adbfSMatthew Knepley /*54*/ 0,
946421e10b8SBarry Smith        0,
947421e10b8SBarry Smith        0,
948421e10b8SBarry Smith        0,
949421e10b8SBarry Smith        0,
950d519adbfSMatthew Knepley /*59*/ MatGetSubMatrix_BlockMat,
951421e10b8SBarry Smith        MatDestroy_BlockMat,
952ccb205f8SBarry Smith        MatView_BlockMat,
953421e10b8SBarry Smith        0,
954421e10b8SBarry Smith        0,
955d519adbfSMatthew Knepley /*64*/ 0,
956421e10b8SBarry Smith        0,
957421e10b8SBarry Smith        0,
958421e10b8SBarry Smith        0,
959421e10b8SBarry Smith        0,
960d519adbfSMatthew Knepley /*69*/ 0,
961421e10b8SBarry Smith        0,
962421e10b8SBarry Smith        0,
963421e10b8SBarry Smith        0,
964421e10b8SBarry Smith        0,
965d519adbfSMatthew Knepley /*74*/ 0,
966421e10b8SBarry Smith        0,
967421e10b8SBarry Smith        0,
968421e10b8SBarry Smith        0,
969421e10b8SBarry Smith        0,
970d519adbfSMatthew Knepley /*79*/ 0,
971421e10b8SBarry Smith        0,
972421e10b8SBarry Smith        0,
973421e10b8SBarry Smith        0,
974421e10b8SBarry Smith        MatLoad_BlockMat,
975d519adbfSMatthew Knepley /*84*/ 0,
976421e10b8SBarry Smith        0,
977421e10b8SBarry Smith        0,
978421e10b8SBarry Smith        0,
979421e10b8SBarry Smith        0,
980d519adbfSMatthew Knepley /*89*/ 0,
981421e10b8SBarry Smith        0,
982421e10b8SBarry Smith        0,
983421e10b8SBarry Smith        0,
984421e10b8SBarry Smith        0,
985d519adbfSMatthew Knepley /*94*/ 0,
986421e10b8SBarry Smith        0,
987421e10b8SBarry Smith        0,
988*a5973382SShri Abhyankar        0,
989*a5973382SShri Abhyankar        0,
990*a5973382SShri Abhyankar /*99*/ 0,
991*a5973382SShri Abhyankar        0,
992*a5973382SShri Abhyankar        0,
993*a5973382SShri Abhyankar        0,
994*a5973382SShri Abhyankar        0,
995*a5973382SShri Abhyankar /*104*/0,
996*a5973382SShri Abhyankar        0,
997*a5973382SShri Abhyankar        0,
998*a5973382SShri Abhyankar        0,
999*a5973382SShri Abhyankar        0,
1000*a5973382SShri Abhyankar /*109*/0,
1001*a5973382SShri Abhyankar        0,
1002*a5973382SShri Abhyankar        0,
1003*a5973382SShri Abhyankar        0,
1004*a5973382SShri Abhyankar        0,
1005*a5973382SShri Abhyankar /*114*/0,
1006*a5973382SShri Abhyankar        0,
1007*a5973382SShri Abhyankar        0,
1008*a5973382SShri Abhyankar        0,
1009*a5973382SShri Abhyankar        0,
1010*a5973382SShri Abhyankar /*119*/0,
1011*a5973382SShri Abhyankar        0,
1012*a5973382SShri Abhyankar        0,
1013*a5973382SShri Abhyankar        0,
1014*a5973382SShri Abhyankar        MatLoadnew_BlockMat
1015*a5973382SShri Abhyankar };
1016421e10b8SBarry Smith 
10178cdf2d9bSBarry Smith #undef __FUNCT__
10188cdf2d9bSBarry Smith #define __FUNCT__ "MatBlockMatSetPreallocation"
10198cdf2d9bSBarry Smith /*@C
10208cdf2d9bSBarry Smith    MatBlockMatSetPreallocation - For good matrix assembly performance
10218cdf2d9bSBarry Smith    the user should preallocate the matrix storage by setting the parameter nz
10228cdf2d9bSBarry Smith    (or the array nnz).  By setting these parameters accurately, performance
10238cdf2d9bSBarry Smith    during matrix assembly can be increased by more than a factor of 50.
10248cdf2d9bSBarry Smith 
10258cdf2d9bSBarry Smith    Collective on MPI_Comm
10268cdf2d9bSBarry Smith 
10278cdf2d9bSBarry Smith    Input Parameters:
10288cdf2d9bSBarry Smith +  B - The matrix
10298cdf2d9bSBarry Smith .  bs - size of each block in matrix
10308cdf2d9bSBarry Smith .  nz - number of nonzeros per block row (same for all rows)
10318cdf2d9bSBarry Smith -  nnz - array containing the number of nonzeros in the various block rows
10328cdf2d9bSBarry Smith          (possibly different for each row) or PETSC_NULL
10338cdf2d9bSBarry Smith 
10348cdf2d9bSBarry Smith    Notes:
10358cdf2d9bSBarry Smith      If nnz is given then nz is ignored
10368cdf2d9bSBarry Smith 
10378cdf2d9bSBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
10388cdf2d9bSBarry Smith    Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory
10398cdf2d9bSBarry Smith    allocation.  For large problems you MUST preallocate memory or you
10408cdf2d9bSBarry Smith    will get TERRIBLE performance, see the users' manual chapter on matrices.
10418cdf2d9bSBarry Smith 
10428cdf2d9bSBarry Smith    Level: intermediate
10438cdf2d9bSBarry Smith 
10448cdf2d9bSBarry Smith .seealso: MatCreate(), MatCreateBlockMat(), MatSetValues()
10458cdf2d9bSBarry Smith 
10468cdf2d9bSBarry Smith @*/
10478cdf2d9bSBarry Smith PetscErrorCode PETSCMAT_DLLEXPORT MatBlockMatSetPreallocation(Mat B,PetscInt bs,PetscInt nz,const PetscInt nnz[])
10488cdf2d9bSBarry Smith {
10498cdf2d9bSBarry Smith   PetscErrorCode ierr,(*f)(Mat,PetscInt,PetscInt,const PetscInt[]);
10508cdf2d9bSBarry Smith 
10518cdf2d9bSBarry Smith   PetscFunctionBegin;
10528cdf2d9bSBarry Smith   ierr = PetscObjectQueryFunction((PetscObject)B,"MatBlockMatSetPreallocation_C",(void (**)(void))&f);CHKERRQ(ierr);
10538cdf2d9bSBarry Smith   if (f) {
10548cdf2d9bSBarry Smith     ierr = (*f)(B,bs,nz,nnz);CHKERRQ(ierr);
10558cdf2d9bSBarry Smith   }
10568cdf2d9bSBarry Smith   PetscFunctionReturn(0);
10578cdf2d9bSBarry Smith }
10588cdf2d9bSBarry Smith 
10598cdf2d9bSBarry Smith EXTERN_C_BEGIN
10608cdf2d9bSBarry Smith #undef __FUNCT__
10618cdf2d9bSBarry Smith #define __FUNCT__ "MatBlockMatSetPreallocation_BlockMat"
10628cdf2d9bSBarry Smith PetscErrorCode PETSCMAT_DLLEXPORT MatBlockMatSetPreallocation_BlockMat(Mat A,PetscInt bs,PetscInt nz,PetscInt *nnz)
10638cdf2d9bSBarry Smith {
10648cdf2d9bSBarry Smith   Mat_BlockMat   *bmat = (Mat_BlockMat*)A->data;
10658cdf2d9bSBarry Smith   PetscErrorCode ierr;
10668cdf2d9bSBarry Smith   PetscInt       i;
10678cdf2d9bSBarry Smith 
10688cdf2d9bSBarry Smith   PetscFunctionBegin;
106934ef9618SShri Abhyankar   ierr = PetscLayoutSetBlockSize(A->rmap,1);CHKERRQ(ierr);
107034ef9618SShri Abhyankar   ierr = PetscLayoutSetBlockSize(A->cmap,1);CHKERRQ(ierr);
107134ef9618SShri Abhyankar   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
107234ef9618SShri Abhyankar   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
107334ef9618SShri Abhyankar 
107465e19b50SBarry Smith   if (bs < 1) SETERRQ1(((PetscObject)A)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Block size given %D must be great than zero",bs);
1075e32f2f54SBarry 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);
1076e32f2f54SBarry 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);
10778cdf2d9bSBarry Smith   if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
1078e32f2f54SBarry Smith   if (nz < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %d",nz);
10798cdf2d9bSBarry Smith   if (nnz) {
1080d0f46423SBarry Smith     for (i=0; i<A->rmap->n/bs; i++) {
1081e32f2f54SBarry 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]);
1082e32f2f54SBarry 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);
10838cdf2d9bSBarry Smith     }
10848cdf2d9bSBarry Smith   }
1085d0f46423SBarry Smith   A->rmap->bs = A->cmap->bs = bs;
1086d0f46423SBarry Smith   bmat->mbs  = A->rmap->n/bs;
10878cdf2d9bSBarry Smith 
10888cdf2d9bSBarry Smith   ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,bs,PETSC_NULL,&bmat->right);CHKERRQ(ierr);
10898cdf2d9bSBarry Smith   ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,bs,PETSC_NULL,&bmat->middle);CHKERRQ(ierr);
10908cdf2d9bSBarry Smith   ierr = VecCreateSeq(PETSC_COMM_SELF,bs,&bmat->left);CHKERRQ(ierr);
10918cdf2d9bSBarry Smith 
10922ee49352SLisandro Dalcin   if (!bmat->imax) {
1093d0f46423SBarry Smith     ierr = PetscMalloc2(A->rmap->n,PetscInt,&bmat->imax,A->rmap->n,PetscInt,&bmat->ilen);CHKERRQ(ierr);
1094d0f46423SBarry Smith     ierr = PetscLogObjectMemory(A,2*A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
10952ee49352SLisandro Dalcin   }
10968cdf2d9bSBarry Smith   if (nnz) {
10978cdf2d9bSBarry Smith     nz = 0;
1098d0f46423SBarry Smith     for (i=0; i<A->rmap->n/A->rmap->bs; i++) {
10998cdf2d9bSBarry Smith       bmat->imax[i] = nnz[i];
11008cdf2d9bSBarry Smith       nz           += nnz[i];
11018cdf2d9bSBarry Smith     }
11028cdf2d9bSBarry Smith   } else {
1103e32f2f54SBarry Smith     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Currently requires block row by row preallocation");
11048cdf2d9bSBarry Smith   }
11058cdf2d9bSBarry Smith 
11068cdf2d9bSBarry Smith   /* bmat->ilen will count nonzeros in each row so far. */
11078cdf2d9bSBarry Smith   for (i=0; i<bmat->mbs; i++) { bmat->ilen[i] = 0;}
11088cdf2d9bSBarry Smith 
11098cdf2d9bSBarry Smith   /* allocate the matrix space */
11102ee49352SLisandro Dalcin   ierr = MatSeqXAIJFreeAIJ(A,(PetscScalar**)&bmat->a,&bmat->j,&bmat->i);CHKERRQ(ierr);
1111d0f46423SBarry Smith   ierr = PetscMalloc3(nz,Mat,&bmat->a,nz,PetscInt,&bmat->j,A->rmap->n+1,PetscInt,&bmat->i);CHKERRQ(ierr);
1112d0f46423SBarry Smith   ierr = PetscLogObjectMemory(A,(A->rmap->n+1)*sizeof(PetscInt)+nz*(sizeof(PetscScalar)+sizeof(PetscInt)));CHKERRQ(ierr);
11138cdf2d9bSBarry Smith   bmat->i[0] = 0;
11148cdf2d9bSBarry Smith   for (i=1; i<bmat->mbs+1; i++) {
11158cdf2d9bSBarry Smith     bmat->i[i] = bmat->i[i-1] + bmat->imax[i-1];
11168cdf2d9bSBarry Smith   }
11178cdf2d9bSBarry Smith   bmat->singlemalloc = PETSC_TRUE;
11188cdf2d9bSBarry Smith   bmat->free_a       = PETSC_TRUE;
11198cdf2d9bSBarry Smith   bmat->free_ij      = PETSC_TRUE;
11208cdf2d9bSBarry Smith 
11218cdf2d9bSBarry Smith   bmat->nz                = 0;
11228cdf2d9bSBarry Smith   bmat->maxnz             = nz;
11238cdf2d9bSBarry Smith   A->info.nz_unneeded  = (double)bmat->maxnz;
11248cdf2d9bSBarry Smith 
11258cdf2d9bSBarry Smith   PetscFunctionReturn(0);
11268cdf2d9bSBarry Smith }
11278cdf2d9bSBarry Smith EXTERN_C_END
11288cdf2d9bSBarry Smith 
1129421e10b8SBarry Smith /*MC
1130421e10b8SBarry Smith    MATBLOCKMAT - A matrix that is defined by a set of Mat's that represents a sparse block matrix
1131421e10b8SBarry Smith                  consisting of (usually) sparse blocks.
1132421e10b8SBarry Smith 
1133421e10b8SBarry Smith   Level: advanced
1134421e10b8SBarry Smith 
1135421e10b8SBarry Smith .seealso: MatCreateBlockMat()
1136421e10b8SBarry Smith 
1137421e10b8SBarry Smith M*/
1138421e10b8SBarry Smith 
1139421e10b8SBarry Smith EXTERN_C_BEGIN
1140421e10b8SBarry Smith #undef __FUNCT__
1141421e10b8SBarry Smith #define __FUNCT__ "MatCreate_BlockMat"
1142421e10b8SBarry Smith PetscErrorCode PETSCMAT_DLLEXPORT MatCreate_BlockMat(Mat A)
1143421e10b8SBarry Smith {
1144421e10b8SBarry Smith   Mat_BlockMat   *b;
1145421e10b8SBarry Smith   PetscErrorCode ierr;
1146421e10b8SBarry Smith 
1147421e10b8SBarry Smith   PetscFunctionBegin;
114838f2d2fdSLisandro Dalcin   ierr = PetscNewLog(A,Mat_BlockMat,&b);CHKERRQ(ierr);
1149421e10b8SBarry Smith   A->data = (void*)b;
115038f2d2fdSLisandro Dalcin   ierr = PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
1151421e10b8SBarry Smith 
1152421e10b8SBarry Smith   A->assembled     = PETSC_TRUE;
1153421e10b8SBarry Smith   A->preallocated  = PETSC_FALSE;
1154421e10b8SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)A,MATBLOCKMAT);CHKERRQ(ierr);
1155290bbb0aSBarry Smith 
11568cdf2d9bSBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatBlockMatSetPreallocation_C",
11578cdf2d9bSBarry Smith                                      "MatBlockMatSetPreallocation_BlockMat",
11588cdf2d9bSBarry Smith                                       MatBlockMatSetPreallocation_BlockMat);CHKERRQ(ierr);
11598cdf2d9bSBarry Smith 
1160421e10b8SBarry Smith   PetscFunctionReturn(0);
1161421e10b8SBarry Smith }
1162421e10b8SBarry Smith EXTERN_C_END
1163421e10b8SBarry Smith 
1164421e10b8SBarry Smith #undef __FUNCT__
1165421e10b8SBarry Smith #define __FUNCT__ "MatCreateBlockMat"
1166421e10b8SBarry Smith /*@C
1167421e10b8SBarry Smith    MatCreateBlockMat - Creates a new matrix based sparse Mat storage
1168421e10b8SBarry Smith 
1169421e10b8SBarry Smith   Collective on MPI_Comm
1170421e10b8SBarry Smith 
1171421e10b8SBarry Smith    Input Parameters:
1172421e10b8SBarry Smith +  comm - MPI communicator
1173421e10b8SBarry Smith .  m - number of rows
1174421e10b8SBarry Smith .  n  - number of columns
11758cdf2d9bSBarry Smith .  bs - size of each submatrix
11768cdf2d9bSBarry Smith .  nz  - expected maximum number of nonzero blocks in row (use PETSC_DEFAULT if not known)
11778cdf2d9bSBarry Smith -  nnz - expected number of nonzers per block row if known (use PETSC_NULL otherwise)
1178421e10b8SBarry Smith 
1179421e10b8SBarry Smith 
1180421e10b8SBarry Smith    Output Parameter:
1181421e10b8SBarry Smith .  A - the matrix
1182421e10b8SBarry Smith 
1183421e10b8SBarry Smith    Level: intermediate
1184421e10b8SBarry Smith 
1185421e10b8SBarry Smith    PETSc requires that matrices and vectors being used for certain
1186421e10b8SBarry Smith    operations are partitioned accordingly.  For example, when
1187421e10b8SBarry Smith    creating a bmat matrix, A, that supports parallel matrix-vector
1188421e10b8SBarry Smith    products using MatMult(A,x,y) the user should set the number
1189421e10b8SBarry Smith    of local matrix rows to be the number of local elements of the
1190421e10b8SBarry Smith    corresponding result vector, y. Note that this is information is
1191421e10b8SBarry Smith    required for use of the matrix interface routines, even though
1192421e10b8SBarry Smith    the bmat matrix may not actually be physically partitioned.
1193421e10b8SBarry Smith    For example,
1194421e10b8SBarry Smith 
1195421e10b8SBarry Smith .keywords: matrix, bmat, create
1196421e10b8SBarry Smith 
1197421e10b8SBarry Smith .seealso: MATBLOCKMAT
1198421e10b8SBarry Smith @*/
11998cdf2d9bSBarry Smith PetscErrorCode PETSCMAT_DLLEXPORT MatCreateBlockMat(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt bs,PetscInt nz,PetscInt *nnz, Mat *A)
1200421e10b8SBarry Smith {
1201421e10b8SBarry Smith   PetscErrorCode ierr;
1202421e10b8SBarry Smith 
1203421e10b8SBarry Smith   PetscFunctionBegin;
1204421e10b8SBarry Smith   ierr = MatCreate(comm,A);CHKERRQ(ierr);
1205421e10b8SBarry Smith   ierr = MatSetSizes(*A,m,n,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
1206421e10b8SBarry Smith   ierr = MatSetType(*A,MATBLOCKMAT);CHKERRQ(ierr);
12078cdf2d9bSBarry Smith   ierr = MatBlockMatSetPreallocation(*A,bs,nz,nnz);CHKERRQ(ierr);
1208421e10b8SBarry Smith   PetscFunctionReturn(0);
1209421e10b8SBarry Smith }
1210421e10b8SBarry Smith 
1211421e10b8SBarry Smith 
1212421e10b8SBarry Smith 
1213