xref: /petsc/src/mat/impls/nest/matnest.c (revision 429bac76d83bdb4946a08a318877fb577ff60667)
1d8588912SDave May 
2ec9811eeSJed Brown #include "matnestimpl.h" /*I   "petscmat.h"   I*/
3d8588912SDave May 
4c8883902SJed Brown static PetscErrorCode MatSetUp_NestIS_Private(Mat,PetscInt,const IS[],PetscInt,const IS[]);
57874fa86SDave May static PetscErrorCode MatGetVecs_Nest(Mat A,Vec *right,Vec *left);
6c8883902SJed Brown 
7d8588912SDave May /* private functions */
8d8588912SDave May #undef __FUNCT__
98188e55aSJed Brown #define __FUNCT__ "MatNestGetSizes_Private"
108188e55aSJed Brown static PetscErrorCode MatNestGetSizes_Private(Mat A,PetscInt *m,PetscInt *n,PetscInt *M,PetscInt *N)
11d8588912SDave May {
12d8588912SDave May   Mat_Nest       *bA = (Mat_Nest*)A->data;
138188e55aSJed Brown   PetscInt       i,j;
14d8588912SDave May   PetscErrorCode ierr;
15d8588912SDave May 
16d8588912SDave May   PetscFunctionBegin;
178188e55aSJed Brown   *m = *n = *M = *N = 0;
188188e55aSJed Brown   for (i=0; i<bA->nr; i++) {  /* rows */
198188e55aSJed Brown     PetscInt sm,sM;
208188e55aSJed Brown     ierr = ISGetLocalSize(bA->isglobal.row[i],&sm);CHKERRQ(ierr);
218188e55aSJed Brown     ierr = ISGetSize(bA->isglobal.row[i],&sM);CHKERRQ(ierr);
228188e55aSJed Brown     *m += sm;
238188e55aSJed Brown     *M += sM;
24d8588912SDave May   }
258188e55aSJed Brown   for (j=0; j<bA->nc; j++) {  /* cols */
268188e55aSJed Brown     PetscInt sn,sN;
278188e55aSJed Brown     ierr = ISGetLocalSize(bA->isglobal.col[j],&sn);CHKERRQ(ierr);
288188e55aSJed Brown     ierr = ISGetSize(bA->isglobal.col[j],&sN);CHKERRQ(ierr);
298188e55aSJed Brown     *n += sn;
308188e55aSJed Brown     *N += sN;
31d8588912SDave May   }
32d8588912SDave May   PetscFunctionReturn(0);
33d8588912SDave May }
34d8588912SDave May 
35d8588912SDave May /* operations */
36d8588912SDave May #undef __FUNCT__
37d8588912SDave May #define __FUNCT__ "MatMult_Nest"
38207556f9SJed Brown static PetscErrorCode MatMult_Nest(Mat A,Vec x,Vec y)
39d8588912SDave May {
40d8588912SDave May   Mat_Nest       *bA = (Mat_Nest*)A->data;
41207556f9SJed Brown   Vec            *bx = bA->right,*by = bA->left;
42207556f9SJed Brown   PetscInt       i,j,nr = bA->nr,nc = bA->nc;
43d8588912SDave May   PetscErrorCode ierr;
44d8588912SDave May 
45d8588912SDave May   PetscFunctionBegin;
46207556f9SJed Brown   for (i=0; i<nr; i++) {ierr = VecGetSubVector(y,bA->isglobal.row[i],&by[i]);CHKERRQ(ierr);}
47207556f9SJed Brown   for (i=0; i<nc; i++) {ierr = VecGetSubVector(x,bA->isglobal.col[i],&bx[i]);CHKERRQ(ierr);}
48207556f9SJed Brown   for (i=0; i<nr; i++) {
49d8588912SDave May     ierr = VecZeroEntries(by[i]);CHKERRQ(ierr);
50207556f9SJed Brown     for (j=0; j<nc; j++) {
51207556f9SJed Brown       if (!bA->m[i][j]) continue;
52d8588912SDave May       /* y[i] <- y[i] + A[i][j] * x[j] */
53d8588912SDave May       ierr = MatMultAdd(bA->m[i][j],bx[j],by[i],by[i]);CHKERRQ(ierr);
54d8588912SDave May     }
55d8588912SDave May   }
56207556f9SJed Brown   for (i=0; i<nr; i++) {ierr = VecRestoreSubVector(y,bA->isglobal.row[i],&by[i]);CHKERRQ(ierr);}
57207556f9SJed Brown   for (i=0; i<nc; i++) {ierr = VecRestoreSubVector(x,bA->isglobal.col[i],&bx[i]);CHKERRQ(ierr);}
58d8588912SDave May   PetscFunctionReturn(0);
59d8588912SDave May }
60d8588912SDave May 
61d8588912SDave May #undef __FUNCT__
629194d70fSJed Brown #define __FUNCT__ "MatMultAdd_Nest"
639194d70fSJed Brown static PetscErrorCode MatMultAdd_Nest(Mat A,Vec x,Vec y,Vec z)
649194d70fSJed Brown {
659194d70fSJed Brown   Mat_Nest       *bA = (Mat_Nest*)A->data;
669194d70fSJed Brown   Vec            *bx = bA->right,*bz = bA->left;
679194d70fSJed Brown   PetscInt       i,j,nr = bA->nr,nc = bA->nc;
689194d70fSJed Brown   PetscErrorCode ierr;
699194d70fSJed Brown 
709194d70fSJed Brown   PetscFunctionBegin;
719194d70fSJed Brown   for (i=0; i<nr; i++) {ierr = VecGetSubVector(z,bA->isglobal.row[i],&bz[i]);CHKERRQ(ierr);}
729194d70fSJed Brown   for (i=0; i<nc; i++) {ierr = VecGetSubVector(x,bA->isglobal.col[i],&bx[i]);CHKERRQ(ierr);}
739194d70fSJed Brown   for (i=0; i<nr; i++) {
749194d70fSJed Brown     if (y != z) {
759194d70fSJed Brown       Vec by;
769194d70fSJed Brown       ierr = VecGetSubVector(y,bA->isglobal.row[i],&by);CHKERRQ(ierr);
779194d70fSJed Brown       ierr = VecCopy(by,bz[i]);CHKERRQ(ierr);
789194d70fSJed Brown       ierr = VecRestoreSubVector(y,bA->isglobal.col[j],&by);CHKERRQ(ierr);
799194d70fSJed Brown     }
809194d70fSJed Brown     for (j=0; j<nc; j++) {
819194d70fSJed Brown       if (!bA->m[i][j]) continue;
829194d70fSJed Brown       /* y[i] <- y[i] + A[i][j] * x[j] */
839194d70fSJed Brown       ierr = MatMultAdd(bA->m[i][j],bx[j],bz[i],bz[i]);CHKERRQ(ierr);
849194d70fSJed Brown     }
859194d70fSJed Brown   }
869194d70fSJed Brown   for (i=0; i<nr; i++) {ierr = VecRestoreSubVector(z,bA->isglobal.row[i],&bz[i]);CHKERRQ(ierr);}
879194d70fSJed Brown   for (i=0; i<nc; i++) {ierr = VecRestoreSubVector(x,bA->isglobal.col[i],&bx[i]);CHKERRQ(ierr);}
889194d70fSJed Brown   PetscFunctionReturn(0);
899194d70fSJed Brown }
909194d70fSJed Brown 
919194d70fSJed Brown #undef __FUNCT__
92d8588912SDave May #define __FUNCT__ "MatMultTranspose_Nest"
93207556f9SJed Brown static PetscErrorCode MatMultTranspose_Nest(Mat A,Vec x,Vec y)
94d8588912SDave May {
95d8588912SDave May   Mat_Nest       *bA = (Mat_Nest*)A->data;
96207556f9SJed Brown   Vec            *bx = bA->left,*by = bA->right;
97207556f9SJed Brown   PetscInt       i,j,nr = bA->nr,nc = bA->nc;
98d8588912SDave May   PetscErrorCode ierr;
99d8588912SDave May 
100d8588912SDave May   PetscFunctionBegin;
101609e31cbSJed Brown   for (i=0; i<nr; i++) {ierr = VecGetSubVector(x,bA->isglobal.row[i],&bx[i]);CHKERRQ(ierr);}
102609e31cbSJed Brown   for (i=0; i<nc; i++) {ierr = VecGetSubVector(y,bA->isglobal.col[i],&by[i]);CHKERRQ(ierr);}
103207556f9SJed Brown   for (j=0; j<nc; j++) {
104609e31cbSJed Brown     ierr = VecZeroEntries(by[j]);CHKERRQ(ierr);
105609e31cbSJed Brown     for (i=0; i<nr; i++) {
106207556f9SJed Brown       if (!bA->m[j][i]) continue;
107609e31cbSJed Brown       /* y[j] <- y[j] + (A[i][j])^T * x[i] */
108609e31cbSJed Brown       ierr = MatMultTransposeAdd(bA->m[i][j],bx[i],by[j],by[j]);CHKERRQ(ierr);
109d8588912SDave May     }
110d8588912SDave May   }
111609e31cbSJed Brown   for (i=0; i<nr; i++) {ierr = VecRestoreSubVector(x,bA->isglobal.row[i],&bx[i]);CHKERRQ(ierr);}
112609e31cbSJed Brown   for (i=0; i<nc; i++) {ierr = VecRestoreSubVector(y,bA->isglobal.col[i],&by[i]);CHKERRQ(ierr);}
113d8588912SDave May   PetscFunctionReturn(0);
114d8588912SDave May }
115d8588912SDave May 
116d8588912SDave May #undef __FUNCT__
1179194d70fSJed Brown #define __FUNCT__ "MatMultTransposeAdd_Nest"
1189194d70fSJed Brown static PetscErrorCode MatMultTransposeAdd_Nest(Mat A,Vec x,Vec y,Vec z)
1199194d70fSJed Brown {
1209194d70fSJed Brown   Mat_Nest       *bA = (Mat_Nest*)A->data;
1219194d70fSJed Brown   Vec            *bx = bA->left,*bz = bA->right;
1229194d70fSJed Brown   PetscInt       i,j,nr = bA->nr,nc = bA->nc;
1239194d70fSJed Brown   PetscErrorCode ierr;
1249194d70fSJed Brown 
1259194d70fSJed Brown   PetscFunctionBegin;
1269194d70fSJed Brown   for (i=0; i<nr; i++) {ierr = VecGetSubVector(x,bA->isglobal.row[i],&bx[i]);CHKERRQ(ierr);}
1279194d70fSJed Brown   for (i=0; i<nc; i++) {ierr = VecGetSubVector(z,bA->isglobal.col[i],&bz[i]);CHKERRQ(ierr);}
1289194d70fSJed Brown   for (j=0; j<nc; j++) {
1299194d70fSJed Brown     if (y != z) {
1309194d70fSJed Brown       Vec by;
1319194d70fSJed Brown       ierr = VecGetSubVector(y,bA->isglobal.col[j],&by);CHKERRQ(ierr);
1329194d70fSJed Brown       ierr = VecCopy(by,bz[j]);CHKERRQ(ierr);
1339194d70fSJed Brown       ierr = VecRestoreSubVector(y,bA->isglobal.col[j],&by);CHKERRQ(ierr);
1349194d70fSJed Brown     }
1359194d70fSJed Brown     for (i=0; i<nr; i++) {
1369194d70fSJed Brown       if (!bA->m[j][i]) continue;
1379194d70fSJed Brown       /* z[j] <- y[j] + (A[i][j])^T * x[i] */
1389194d70fSJed Brown       ierr = MatMultTransposeAdd(bA->m[i][j],bx[i],bz[j],bz[j]);CHKERRQ(ierr);
1399194d70fSJed Brown     }
1409194d70fSJed Brown   }
1419194d70fSJed Brown   for (i=0; i<nr; i++) {ierr = VecRestoreSubVector(x,bA->isglobal.row[i],&bx[i]);CHKERRQ(ierr);}
1429194d70fSJed Brown   for (i=0; i<nc; i++) {ierr = VecRestoreSubVector(z,bA->isglobal.col[i],&bz[i]);CHKERRQ(ierr);}
1439194d70fSJed Brown   PetscFunctionReturn(0);
1449194d70fSJed Brown }
1459194d70fSJed Brown 
1469194d70fSJed Brown #undef __FUNCT__
147e2d7f03fSJed Brown #define __FUNCT__ "MatNestDestroyISList"
148e2d7f03fSJed Brown static PetscErrorCode MatNestDestroyISList(PetscInt n,IS **list)
149e2d7f03fSJed Brown {
150e2d7f03fSJed Brown   PetscErrorCode ierr;
151e2d7f03fSJed Brown   IS             *lst = *list;
152e2d7f03fSJed Brown   PetscInt       i;
153e2d7f03fSJed Brown 
154e2d7f03fSJed Brown   PetscFunctionBegin;
155e2d7f03fSJed Brown   if (!lst) PetscFunctionReturn(0);
1566bf464f9SBarry Smith   for (i=0; i<n; i++) if (lst[i]) {ierr = ISDestroy(&lst[i]);CHKERRQ(ierr);}
157e2d7f03fSJed Brown   ierr = PetscFree(lst);CHKERRQ(ierr);
158e2d7f03fSJed Brown   *list = PETSC_NULL;
159e2d7f03fSJed Brown   PetscFunctionReturn(0);
160e2d7f03fSJed Brown }
161e2d7f03fSJed Brown 
162e2d7f03fSJed Brown #undef __FUNCT__
163d8588912SDave May #define __FUNCT__ "MatDestroy_Nest"
164207556f9SJed Brown static PetscErrorCode MatDestroy_Nest(Mat A)
165d8588912SDave May {
166d8588912SDave May   Mat_Nest       *vs = (Mat_Nest*)A->data;
167d8588912SDave May   PetscInt       i,j;
168d8588912SDave May   PetscErrorCode ierr;
169d8588912SDave May 
170d8588912SDave May   PetscFunctionBegin;
171d8588912SDave May   /* release the matrices and the place holders */
172e2d7f03fSJed Brown   ierr = MatNestDestroyISList(vs->nr,&vs->isglobal.row);CHKERRQ(ierr);
173e2d7f03fSJed Brown   ierr = MatNestDestroyISList(vs->nc,&vs->isglobal.col);CHKERRQ(ierr);
174e2d7f03fSJed Brown   ierr = MatNestDestroyISList(vs->nr,&vs->islocal.row);CHKERRQ(ierr);
175e2d7f03fSJed Brown   ierr = MatNestDestroyISList(vs->nc,&vs->islocal.col);CHKERRQ(ierr);
176d8588912SDave May 
177d8588912SDave May   ierr = PetscFree(vs->row_len);CHKERRQ(ierr);
178d8588912SDave May   ierr = PetscFree(vs->col_len);CHKERRQ(ierr);
179d8588912SDave May 
180207556f9SJed Brown   ierr = PetscFree2(vs->left,vs->right);CHKERRQ(ierr);
181207556f9SJed Brown 
182d8588912SDave May   /* release the matrices and the place holders */
183d8588912SDave May   if (vs->m) {
184d8588912SDave May     for (i=0; i<vs->nr; i++) {
185d8588912SDave May       for (j=0; j<vs->nc; j++) {
1866bf464f9SBarry Smith         ierr = MatDestroy(&vs->m[i][j]);CHKERRQ(ierr);
187d8588912SDave May       }
188d8588912SDave May       ierr = PetscFree( vs->m[i] );CHKERRQ(ierr);
189d8588912SDave May     }
190d8588912SDave May     ierr = PetscFree(vs->m);CHKERRQ(ierr);
191d8588912SDave May   }
192bf0cc555SLisandro Dalcin   ierr = PetscFree(A->data);CHKERRQ(ierr);
193d8588912SDave May 
194c8883902SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatNestGetSubMat_C",   "",0);CHKERRQ(ierr);
1950782ca92SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatNestSetSubMat_C",   "",0);CHKERRQ(ierr);
196c8883902SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatNestGetSubMats_C",  "",0);CHKERRQ(ierr);
197c8883902SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatNestGetSize_C",     "",0);CHKERRQ(ierr);
198c8883902SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatNestSetVecType_C",  "",0);CHKERRQ(ierr);
199c8883902SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatNestSetSubMats_C",   "",0);CHKERRQ(ierr);
200d8588912SDave May   PetscFunctionReturn(0);
201d8588912SDave May }
202d8588912SDave May 
203d8588912SDave May #undef __FUNCT__
204d8588912SDave May #define __FUNCT__ "MatAssemblyBegin_Nest"
205207556f9SJed Brown static PetscErrorCode MatAssemblyBegin_Nest(Mat A,MatAssemblyType type)
206d8588912SDave May {
207d8588912SDave May   Mat_Nest       *vs = (Mat_Nest*)A->data;
208d8588912SDave May   PetscInt       i,j;
209d8588912SDave May   PetscErrorCode ierr;
210d8588912SDave May 
211d8588912SDave May   PetscFunctionBegin;
212d8588912SDave May   for (i=0; i<vs->nr; i++) {
213d8588912SDave May     for (j=0; j<vs->nc; j++) {
214d8588912SDave May       if (vs->m[i][j]) { ierr = MatAssemblyBegin(vs->m[i][j],type);CHKERRQ(ierr); }
215d8588912SDave May     }
216d8588912SDave May   }
217d8588912SDave May   PetscFunctionReturn(0);
218d8588912SDave May }
219d8588912SDave May 
220d8588912SDave May #undef __FUNCT__
221d8588912SDave May #define __FUNCT__ "MatAssemblyEnd_Nest"
222207556f9SJed Brown static PetscErrorCode MatAssemblyEnd_Nest(Mat A, MatAssemblyType type)
223d8588912SDave May {
224d8588912SDave May   Mat_Nest       *vs = (Mat_Nest*)A->data;
225d8588912SDave May   PetscInt       i,j;
226d8588912SDave May   PetscErrorCode ierr;
227d8588912SDave May 
228d8588912SDave May   PetscFunctionBegin;
229d8588912SDave May   for (i=0; i<vs->nr; i++) {
230d8588912SDave May     for (j=0; j<vs->nc; j++) {
231d8588912SDave May       if (vs->m[i][j]) { ierr = MatAssemblyEnd(vs->m[i][j],type);CHKERRQ(ierr); }
232d8588912SDave May     }
233d8588912SDave May   }
234d8588912SDave May   PetscFunctionReturn(0);
235d8588912SDave May }
236d8588912SDave May 
237d8588912SDave May #undef __FUNCT__
238f349c1fdSJed Brown #define __FUNCT__ "MatNestFindNonzeroSubMatRow"
239f349c1fdSJed Brown static PetscErrorCode MatNestFindNonzeroSubMatRow(Mat A,PetscInt row,Mat *B)
240d8588912SDave May {
241207556f9SJed Brown   PetscErrorCode ierr;
242f349c1fdSJed Brown   Mat_Nest       *vs = (Mat_Nest*)A->data;
243f349c1fdSJed Brown   PetscInt       j;
244f349c1fdSJed Brown   Mat            sub;
245d8588912SDave May 
246d8588912SDave May   PetscFunctionBegin;
2478188e55aSJed Brown   sub = (row < vs->nc) ? vs->m[row][row] : PETSC_NULL; /* Prefer to find on the diagonal */
248f349c1fdSJed Brown   for (j=0; !sub && j<vs->nc; j++) sub = vs->m[row][j];
2498188e55aSJed Brown   if (sub) {ierr = MatPreallocated(sub);CHKERRQ(ierr);} /* Ensure that the sizes are available */
250f349c1fdSJed Brown   *B = sub;
251f349c1fdSJed Brown   PetscFunctionReturn(0);
252d8588912SDave May }
253d8588912SDave May 
254f349c1fdSJed Brown #undef __FUNCT__
255f349c1fdSJed Brown #define __FUNCT__ "MatNestFindNonzeroSubMatCol"
256f349c1fdSJed Brown static PetscErrorCode MatNestFindNonzeroSubMatCol(Mat A,PetscInt col,Mat *B)
257f349c1fdSJed Brown {
258207556f9SJed Brown   PetscErrorCode ierr;
259f349c1fdSJed Brown   Mat_Nest       *vs = (Mat_Nest*)A->data;
260f349c1fdSJed Brown   PetscInt       i;
261f349c1fdSJed Brown   Mat            sub;
262f349c1fdSJed Brown 
263f349c1fdSJed Brown   PetscFunctionBegin;
2648188e55aSJed Brown   sub = (col < vs->nr) ? vs->m[col][col] : PETSC_NULL; /* Prefer to find on the diagonal */
265f349c1fdSJed Brown   for (i=0; !sub && i<vs->nr; i++) sub = vs->m[i][col];
2668188e55aSJed Brown   if (sub) {ierr = MatPreallocated(sub);CHKERRQ(ierr);} /* Ensure that the sizes are available */
267f349c1fdSJed Brown   *B = sub;
268f349c1fdSJed Brown   PetscFunctionReturn(0);
269d8588912SDave May }
270d8588912SDave May 
271f349c1fdSJed Brown #undef __FUNCT__
272f349c1fdSJed Brown #define __FUNCT__ "MatNestFindIS"
273f349c1fdSJed Brown static PetscErrorCode MatNestFindIS(Mat A,PetscInt n,const IS list[],IS is,PetscInt *found)
274f349c1fdSJed Brown {
275f349c1fdSJed Brown   PetscErrorCode ierr;
276f349c1fdSJed Brown   PetscInt       i;
277f349c1fdSJed Brown   PetscBool      flg;
278f349c1fdSJed Brown 
279f349c1fdSJed Brown   PetscFunctionBegin;
280f349c1fdSJed Brown   PetscValidPointer(list,3);
281f349c1fdSJed Brown   PetscValidHeaderSpecific(is,IS_CLASSID,4);
282f349c1fdSJed Brown   PetscValidIntPointer(found,5);
283f349c1fdSJed Brown   *found = -1;
284f349c1fdSJed Brown   for (i=0; i<n; i++) {
285207556f9SJed Brown     if (!list[i]) continue;
286f349c1fdSJed Brown     ierr = ISEqual(list[i],is,&flg);CHKERRQ(ierr);
287f349c1fdSJed Brown     if (flg) {
288f349c1fdSJed Brown       *found = i;
289f349c1fdSJed Brown       PetscFunctionReturn(0);
290f349c1fdSJed Brown     }
291f349c1fdSJed Brown   }
292f349c1fdSJed Brown   SETERRQ(((PetscObject)A)->comm,PETSC_ERR_ARG_INCOMP,"Could not find index set");
293f349c1fdSJed Brown   PetscFunctionReturn(0);
294f349c1fdSJed Brown }
295f349c1fdSJed Brown 
296f349c1fdSJed Brown #undef __FUNCT__
2978188e55aSJed Brown #define __FUNCT__ "MatNestGetRow"
2988188e55aSJed Brown /* Get a block row as a new MatNest */
2998188e55aSJed Brown static PetscErrorCode MatNestGetRow(Mat A,PetscInt row,Mat *B)
3008188e55aSJed Brown {
3018188e55aSJed Brown   Mat_Nest       *vs = (Mat_Nest*)A->data;
3028188e55aSJed Brown   char           keyname[256];
3038188e55aSJed Brown   PetscErrorCode ierr;
3048188e55aSJed Brown 
3058188e55aSJed Brown   PetscFunctionBegin;
3068188e55aSJed Brown   *B = PETSC_NULL;
3078188e55aSJed Brown   ierr = PetscSNPrintf(keyname,sizeof keyname,"NestRow_%D",row);CHKERRQ(ierr);
3088188e55aSJed Brown   ierr = PetscObjectQuery((PetscObject)A,keyname,(PetscObject*)B);CHKERRQ(ierr);
3098188e55aSJed Brown   if (*B) PetscFunctionReturn(0);
3108188e55aSJed Brown 
3118188e55aSJed Brown   ierr = MatCreateNest(((PetscObject)A)->comm,1,PETSC_NULL,vs->nc,vs->isglobal.col,vs->m[row],B);CHKERRQ(ierr);
3128188e55aSJed Brown   (*B)->assembled = A->assembled;
3138188e55aSJed Brown   ierr = PetscObjectCompose((PetscObject)A,keyname,(PetscObject)*B);CHKERRQ(ierr);
3148188e55aSJed Brown   ierr = PetscObjectDereference((PetscObject)*B);CHKERRQ(ierr); /* Leave the only remaining reference in the composition */
3158188e55aSJed Brown   PetscFunctionReturn(0);
3168188e55aSJed Brown }
3178188e55aSJed Brown 
3188188e55aSJed Brown #undef __FUNCT__
319f349c1fdSJed Brown #define __FUNCT__ "MatNestFindSubMat"
320f349c1fdSJed Brown static PetscErrorCode MatNestFindSubMat(Mat A,struct MatNestISPair *is,IS isrow,IS iscol,Mat *B)
321f349c1fdSJed Brown {
322f349c1fdSJed Brown   Mat_Nest       *vs = (Mat_Nest*)A->data;
3238188e55aSJed Brown   PetscErrorCode ierr;
3246b3a5b13SJed Brown   PetscInt       row,col;
3258188e55aSJed Brown   PetscBool      same,isFullCol;
326f349c1fdSJed Brown 
327f349c1fdSJed Brown   PetscFunctionBegin;
3288188e55aSJed Brown   /* Check if full column space. This is a hack */
3298188e55aSJed Brown   isFullCol = PETSC_FALSE;
3308188e55aSJed Brown   ierr = PetscTypeCompare((PetscObject)iscol,ISSTRIDE,&same);CHKERRQ(ierr);
3318188e55aSJed Brown   if (same) {
3328188e55aSJed Brown     PetscInt n,first,step;
3338188e55aSJed Brown     ierr = ISStrideGetInfo(iscol,&first,&step);CHKERRQ(ierr);
3348188e55aSJed Brown     ierr = ISGetLocalSize(iscol,&n);CHKERRQ(ierr);
3358188e55aSJed Brown     if (A->cmap->n == n && A->cmap->rstart == first && step == 1) isFullCol = PETSC_TRUE;
3368188e55aSJed Brown   }
3378188e55aSJed Brown 
3388188e55aSJed Brown   if (isFullCol) {
3398188e55aSJed Brown     PetscInt row;
3408188e55aSJed Brown     ierr = MatNestFindIS(A,vs->nr,is->row,isrow,&row);CHKERRQ(ierr);
3418188e55aSJed Brown     ierr = MatNestGetRow(A,row,B);CHKERRQ(ierr);
3428188e55aSJed Brown   } else {
343f349c1fdSJed Brown     ierr = MatNestFindIS(A,vs->nr,is->row,isrow,&row);CHKERRQ(ierr);
344f349c1fdSJed Brown     ierr = MatNestFindIS(A,vs->nc,is->col,iscol,&col);CHKERRQ(ierr);
345f349c1fdSJed Brown     *B = vs->m[row][col];
3468188e55aSJed Brown   }
347f349c1fdSJed Brown   PetscFunctionReturn(0);
348f349c1fdSJed Brown }
349f349c1fdSJed Brown 
350f349c1fdSJed Brown #undef __FUNCT__
351f349c1fdSJed Brown #define __FUNCT__ "MatGetSubMatrix_Nest"
352f349c1fdSJed Brown static PetscErrorCode MatGetSubMatrix_Nest(Mat A,IS isrow,IS iscol,MatReuse reuse,Mat *B)
353f349c1fdSJed Brown {
354f349c1fdSJed Brown   PetscErrorCode ierr;
355f349c1fdSJed Brown   Mat_Nest       *vs = (Mat_Nest*)A->data;
356f349c1fdSJed Brown   Mat            sub;
357f349c1fdSJed Brown 
358f349c1fdSJed Brown   PetscFunctionBegin;
359f349c1fdSJed Brown   ierr = MatNestFindSubMat(A,&vs->isglobal,isrow,iscol,&sub);CHKERRQ(ierr);
360f349c1fdSJed Brown   switch (reuse) {
361f349c1fdSJed Brown   case MAT_INITIAL_MATRIX:
3627874fa86SDave May     if (sub) { ierr = PetscObjectReference((PetscObject)sub);CHKERRQ(ierr); }
363f349c1fdSJed Brown     *B = sub;
364f349c1fdSJed Brown     break;
365f349c1fdSJed Brown   case MAT_REUSE_MATRIX:
366f349c1fdSJed Brown     if (sub != *B) SETERRQ(((PetscObject)A)->comm,PETSC_ERR_ARG_WRONGSTATE,"Submatrix was not used before in this call");
367f349c1fdSJed Brown     break;
368f349c1fdSJed Brown   case MAT_IGNORE_MATRIX:       /* Nothing to do */
369f349c1fdSJed Brown     break;
370f349c1fdSJed Brown   }
371f349c1fdSJed Brown   PetscFunctionReturn(0);
372f349c1fdSJed Brown }
373f349c1fdSJed Brown 
374f349c1fdSJed Brown #undef __FUNCT__
375f349c1fdSJed Brown #define __FUNCT__ "MatGetLocalSubMatrix_Nest"
376f349c1fdSJed Brown PetscErrorCode MatGetLocalSubMatrix_Nest(Mat A,IS isrow,IS iscol,Mat *B)
377f349c1fdSJed Brown {
378f349c1fdSJed Brown   PetscErrorCode ierr;
379f349c1fdSJed Brown   Mat_Nest       *vs = (Mat_Nest*)A->data;
380f349c1fdSJed Brown   Mat            sub;
381f349c1fdSJed Brown 
382f349c1fdSJed Brown   PetscFunctionBegin;
383f349c1fdSJed Brown   ierr = MatNestFindSubMat(A,&vs->islocal,isrow,iscol,&sub);CHKERRQ(ierr);
384f349c1fdSJed Brown   /* We allow the submatrix to be NULL, perhaps it would be better for the user to return an empty matrix instead */
385f349c1fdSJed Brown   if (sub) {ierr = PetscObjectReference((PetscObject)sub);CHKERRQ(ierr);}
386f349c1fdSJed Brown   *B = sub;
387d8588912SDave May   PetscFunctionReturn(0);
388d8588912SDave May }
389d8588912SDave May 
390d8588912SDave May #undef __FUNCT__
391d8588912SDave May #define __FUNCT__ "MatRestoreLocalSubMatrix_Nest"
392207556f9SJed Brown static PetscErrorCode MatRestoreLocalSubMatrix_Nest(Mat A,IS isrow,IS iscol,Mat *B)
393d8588912SDave May {
394d8588912SDave May   PetscErrorCode ierr;
395f349c1fdSJed Brown   Mat_Nest       *vs = (Mat_Nest*)A->data;
396f349c1fdSJed Brown   Mat            sub;
397d8588912SDave May 
398d8588912SDave May   PetscFunctionBegin;
399f349c1fdSJed Brown   ierr = MatNestFindSubMat(A,&vs->islocal,isrow,iscol,&sub);CHKERRQ(ierr);
400f349c1fdSJed Brown   if (*B != sub) SETERRQ(((PetscObject)A)->comm,PETSC_ERR_ARG_WRONGSTATE,"Local submatrix has not been gotten");
401f349c1fdSJed Brown   if (sub) {
402f349c1fdSJed Brown     if (((PetscObject)sub)->refct <= 1) SETERRQ(((PetscObject)A)->comm,PETSC_ERR_ARG_WRONGSTATE,"Local submatrix has had reference count decremented too many times");
4036bf464f9SBarry Smith     ierr = MatDestroy(B);CHKERRQ(ierr);
404d8588912SDave May   }
405d8588912SDave May   PetscFunctionReturn(0);
406d8588912SDave May }
407d8588912SDave May 
408d8588912SDave May #undef __FUNCT__
4097874fa86SDave May #define __FUNCT__ "MatGetDiagonal_Nest"
4107874fa86SDave May static PetscErrorCode MatGetDiagonal_Nest(Mat A,Vec v)
4117874fa86SDave May {
4127874fa86SDave May   Mat_Nest       *bA = (Mat_Nest*)A->data;
4137874fa86SDave May   PetscInt       i;
4147874fa86SDave May   PetscErrorCode ierr;
4157874fa86SDave May 
4167874fa86SDave May   PetscFunctionBegin;
4177874fa86SDave May   for (i=0; i<bA->nr; i++) {
418*429bac76SJed Brown     Vec bv;
419*429bac76SJed Brown     ierr = VecGetSubVector(v,bA->isglobal.row[i],&bv);CHKERRQ(ierr);
4207874fa86SDave May     if (bA->m[i][i]) {
421*429bac76SJed Brown       ierr = MatGetDiagonal(bA->m[i][i],bv);CHKERRQ(ierr);
4227874fa86SDave May     } else {
423*429bac76SJed Brown       ierr = VecSet(bv,1.0);CHKERRQ(ierr);
4247874fa86SDave May     }
425*429bac76SJed Brown     ierr = VecRestoreSubVector(v,bA->isglobal.row[i],&bv);CHKERRQ(ierr);
4267874fa86SDave May   }
4277874fa86SDave May   PetscFunctionReturn(0);
4287874fa86SDave May }
4297874fa86SDave May 
4307874fa86SDave May #undef __FUNCT__
4317874fa86SDave May #define __FUNCT__ "MatDiagonalScale_Nest"
4327874fa86SDave May static PetscErrorCode MatDiagonalScale_Nest(Mat A,Vec l,Vec r)
4337874fa86SDave May {
4347874fa86SDave May   Mat_Nest       *bA = (Mat_Nest*)A->data;
435*429bac76SJed Brown   Vec            bl,*br;
4367874fa86SDave May   PetscInt       i,j;
4377874fa86SDave May   PetscErrorCode ierr;
4387874fa86SDave May 
4397874fa86SDave May   PetscFunctionBegin;
440*429bac76SJed Brown   ierr = PetscMalloc(bA->nc*sizeof(Vec),&br);CHKERRQ(ierr);
441*429bac76SJed Brown   for (j=0; j<bA->nc; j++) {ierr = VecGetSubVector(r,bA->isglobal.col[j],&br[j]);CHKERRQ(ierr);}
4427874fa86SDave May   for (i=0; i<bA->nr; i++) {
443*429bac76SJed Brown     ierr = VecGetSubVector(l,bA->isglobal.row[i],&bl);CHKERRQ(ierr);
4447874fa86SDave May     for (j=0; j<bA->nc; j++) {
4457874fa86SDave May       if (bA->m[i][j]) {
446*429bac76SJed Brown         ierr = MatDiagonalScale(bA->m[i][j],bl,br[j]);CHKERRQ(ierr);
4477874fa86SDave May       }
4487874fa86SDave May     }
4497874fa86SDave May   }
450*429bac76SJed Brown   for (j=0; j<bA->nc; j++) {ierr = VecRestoreSubVector(r,bA->isglobal.col[j],&br[j]);CHKERRQ(ierr);}
451*429bac76SJed Brown   ierr = PetscFree(br);CHKERRQ(ierr);
4527874fa86SDave May   PetscFunctionReturn(0);
4537874fa86SDave May }
4547874fa86SDave May 
4557874fa86SDave May #undef __FUNCT__
456d8588912SDave May #define __FUNCT__ "MatGetVecs_Nest"
457207556f9SJed Brown static PetscErrorCode MatGetVecs_Nest(Mat A,Vec *right,Vec *left)
458d8588912SDave May {
459d8588912SDave May   Mat_Nest       *bA = (Mat_Nest*)A->data;
460d8588912SDave May   Vec            *L,*R;
461d8588912SDave May   MPI_Comm       comm;
462d8588912SDave May   PetscInt       i,j;
463d8588912SDave May   PetscErrorCode ierr;
464d8588912SDave May 
465d8588912SDave May   PetscFunctionBegin;
466d8588912SDave May   comm = ((PetscObject)A)->comm;
467d8588912SDave May   if (right) {
468d8588912SDave May     /* allocate R */
469d8588912SDave May     ierr = PetscMalloc( sizeof(Vec) * bA->nc, &R );CHKERRQ(ierr);
470d8588912SDave May     /* Create the right vectors */
471d8588912SDave May     for (j=0; j<bA->nc; j++) {
472d8588912SDave May       for (i=0; i<bA->nr; i++) {
473d8588912SDave May         if (bA->m[i][j]) {
474d8588912SDave May           ierr = MatGetVecs(bA->m[i][j],&R[j],PETSC_NULL);CHKERRQ(ierr);
475d8588912SDave May           break;
476d8588912SDave May         }
477d8588912SDave May       }
478d8588912SDave May       if (i==bA->nr) {
479d8588912SDave May         /* have an empty column */
480d8588912SDave May         SETERRQ( ((PetscObject)A)->comm, PETSC_ERR_ARG_WRONG, "Mat(Nest) contains a null column.");
481d8588912SDave May       }
482d8588912SDave May     }
483f349c1fdSJed Brown     ierr = VecCreateNest(comm,bA->nc,bA->isglobal.col,R,right);CHKERRQ(ierr);
484d8588912SDave May     /* hand back control to the nest vector */
485d8588912SDave May     for (j=0; j<bA->nc; j++) {
4866bf464f9SBarry Smith       ierr = VecDestroy(&R[j]);CHKERRQ(ierr);
487d8588912SDave May     }
488d8588912SDave May     ierr = PetscFree(R);CHKERRQ(ierr);
489d8588912SDave May   }
490d8588912SDave May 
491d8588912SDave May   if (left) {
492d8588912SDave May     /* allocate L */
493d8588912SDave May     ierr = PetscMalloc( sizeof(Vec) * bA->nr, &L );CHKERRQ(ierr);
494d8588912SDave May     /* Create the left vectors */
495d8588912SDave May     for (i=0; i<bA->nr; i++) {
496d8588912SDave May       for (j=0; j<bA->nc; j++) {
497d8588912SDave May         if (bA->m[i][j]) {
498d8588912SDave May           ierr = MatGetVecs(bA->m[i][j],PETSC_NULL,&L[i]);CHKERRQ(ierr);
499d8588912SDave May           break;
500d8588912SDave May         }
501d8588912SDave May       }
502d8588912SDave May       if (j==bA->nc) {
503d8588912SDave May         /* have an empty row */
504d8588912SDave May         SETERRQ( ((PetscObject)A)->comm, PETSC_ERR_ARG_WRONG, "Mat(Nest) contains a null row.");
505d8588912SDave May       }
506d8588912SDave May     }
507d8588912SDave May 
508f349c1fdSJed Brown     ierr = VecCreateNest(comm,bA->nr,bA->isglobal.row,L,left);CHKERRQ(ierr);
509d8588912SDave May     for (i=0; i<bA->nr; i++) {
5106bf464f9SBarry Smith       ierr = VecDestroy(&L[i]);CHKERRQ(ierr);
511d8588912SDave May     }
512d8588912SDave May 
513d8588912SDave May     ierr = PetscFree(L);CHKERRQ(ierr);
514d8588912SDave May   }
515d8588912SDave May   PetscFunctionReturn(0);
516d8588912SDave May }
517d8588912SDave May 
518d8588912SDave May #undef __FUNCT__
519d8588912SDave May #define __FUNCT__ "MatView_Nest"
520207556f9SJed Brown static PetscErrorCode MatView_Nest(Mat A,PetscViewer viewer)
521d8588912SDave May {
522d8588912SDave May   Mat_Nest       *bA = (Mat_Nest*)A->data;
523d8588912SDave May   PetscBool      isascii;
524d8588912SDave May   PetscInt       i,j;
525d8588912SDave May   PetscErrorCode ierr;
526d8588912SDave May 
527d8588912SDave May   PetscFunctionBegin;
528d8588912SDave May   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
529d8588912SDave May   if (isascii) {
530d8588912SDave May 
531d8588912SDave May     PetscViewerASCIIPrintf(viewer,"Matrix object: \n" );
532d8588912SDave May     PetscViewerASCIIPushTab( viewer );    /* push0 */
533d8588912SDave May     PetscViewerASCIIPrintf( viewer, "type=nest, rows=%d, cols=%d \n",bA->nr,bA->nc);
534d8588912SDave May 
535d8588912SDave May     PetscViewerASCIIPrintf(viewer,"MatNest structure: \n" );
536d8588912SDave May     for (i=0; i<bA->nr; i++) {
537d8588912SDave May       for (j=0; j<bA->nc; j++) {
538d8588912SDave May         const MatType type;
539d8588912SDave May         const char *name;
540d8588912SDave May         PetscInt NR,NC;
541d8588912SDave May         PetscBool isNest = PETSC_FALSE;
542d8588912SDave May 
543d8588912SDave May         if (!bA->m[i][j]) {
544d8588912SDave May           PetscViewerASCIIPrintf( viewer, "(%D,%D) : PETSC_NULL \n",i,j);
545d8588912SDave May           continue;
546d8588912SDave May         }
547d8588912SDave May         ierr = MatGetSize(bA->m[i][j],&NR,&NC);CHKERRQ(ierr);
548d8588912SDave May         ierr = MatGetType( bA->m[i][j], &type );CHKERRQ(ierr);
549d8588912SDave May         name = ((PetscObject)bA->m[i][j])->prefix;
550d8588912SDave May         ierr = PetscTypeCompare((PetscObject)bA->m[i][j],MATNEST,&isNest);CHKERRQ(ierr);
551d8588912SDave May 
552d8588912SDave May         PetscViewerASCIIPrintf( viewer, "(%D,%D) : name=\"%s\", type=%s, rows=%D, cols=%D \n",i,j,name,type,NR,NC);
553d8588912SDave May 
554d8588912SDave May         if (isNest) {
555d8588912SDave May           PetscViewerASCIIPushTab( viewer );  /* push1 */
556d8588912SDave May           ierr = MatView( bA->m[i][j], viewer );CHKERRQ(ierr);
557d8588912SDave May           PetscViewerASCIIPopTab(viewer);    /* pop1 */
558d8588912SDave May         }
559d8588912SDave May       }
560d8588912SDave May     }
561d8588912SDave May     PetscViewerASCIIPopTab(viewer);    /* pop0 */
562d8588912SDave May   }
563d8588912SDave May   PetscFunctionReturn(0);
564d8588912SDave May }
565d8588912SDave May 
566d8588912SDave May #undef __FUNCT__
567d8588912SDave May #define __FUNCT__ "MatZeroEntries_Nest"
568207556f9SJed Brown static PetscErrorCode MatZeroEntries_Nest(Mat A)
569d8588912SDave May {
570d8588912SDave May   Mat_Nest       *bA = (Mat_Nest*)A->data;
571d8588912SDave May   PetscInt       i,j;
572d8588912SDave May   PetscErrorCode ierr;
573d8588912SDave May 
574d8588912SDave May   PetscFunctionBegin;
575d8588912SDave May   for (i=0; i<bA->nr; i++) {
576d8588912SDave May     for (j=0; j<bA->nc; j++) {
577d8588912SDave May       if (!bA->m[i][j]) continue;
578d8588912SDave May       ierr = MatZeroEntries(bA->m[i][j]);CHKERRQ(ierr);
579d8588912SDave May     }
580d8588912SDave May   }
581d8588912SDave May   PetscFunctionReturn(0);
582d8588912SDave May }
583d8588912SDave May 
584d8588912SDave May #undef __FUNCT__
585d8588912SDave May #define __FUNCT__ "MatDuplicate_Nest"
586207556f9SJed Brown static PetscErrorCode MatDuplicate_Nest(Mat A,MatDuplicateOption op,Mat *B)
587d8588912SDave May {
588d8588912SDave May   Mat_Nest       *bA = (Mat_Nest*)A->data;
589841e96a3SJed Brown   Mat            *b;
590841e96a3SJed Brown   PetscInt       i,j,nr = bA->nr,nc = bA->nc;
591d8588912SDave May   PetscErrorCode ierr;
592d8588912SDave May 
593d8588912SDave May   PetscFunctionBegin;
594841e96a3SJed Brown   ierr = PetscMalloc(nr*nc*sizeof(Mat),&b);CHKERRQ(ierr);
595841e96a3SJed Brown   for (i=0; i<nr; i++) {
596841e96a3SJed Brown     for (j=0; j<nc; j++) {
597841e96a3SJed Brown       if (bA->m[i][j]) {
598841e96a3SJed Brown         ierr = MatDuplicate(bA->m[i][j],op,&b[i*nc+j]);CHKERRQ(ierr);
599841e96a3SJed Brown       } else {
600841e96a3SJed Brown         b[i*nc+j] = PETSC_NULL;
601d8588912SDave May       }
602d8588912SDave May     }
603d8588912SDave May   }
604f349c1fdSJed Brown   ierr = MatCreateNest(((PetscObject)A)->comm,nr,bA->isglobal.row,nc,bA->isglobal.col,b,B);CHKERRQ(ierr);
605841e96a3SJed Brown   /* Give the new MatNest exclusive ownership */
606841e96a3SJed Brown   for (i=0; i<nr*nc; i++) {
6076bf464f9SBarry Smith     ierr = MatDestroy(&b[i]);CHKERRQ(ierr);
608d8588912SDave May   }
609d8588912SDave May   ierr = PetscFree(b);CHKERRQ(ierr);
610d8588912SDave May 
611841e96a3SJed Brown   ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
612841e96a3SJed Brown   ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
613d8588912SDave May   PetscFunctionReturn(0);
614d8588912SDave May }
615d8588912SDave May 
616d8588912SDave May /* nest api */
617d8588912SDave May EXTERN_C_BEGIN
618d8588912SDave May #undef __FUNCT__
619d8588912SDave May #define __FUNCT__ "MatNestGetSubMat_Nest"
620d8588912SDave May PetscErrorCode MatNestGetSubMat_Nest(Mat A,PetscInt idxm,PetscInt jdxm,Mat *mat)
621d8588912SDave May {
622d8588912SDave May   Mat_Nest *bA = (Mat_Nest*)A->data;
623d8588912SDave May   PetscFunctionBegin;
624d8588912SDave May   if (idxm >= bA->nr) SETERRQ2(((PetscObject)A)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",idxm,bA->nr-1);
625d8588912SDave May   if (jdxm >= bA->nc) SETERRQ2(((PetscObject)A)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Col too large: row %D max %D",jdxm,bA->nc-1);
626d8588912SDave May   *mat = bA->m[idxm][jdxm];
627d8588912SDave May   PetscFunctionReturn(0);
628d8588912SDave May }
629d8588912SDave May EXTERN_C_END
630d8588912SDave May 
631d8588912SDave May #undef __FUNCT__
632d8588912SDave May #define __FUNCT__ "MatNestGetSubMat"
633d8588912SDave May /*@C
634d8588912SDave May  MatNestGetSubMat - Returns a single, sub-matrix from a nest matrix.
635d8588912SDave May 
636d8588912SDave May  Not collective
637d8588912SDave May 
638d8588912SDave May  Input Parameters:
639629881c0SJed Brown +   A  - nest matrix
640d8588912SDave May .   idxm - index of the matrix within the nest matrix
641629881c0SJed Brown -   jdxm - index of the matrix within the nest matrix
642d8588912SDave May 
643d8588912SDave May  Output Parameter:
644d8588912SDave May .   sub - matrix at index idxm,jdxm within the nest matrix
645d8588912SDave May 
646d8588912SDave May  Level: developer
647d8588912SDave May 
648d8588912SDave May .seealso: MatNestGetSize(), MatNestGetSubMats()
649d8588912SDave May @*/
6507087cfbeSBarry Smith PetscErrorCode  MatNestGetSubMat(Mat A,PetscInt idxm,PetscInt jdxm,Mat *sub)
651d8588912SDave May {
652699a902aSJed Brown   PetscErrorCode ierr;
653d8588912SDave May 
654d8588912SDave May   PetscFunctionBegin;
655699a902aSJed Brown   ierr = PetscUseMethod(A,"MatNestGetSubMat_C",(Mat,PetscInt,PetscInt,Mat*),(A,idxm,jdxm,sub));CHKERRQ(ierr);
656d8588912SDave May   PetscFunctionReturn(0);
657d8588912SDave May }
658d8588912SDave May 
659d8588912SDave May EXTERN_C_BEGIN
660d8588912SDave May #undef __FUNCT__
6610782ca92SJed Brown #define __FUNCT__ "MatNestSetSubMat_Nest"
6620782ca92SJed Brown PetscErrorCode MatNestSetSubMat_Nest(Mat A,PetscInt idxm,PetscInt jdxm,Mat mat)
6630782ca92SJed Brown {
6640782ca92SJed Brown   Mat_Nest *bA = (Mat_Nest*)A->data;
6650782ca92SJed Brown   PetscInt m,n,M,N,mi,ni,Mi,Ni;
6660782ca92SJed Brown   PetscErrorCode ierr;
6670782ca92SJed Brown 
6680782ca92SJed Brown   PetscFunctionBegin;
6690782ca92SJed Brown   if (idxm >= bA->nr) SETERRQ2(((PetscObject)A)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",idxm,bA->nr-1);
6700782ca92SJed Brown   if (jdxm >= bA->nc) SETERRQ2(((PetscObject)A)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Col too large: row %D max %D",jdxm,bA->nc-1);
6710782ca92SJed Brown   ierr = MatGetLocalSize(mat,&m,&n);CHKERRQ(ierr);
6720782ca92SJed Brown   ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr);
6730782ca92SJed Brown   ierr = ISGetLocalSize(bA->isglobal.row[idxm],&mi);CHKERRQ(ierr);
6740782ca92SJed Brown   ierr = ISGetSize(bA->isglobal.row[idxm],&Mi);CHKERRQ(ierr);
6750782ca92SJed Brown   ierr = ISGetLocalSize(bA->isglobal.col[jdxm],&ni);CHKERRQ(ierr);
6760782ca92SJed Brown   ierr = ISGetSize(bA->isglobal.col[jdxm],&Ni);CHKERRQ(ierr);
6770782ca92SJed Brown   if (M != Mi || N != Ni) SETERRQ4(((PetscObject)mat)->comm,PETSC_ERR_ARG_INCOMP,"Submatrix dimension (%D,%D) incompatible with nest block (%D,%D)",M,N,Mi,Ni);
6780782ca92SJed Brown   if (m != mi || n != ni) SETERRQ4(((PetscObject)mat)->comm,PETSC_ERR_ARG_INCOMP,"Submatrix local dimension (%D,%D) incompatible with nest block (%D,%D)",m,n,mi,ni);
6790782ca92SJed Brown   ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr);
6800782ca92SJed Brown   ierr = MatDestroy(&bA->m[idxm][jdxm]);CHKERRQ(ierr);
6810782ca92SJed Brown   bA->m[idxm][jdxm] = mat;
6820782ca92SJed Brown   PetscFunctionReturn(0);
6830782ca92SJed Brown }
6840782ca92SJed Brown EXTERN_C_END
6850782ca92SJed Brown 
6860782ca92SJed Brown #undef __FUNCT__
6870782ca92SJed Brown #define __FUNCT__ "MatNestSetSubMat"
6880782ca92SJed Brown /*@C
6890782ca92SJed Brown  MatNestSetSubMat - Set a single submatrix in the nest matrix.
6900782ca92SJed Brown 
6910782ca92SJed Brown  Logically collective on the submatrix communicator
6920782ca92SJed Brown 
6930782ca92SJed Brown  Input Parameters:
6940782ca92SJed Brown +   A  - nest matrix
6950782ca92SJed Brown .   idxm - index of the matrix within the nest matrix
6960782ca92SJed Brown .   jdxm - index of the matrix within the nest matrix
6970782ca92SJed Brown -   sub - matrix at index idxm,jdxm within the nest matrix
6980782ca92SJed Brown 
6990782ca92SJed Brown  Notes:
7000782ca92SJed Brown  The new submatrix must have the same size and communicator as that block of the nest.
7010782ca92SJed Brown 
7020782ca92SJed Brown  This increments the reference count of the submatrix.
7030782ca92SJed Brown 
7040782ca92SJed Brown  Level: developer
7050782ca92SJed Brown 
7060782ca92SJed Brown .seealso: MatNestSetSubMats(), MatNestGetSubMat()
7070782ca92SJed Brown @*/
7080782ca92SJed Brown PetscErrorCode  MatNestSetSubMat(Mat A,PetscInt idxm,PetscInt jdxm,Mat sub)
7090782ca92SJed Brown {
7100782ca92SJed Brown   PetscErrorCode ierr;
7110782ca92SJed Brown 
7120782ca92SJed Brown   PetscFunctionBegin;
7130782ca92SJed Brown   ierr = PetscUseMethod(A,"MatNestSetSubMat_C",(Mat,PetscInt,PetscInt,Mat),(A,idxm,jdxm,sub));CHKERRQ(ierr);
7140782ca92SJed Brown   PetscFunctionReturn(0);
7150782ca92SJed Brown }
7160782ca92SJed Brown 
7170782ca92SJed Brown EXTERN_C_BEGIN
7180782ca92SJed Brown #undef __FUNCT__
719d8588912SDave May #define __FUNCT__ "MatNestGetSubMats_Nest"
720d8588912SDave May PetscErrorCode MatNestGetSubMats_Nest(Mat A,PetscInt *M,PetscInt *N,Mat ***mat)
721d8588912SDave May {
722d8588912SDave May   Mat_Nest *bA = (Mat_Nest*)A->data;
723d8588912SDave May   PetscFunctionBegin;
724d8588912SDave May   if (M)   { *M   = bA->nr; }
725d8588912SDave May   if (N)   { *N   = bA->nc; }
726d8588912SDave May   if (mat) { *mat = bA->m;  }
727d8588912SDave May   PetscFunctionReturn(0);
728d8588912SDave May }
729d8588912SDave May EXTERN_C_END
730d8588912SDave May 
731d8588912SDave May #undef __FUNCT__
732d8588912SDave May #define __FUNCT__ "MatNestGetSubMats"
733d8588912SDave May /*@C
734d8588912SDave May  MatNestGetSubMats - Returns the entire two dimensional array of matrices defining a nest matrix.
735d8588912SDave May 
736d8588912SDave May  Not collective
737d8588912SDave May 
738d8588912SDave May  Input Parameters:
739629881c0SJed Brown .   A  - nest matrix
740d8588912SDave May 
741d8588912SDave May  Output Parameter:
742629881c0SJed Brown +   M - number of rows in the nest matrix
743d8588912SDave May .   N - number of cols in the nest matrix
744629881c0SJed Brown -   mat - 2d array of matrices
745d8588912SDave May 
746d8588912SDave May  Notes:
747d8588912SDave May 
748d8588912SDave May  The user should not free the array mat.
749d8588912SDave May 
750d8588912SDave May  Level: developer
751d8588912SDave May 
752d8588912SDave May .seealso: MatNestGetSize(), MatNestGetSubMat()
753d8588912SDave May @*/
7547087cfbeSBarry Smith PetscErrorCode  MatNestGetSubMats(Mat A,PetscInt *M,PetscInt *N,Mat ***mat)
755d8588912SDave May {
756699a902aSJed Brown   PetscErrorCode ierr;
757d8588912SDave May 
758d8588912SDave May   PetscFunctionBegin;
759699a902aSJed Brown   ierr = PetscUseMethod(A,"MatNestGetSubMats_C",(Mat,PetscInt*,PetscInt*,Mat***),(A,M,N,mat));CHKERRQ(ierr);
760d8588912SDave May   PetscFunctionReturn(0);
761d8588912SDave May }
762d8588912SDave May 
763d8588912SDave May EXTERN_C_BEGIN
764d8588912SDave May #undef __FUNCT__
765d8588912SDave May #define __FUNCT__ "MatNestGetSize_Nest"
7667087cfbeSBarry Smith PetscErrorCode  MatNestGetSize_Nest(Mat A,PetscInt *M,PetscInt *N)
767d8588912SDave May {
768d8588912SDave May   Mat_Nest  *bA = (Mat_Nest*)A->data;
769d8588912SDave May 
770d8588912SDave May   PetscFunctionBegin;
771d8588912SDave May   if (M) { *M  = bA->nr; }
772d8588912SDave May   if (N) { *N  = bA->nc; }
773d8588912SDave May   PetscFunctionReturn(0);
774d8588912SDave May }
775d8588912SDave May EXTERN_C_END
776d8588912SDave May 
777d8588912SDave May #undef __FUNCT__
778d8588912SDave May #define __FUNCT__ "MatNestGetSize"
779d8588912SDave May /*@C
780d8588912SDave May  MatNestGetSize - Returns the size of the nest matrix.
781d8588912SDave May 
782d8588912SDave May  Not collective
783d8588912SDave May 
784d8588912SDave May  Input Parameters:
785d8588912SDave May .   A  - nest matrix
786d8588912SDave May 
787d8588912SDave May  Output Parameter:
788629881c0SJed Brown +   M - number of rows in the nested mat
789629881c0SJed Brown -   N - number of cols in the nested mat
790d8588912SDave May 
791d8588912SDave May  Notes:
792d8588912SDave May 
793d8588912SDave May  Level: developer
794d8588912SDave May 
795d8588912SDave May .seealso: MatNestGetSubMat(), MatNestGetSubMats()
796d8588912SDave May @*/
7977087cfbeSBarry Smith PetscErrorCode  MatNestGetSize(Mat A,PetscInt *M,PetscInt *N)
798d8588912SDave May {
799699a902aSJed Brown   PetscErrorCode ierr;
800d8588912SDave May 
801d8588912SDave May   PetscFunctionBegin;
802699a902aSJed Brown   ierr = PetscUseMethod(A,"MatNestGetSize_C",(Mat,PetscInt*,PetscInt*),(A,M,N));CHKERRQ(ierr);
803d8588912SDave May   PetscFunctionReturn(0);
804d8588912SDave May }
805d8588912SDave May 
806207556f9SJed Brown EXTERN_C_BEGIN
807207556f9SJed Brown #undef __FUNCT__
808207556f9SJed Brown #define __FUNCT__ "MatNestSetVecType_Nest"
8097087cfbeSBarry Smith PetscErrorCode  MatNestSetVecType_Nest(Mat A,const VecType vtype)
810207556f9SJed Brown {
811207556f9SJed Brown   PetscErrorCode ierr;
812207556f9SJed Brown   PetscBool      flg;
813207556f9SJed Brown 
814207556f9SJed Brown   PetscFunctionBegin;
815207556f9SJed Brown   ierr = PetscStrcmp(vtype,VECNEST,&flg);CHKERRQ(ierr);
816207556f9SJed Brown   /* In reality, this only distinguishes VECNEST and "other" */
817207556f9SJed Brown   A->ops->getvecs       = flg ? MatGetVecs_Nest       : 0;
818207556f9SJed Brown  PetscFunctionReturn(0);
819207556f9SJed Brown }
820207556f9SJed Brown EXTERN_C_END
821207556f9SJed Brown 
822207556f9SJed Brown #undef __FUNCT__
823207556f9SJed Brown #define __FUNCT__ "MatNestSetVecType"
824207556f9SJed Brown /*@C
825207556f9SJed Brown  MatNestSetVecType - Sets the type of Vec returned by MatGetVecs()
826207556f9SJed Brown 
827207556f9SJed Brown  Not collective
828207556f9SJed Brown 
829207556f9SJed Brown  Input Parameters:
830207556f9SJed Brown +  A  - nest matrix
831207556f9SJed Brown -  vtype - type to use for creating vectors
832207556f9SJed Brown 
833207556f9SJed Brown  Notes:
834207556f9SJed Brown 
835207556f9SJed Brown  Level: developer
836207556f9SJed Brown 
837207556f9SJed Brown .seealso: MatGetVecs()
838207556f9SJed Brown @*/
8397087cfbeSBarry Smith PetscErrorCode  MatNestSetVecType(Mat A,const VecType vtype)
840207556f9SJed Brown {
841207556f9SJed Brown   PetscErrorCode ierr;
842207556f9SJed Brown 
843207556f9SJed Brown   PetscFunctionBegin;
844207556f9SJed Brown   ierr = PetscTryMethod(A,"MatNestSetVecType_C",(Mat,const VecType),(A,vtype));CHKERRQ(ierr);
845207556f9SJed Brown   PetscFunctionReturn(0);
846207556f9SJed Brown }
847207556f9SJed Brown 
848c8883902SJed Brown EXTERN_C_BEGIN
849d8588912SDave May #undef __FUNCT__
850c8883902SJed Brown #define __FUNCT__ "MatNestSetSubMats_Nest"
851c8883902SJed Brown PetscErrorCode MatNestSetSubMats_Nest(Mat A,PetscInt nr,const IS is_row[],PetscInt nc,const IS is_col[],const Mat a[])
852d8588912SDave May {
853c8883902SJed Brown   Mat_Nest       *s = (Mat_Nest*)A->data;
854c8883902SJed Brown   PetscInt       i,j,m,n,M,N;
855d8588912SDave May   PetscErrorCode ierr;
856d8588912SDave May 
857d8588912SDave May   PetscFunctionBegin;
858c8883902SJed Brown   s->nr = nr;
859c8883902SJed Brown   s->nc = nc;
860d8588912SDave May 
861c8883902SJed Brown   /* Create space for submatrices */
862c8883902SJed Brown   ierr = PetscMalloc(sizeof(Mat*)*nr,&s->m);CHKERRQ(ierr);
863c8883902SJed Brown   for (i=0; i<nr; i++) {
864c8883902SJed Brown     ierr = PetscMalloc(sizeof(Mat)*nc,&s->m[i]);CHKERRQ(ierr);
865d8588912SDave May   }
866c8883902SJed Brown   for (i=0; i<nr; i++) {
867c8883902SJed Brown     for (j=0; j<nc; j++) {
868c8883902SJed Brown       s->m[i][j] = a[i*nc+j];
869c8883902SJed Brown       if (a[i*nc+j]) {
870c8883902SJed Brown         ierr = PetscObjectReference((PetscObject)a[i*nc+j]);CHKERRQ(ierr);
871d8588912SDave May       }
872d8588912SDave May     }
873d8588912SDave May   }
874d8588912SDave May 
8758188e55aSJed Brown   ierr = MatSetUp_NestIS_Private(A,nr,is_row,nc,is_col);CHKERRQ(ierr);
876d8588912SDave May 
877c8883902SJed Brown   ierr = PetscMalloc(sizeof(PetscInt)*nr,&s->row_len);CHKERRQ(ierr);
878c8883902SJed Brown   ierr = PetscMalloc(sizeof(PetscInt)*nc,&s->col_len);CHKERRQ(ierr);
879c8883902SJed Brown   for (i=0; i<nr; i++) s->row_len[i]=-1;
880c8883902SJed Brown   for (j=0; j<nc; j++) s->col_len[j]=-1;
881d8588912SDave May 
8828188e55aSJed Brown   ierr = MatNestGetSizes_Private(A,&m,&n,&M,&N);CHKERRQ(ierr);
883d8588912SDave May 
884c8883902SJed Brown   ierr = PetscLayoutSetSize(A->rmap,M);CHKERRQ(ierr);
885c8883902SJed Brown   ierr = PetscLayoutSetLocalSize(A->rmap,m);CHKERRQ(ierr);
886c8883902SJed Brown   ierr = PetscLayoutSetBlockSize(A->rmap,1);CHKERRQ(ierr);
887c8883902SJed Brown   ierr = PetscLayoutSetSize(A->cmap,N);CHKERRQ(ierr);
888c8883902SJed Brown   ierr = PetscLayoutSetLocalSize(A->cmap,n);CHKERRQ(ierr);
889c8883902SJed Brown   ierr = PetscLayoutSetBlockSize(A->cmap,1);CHKERRQ(ierr);
890c8883902SJed Brown 
891c8883902SJed Brown   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
892c8883902SJed Brown   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
893c8883902SJed Brown 
894c8883902SJed Brown   ierr = PetscMalloc2(nr,Vec,&s->left,nc,Vec,&s->right);CHKERRQ(ierr);
895c8883902SJed Brown   ierr = PetscMemzero(s->left,nr*sizeof(Vec));CHKERRQ(ierr);
896c8883902SJed Brown   ierr = PetscMemzero(s->right,nc*sizeof(Vec));CHKERRQ(ierr);
897d8588912SDave May   PetscFunctionReturn(0);
898d8588912SDave May }
899c8883902SJed Brown EXTERN_C_END
900d8588912SDave May 
901c8883902SJed Brown #undef __FUNCT__
902c8883902SJed Brown #define __FUNCT__ "MatNestSetSubMats"
903c8883902SJed Brown /*@
904c8883902SJed Brown    MatNestSetSubMats - Sets the nested submatrices
905c8883902SJed Brown 
906c8883902SJed Brown    Collective on Mat
907c8883902SJed Brown 
908c8883902SJed Brown    Input Parameter:
909c8883902SJed Brown +  N - nested matrix
910c8883902SJed Brown .  nr - number of nested row blocks
911c8883902SJed Brown .  is_row - index sets for each nested row block, or PETSC_NULL to make contiguous
912c8883902SJed Brown .  nc - number of nested column blocks
913c8883902SJed Brown .  is_col - index sets for each nested column block, or PETSC_NULL to make contiguous
914c8883902SJed Brown -  a - row-aligned array of nr*nc submatrices, empty submatrices can be passed using PETSC_NULL
915c8883902SJed Brown 
916c8883902SJed Brown    Level: advanced
917c8883902SJed Brown 
918c8883902SJed Brown .seealso: MatCreateNest(), MATNEST
919c8883902SJed Brown @*/
920c8883902SJed Brown PetscErrorCode MatNestSetSubMats(Mat A,PetscInt nr,const IS is_row[],PetscInt nc,const IS is_col[],const Mat a[])
921c8883902SJed Brown {
922c8883902SJed Brown   PetscErrorCode ierr;
923c8883902SJed Brown   PetscInt i;
924c8883902SJed Brown 
925c8883902SJed Brown   PetscFunctionBegin;
926c8883902SJed Brown   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
927c8883902SJed Brown   if (nr < 0) SETERRQ(((PetscObject)A)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Number of rows cannot be negative");
928c8883902SJed Brown   if (nr && is_row) {
929c8883902SJed Brown     PetscValidPointer(is_row,3);
930c8883902SJed Brown     for (i=0; i<nr; i++) PetscValidHeaderSpecific(is_row[i],IS_CLASSID,3);
931c8883902SJed Brown   }
932c8883902SJed Brown   if (nc < 0) SETERRQ(((PetscObject)A)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Number of columns cannot be negative");
9331664e352SJed Brown   if (nc && is_col) {
934c8883902SJed Brown     PetscValidPointer(is_col,5);
935c8883902SJed Brown     for (i=0; i<nr; i++) PetscValidHeaderSpecific(is_col[i],IS_CLASSID,5);
936c8883902SJed Brown   }
937c8883902SJed Brown   if (nr*nc) PetscValidPointer(a,6);
938c8883902SJed Brown   ierr = PetscUseMethod(A,"MatNestSetSubMats_C",(Mat,PetscInt,const IS[],PetscInt,const IS[],const Mat[]),(A,nr,is_row,nc,is_col,a));CHKERRQ(ierr);
939c8883902SJed Brown   PetscFunctionReturn(0);
940c8883902SJed Brown }
941d8588912SDave May 
942d8588912SDave May /* If an IS was provided, there is nothing Nest needs to do, otherwise Nest will build a strided IS */
943d8588912SDave May /*
944d8588912SDave May   nprocessors = NP
945d8588912SDave May   Nest x^T = ( (g_0,g_1,...g_nprocs-1), (h_0,h_1,...h_NP-1) )
946d8588912SDave May        proc 0: => (g_0,h_0,)
947d8588912SDave May        proc 1: => (g_1,h_1,)
948d8588912SDave May        ...
949d8588912SDave May        proc nprocs-1: => (g_NP-1,h_NP-1,)
950d8588912SDave May 
951d8588912SDave May             proc 0:                      proc 1:                    proc nprocs-1:
952d8588912SDave May     is[0] = ( 0,1,2,...,nlocal(g_0)-1 )  ( 0,1,...,nlocal(g_1)-1 )  ( 0,1,...,nlocal(g_NP-1) )
953d8588912SDave May 
954d8588912SDave May             proc 0:
955d8588912SDave May     is[1] = ( nlocal(g_0),nlocal(g_0)+1,...,nlocal(g_0)+nlocal(h_0)-1 )
956d8588912SDave May             proc 1:
957d8588912SDave May     is[1] = ( nlocal(g_1),nlocal(g_1)+1,...,nlocal(g_1)+nlocal(h_1)-1 )
958d8588912SDave May 
959d8588912SDave May             proc NP-1:
960d8588912SDave May     is[1] = ( nlocal(g_NP-1),nlocal(g_NP-1)+1,...,nlocal(g_NP-1)+nlocal(h_NP-1)-1 )
961d8588912SDave May */
962d8588912SDave May #undef __FUNCT__
963d8588912SDave May #define __FUNCT__ "MatSetUp_NestIS_Private"
964841e96a3SJed Brown static PetscErrorCode MatSetUp_NestIS_Private(Mat A,PetscInt nr,const IS is_row[],PetscInt nc,const IS is_col[])
965d8588912SDave May {
966e2d7f03fSJed Brown   Mat_Nest       *vs = (Mat_Nest*)A->data;
9678188e55aSJed Brown   PetscInt       i,j,offset,n,nsum,bs;
968d8588912SDave May   PetscErrorCode ierr;
9692ae74bdbSJed Brown   Mat            sub;
970d8588912SDave May 
971d8588912SDave May   PetscFunctionBegin;
9728188e55aSJed Brown   ierr = PetscMalloc(sizeof(IS)*nr,&vs->isglobal.row);CHKERRQ(ierr);
9738188e55aSJed Brown   ierr = PetscMalloc(sizeof(IS)*nc,&vs->isglobal.col);CHKERRQ(ierr);
974d8588912SDave May   if (is_row) { /* valid IS is passed in */
975d8588912SDave May     /* refs on is[] are incremeneted */
976e2d7f03fSJed Brown     for (i=0; i<vs->nr; i++) {
977d8588912SDave May       ierr = PetscObjectReference((PetscObject)is_row[i]);CHKERRQ(ierr);
978e2d7f03fSJed Brown       vs->isglobal.row[i] = is_row[i];
979d8588912SDave May     }
9802ae74bdbSJed Brown   } else {                      /* Create the ISs by inspecting sizes of a submatrix in each row */
9818188e55aSJed Brown     nsum = 0;
9828188e55aSJed Brown     for (i=0; i<vs->nr; i++) {  /* Add up the local sizes to compute the aggregate offset */
9838188e55aSJed Brown       ierr = MatNestFindNonzeroSubMatRow(A,i,&sub);CHKERRQ(ierr);
9848188e55aSJed Brown       if (!sub) SETERRQ1(((PetscObject)A)->comm,PETSC_ERR_ARG_WRONG,"No nonzero submatrix in row %D",i);
9858188e55aSJed Brown       ierr = MatGetLocalSize(sub,&n,PETSC_NULL);CHKERRQ(ierr);
9868188e55aSJed Brown       if (n < 0) SETERRQ(((PetscObject)A)->comm,PETSC_ERR_ARG_WRONGSTATE,"Sizes have not yet been set for submatrix");
9878188e55aSJed Brown       nsum += n;
9888188e55aSJed Brown     }
9898188e55aSJed Brown     offset = 0;
9908188e55aSJed Brown     ierr = MPI_Exscan(&nsum,&offset,1,MPIU_INT,MPI_SUM,((PetscObject)A)->comm);CHKERRQ(ierr);
991e2d7f03fSJed Brown     for (i=0; i<vs->nr; i++) {
992f349c1fdSJed Brown       ierr = MatNestFindNonzeroSubMatRow(A,i,&sub);CHKERRQ(ierr);
9932ae74bdbSJed Brown       ierr = MatGetLocalSize(sub,&n,PETSC_NULL);CHKERRQ(ierr);
9942ae74bdbSJed Brown       ierr = MatGetBlockSize(sub,&bs);CHKERRQ(ierr);
995e2d7f03fSJed Brown       ierr = ISCreateStride(((PetscObject)sub)->comm,n,offset,1,&vs->isglobal.row[i]);CHKERRQ(ierr);
996e2d7f03fSJed Brown       ierr = ISSetBlockSize(vs->isglobal.row[i],bs);CHKERRQ(ierr);
9972ae74bdbSJed Brown       offset += n;
998d8588912SDave May     }
999d8588912SDave May   }
1000d8588912SDave May 
1001d8588912SDave May   if (is_col) { /* valid IS is passed in */
1002d8588912SDave May     /* refs on is[] are incremeneted */
1003e2d7f03fSJed Brown     for (j=0; j<vs->nc; j++) {
1004d8588912SDave May       ierr = PetscObjectReference((PetscObject)is_col[j]);CHKERRQ(ierr);
1005e2d7f03fSJed Brown       vs->isglobal.col[j] = is_col[j];
1006d8588912SDave May     }
10072ae74bdbSJed Brown   } else {                      /* Create the ISs by inspecting sizes of a submatrix in each column */
10082ae74bdbSJed Brown     offset = A->cmap->rstart;
10098188e55aSJed Brown     nsum = 0;
10108188e55aSJed Brown     for (j=0; j<vs->nc; j++) {
10118188e55aSJed Brown       ierr = MatNestFindNonzeroSubMatCol(A,j,&sub);CHKERRQ(ierr);
10128188e55aSJed Brown       if (!sub) SETERRQ1(((PetscObject)A)->comm,PETSC_ERR_ARG_WRONG,"No nonzero submatrix in column %D",i);
10138188e55aSJed Brown       ierr = MatGetLocalSize(sub,PETSC_NULL,&n);CHKERRQ(ierr);
10148188e55aSJed Brown       if (n < 0) SETERRQ(((PetscObject)A)->comm,PETSC_ERR_ARG_WRONGSTATE,"Sizes have not yet been set for submatrix");
10158188e55aSJed Brown       nsum += n;
10168188e55aSJed Brown     }
10178188e55aSJed Brown     offset = 0;
10188188e55aSJed Brown     ierr = MPI_Exscan(&nsum,&offset,1,MPIU_INT,MPI_SUM,((PetscObject)A)->comm);CHKERRQ(ierr);
1019e2d7f03fSJed Brown     for (j=0; j<vs->nc; j++) {
1020f349c1fdSJed Brown       ierr = MatNestFindNonzeroSubMatCol(A,j,&sub);CHKERRQ(ierr);
10212ae74bdbSJed Brown       ierr = MatGetLocalSize(sub,PETSC_NULL,&n);CHKERRQ(ierr);
10222ae74bdbSJed Brown       ierr = MatGetBlockSize(sub,&bs);CHKERRQ(ierr);
1023e2d7f03fSJed Brown       ierr = ISCreateStride(((PetscObject)sub)->comm,n,offset,1,&vs->isglobal.col[j]);CHKERRQ(ierr);
1024e2d7f03fSJed Brown       ierr = ISSetBlockSize(vs->isglobal.col[j],bs);CHKERRQ(ierr);
10252ae74bdbSJed Brown       offset += n;
1026d8588912SDave May     }
1027d8588912SDave May   }
1028e2d7f03fSJed Brown 
1029e2d7f03fSJed Brown   /* Set up the local ISs */
1030e2d7f03fSJed Brown   ierr = PetscMalloc(vs->nr*sizeof(IS),&vs->islocal.row);CHKERRQ(ierr);
1031e2d7f03fSJed Brown   ierr = PetscMalloc(vs->nc*sizeof(IS),&vs->islocal.col);CHKERRQ(ierr);
1032e2d7f03fSJed Brown   for (i=0,offset=0; i<vs->nr; i++) {
1033e2d7f03fSJed Brown     IS                     isloc;
10348188e55aSJed Brown     ISLocalToGlobalMapping rmap = PETSC_NULL;
1035e2d7f03fSJed Brown     PetscInt               nlocal,bs;
1036e2d7f03fSJed Brown     ierr = MatNestFindNonzeroSubMatRow(A,i,&sub);CHKERRQ(ierr);
10378188e55aSJed Brown     if (sub) {ierr = MatGetLocalToGlobalMapping(sub,&rmap,PETSC_NULL);CHKERRQ(ierr);}
1038207556f9SJed Brown     if (rmap) {
1039e2d7f03fSJed Brown       ierr = MatGetBlockSize(sub,&bs);CHKERRQ(ierr);
1040e2d7f03fSJed Brown       ierr = ISLocalToGlobalMappingGetSize(rmap,&nlocal);CHKERRQ(ierr);
1041e2d7f03fSJed Brown       ierr = ISCreateStride(PETSC_COMM_SELF,nlocal,offset,1,&isloc);CHKERRQ(ierr);
1042e2d7f03fSJed Brown       ierr = ISSetBlockSize(isloc,bs);CHKERRQ(ierr);
1043207556f9SJed Brown     } else {
1044207556f9SJed Brown       nlocal = 0;
1045207556f9SJed Brown       isloc  = PETSC_NULL;
1046207556f9SJed Brown     }
1047e2d7f03fSJed Brown     vs->islocal.row[i] = isloc;
1048e2d7f03fSJed Brown     offset += nlocal;
1049e2d7f03fSJed Brown   }
10508188e55aSJed Brown   for (i=0,offset=0; i<vs->nc; i++) {
1051e2d7f03fSJed Brown     IS                     isloc;
10528188e55aSJed Brown     ISLocalToGlobalMapping cmap = PETSC_NULL;
1053e2d7f03fSJed Brown     PetscInt               nlocal,bs;
1054e2d7f03fSJed Brown     ierr = MatNestFindNonzeroSubMatCol(A,i,&sub);CHKERRQ(ierr);
10558188e55aSJed Brown     if (sub) {ierr = MatGetLocalToGlobalMapping(sub,PETSC_NULL,&cmap);CHKERRQ(ierr);}
1056207556f9SJed Brown     if (cmap) {
1057e2d7f03fSJed Brown       ierr = MatGetBlockSize(sub,&bs);CHKERRQ(ierr);
1058e2d7f03fSJed Brown       ierr = ISLocalToGlobalMappingGetSize(cmap,&nlocal);CHKERRQ(ierr);
1059e2d7f03fSJed Brown       ierr = ISCreateStride(PETSC_COMM_SELF,nlocal,offset,1,&isloc);CHKERRQ(ierr);
1060e2d7f03fSJed Brown       ierr = ISSetBlockSize(isloc,bs);CHKERRQ(ierr);
1061207556f9SJed Brown     } else {
1062207556f9SJed Brown       nlocal = 0;
1063207556f9SJed Brown       isloc  = PETSC_NULL;
1064207556f9SJed Brown     }
1065e2d7f03fSJed Brown     vs->islocal.col[i] = isloc;
1066e2d7f03fSJed Brown     offset += nlocal;
1067e2d7f03fSJed Brown   }
10680189643fSJed Brown 
10690189643fSJed Brown #if defined(PETSC_USE_DEBUG)
10700189643fSJed Brown   for (i=0; i<vs->nr; i++) {
10710189643fSJed Brown     for (j=0; j<vs->nc; j++) {
10720189643fSJed Brown       PetscInt m,n,M,N,mi,ni,Mi,Ni;
10730189643fSJed Brown       Mat B = vs->m[i][j];
10740189643fSJed Brown       if (!B) continue;
10750189643fSJed Brown       ierr = MatGetSize(B,&M,&N);CHKERRQ(ierr);
10760189643fSJed Brown       ierr = MatGetLocalSize(B,&m,&n);CHKERRQ(ierr);
10770189643fSJed Brown       ierr = ISGetSize(vs->isglobal.row[i],&Mi);CHKERRQ(ierr);
10780189643fSJed Brown       ierr = ISGetSize(vs->isglobal.col[j],&Ni);CHKERRQ(ierr);
10790189643fSJed Brown       ierr = ISGetLocalSize(vs->isglobal.row[i],&mi);CHKERRQ(ierr);
10800189643fSJed Brown       ierr = ISGetLocalSize(vs->isglobal.col[j],&ni);CHKERRQ(ierr);
10810189643fSJed Brown       if (M != Mi || N != Ni) SETERRQ6(((PetscObject)sub)->comm,PETSC_ERR_ARG_INCOMP,"Global sizes (%D,%D) of nested submatrix (%D,%D) do not agree with space defined by index sets (%D,%D)",M,N,i,j,Mi,Ni);
10820189643fSJed Brown       if (m != mi || n != ni) SETERRQ6(((PetscObject)sub)->comm,PETSC_ERR_ARG_INCOMP,"Local sizes (%D,%D) of nested submatrix (%D,%D) do not agree with space defined by index sets (%D,%D)",m,n,i,j,mi,ni);
10830189643fSJed Brown     }
10840189643fSJed Brown   }
10850189643fSJed Brown #endif
1086d8588912SDave May   PetscFunctionReturn(0);
1087d8588912SDave May }
1088d8588912SDave May 
1089d8588912SDave May #undef __FUNCT__
1090d8588912SDave May #define __FUNCT__ "MatCreateNest"
1091659c6bb0SJed Brown /*@
1092659c6bb0SJed Brown    MatCreateNest - Creates a new matrix containing several nested submatrices, each stored separately
1093659c6bb0SJed Brown 
1094659c6bb0SJed Brown    Collective on Mat
1095659c6bb0SJed Brown 
1096659c6bb0SJed Brown    Input Parameter:
1097659c6bb0SJed Brown +  comm - Communicator for the new Mat
1098659c6bb0SJed Brown .  nr - number of nested row blocks
1099659c6bb0SJed Brown .  is_row - index sets for each nested row block, or PETSC_NULL to make contiguous
1100659c6bb0SJed Brown .  nc - number of nested column blocks
1101659c6bb0SJed Brown .  is_col - index sets for each nested column block, or PETSC_NULL to make contiguous
1102659c6bb0SJed Brown -  a - row-aligned array of nr*nc submatrices, empty submatrices can be passed using PETSC_NULL
1103659c6bb0SJed Brown 
1104659c6bb0SJed Brown    Output Parameter:
1105659c6bb0SJed Brown .  B - new matrix
1106659c6bb0SJed Brown 
1107659c6bb0SJed Brown    Level: advanced
1108659c6bb0SJed Brown 
1109659c6bb0SJed Brown .seealso: MatCreate(), VecCreateNest(), DMGetMatrix(), MATNEST
1110659c6bb0SJed Brown @*/
11117087cfbeSBarry Smith PetscErrorCode MatCreateNest(MPI_Comm comm,PetscInt nr,const IS is_row[],PetscInt nc,const IS is_col[],const Mat a[],Mat *B)
1112d8588912SDave May {
1113d8588912SDave May   Mat            A;
1114d8588912SDave May   PetscErrorCode ierr;
1115d8588912SDave May 
1116d8588912SDave May   PetscFunctionBegin;
1117c8883902SJed Brown   *B = 0;
1118d8588912SDave May   ierr = MatCreate(comm,&A);CHKERRQ(ierr);
1119c8883902SJed Brown   ierr = MatSetType(A,MATNEST);CHKERRQ(ierr);
1120c8883902SJed Brown   ierr = MatNestSetSubMats(A,nr,is_row,nc,is_col,a);CHKERRQ(ierr);
1121d8588912SDave May   *B = A;
1122d8588912SDave May   PetscFunctionReturn(0);
1123d8588912SDave May }
1124659c6bb0SJed Brown 
1125659c6bb0SJed Brown /*MC
1126659c6bb0SJed Brown   MATNEST - MATNEST = "nest" - Matrix type consisting of nested submatrices, each stored separately.
1127659c6bb0SJed Brown 
1128659c6bb0SJed Brown   Level: intermediate
1129659c6bb0SJed Brown 
1130659c6bb0SJed Brown   Notes:
1131659c6bb0SJed Brown   This matrix type permits scalable use of PCFieldSplit and avoids the large memory costs of extracting submatrices.
1132659c6bb0SJed Brown   It allows the use of symmetric and block formats for parts of multi-physics simulations.
1133659c6bb0SJed Brown   It is usually used with DMComposite and DMGetMatrix()
1134659c6bb0SJed Brown 
1135659c6bb0SJed Brown .seealso: MatCreate(), MatType, MatCreateNest()
1136659c6bb0SJed Brown M*/
1137c8883902SJed Brown EXTERN_C_BEGIN
1138c8883902SJed Brown #undef __FUNCT__
1139c8883902SJed Brown #define __FUNCT__ "MatCreate_Nest"
1140c8883902SJed Brown PetscErrorCode MatCreate_Nest(Mat A)
1141c8883902SJed Brown {
1142c8883902SJed Brown   Mat_Nest       *s;
1143c8883902SJed Brown   PetscErrorCode ierr;
1144c8883902SJed Brown 
1145c8883902SJed Brown   PetscFunctionBegin;
1146c8883902SJed Brown   ierr = PetscNewLog(A,Mat_Nest,&s);CHKERRQ(ierr);
1147c8883902SJed Brown   A->data         = (void*)s;
1148c8883902SJed Brown   s->nr = s->nc   = -1;
1149c8883902SJed Brown   s->m            = PETSC_NULL;
1150c8883902SJed Brown 
1151c8883902SJed Brown   ierr = PetscMemzero(A->ops,sizeof(*A->ops));CHKERRQ(ierr);
1152c8883902SJed Brown   A->ops->mult                  = MatMult_Nest;
11539194d70fSJed Brown   A->ops->multadd               = MatMultAdd_Nest;
1154c8883902SJed Brown   A->ops->multtranspose         = MatMultTranspose_Nest;
11559194d70fSJed Brown   A->ops->multtransposeadd      = MatMultTransposeAdd_Nest;
1156c8883902SJed Brown   A->ops->assemblybegin         = MatAssemblyBegin_Nest;
1157c8883902SJed Brown   A->ops->assemblyend           = MatAssemblyEnd_Nest;
1158c8883902SJed Brown   A->ops->zeroentries           = MatZeroEntries_Nest;
1159c8883902SJed Brown   A->ops->duplicate             = MatDuplicate_Nest;
1160c8883902SJed Brown   A->ops->getsubmatrix          = MatGetSubMatrix_Nest;
1161c8883902SJed Brown   A->ops->destroy               = MatDestroy_Nest;
1162c8883902SJed Brown   A->ops->view                  = MatView_Nest;
1163c8883902SJed Brown   A->ops->getvecs               = 0; /* Use VECNEST by calling MatNestSetVecType(A,VECNEST) */
1164c8883902SJed Brown   A->ops->getlocalsubmatrix     = MatGetLocalSubMatrix_Nest;
1165c8883902SJed Brown   A->ops->restorelocalsubmatrix = MatRestoreLocalSubMatrix_Nest;
1166*429bac76SJed Brown   A->ops->getdiagonal           = MatGetDiagonal_Nest;
1167*429bac76SJed Brown   A->ops->diagonalscale         = MatDiagonalScale_Nest;
1168c8883902SJed Brown 
1169c8883902SJed Brown   A->spptr        = 0;
1170c8883902SJed Brown   A->same_nonzero = PETSC_FALSE;
1171c8883902SJed Brown   A->assembled    = PETSC_FALSE;
1172c8883902SJed Brown 
1173c8883902SJed Brown   /* expose Nest api's */
1174c8883902SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatNestGetSubMat_C",   "MatNestGetSubMat_Nest",   MatNestGetSubMat_Nest);CHKERRQ(ierr);
11750782ca92SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatNestSetSubMat_C",   "MatNestSetSubMat_Nest",   MatNestSetSubMat_Nest);CHKERRQ(ierr);
1176c8883902SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatNestGetSubMats_C",  "MatNestGetSubMats_Nest",  MatNestGetSubMats_Nest);CHKERRQ(ierr);
1177c8883902SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatNestGetSize_C",     "MatNestGetSize_Nest",     MatNestGetSize_Nest);CHKERRQ(ierr);
1178c8883902SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatNestSetVecType_C",  "MatNestSetVecType_Nest",  MatNestSetVecType_Nest);CHKERRQ(ierr);
1179c8883902SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatNestSetSubMats_C",  "MatNestSetSubMats_Nest",  MatNestSetSubMats_Nest);CHKERRQ(ierr);
1180c8883902SJed Brown 
1181c8883902SJed Brown   ierr = PetscObjectChangeTypeName((PetscObject)A,MATNEST);CHKERRQ(ierr);
1182c8883902SJed Brown   PetscFunctionReturn(0);
1183c8883902SJed Brown }
118486e80854SHong Zhang EXTERN_C_END
1185