xref: /petsc/src/mat/impls/nest/matnest.c (revision e2d7f03f477b038e115ffdf3cadacf9a870ae488)
1d8588912SDave May #define PETSCMAT_DLL
2d8588912SDave May 
3d8588912SDave May #include "matnestimpl.h"
4d8588912SDave May 
5d8588912SDave May /* private functions */
6d8588912SDave May #undef __FUNCT__
7d8588912SDave May #define __FUNCT__ "MatNestGetSize_Recursive"
8d8588912SDave May static PetscErrorCode MatNestGetSize_Recursive(Mat A,PetscBool globalsize,PetscInt *M,PetscInt *N)
9d8588912SDave May {
10d8588912SDave May   Mat_Nest       *bA = (Mat_Nest*)A->data;
11d8588912SDave May   PetscInt       sizeM,sizeN,i,j,index;
12d8588912SDave May   PetscErrorCode ierr;
13d8588912SDave May 
14d8588912SDave May   PetscFunctionBegin;
15d8588912SDave May   /* rows */
16d8588912SDave May   /* now descend recursively */
17d8588912SDave May   for (i=0; i<bA->nr; i++) {
18d8588912SDave May     for (j=0; j<bA->nc; j++) {
19d8588912SDave May       if (bA->m[i][j]) { index = j; break; }
20d8588912SDave May     }
21d8588912SDave May     if (bA->m[i][index]) {
22d8588912SDave May       if (globalsize) { ierr = MatGetSize(bA->m[i][index],&sizeM,&sizeN);CHKERRQ(ierr); }
23d8588912SDave May       else {            ierr = MatGetLocalSize(bA->m[i][index],&sizeM,&sizeN);CHKERRQ(ierr); }
24d8588912SDave May       *M = *M + sizeM;
25d8588912SDave May     }
26d8588912SDave May   }
27d8588912SDave May 
28d8588912SDave May   /* cols */
29d8588912SDave May   /* now descend recursively */
30d8588912SDave May   for (j=0; j<bA->nc; j++) {
31d8588912SDave May     for (i=0; i<bA->nr; i++) {
32d8588912SDave May       if (bA->m[i][j]) { index = i; break; }
33d8588912SDave May     }
34d8588912SDave May     if (bA->m[index][j]) {
35d8588912SDave May       if (globalsize) { ierr = MatGetSize(bA->m[index][j],&sizeM,&sizeN);CHKERRQ(ierr); }
36d8588912SDave May       else {            ierr = MatGetLocalSize(bA->m[index][j],&sizeM,&sizeN);CHKERRQ(ierr); }
37d8588912SDave May       *N = *N + sizeN;
38d8588912SDave May     }
39d8588912SDave May   }
40d8588912SDave May   PetscFunctionReturn(0);
41d8588912SDave May }
42d8588912SDave May 
43d8588912SDave May #undef __FUNCT__
44d8588912SDave May #define __FUNCT__ "PETSc_MatNest_CheckMatVecCompatibility2"
45d8588912SDave May static PetscErrorCode PETSc_MatNest_CheckMatVecCompatibility2(Mat A,Vec x,Vec y)
46d8588912SDave May {
47d8588912SDave May   PetscBool      isANest, isxNest, isyNest;
48d8588912SDave May   PetscErrorCode ierr;
49d8588912SDave May 
50d8588912SDave May   PetscFunctionBegin;
51d8588912SDave May   isANest = isxNest = isyNest = PETSC_FALSE;
52d8588912SDave May   ierr = PetscTypeCompare( (PetscObject)A, MATNEST, &isANest );CHKERRQ(ierr);
53d8588912SDave May   ierr = PetscTypeCompare( (PetscObject)x, VECNEST, &isxNest );CHKERRQ(ierr);
54d8588912SDave May   ierr = PetscTypeCompare( (PetscObject)y, VECNEST, &isyNest );CHKERRQ(ierr);
55d8588912SDave May 
56d8588912SDave May   if (isANest && isxNest && isyNest) {
57d8588912SDave May     PetscFunctionReturn(0);
58d8588912SDave May   } else {
59d8588912SDave May     SETERRQ( ((PetscObject)A)->comm, PETSC_ERR_SUP, "Operation only valid for Mat(Nest)-Vec(Nest) combinations");
60d8588912SDave May     PetscFunctionReturn(0);
61d8588912SDave May   }
62d8588912SDave May   PetscFunctionReturn(0);
63d8588912SDave May }
64d8588912SDave May 
65d8588912SDave May /*
66d8588912SDave May  This function is called every time we insert a sub matrix the Nest.
67d8588912SDave May  It ensures that every Nest along row r, and col c has the same dimensions
68d8588912SDave May  as the submat being inserted.
69d8588912SDave May */
70d8588912SDave May #undef __FUNCT__
71d8588912SDave May #define __FUNCT__ "PETSc_MatNest_CheckConsistency"
72063a28d4SJed Brown PETSC_UNUSED
73d8588912SDave May static PetscErrorCode PETSc_MatNest_CheckConsistency(Mat A,Mat submat,PetscInt r,PetscInt c)
74d8588912SDave May {
75d8588912SDave May   Mat_Nest       *b = (Mat_Nest*)A->data;
76d8588912SDave May   PetscInt       i,j;
77d8588912SDave May   PetscInt       nr,nc;
78d8588912SDave May   PetscInt       sM,sN,M,N;
79d8588912SDave May   Mat            mat;
80d8588912SDave May   PetscErrorCode ierr;
81d8588912SDave May 
82d8588912SDave May   PetscFunctionBegin;
83d8588912SDave May   nr = b->nr;
84d8588912SDave May   nc = b->nc;
85d8588912SDave May   ierr = MatGetSize(submat,&sM,&sN);CHKERRQ(ierr);
86d8588912SDave May   for (i=0; i<nr; i++) {
87d8588912SDave May     mat = b->m[i][c];
88d8588912SDave May     if (mat) {
89d8588912SDave May       ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr);
90d8588912SDave May       /* Check columns match */
91d8588912SDave May       if (sN != N) {
92d8588912SDave May         SETERRQ3(((PetscObject)A)->comm,PETSC_ERR_SUP,"Inserted incompatible submatrix into Nest at (%D,%D). Submatrix must have %D rows",r,c,N );
93d8588912SDave May       }
94d8588912SDave May     }
95d8588912SDave May   }
96d8588912SDave May 
97d8588912SDave May   for (j=0; j<nc; j++) {
98d8588912SDave May     mat = b->m[r][j];
99d8588912SDave May     if (mat) {
100d8588912SDave May       ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr);
101d8588912SDave May       /* Check rows match */
102d8588912SDave May       if (sM != M) {
103d8588912SDave May         SETERRQ3(((PetscObject)A)->comm,PETSC_ERR_SUP,"Inserted incompatible submatrix into Nest at (%D,%D). Submatrix must have %D cols",r,c,M );
104d8588912SDave May       }
105d8588912SDave May     }
106d8588912SDave May   }
107d8588912SDave May   PetscFunctionReturn(0);
108d8588912SDave May }
109d8588912SDave May 
110d8588912SDave May /*
111d8588912SDave May  Checks if the row/col's contain a complete set of IS's.
112d8588912SDave May  Once they are filled, the offsets are computed. This saves having to update
113d8588912SDave May  the index set entries each time we insert something new.
114d8588912SDave May  */
115d8588912SDave May #undef __FUNCT__
116d8588912SDave May #define __FUNCT__ "PETSc_MatNest_UpdateStructure"
117063a28d4SJed Brown PETSC_UNUSED
118d8588912SDave May static PetscErrorCode PETSc_MatNest_UpdateStructure(Mat A,PetscInt ridx,PetscInt cidx)
119d8588912SDave May {
120d8588912SDave May   Mat_Nest       *b = (Mat_Nest*)A->data;
121d8588912SDave May   PetscInt       m,n,i,j;
122d8588912SDave May   PetscBool      fullrow,fullcol;
123d8588912SDave May   PetscErrorCode ierr;
124d8588912SDave May 
125d8588912SDave May   PetscFunctionBegin;
126d8588912SDave May   ierr = MatGetLocalSize(b->m[ridx][cidx],&m,&n);CHKERRQ(ierr);
127d8588912SDave May   b->row_len[ridx] = m;
128d8588912SDave May   b->col_len[cidx] = n;
129d8588912SDave May 
130d8588912SDave May   fullrow = PETSC_TRUE;
131d8588912SDave May   for (i=0; i<b->nr; i++) {
132d8588912SDave May     if (b->row_len[i]==-1) { fullrow = PETSC_FALSE; break; }
133d8588912SDave May   }
134f349c1fdSJed Brown   if ( (fullrow) && (!b->isglobal.row[0]) ){
135d8588912SDave May     PetscInt cnt = 0;
136d8588912SDave May     for (i=0; i<b->nr; i++) {
137f349c1fdSJed Brown       ierr = ISCreateStride(PETSC_COMM_SELF,b->row_len[i],cnt,1,&b->isglobal.row[i]);CHKERRQ(ierr);
138d8588912SDave May       cnt = cnt + b->row_len[i];
139d8588912SDave May     }
140d8588912SDave May   }
141d8588912SDave May 
142d8588912SDave May   fullcol = PETSC_TRUE;
143d8588912SDave May   for (j=0; j<b->nc; j++) {
144d8588912SDave May     if (b->col_len[j]==-1) { fullcol = PETSC_FALSE; break; }
145d8588912SDave May   }
146f349c1fdSJed Brown   if( (fullcol) && (!b->isglobal.col[0]) ){
147d8588912SDave May     PetscInt cnt = 0;
148d8588912SDave May     for (j=0; j<b->nc; j++) {
149f349c1fdSJed Brown       ierr = ISCreateStride(PETSC_COMM_SELF,b->col_len[j],cnt,1,&b->isglobal.col[j]);CHKERRQ(ierr);
150d8588912SDave May       cnt = cnt + b->col_len[j];
151d8588912SDave May     }
152d8588912SDave May   }
153d8588912SDave May   PetscFunctionReturn(0);
154d8588912SDave May }
155d8588912SDave May 
156d8588912SDave May /* operations */
157d8588912SDave May #undef __FUNCT__
158d8588912SDave May #define __FUNCT__ "MatMult_Nest"
159d8588912SDave May PetscErrorCode MatMult_Nest(Mat A,Vec x,Vec y)
160d8588912SDave May {
161d8588912SDave May   Mat_Nest       *bA = (Mat_Nest*)A->data;
162d8588912SDave May   Vec            *bx;
163d8588912SDave May   Vec            *by;
164d8588912SDave May   PetscInt       i,j;
165d8588912SDave May   PetscErrorCode ierr;
166d8588912SDave May 
167d8588912SDave May   PetscFunctionBegin;
168d8588912SDave May   ierr = PETSc_MatNest_CheckMatVecCompatibility2(A,x,y);CHKERRQ(ierr);
169d8588912SDave May   ierr = VecNestGetSubVecs(x,PETSC_NULL,&bx);CHKERRQ(ierr);
170d8588912SDave May   ierr = VecNestGetSubVecs(y,PETSC_NULL,&by);CHKERRQ(ierr);
171d8588912SDave May 
172d8588912SDave May   for (i=0; i<bA->nr; i++) {
173d8588912SDave May     ierr = VecZeroEntries(by[i]);CHKERRQ(ierr);
174d8588912SDave May     for (j=0; j<bA->nc; j++) {
175d8588912SDave May       if (!bA->m[i][j]) {
176d8588912SDave May         continue;
177d8588912SDave May       }
178d8588912SDave May       /* y[i] <- y[i] + A[i][j] * x[j] */
179d8588912SDave May       ierr = MatMultAdd(bA->m[i][j],bx[j],by[i],by[i]);CHKERRQ(ierr);
180d8588912SDave May     }
181d8588912SDave May   }
182d8588912SDave May   PetscFunctionReturn(0);
183d8588912SDave May }
184d8588912SDave May 
185d8588912SDave May #undef __FUNCT__
186d8588912SDave May #define __FUNCT__ "MatMultTranspose_Nest"
187d8588912SDave May PetscErrorCode MatMultTranspose_Nest(Mat A,Vec x,Vec y)
188d8588912SDave May {
189d8588912SDave May   Mat_Nest       *bA = (Mat_Nest*)A->data;
190d8588912SDave May   Vec            *bx;
191d8588912SDave May   Vec            *by;
192d8588912SDave May   PetscInt       i,j;
193d8588912SDave May   PetscErrorCode ierr;
194d8588912SDave May 
195d8588912SDave May   PetscFunctionBegin;
196d8588912SDave May   ierr = PETSc_MatNest_CheckMatVecCompatibility2(A,x,y);CHKERRQ(ierr);
197d8588912SDave May   ierr = VecNestGetSubVecs(x,PETSC_NULL,&bx);CHKERRQ(ierr);
198d8588912SDave May   ierr = VecNestGetSubVecs(y,PETSC_NULL,&by);CHKERRQ(ierr);
199d8588912SDave May   if (A->symmetric) {
200d8588912SDave May     ierr = MatMult_Nest(A,x,y);CHKERRQ(ierr);
201d8588912SDave May     PetscFunctionReturn(0);
202d8588912SDave May   }
203d8588912SDave May   for (i=0; i<bA->nr; i++) {
204d8588912SDave May     ierr = VecZeroEntries(by[i]);CHKERRQ(ierr);
205d8588912SDave May     for (j=0; j<bA->nc; j++) {
206d8588912SDave May       if (!bA->m[j][i]) {
207d8588912SDave May         continue;
208d8588912SDave May       }
209d8588912SDave May       /* y[i] <- y[i] + A^T[i][j] * x[j], so we swap i,j in mat[][] */
210d8588912SDave May       ierr = MatMultTransposeAdd(bA->m[j][i],bx[j],by[i],by[i]);CHKERRQ(ierr);
211d8588912SDave May     }
212d8588912SDave May   }
213d8588912SDave May   PetscFunctionReturn(0);
214d8588912SDave May }
215d8588912SDave May 
216d8588912SDave May /* Returns the sum of the global size of all the consituent vectors in the nest */
217d8588912SDave May #undef __FUNCT__
218d8588912SDave May #define __FUNCT__ "MatGetSize_Nest"
219d8588912SDave May PetscErrorCode MatGetSize_Nest(Mat A,PetscInt *M,PetscInt *N)
220d8588912SDave May {
221d8588912SDave May   PetscFunctionBegin;
222d8588912SDave May   if (M) { *M = A->rmap->N; }
223d8588912SDave May   if (N) { *N = A->cmap->N; }
224d8588912SDave May   PetscFunctionReturn(0);
225d8588912SDave May }
226d8588912SDave May 
227d8588912SDave May /* Returns the sum of the local size of all the consituent vectors in the nest */
228d8588912SDave May #undef __FUNCT__
229d8588912SDave May #define __FUNCT__ "MatGetLocalSize_Nest"
230d8588912SDave May PetscErrorCode MatGetLocalSize_Nest(Mat A,PetscInt *m,PetscInt *n)
231d8588912SDave May {
232d8588912SDave May   PetscFunctionBegin;
233d8588912SDave May   if (m) { *m = A->rmap->n; }
234d8588912SDave May   if (n) { *n = A->cmap->n; }
235d8588912SDave May   PetscFunctionReturn(0);
236d8588912SDave May }
237d8588912SDave May 
238d8588912SDave May #undef __FUNCT__
239*e2d7f03fSJed Brown #define __FUNCT__ "MatNestDestroyISList"
240*e2d7f03fSJed Brown static PetscErrorCode MatNestDestroyISList(PetscInt n,IS **list)
241*e2d7f03fSJed Brown {
242*e2d7f03fSJed Brown   PetscErrorCode ierr;
243*e2d7f03fSJed Brown   IS             *lst = *list;
244*e2d7f03fSJed Brown   PetscInt       i;
245*e2d7f03fSJed Brown 
246*e2d7f03fSJed Brown   PetscFunctionBegin;
247*e2d7f03fSJed Brown   if (!lst) PetscFunctionReturn(0);
248*e2d7f03fSJed Brown   for (i=0; i<n; i++) if (lst[i]) {ierr = ISDestroy(lst[i]);CHKERRQ(ierr);}
249*e2d7f03fSJed Brown   ierr = PetscFree(lst);CHKERRQ(ierr);
250*e2d7f03fSJed Brown   *list = PETSC_NULL;
251*e2d7f03fSJed Brown   PetscFunctionReturn(0);
252*e2d7f03fSJed Brown }
253*e2d7f03fSJed Brown 
254*e2d7f03fSJed Brown 
255*e2d7f03fSJed Brown #undef __FUNCT__
256d8588912SDave May #define __FUNCT__ "MatDestroy_Nest"
257d8588912SDave May PetscErrorCode MatDestroy_Nest(Mat A)
258d8588912SDave May {
259d8588912SDave May   Mat_Nest       *vs = (Mat_Nest*)A->data;
260d8588912SDave May   PetscInt       i,j;
261d8588912SDave May   PetscErrorCode ierr;
262d8588912SDave May 
263d8588912SDave May   PetscFunctionBegin;
264d8588912SDave May   /* release the matrices and the place holders */
265*e2d7f03fSJed Brown   ierr = MatNestDestroyISList(vs->nr,&vs->isglobal.row);CHKERRQ(ierr);
266*e2d7f03fSJed Brown   ierr = MatNestDestroyISList(vs->nc,&vs->isglobal.col);CHKERRQ(ierr);
267*e2d7f03fSJed Brown   ierr = MatNestDestroyISList(vs->nr,&vs->islocal.row);CHKERRQ(ierr);
268*e2d7f03fSJed Brown   ierr = MatNestDestroyISList(vs->nc,&vs->islocal.col);CHKERRQ(ierr);
269d8588912SDave May 
270d8588912SDave May   ierr = PetscFree(vs->row_len);CHKERRQ(ierr);
271d8588912SDave May   ierr = PetscFree(vs->col_len);CHKERRQ(ierr);
272d8588912SDave May 
273d8588912SDave May   /* release the matrices and the place holders */
274d8588912SDave May   if (vs->m) {
275d8588912SDave May     for (i=0; i<vs->nr; i++) {
276d8588912SDave May       for (j=0; j<vs->nc; j++) {
277d8588912SDave May 
278d8588912SDave May         if (vs->m[i][j]) {
279d8588912SDave May           ierr = MatDestroy(vs->m[i][j]);CHKERRQ(ierr);
280d8588912SDave May           vs->m[i][j] = PETSC_NULL;
281d8588912SDave May         }
282d8588912SDave May       }
283d8588912SDave May       ierr = PetscFree( vs->m[i] );CHKERRQ(ierr);
284d8588912SDave May       vs->m[i] = PETSC_NULL;
285d8588912SDave May     }
286d8588912SDave May     ierr = PetscFree(vs->m);CHKERRQ(ierr);
287d8588912SDave May     vs->m = PETSC_NULL;
288d8588912SDave May   }
289d8588912SDave May   ierr = PetscFree(vs);CHKERRQ(ierr);
290d8588912SDave May 
291d8588912SDave May   PetscFunctionReturn(0);
292d8588912SDave May }
293d8588912SDave May 
294d8588912SDave May #undef __FUNCT__
295d8588912SDave May #define __FUNCT__ "MatAssemblyBegin_Nest"
296d8588912SDave May PetscErrorCode MatAssemblyBegin_Nest(Mat A,MatAssemblyType type)
297d8588912SDave May {
298d8588912SDave May   Mat_Nest       *vs = (Mat_Nest*)A->data;
299d8588912SDave May   PetscInt       i,j;
300d8588912SDave May   PetscErrorCode ierr;
301d8588912SDave May 
302d8588912SDave May   PetscFunctionBegin;
303d8588912SDave May   for (i=0; i<vs->nr; i++) {
304d8588912SDave May     for (j=0; j<vs->nc; j++) {
305d8588912SDave May       if (vs->m[i][j]) { ierr = MatAssemblyBegin(vs->m[i][j],type);CHKERRQ(ierr); }
306d8588912SDave May     }
307d8588912SDave May   }
308d8588912SDave May   PetscFunctionReturn(0);
309d8588912SDave May }
310d8588912SDave May 
311d8588912SDave May #undef __FUNCT__
312d8588912SDave May #define __FUNCT__ "MatAssemblyEnd_Nest"
313d8588912SDave May PetscErrorCode MatAssemblyEnd_Nest(Mat A, MatAssemblyType type)
314d8588912SDave May {
315d8588912SDave May   Mat_Nest       *vs = (Mat_Nest*)A->data;
316d8588912SDave May   PetscInt       i,j;
317d8588912SDave May   PetscErrorCode ierr;
318d8588912SDave May 
319d8588912SDave May   PetscFunctionBegin;
320d8588912SDave May   for (i=0; i<vs->nr; i++) {
321d8588912SDave May     for (j=0; j<vs->nc; j++) {
322d8588912SDave May       if (vs->m[i][j]) { ierr = MatAssemblyEnd(vs->m[i][j],type);CHKERRQ(ierr); }
323d8588912SDave May     }
324d8588912SDave May   }
325d8588912SDave May   PetscFunctionReturn(0);
326d8588912SDave May }
327d8588912SDave May 
328d8588912SDave May #undef __FUNCT__
329f349c1fdSJed Brown #define __FUNCT__ "MatNestFindNonzeroSubMatRow"
330f349c1fdSJed Brown static PetscErrorCode MatNestFindNonzeroSubMatRow(Mat A,PetscInt row,Mat *B)
331d8588912SDave May {
332f349c1fdSJed Brown   Mat_Nest       *vs = (Mat_Nest*)A->data;
333f349c1fdSJed Brown   PetscInt       j;
334f349c1fdSJed Brown   Mat            sub;
335d8588912SDave May 
336d8588912SDave May   PetscFunctionBegin;
337f349c1fdSJed Brown   sub = vs->m[row][row];        /* Prefer to find on the diagonal */
338f349c1fdSJed Brown   for (j=0; !sub && j<vs->nc; j++) sub = vs->m[row][j];
339f349c1fdSJed Brown   if (!sub) SETERRQ1(((PetscObject)A)->comm,PETSC_ERR_ARG_WRONG,"No nonzero submatrix in row %D",row);
340f349c1fdSJed Brown   *B = sub;
341f349c1fdSJed Brown   PetscFunctionReturn(0);
342d8588912SDave May }
343d8588912SDave May 
344f349c1fdSJed Brown #undef __FUNCT__
345f349c1fdSJed Brown #define __FUNCT__ "MatNestFindNonzeroSubMatCol"
346f349c1fdSJed Brown static PetscErrorCode MatNestFindNonzeroSubMatCol(Mat A,PetscInt col,Mat *B)
347f349c1fdSJed Brown {
348f349c1fdSJed Brown   Mat_Nest       *vs = (Mat_Nest*)A->data;
349f349c1fdSJed Brown   PetscInt       i;
350f349c1fdSJed Brown   Mat            sub;
351f349c1fdSJed Brown 
352f349c1fdSJed Brown   PetscFunctionBegin;
353f349c1fdSJed Brown   sub = vs->m[col][col];        /* Prefer to find on the diagonal */
354f349c1fdSJed Brown   for (i=0; !sub && i<vs->nr; i++) sub = vs->m[i][col];
355f349c1fdSJed Brown   if (!sub) SETERRQ1(((PetscObject)A)->comm,PETSC_ERR_ARG_WRONG,"No nonzero submatrix in column %D",col);
356f349c1fdSJed Brown   *B = sub;
357f349c1fdSJed Brown   PetscFunctionReturn(0);
358d8588912SDave May }
359d8588912SDave May 
360f349c1fdSJed Brown #undef __FUNCT__
361f349c1fdSJed Brown #define __FUNCT__ "MatNestFindIS"
362f349c1fdSJed Brown static PetscErrorCode MatNestFindIS(Mat A,PetscInt n,const IS list[],IS is,PetscInt *found)
363f349c1fdSJed Brown {
364f349c1fdSJed Brown   PetscErrorCode ierr;
365f349c1fdSJed Brown   PetscInt       i;
366f349c1fdSJed Brown   PetscBool      flg;
367f349c1fdSJed Brown 
368f349c1fdSJed Brown   PetscFunctionBegin;
369f349c1fdSJed Brown   PetscValidPointer(list,3);
370f349c1fdSJed Brown   PetscValidHeaderSpecific(is,IS_CLASSID,4);
371f349c1fdSJed Brown   PetscValidIntPointer(found,5);
372f349c1fdSJed Brown   *found = -1;
373f349c1fdSJed Brown   for (i=0; i<n; i++) {
374f349c1fdSJed Brown     ierr = ISEqual(list[i],is,&flg);CHKERRQ(ierr);
375f349c1fdSJed Brown     if (flg) {
376f349c1fdSJed Brown       *found = i;
377f349c1fdSJed Brown       PetscFunctionReturn(0);
378f349c1fdSJed Brown     }
379f349c1fdSJed Brown   }
380f349c1fdSJed Brown   SETERRQ(((PetscObject)A)->comm,PETSC_ERR_ARG_INCOMP,"Could not find index set");
381f349c1fdSJed Brown   PetscFunctionReturn(0);
382f349c1fdSJed Brown }
383f349c1fdSJed Brown 
384f349c1fdSJed Brown #undef __FUNCT__
385f349c1fdSJed Brown #define __FUNCT__ "MatNestFindSubMat"
386f349c1fdSJed Brown static PetscErrorCode MatNestFindSubMat(Mat A,struct MatNestISPair *is,IS isrow,IS iscol,Mat *B)
387f349c1fdSJed Brown {
388f349c1fdSJed Brown   PetscErrorCode ierr;
389f349c1fdSJed Brown   Mat_Nest       *vs = (Mat_Nest*)A->data;
390f349c1fdSJed Brown   PetscInt       row,col;
391f349c1fdSJed Brown 
392f349c1fdSJed Brown   PetscFunctionBegin;
393f349c1fdSJed Brown   ierr = MatNestFindIS(A,vs->nr,is->row,isrow,&row);CHKERRQ(ierr);
394f349c1fdSJed Brown   ierr = MatNestFindIS(A,vs->nc,is->col,iscol,&col);CHKERRQ(ierr);
395f349c1fdSJed Brown   *B = vs->m[row][col];
396f349c1fdSJed Brown   PetscFunctionReturn(0);
397f349c1fdSJed Brown }
398f349c1fdSJed Brown 
399f349c1fdSJed Brown #undef __FUNCT__
400f349c1fdSJed Brown #define __FUNCT__ "MatGetSubMatrix_Nest"
401f349c1fdSJed Brown static PetscErrorCode MatGetSubMatrix_Nest(Mat A,IS isrow,IS iscol,MatReuse reuse,Mat *B)
402f349c1fdSJed Brown {
403f349c1fdSJed Brown   PetscErrorCode ierr;
404f349c1fdSJed Brown   Mat_Nest       *vs = (Mat_Nest*)A->data;
405f349c1fdSJed Brown   Mat            sub;
406f349c1fdSJed Brown 
407f349c1fdSJed Brown   PetscFunctionBegin;
408f349c1fdSJed Brown   ierr = MatNestFindSubMat(A,&vs->isglobal,isrow,iscol,&sub);CHKERRQ(ierr);
409f349c1fdSJed Brown   switch (reuse) {
410f349c1fdSJed Brown   case MAT_INITIAL_MATRIX:
411f349c1fdSJed Brown     ierr = PetscObjectReference((PetscObject)sub);CHKERRQ(ierr);
412f349c1fdSJed Brown     *B = sub;
413f349c1fdSJed Brown     break;
414f349c1fdSJed Brown   case MAT_REUSE_MATRIX:
415f349c1fdSJed Brown     if (sub != *B) SETERRQ(((PetscObject)A)->comm,PETSC_ERR_ARG_WRONGSTATE,"Submatrix was not used before in this call");
416f349c1fdSJed Brown     break;
417f349c1fdSJed Brown   case MAT_IGNORE_MATRIX:       /* Nothing to do */
418f349c1fdSJed Brown     break;
419f349c1fdSJed Brown   }
420f349c1fdSJed Brown   PetscFunctionReturn(0);
421f349c1fdSJed Brown }
422f349c1fdSJed Brown 
423f349c1fdSJed Brown #undef __FUNCT__
424f349c1fdSJed Brown #define __FUNCT__ "MatGetLocalSubMatrix_Nest"
425f349c1fdSJed Brown PetscErrorCode MatGetLocalSubMatrix_Nest(Mat A,IS isrow,IS iscol,Mat *B)
426f349c1fdSJed Brown {
427f349c1fdSJed Brown   PetscErrorCode ierr;
428f349c1fdSJed Brown   Mat_Nest       *vs = (Mat_Nest*)A->data;
429f349c1fdSJed Brown   Mat            sub;
430f349c1fdSJed Brown 
431f349c1fdSJed Brown   PetscFunctionBegin;
432f349c1fdSJed Brown   ierr = MatNestFindSubMat(A,&vs->islocal,isrow,iscol,&sub);CHKERRQ(ierr);
433f349c1fdSJed Brown   /* We allow the submatrix to be NULL, perhaps it would be better for the user to return an empty matrix instead */
434f349c1fdSJed Brown   if (sub) {ierr = PetscObjectReference((PetscObject)sub);CHKERRQ(ierr);}
435f349c1fdSJed Brown   *B = sub;
436d8588912SDave May   PetscFunctionReturn(0);
437d8588912SDave May }
438d8588912SDave May 
439d8588912SDave May #undef __FUNCT__
440d8588912SDave May #define __FUNCT__ "MatRestoreLocalSubMatrix_Nest"
441f349c1fdSJed Brown PetscErrorCode MatRestoreLocalSubMatrix_Nest(Mat A,IS isrow,IS iscol,Mat *B)
442d8588912SDave May {
443d8588912SDave May   PetscErrorCode ierr;
444f349c1fdSJed Brown   Mat_Nest       *vs = (Mat_Nest*)A->data;
445f349c1fdSJed Brown   Mat            sub;
446d8588912SDave May 
447d8588912SDave May   PetscFunctionBegin;
448f349c1fdSJed Brown   ierr = MatNestFindSubMat(A,&vs->islocal,isrow,iscol,&sub);CHKERRQ(ierr);
449f349c1fdSJed Brown   if (*B != sub) SETERRQ(((PetscObject)A)->comm,PETSC_ERR_ARG_WRONGSTATE,"Local submatrix has not been gotten");
450f349c1fdSJed Brown   if (sub) {
451f349c1fdSJed Brown     if (((PetscObject)sub)->refct <= 1) SETERRQ(((PetscObject)A)->comm,PETSC_ERR_ARG_WRONGSTATE,"Local submatrix has had reference count decremented too many times");
452f349c1fdSJed Brown     ierr = MatDestroy(*B);CHKERRQ(ierr);
453d8588912SDave May   }
454f349c1fdSJed Brown   *B = PETSC_NULL;
455d8588912SDave May   PetscFunctionReturn(0);
456d8588912SDave May }
457d8588912SDave May 
458d8588912SDave May #undef __FUNCT__
459d8588912SDave May #define __FUNCT__ "MatGetVecs_Nest"
460d8588912SDave May PetscErrorCode MatGetVecs_Nest(Mat A,Vec *right,Vec *left)
461d8588912SDave May {
462d8588912SDave May   Mat_Nest       *bA = (Mat_Nest*)A->data;
463d8588912SDave May   Vec            *L,*R;
464d8588912SDave May   MPI_Comm       comm;
465d8588912SDave May   PetscInt       i,j;
466d8588912SDave May   PetscErrorCode ierr;
467d8588912SDave May 
468d8588912SDave May   PetscFunctionBegin;
469d8588912SDave May   comm = ((PetscObject)A)->comm;
470d8588912SDave May   if (right) {
471d8588912SDave May     /* allocate R */
472d8588912SDave May     ierr = PetscMalloc( sizeof(Vec) * bA->nc, &R );CHKERRQ(ierr);
473d8588912SDave May     /* Create the right vectors */
474d8588912SDave May     for (j=0; j<bA->nc; j++) {
475d8588912SDave May       for (i=0; i<bA->nr; i++) {
476d8588912SDave May         if (bA->m[i][j]) {
477d8588912SDave May           ierr = MatGetVecs(bA->m[i][j],&R[j],PETSC_NULL);CHKERRQ(ierr);
478d8588912SDave May           break;
479d8588912SDave May         }
480d8588912SDave May       }
481d8588912SDave May       if (i==bA->nr) {
482d8588912SDave May         /* have an empty column */
483d8588912SDave May         SETERRQ( ((PetscObject)A)->comm, PETSC_ERR_ARG_WRONG, "Mat(Nest) contains a null column.");
484d8588912SDave May       }
485d8588912SDave May     }
486f349c1fdSJed Brown     ierr = VecCreateNest(comm,bA->nc,bA->isglobal.col,R,right);CHKERRQ(ierr);
487d8588912SDave May     /* hand back control to the nest vector */
488d8588912SDave May     for (j=0; j<bA->nc; j++) {
489d8588912SDave May       ierr = VecDestroy(R[j]);CHKERRQ(ierr);
490d8588912SDave May     }
491d8588912SDave May     ierr = PetscFree(R);CHKERRQ(ierr);
492d8588912SDave May   }
493d8588912SDave May 
494d8588912SDave May   if (left) {
495d8588912SDave May     /* allocate L */
496d8588912SDave May     ierr = PetscMalloc( sizeof(Vec) * bA->nr, &L );CHKERRQ(ierr);
497d8588912SDave May     /* Create the left vectors */
498d8588912SDave May     for (i=0; i<bA->nr; i++) {
499d8588912SDave May       for (j=0; j<bA->nc; j++) {
500d8588912SDave May         if (bA->m[i][j]) {
501d8588912SDave May           ierr = MatGetVecs(bA->m[i][j],PETSC_NULL,&L[i]);CHKERRQ(ierr);
502d8588912SDave May           break;
503d8588912SDave May         }
504d8588912SDave May       }
505d8588912SDave May       if (j==bA->nc) {
506d8588912SDave May         /* have an empty row */
507d8588912SDave May         SETERRQ( ((PetscObject)A)->comm, PETSC_ERR_ARG_WRONG, "Mat(Nest) contains a null row.");
508d8588912SDave May       }
509d8588912SDave May     }
510d8588912SDave May 
511f349c1fdSJed Brown     ierr = VecCreateNest(comm,bA->nr,bA->isglobal.row,L,left);CHKERRQ(ierr);
512d8588912SDave May     for (i=0; i<bA->nr; i++) {
513d8588912SDave May       ierr = VecDestroy(L[i]);CHKERRQ(ierr);
514d8588912SDave May     }
515d8588912SDave May 
516d8588912SDave May     ierr = PetscFree(L);CHKERRQ(ierr);
517d8588912SDave May   }
518d8588912SDave May   PetscFunctionReturn(0);
519d8588912SDave May }
520d8588912SDave May 
521d8588912SDave May #undef __FUNCT__
522d8588912SDave May #define __FUNCT__ "MatView_Nest"
523d8588912SDave May PetscErrorCode MatView_Nest(Mat A,PetscViewer viewer)
524d8588912SDave May {
525d8588912SDave May   Mat_Nest       *bA = (Mat_Nest*)A->data;
526d8588912SDave May   PetscBool      isascii;
527d8588912SDave May   PetscInt       i,j;
528d8588912SDave May   PetscErrorCode ierr;
529d8588912SDave May 
530d8588912SDave May   PetscFunctionBegin;
531d8588912SDave May   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
532d8588912SDave May   if (isascii) {
533d8588912SDave May 
534d8588912SDave May     PetscViewerASCIIPrintf(viewer,"Matrix object: \n" );
535d8588912SDave May     PetscViewerASCIIPushTab( viewer );    /* push0 */
536d8588912SDave May     PetscViewerASCIIPrintf( viewer, "type=nest, rows=%d, cols=%d \n",bA->nr,bA->nc);
537d8588912SDave May 
538d8588912SDave May     PetscViewerASCIIPrintf(viewer,"MatNest structure: \n" );
539d8588912SDave May     for (i=0; i<bA->nr; i++) {
540d8588912SDave May       for (j=0; j<bA->nc; j++) {
541d8588912SDave May         const MatType type;
542d8588912SDave May         const char *name;
543d8588912SDave May         PetscInt NR,NC;
544d8588912SDave May         PetscBool isNest = PETSC_FALSE;
545d8588912SDave May 
546d8588912SDave May         if (!bA->m[i][j]) {
547d8588912SDave May           PetscViewerASCIIPrintf( viewer, "(%D,%D) : PETSC_NULL \n",i,j);
548d8588912SDave May           continue;
549d8588912SDave May         }
550d8588912SDave May         ierr = MatGetSize(bA->m[i][j],&NR,&NC);CHKERRQ(ierr);
551d8588912SDave May         ierr = MatGetType( bA->m[i][j], &type );CHKERRQ(ierr);
552d8588912SDave May         name = ((PetscObject)bA->m[i][j])->prefix;
553d8588912SDave May         ierr = PetscTypeCompare((PetscObject)bA->m[i][j],MATNEST,&isNest);CHKERRQ(ierr);
554d8588912SDave May 
555d8588912SDave May         PetscViewerASCIIPrintf( viewer, "(%D,%D) : name=\"%s\", type=%s, rows=%D, cols=%D \n",i,j,name,type,NR,NC);
556d8588912SDave May 
557d8588912SDave May         if (isNest) {
558d8588912SDave May           PetscViewerASCIIPushTab( viewer );  /* push1 */
559d8588912SDave May           ierr = MatView( bA->m[i][j], viewer );CHKERRQ(ierr);
560d8588912SDave May           PetscViewerASCIIPopTab(viewer);    /* pop1 */
561d8588912SDave May         }
562d8588912SDave May       }
563d8588912SDave May     }
564d8588912SDave May     PetscViewerASCIIPopTab(viewer);    /* pop0 */
565d8588912SDave May   }
566d8588912SDave May   PetscFunctionReturn(0);
567d8588912SDave May }
568d8588912SDave May 
569d8588912SDave May #undef __FUNCT__
570d8588912SDave May #define __FUNCT__ "MatZeroEntries_Nest"
571d8588912SDave May PetscErrorCode MatZeroEntries_Nest(Mat A)
572d8588912SDave May {
573d8588912SDave May   Mat_Nest       *bA = (Mat_Nest*)A->data;
574d8588912SDave May   PetscInt       i,j;
575d8588912SDave May   PetscErrorCode ierr;
576d8588912SDave May 
577d8588912SDave May   PetscFunctionBegin;
578d8588912SDave May   for (i=0; i<bA->nr; i++) {
579d8588912SDave May     for (j=0; j<bA->nc; j++) {
580d8588912SDave May       if (!bA->m[i][j]) continue;
581d8588912SDave May       ierr = MatZeroEntries(bA->m[i][j]);CHKERRQ(ierr);
582d8588912SDave May     }
583d8588912SDave May   }
584d8588912SDave May   PetscFunctionReturn(0);
585d8588912SDave May }
586d8588912SDave May 
587d8588912SDave May #undef __FUNCT__
588d8588912SDave May #define __FUNCT__ "MatDuplicate_Nest"
589d8588912SDave May PetscErrorCode MatDuplicate_Nest(Mat A,MatDuplicateOption op,Mat *B)
590d8588912SDave May {
591d8588912SDave May   Mat_Nest       *bA = (Mat_Nest*)A->data;
592841e96a3SJed Brown   Mat            *b;
593841e96a3SJed Brown   PetscInt       i,j,nr = bA->nr,nc = bA->nc;
594d8588912SDave May   PetscErrorCode ierr;
595d8588912SDave May 
596d8588912SDave May   PetscFunctionBegin;
597841e96a3SJed Brown   ierr = PetscMalloc(nr*nc*sizeof(Mat),&b);CHKERRQ(ierr);
598841e96a3SJed Brown   for (i=0; i<nr; i++) {
599841e96a3SJed Brown     for (j=0; j<nc; j++) {
600841e96a3SJed Brown       if (bA->m[i][j]) {
601841e96a3SJed Brown         ierr = MatDuplicate(bA->m[i][j],op,&b[i*nc+j]);CHKERRQ(ierr);
602841e96a3SJed Brown       } else {
603841e96a3SJed Brown         b[i*nc+j] = PETSC_NULL;
604d8588912SDave May       }
605d8588912SDave May     }
606d8588912SDave May   }
607f349c1fdSJed Brown   ierr = MatCreateNest(((PetscObject)A)->comm,nr,bA->isglobal.row,nc,bA->isglobal.col,b,B);CHKERRQ(ierr);
608841e96a3SJed Brown   /* Give the new MatNest exclusive ownership */
609841e96a3SJed Brown   for (i=0; i<nr*nc; i++) {
610841e96a3SJed Brown     if (b[i]) {ierr = MatDestroy(b[i]);CHKERRQ(ierr);}
611d8588912SDave May   }
612d8588912SDave May   ierr = PetscFree(b);CHKERRQ(ierr);
613d8588912SDave May 
614841e96a3SJed Brown   ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
615841e96a3SJed Brown   ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
616d8588912SDave May   PetscFunctionReturn(0);
617d8588912SDave May }
618d8588912SDave May 
619d8588912SDave May /* nest api */
620d8588912SDave May EXTERN_C_BEGIN
621d8588912SDave May #undef __FUNCT__
622d8588912SDave May #define __FUNCT__ "MatNestGetSubMat_Nest"
623d8588912SDave May PetscErrorCode MatNestGetSubMat_Nest(Mat A,PetscInt idxm,PetscInt jdxm,Mat *mat)
624d8588912SDave May {
625d8588912SDave May   Mat_Nest *bA = (Mat_Nest*)A->data;
626d8588912SDave May   PetscFunctionBegin;
627d8588912SDave May   if (idxm >= bA->nr) SETERRQ2(((PetscObject)A)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",idxm,bA->nr-1);
628d8588912SDave May   if (jdxm >= bA->nc) SETERRQ2(((PetscObject)A)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Col too large: row %D max %D",jdxm,bA->nc-1);
629d8588912SDave May   *mat = bA->m[idxm][jdxm];
630d8588912SDave May   PetscFunctionReturn(0);
631d8588912SDave May }
632d8588912SDave May EXTERN_C_END
633d8588912SDave May 
634d8588912SDave May #undef __FUNCT__
635d8588912SDave May #define __FUNCT__ "MatNestGetSubMat"
636d8588912SDave May /*@C
637d8588912SDave May  MatNestGetSubMat - Returns a single, sub-matrix from a nest matrix.
638d8588912SDave May 
639d8588912SDave May  Not collective
640d8588912SDave May 
641d8588912SDave May  Input Parameters:
642d8588912SDave May  .  A  - nest matrix
643d8588912SDave May  .  idxm - index of the matrix within the nest matrix
644d8588912SDave May  .  jdxm - index of the matrix within the nest matrix
645d8588912SDave May 
646d8588912SDave May  Output Parameter:
647d8588912SDave May  .  sub - matrix at index idxm,jdxm within the nest matrix
648d8588912SDave May 
649d8588912SDave May  Notes:
650d8588912SDave May 
651d8588912SDave May  Level: developer
652d8588912SDave May 
653d8588912SDave May  .seealso: MatNestGetSize(), MatNestGetSubMats()
654d8588912SDave May @*/
655d8588912SDave May PetscErrorCode PETSCMAT_DLLEXPORT MatNestGetSubMat(Mat A,PetscInt idxm,PetscInt jdxm,Mat *sub)
656d8588912SDave May {
657699a902aSJed Brown   PetscErrorCode ierr;
658d8588912SDave May 
659d8588912SDave May   PetscFunctionBegin;
660699a902aSJed Brown   ierr = PetscUseMethod(A,"MatNestGetSubMat_C",(Mat,PetscInt,PetscInt,Mat*),(A,idxm,jdxm,sub));CHKERRQ(ierr);
661d8588912SDave May   PetscFunctionReturn(0);
662d8588912SDave May }
663d8588912SDave May 
664d8588912SDave May EXTERN_C_BEGIN
665d8588912SDave May #undef __FUNCT__
666d8588912SDave May #define __FUNCT__ "MatNestGetSubMats_Nest"
667d8588912SDave May PetscErrorCode MatNestGetSubMats_Nest(Mat A,PetscInt *M,PetscInt *N,Mat ***mat)
668d8588912SDave May {
669d8588912SDave May   Mat_Nest *bA = (Mat_Nest*)A->data;
670d8588912SDave May   PetscFunctionBegin;
671d8588912SDave May   if (M)   { *M   = bA->nr; }
672d8588912SDave May   if (N)   { *N   = bA->nc; }
673d8588912SDave May   if (mat) { *mat = bA->m;  }
674d8588912SDave May   PetscFunctionReturn(0);
675d8588912SDave May }
676d8588912SDave May EXTERN_C_END
677d8588912SDave May 
678d8588912SDave May #undef __FUNCT__
679d8588912SDave May #define __FUNCT__ "MatNestGetSubMats"
680d8588912SDave May /*@C
681d8588912SDave May  MatNestGetSubMats - Returns the entire two dimensional array of matrices defining a nest matrix.
682d8588912SDave May 
683d8588912SDave May  Not collective
684d8588912SDave May 
685d8588912SDave May  Input Parameters:
686d8588912SDave May  .  A  - nest matri
687d8588912SDave May 
688d8588912SDave May  Output Parameter:
689d8588912SDave May  .  M - number of rows in the nest matrix
690d8588912SDave May  .  N - number of cols in the nest matrix
691d8588912SDave May  .  mat - 2d array of matrices
692d8588912SDave May 
693d8588912SDave May  Notes:
694d8588912SDave May 
695d8588912SDave May  The user should not free the array mat.
696d8588912SDave May 
697d8588912SDave May  Level: developer
698d8588912SDave May 
699d8588912SDave May  .seealso: MatNestGetSize(), MatNestGetSubMat()
700d8588912SDave May @*/
701d8588912SDave May PetscErrorCode PETSCMAT_DLLEXPORT MatNestGetSubMats(Mat A,PetscInt *M,PetscInt *N,Mat ***mat)
702d8588912SDave May {
703699a902aSJed Brown   PetscErrorCode ierr;
704d8588912SDave May 
705d8588912SDave May   PetscFunctionBegin;
706699a902aSJed Brown   ierr = PetscUseMethod(A,"MatNestGetSubMats_C",(Mat,PetscInt*,PetscInt*,Mat***),(A,M,N,mat));CHKERRQ(ierr);
707d8588912SDave May   PetscFunctionReturn(0);
708d8588912SDave May }
709d8588912SDave May 
710d8588912SDave May EXTERN_C_BEGIN
711d8588912SDave May #undef __FUNCT__
712d8588912SDave May #define __FUNCT__ "MatNestGetSize_Nest"
713d8588912SDave May PetscErrorCode PETSCMAT_DLLEXPORT MatNestGetSize_Nest(Mat A,PetscInt *M,PetscInt *N)
714d8588912SDave May {
715d8588912SDave May   Mat_Nest  *bA = (Mat_Nest*)A->data;
716d8588912SDave May 
717d8588912SDave May   PetscFunctionBegin;
718d8588912SDave May   if (M) { *M  = bA->nr; }
719d8588912SDave May   if (N) { *N  = bA->nc; }
720d8588912SDave May   PetscFunctionReturn(0);
721d8588912SDave May }
722d8588912SDave May EXTERN_C_END
723d8588912SDave May 
724d8588912SDave May #undef __FUNCT__
725d8588912SDave May #define __FUNCT__ "MatNestGetSize"
726d8588912SDave May /*@C
727d8588912SDave May  MatNestGetSize - Returns the size of the nest matrix.
728d8588912SDave May 
729d8588912SDave May  Not collective
730d8588912SDave May 
731d8588912SDave May  Input Parameters:
732d8588912SDave May  .  A  - nest matrix
733d8588912SDave May 
734d8588912SDave May  Output Parameter:
735d8588912SDave May  .  M - number of rows in the nested mat
736d8588912SDave May  .  N - number of cols in the nested mat
737d8588912SDave May 
738d8588912SDave May  Notes:
739d8588912SDave May 
740d8588912SDave May  Level: developer
741d8588912SDave May 
742d8588912SDave May  .seealso: MatNestGetSubMat(), MatNestGetSubMats()
743d8588912SDave May @*/
744d8588912SDave May PetscErrorCode PETSCMAT_DLLEXPORT MatNestGetSize(Mat A,PetscInt *M,PetscInt *N)
745d8588912SDave May {
746699a902aSJed Brown   PetscErrorCode ierr;
747d8588912SDave May 
748d8588912SDave May   PetscFunctionBegin;
749699a902aSJed Brown   ierr = PetscUseMethod(A,"MatNestGetSize_C",(Mat,PetscInt*,PetscInt*),(A,M,N));CHKERRQ(ierr);
750d8588912SDave May   PetscFunctionReturn(0);
751d8588912SDave May }
752d8588912SDave May 
753d8588912SDave May /* constructor */
754d8588912SDave May #undef __FUNCT__
755d8588912SDave May #define __FUNCT__ "MatNestSetOps_Private"
756d8588912SDave May static PetscErrorCode MatNestSetOps_Private(struct _MatOps* ops)
757d8588912SDave May {
758d8588912SDave May   PetscFunctionBegin;
759d8588912SDave May   /* 0*/
760d8588912SDave May   ops->setvalues  = 0;
761d8588912SDave May   ops->getrow     = 0;
762d8588912SDave May   ops->restorerow = 0;
763d8588912SDave May   ops->mult       = MatMult_Nest;
764d8588912SDave May   ops->multadd    = 0;
765d8588912SDave May   /* 5*/
766d8588912SDave May   ops->multtranspose    = MatMultTranspose_Nest;
767d8588912SDave May   ops->multtransposeadd = 0;
768d8588912SDave May   ops->solve            = 0;
769d8588912SDave May   ops->solveadd         = 0;
770d8588912SDave May   ops->solvetranspose   = 0;
771d8588912SDave May   /*10*/
772d8588912SDave May   ops->solvetransposeadd = 0;
773d8588912SDave May   ops->lufactor          = 0;
774d8588912SDave May   ops->choleskyfactor    = 0;
775d8588912SDave May   ops->sor               = 0;
776d8588912SDave May   ops->transpose         = 0;
777d8588912SDave May   /*15*/
778d8588912SDave May   ops->getinfo       = 0;
779d8588912SDave May   ops->equal         = 0;
780d8588912SDave May   ops->getdiagonal   = 0;
781d8588912SDave May   ops->diagonalscale = 0;
782d8588912SDave May   ops->norm          = 0;
783d8588912SDave May   /*20*/
784d8588912SDave May   ops->assemblybegin = MatAssemblyBegin_Nest;
785d8588912SDave May   ops->assemblyend   = MatAssemblyEnd_Nest;
786d8588912SDave May   ops->setoption     = 0;
787d8588912SDave May   ops->zeroentries   = MatZeroEntries_Nest;
788d8588912SDave May   /*24*/
789d8588912SDave May   ops->zerorows               = 0;
790d8588912SDave May   ops->lufactorsymbolic       = 0;
791d8588912SDave May   ops->lufactornumeric        = 0;
792d8588912SDave May   ops->choleskyfactorsymbolic = 0;
793d8588912SDave May   ops->choleskyfactornumeric  = 0;
794d8588912SDave May   /*29*/
795d8588912SDave May   ops->setuppreallocation = 0;
796d8588912SDave May   ops->ilufactorsymbolic  = 0;
797d8588912SDave May   ops->iccfactorsymbolic  = 0;
798d8588912SDave May   ops->getarray           = 0;
799d8588912SDave May   ops->restorearray       = 0;
800d8588912SDave May   /*34*/
801d8588912SDave May   ops->duplicate     = MatDuplicate_Nest;
802d8588912SDave May   ops->forwardsolve  = 0;
803d8588912SDave May   ops->backwardsolve = 0;
804d8588912SDave May   ops->ilufactor     = 0;
805d8588912SDave May   ops->iccfactor     = 0;
806d8588912SDave May   /*39*/
807d8588912SDave May   ops->axpy            = 0;
808d8588912SDave May   ops->getsubmatrices  = 0;
809d8588912SDave May   ops->increaseoverlap = 0;
810d8588912SDave May   ops->getvalues       = 0;
811d8588912SDave May   ops->copy            = 0;
812d8588912SDave May   /*44*/
813d8588912SDave May   ops->getrowmax   = 0;
814d8588912SDave May   ops->scale       = 0;
815d8588912SDave May   ops->shift       = 0;
816d8588912SDave May   ops->diagonalset = 0;
817d8588912SDave May   ops->zerorowscolumns  = 0;
818d8588912SDave May   /*49*/
819d8588912SDave May   ops->setblocksize    = 0;
820d8588912SDave May   ops->getrowij        = 0;
821d8588912SDave May   ops->restorerowij    = 0;
822d8588912SDave May   ops->getcolumnij     = 0;
823d8588912SDave May   ops->restorecolumnij = 0;
824d8588912SDave May   /*54*/
825d8588912SDave May   ops->fdcoloringcreate = 0;
826d8588912SDave May   ops->coloringpatch    = 0;
827d8588912SDave May   ops->setunfactored    = 0;
828d8588912SDave May   ops->permute          = 0;
829d8588912SDave May   ops->setvaluesblocked = 0;
830d8588912SDave May   /*59*/
831f349c1fdSJed Brown   ops->getsubmatrix  = MatGetSubMatrix_Nest;
832d8588912SDave May   ops->destroy       = MatDestroy_Nest;
833d8588912SDave May   ops->view          = MatView_Nest;
834d8588912SDave May   ops->convertfrom   = 0;
835d8588912SDave May   ops->usescaledform = 0;
836d8588912SDave May   /*64*/
837d8588912SDave May   ops->scalesystem             = 0;
838d8588912SDave May   ops->unscalesystem           = 0;
839d8588912SDave May   ops->setlocaltoglobalmapping = 0;
840d8588912SDave May   ops->setvalueslocal          = 0;
841d8588912SDave May   ops->zerorowslocal           = 0;
842d8588912SDave May   /*69*/
843d8588912SDave May   ops->getrowmaxabs    = 0;
844d8588912SDave May   ops->getrowminabs    = 0;
845d8588912SDave May   ops->convert         = 0;/*MatConvert_Nest;*/
846d8588912SDave May   ops->setcoloring     = 0;
847d8588912SDave May   ops->setvaluesadic   = 0;
848d8588912SDave May   /* 74 */
849d8588912SDave May   ops->setvaluesadifor = 0;
850d8588912SDave May   ops->fdcoloringapply              = 0;
851d8588912SDave May   ops->setfromoptions               = 0;
852d8588912SDave May   ops->multconstrained              = 0;
853d8588912SDave May   ops->multtransposeconstrained     = 0;
854d8588912SDave May   /*79*/
855d8588912SDave May   ops->permutesparsify = 0;
856d8588912SDave May   ops->mults           = 0;
857d8588912SDave May   ops->solves          = 0;
858d8588912SDave May   ops->getinertia      = 0;
859d8588912SDave May   ops->load            = 0;
860d8588912SDave May   /*84*/
861d8588912SDave May   ops->issymmetric             = 0;
862d8588912SDave May   ops->ishermitian             = 0;
863d8588912SDave May   ops->isstructurallysymmetric = 0;
864d8588912SDave May   ops->dummy4                  = 0;
865d8588912SDave May   ops->getvecs                 = MatGetVecs_Nest;
866d8588912SDave May   /*89*/
867d8588912SDave May   ops->matmult         = 0;/*MatMatMult_Nest;*/
868d8588912SDave May   ops->matmultsymbolic = 0;
869d8588912SDave May   ops->matmultnumeric  = 0;
870d8588912SDave May   ops->ptap            = 0;
871d8588912SDave May   ops->ptapsymbolic    = 0;
872d8588912SDave May   /*94*/
873d8588912SDave May   ops->ptapnumeric              = 0;
874d8588912SDave May   ops->matmulttranspose         = 0;
875d8588912SDave May   ops->matmulttransposesymbolic = 0;
876d8588912SDave May   ops->matmulttransposenumeric  = 0;
877d8588912SDave May   ops->ptapsymbolic_seqaij      = 0;
878d8588912SDave May   /*99*/
879d8588912SDave May   ops->ptapnumeric_seqaij  = 0;
880d8588912SDave May   ops->ptapsymbolic_mpiaij = 0;
881d8588912SDave May   ops->ptapnumeric_mpiaij  = 0;
882d8588912SDave May   ops->conjugate           = 0;
883d8588912SDave May   ops->setsizes            = 0;
884d8588912SDave May   /*104*/
885d8588912SDave May   ops->setvaluesrow              = 0;
886d8588912SDave May   ops->realpart                  = 0;
887d8588912SDave May   ops->imaginarypart             = 0;
888d8588912SDave May   ops->getrowuppertriangular     = 0;
889d8588912SDave May   ops->restorerowuppertriangular = 0;
890d8588912SDave May   /*109*/
891d8588912SDave May   ops->matsolve           = 0;
892d8588912SDave May   ops->getredundantmatrix = 0;
893d8588912SDave May   ops->getrowmin          = 0;
894d8588912SDave May   ops->getcolumnvector    = 0;
895d8588912SDave May   ops->missingdiagonal    = 0;
896d8588912SDave May   /* 114 */
897d8588912SDave May   ops->getseqnonzerostructure = 0;
898d8588912SDave May   ops->create                 = 0;
899d8588912SDave May   ops->getghosts              = 0;
900d8588912SDave May   ops->getlocalsubmatrix      = MatGetLocalSubMatrix_Nest;
901d8588912SDave May   ops->restorelocalsubmatrix  = MatRestoreLocalSubMatrix_Nest;
902d8588912SDave May   /* 119 */
903d8588912SDave May   ops->multdiagonalblock         = 0;
904d8588912SDave May   ops->hermitiantranspose        = 0;
905d8588912SDave May   ops->multhermitiantranspose    = 0;
906d8588912SDave May   ops->multhermitiantransposeadd = 0;
907d8588912SDave May   ops->getmultiprocblock         = 0;
908d8588912SDave May   /* 124 */
909d8588912SDave May   ops->dummy1                 = 0;
910d8588912SDave May   ops->dummy2                 = 0;
911d8588912SDave May   ops->dummy3                 = 0;
912d8588912SDave May   ops->dummy4                 = 0;
913d8588912SDave May   ops->getsubmatricesparallel = 0;
914d8588912SDave May 
915d8588912SDave May   PetscFunctionReturn(0);
916d8588912SDave May }
917d8588912SDave May 
918d8588912SDave May #undef __FUNCT__
919d8588912SDave May #define __FUNCT__ "MatSetUp_Nest_Private"
920841e96a3SJed Brown static PetscErrorCode MatSetUp_Nest_Private(Mat A,PetscInt nr,PetscInt nc,const Mat *sub)
921d8588912SDave May {
922d8588912SDave May   Mat_Nest       *ctx = (Mat_Nest*)A->data;
923d8588912SDave May   PetscInt       i,j;
924d8588912SDave May   PetscErrorCode ierr;
925d8588912SDave May 
926d8588912SDave May   PetscFunctionBegin;
927d8588912SDave May   if(ctx->setup_called) PetscFunctionReturn(0);
928d8588912SDave May 
929d8588912SDave May   ctx->nr = nr;
930d8588912SDave May   ctx->nc = nc;
931d8588912SDave May 
932d8588912SDave May   /* Create space */
933d8588912SDave May   ierr = PetscMalloc(sizeof(Mat*)*ctx->nr,&ctx->m);CHKERRQ(ierr);
934d8588912SDave May   for (i=0; i<ctx->nr; i++) {
935d8588912SDave May     ierr = PetscMalloc(sizeof(Mat)*ctx->nc,&ctx->m[i]);CHKERRQ(ierr);
936d8588912SDave May   }
937d8588912SDave May   for (i=0; i<ctx->nr; i++) {
938d8588912SDave May     for (j=0; j<ctx->nc; j++) {
939841e96a3SJed Brown       ctx->m[i][j] = sub[i*nc+j];
940841e96a3SJed Brown       if (sub[i*nc+j]) {
941841e96a3SJed Brown         ierr = PetscObjectReference((PetscObject)sub[i*nc+j]);CHKERRQ(ierr);
942d8588912SDave May       }
943d8588912SDave May     }
944d8588912SDave May   }
945d8588912SDave May 
946f349c1fdSJed Brown   ierr = PetscMalloc(sizeof(IS)*ctx->nr,&ctx->isglobal.row);CHKERRQ(ierr);
947f349c1fdSJed Brown   ierr = PetscMalloc(sizeof(IS)*ctx->nc,&ctx->isglobal.col);CHKERRQ(ierr);
948d8588912SDave May 
949d8588912SDave May   ierr = PetscMalloc(sizeof(PetscInt)*ctx->nr,&ctx->row_len);CHKERRQ(ierr);
950d8588912SDave May   ierr = PetscMalloc(sizeof(PetscInt)*ctx->nc,&ctx->col_len);CHKERRQ(ierr);
951d8588912SDave May   for (i=0;i<ctx->nr;i++) ctx->row_len[i]=-1;
952d8588912SDave May   for (j=0;j<ctx->nc;j++) ctx->col_len[j]=-1;
953d8588912SDave May 
954d8588912SDave May   ctx->setup_called = PETSC_TRUE;
955d8588912SDave May 
956d8588912SDave May   PetscFunctionReturn(0);
957d8588912SDave May }
958d8588912SDave May 
959d8588912SDave May 
960d8588912SDave May /* If an IS was provided, there is nothing Nest needs to do, otherwise Nest will build a strided IS */
961d8588912SDave May /*
962d8588912SDave May   nprocessors = NP
963d8588912SDave May   Nest x^T = ( (g_0,g_1,...g_nprocs-1), (h_0,h_1,...h_NP-1) )
964d8588912SDave May        proc 0: => (g_0,h_0,)
965d8588912SDave May        proc 1: => (g_1,h_1,)
966d8588912SDave May        ...
967d8588912SDave May        proc nprocs-1: => (g_NP-1,h_NP-1,)
968d8588912SDave May 
969d8588912SDave May             proc 0:                      proc 1:                    proc nprocs-1:
970d8588912SDave May     is[0] = ( 0,1,2,...,nlocal(g_0)-1 )  ( 0,1,...,nlocal(g_1)-1 )  ( 0,1,...,nlocal(g_NP-1) )
971d8588912SDave May 
972d8588912SDave May             proc 0:
973d8588912SDave May     is[1] = ( nlocal(g_0),nlocal(g_0)+1,...,nlocal(g_0)+nlocal(h_0)-1 )
974d8588912SDave May             proc 1:
975d8588912SDave May     is[1] = ( nlocal(g_1),nlocal(g_1)+1,...,nlocal(g_1)+nlocal(h_1)-1 )
976d8588912SDave May 
977d8588912SDave May             proc NP-1:
978d8588912SDave May     is[1] = ( nlocal(g_NP-1),nlocal(g_NP-1)+1,...,nlocal(g_NP-1)+nlocal(h_NP-1)-1 )
979d8588912SDave May */
980d8588912SDave May #undef __FUNCT__
981d8588912SDave May #define __FUNCT__ "MatSetUp_NestIS_Private"
982841e96a3SJed Brown static PetscErrorCode MatSetUp_NestIS_Private(Mat A,PetscInt nr,const IS is_row[],PetscInt nc,const IS is_col[])
983d8588912SDave May {
984*e2d7f03fSJed Brown   Mat_Nest       *vs = (Mat_Nest*)A->data;
9852ae74bdbSJed Brown   PetscInt       i,j,offset,n,bs;
986d8588912SDave May   PetscErrorCode ierr;
9872ae74bdbSJed Brown   Mat            sub;
988d8588912SDave May 
989d8588912SDave May   PetscFunctionBegin;
990d8588912SDave May   if (is_row) { /* valid IS is passed in */
991d8588912SDave May     /* refs on is[] are incremeneted */
992*e2d7f03fSJed Brown     for (i=0; i<vs->nr; i++) {
993d8588912SDave May       ierr = PetscObjectReference((PetscObject)is_row[i]);CHKERRQ(ierr);
994*e2d7f03fSJed Brown       vs->isglobal.row[i] = is_row[i];
995d8588912SDave May     }
9962ae74bdbSJed Brown   } else {                      /* Create the ISs by inspecting sizes of a submatrix in each row */
9972ae74bdbSJed Brown     offset = A->rmap->rstart;
998*e2d7f03fSJed Brown     for (i=0; i<vs->nr; i++) {
999f349c1fdSJed Brown       ierr = MatNestFindNonzeroSubMatRow(A,i,&sub);CHKERRQ(ierr);
10002ae74bdbSJed Brown       ierr = MatGetLocalSize(sub,&n,PETSC_NULL);CHKERRQ(ierr);
10012ae74bdbSJed Brown       ierr = MatGetBlockSize(sub,&bs);CHKERRQ(ierr);
1002*e2d7f03fSJed Brown       ierr = ISCreateStride(((PetscObject)sub)->comm,n,offset,1,&vs->isglobal.row[i]);CHKERRQ(ierr);
1003*e2d7f03fSJed Brown       ierr = ISSetBlockSize(vs->isglobal.row[i],bs);CHKERRQ(ierr);
10042ae74bdbSJed Brown       offset += n;
1005d8588912SDave May     }
1006d8588912SDave May   }
1007d8588912SDave May 
1008d8588912SDave May   if (is_col) { /* valid IS is passed in */
1009d8588912SDave May     /* refs on is[] are incremeneted */
1010*e2d7f03fSJed Brown     for (j=0; j<vs->nc; j++) {
1011d8588912SDave May       ierr = PetscObjectReference((PetscObject)is_col[j]);CHKERRQ(ierr);
1012*e2d7f03fSJed Brown       vs->isglobal.col[j] = is_col[j];
1013d8588912SDave May     }
10142ae74bdbSJed Brown   } else {                      /* Create the ISs by inspecting sizes of a submatrix in each column */
10152ae74bdbSJed Brown     offset = A->cmap->rstart;
1016*e2d7f03fSJed Brown     for (j=0; j<vs->nc; j++) {
1017f349c1fdSJed Brown       ierr = MatNestFindNonzeroSubMatCol(A,j,&sub);CHKERRQ(ierr);
10182ae74bdbSJed Brown       ierr = MatGetLocalSize(sub,PETSC_NULL,&n);CHKERRQ(ierr);
10192ae74bdbSJed Brown       ierr = MatGetBlockSize(sub,&bs);CHKERRQ(ierr);
1020*e2d7f03fSJed Brown       ierr = ISCreateStride(((PetscObject)sub)->comm,n,offset,1,&vs->isglobal.col[j]);CHKERRQ(ierr);
1021*e2d7f03fSJed Brown       ierr = ISSetBlockSize(vs->isglobal.col[j],bs);CHKERRQ(ierr);
10222ae74bdbSJed Brown       offset += n;
1023d8588912SDave May     }
1024d8588912SDave May   }
1025*e2d7f03fSJed Brown 
1026*e2d7f03fSJed Brown   /* Set up the local ISs */
1027*e2d7f03fSJed Brown   ierr = PetscMalloc(vs->nr*sizeof(IS),&vs->islocal.row);CHKERRQ(ierr);
1028*e2d7f03fSJed Brown   ierr = PetscMalloc(vs->nc*sizeof(IS),&vs->islocal.col);CHKERRQ(ierr);
1029*e2d7f03fSJed Brown   for (i=0,offset=0; i<vs->nr; i++) {
1030*e2d7f03fSJed Brown     IS                     isloc;
1031*e2d7f03fSJed Brown     ISLocalToGlobalMapping rmap;
1032*e2d7f03fSJed Brown     PetscInt               nlocal,bs;
1033*e2d7f03fSJed Brown     ierr = MatNestFindNonzeroSubMatRow(A,i,&sub);CHKERRQ(ierr);
1034*e2d7f03fSJed Brown     ierr = MatGetLocalToGlobalMapping(sub,&rmap,PETSC_NULL);CHKERRQ(ierr);
1035*e2d7f03fSJed Brown     ierr = MatGetBlockSize(sub,&bs);CHKERRQ(ierr);
1036*e2d7f03fSJed Brown     ierr = ISLocalToGlobalMappingGetSize(rmap,&nlocal);CHKERRQ(ierr);
1037*e2d7f03fSJed Brown     ierr = ISCreateStride(PETSC_COMM_SELF,nlocal,offset,1,&isloc);CHKERRQ(ierr);
1038*e2d7f03fSJed Brown     ierr = ISSetBlockSize(isloc,bs);CHKERRQ(ierr);
1039*e2d7f03fSJed Brown     vs->islocal.row[i] = isloc;
1040*e2d7f03fSJed Brown     offset += nlocal;
1041*e2d7f03fSJed Brown   }
1042*e2d7f03fSJed Brown   for (i=0,offset=0; i<vs->nr; i++) {
1043*e2d7f03fSJed Brown     IS                     isloc;
1044*e2d7f03fSJed Brown     ISLocalToGlobalMapping cmap;
1045*e2d7f03fSJed Brown     PetscInt               nlocal,bs;
1046*e2d7f03fSJed Brown     ierr = MatNestFindNonzeroSubMatCol(A,i,&sub);CHKERRQ(ierr);
1047*e2d7f03fSJed Brown     ierr = MatGetLocalToGlobalMapping(sub,PETSC_NULL,&cmap);CHKERRQ(ierr);
1048*e2d7f03fSJed Brown     ierr = MatGetBlockSize(sub,&bs);CHKERRQ(ierr);
1049*e2d7f03fSJed Brown     ierr = ISLocalToGlobalMappingGetSize(cmap,&nlocal);CHKERRQ(ierr);
1050*e2d7f03fSJed Brown     ierr = ISCreateStride(PETSC_COMM_SELF,nlocal,offset,1,&isloc);CHKERRQ(ierr);
1051*e2d7f03fSJed Brown     ierr = ISSetBlockSize(isloc,bs);CHKERRQ(ierr);
1052*e2d7f03fSJed Brown     vs->islocal.col[i] = isloc;
1053*e2d7f03fSJed Brown     offset += nlocal;
1054*e2d7f03fSJed Brown   }
1055d8588912SDave May   PetscFunctionReturn(0);
1056d8588912SDave May }
1057d8588912SDave May 
1058d8588912SDave May #undef __FUNCT__
1059d8588912SDave May #define __FUNCT__ "MatCreateNest"
1060841e96a3SJed Brown PetscErrorCode PETSCMAT_DLLEXPORT MatCreateNest(MPI_Comm comm,PetscInt nr,const IS is_row[],PetscInt nc,const IS is_col[],const Mat a[],Mat *B)
1061d8588912SDave May {
1062d8588912SDave May   Mat            A;
1063d8588912SDave May   Mat_Nest       *s;
10642ae74bdbSJed Brown   PetscInt       i,m,n,M,N;
1065d8588912SDave May   PetscErrorCode ierr;
1066d8588912SDave May 
1067d8588912SDave May   PetscFunctionBegin;
1068841e96a3SJed Brown   if (nr < 0) SETERRQ(comm,PETSC_ERR_ARG_OUTOFRANGE,"Number of rows cannot be negative");
10692ae74bdbSJed Brown   if (nr && is_row) {
10702ae74bdbSJed Brown     PetscValidPointer(is_row,3);
10712ae74bdbSJed Brown     for (i=0; i<nr; i++) PetscValidHeaderSpecific(is_row[i],IS_CLASSID,3);
10722ae74bdbSJed Brown   }
1073841e96a3SJed Brown   if (nc < 0) SETERRQ(comm,PETSC_ERR_ARG_OUTOFRANGE,"Number of columns cannot be negative");
10742ae74bdbSJed Brown   if (nc && is_row) {
10752ae74bdbSJed Brown     PetscValidPointer(is_col,5);
10762ae74bdbSJed Brown     for (i=0; i<nr; i++) PetscValidHeaderSpecific(is_col[i],IS_CLASSID,5);
10772ae74bdbSJed Brown   }
1078841e96a3SJed Brown   if (nr*nc) PetscValidPointer(a,6);
1079841e96a3SJed Brown   PetscValidPointer(B,7);
1080841e96a3SJed Brown 
1081d8588912SDave May   ierr = MatCreate(comm,&A);CHKERRQ(ierr);
1082d8588912SDave May 
1083d8588912SDave May   ierr = PetscMalloc( sizeof(Mat_Nest), &s );CHKERRQ(ierr);
1084d8588912SDave May   ierr = PetscMemzero( s, sizeof(Mat_Nest) );CHKERRQ(ierr);
1085d8588912SDave May   A->data         = (void*)s;
1086d8588912SDave May   s->setup_called = PETSC_FALSE;
1087d8588912SDave May   s->nr = s->nc   = -1;
1088d8588912SDave May   s->m            = PETSC_NULL;
1089d8588912SDave May 
1090d8588912SDave May   /* define the operations */
1091d8588912SDave May   ierr = MatNestSetOps_Private(A->ops);CHKERRQ(ierr);
1092d8588912SDave May   A->spptr            = 0;
1093d8588912SDave May   A->same_nonzero     = PETSC_FALSE;
1094d8588912SDave May   A->assembled        = PETSC_FALSE;
1095d8588912SDave May 
1096d8588912SDave May   ierr = PetscObjectChangeTypeName((PetscObject) A, MATNEST );CHKERRQ(ierr);
1097d8588912SDave May   ierr = MatSetUp_Nest_Private(A,nr,nc,a);CHKERRQ(ierr);
1098d8588912SDave May 
1099d8588912SDave May   m = n = 0;
1100d8588912SDave May   M = N = 0;
1101d8588912SDave May   ierr = MatNestGetSize_Recursive(A,PETSC_TRUE,&M,&N);CHKERRQ(ierr);
1102d8588912SDave May   ierr = MatNestGetSize_Recursive(A,PETSC_FALSE,&m,&n);CHKERRQ(ierr);
1103d8588912SDave May 
1104d8588912SDave May   ierr = PetscLayoutSetSize(A->rmap,M);CHKERRQ(ierr);
1105d8588912SDave May   ierr = PetscLayoutSetLocalSize(A->rmap,m);CHKERRQ(ierr);
1106d8588912SDave May   ierr = PetscLayoutSetBlockSize(A->rmap,1);CHKERRQ(ierr);
1107d8588912SDave May   ierr = PetscLayoutSetSize(A->cmap,N);CHKERRQ(ierr);
1108d8588912SDave May   ierr = PetscLayoutSetLocalSize(A->cmap,n);CHKERRQ(ierr);
1109d8588912SDave May   ierr = PetscLayoutSetBlockSize(A->cmap,1);CHKERRQ(ierr);
1110d8588912SDave May 
1111d8588912SDave May   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
1112d8588912SDave May   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
1113d8588912SDave May 
1114841e96a3SJed Brown   ierr = MatSetUp_NestIS_Private(A,nr,is_row,nc,is_col);CHKERRQ(ierr);
1115d8588912SDave May 
1116d8588912SDave May   /* expose Nest api's */
1117d8588912SDave May   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatNestGetSubMat_C","MatNestGetSubMat_Nest",MatNestGetSubMat_Nest);CHKERRQ(ierr);
1118d8588912SDave May   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatNestGetSubMats_C","MatNestGetSubMats_Nest",MatNestGetSubMats_Nest);CHKERRQ(ierr);
1119d8588912SDave May   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatNestGetSize_C","MatNestGetSize_Nest",MatNestGetSize_Nest);CHKERRQ(ierr);
1120d8588912SDave May 
1121d8588912SDave May   *B = A;
1122d8588912SDave May   PetscFunctionReturn(0);
1123d8588912SDave May }
1124d8588912SDave May 
1125