xref: /petsc/src/mat/impls/nest/matnest.c (revision 6b3a5b133cf0f69f364eafe712a06449f824931a)
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 #undef __FUNCT__
36d8588912SDave May #define __FUNCT__ "PETSc_MatNest_CheckMatVecCompatibility2"
37207556f9SJed Brown PETSC_UNUSED
38d8588912SDave May static PetscErrorCode PETSc_MatNest_CheckMatVecCompatibility2(Mat A,Vec x,Vec y)
39d8588912SDave May {
40d8588912SDave May   PetscBool      isANest, isxNest, isyNest;
41d8588912SDave May   PetscErrorCode ierr;
42d8588912SDave May 
43d8588912SDave May   PetscFunctionBegin;
44d8588912SDave May   isANest = isxNest = isyNest = PETSC_FALSE;
45d8588912SDave May   ierr = PetscTypeCompare( (PetscObject)A, MATNEST, &isANest );CHKERRQ(ierr);
46d8588912SDave May   ierr = PetscTypeCompare( (PetscObject)x, VECNEST, &isxNest );CHKERRQ(ierr);
47d8588912SDave May   ierr = PetscTypeCompare( (PetscObject)y, VECNEST, &isyNest );CHKERRQ(ierr);
48d8588912SDave May 
49d8588912SDave May   if (isANest && isxNest && isyNest) {
50d8588912SDave May     PetscFunctionReturn(0);
51d8588912SDave May   } else {
52d8588912SDave May     SETERRQ( ((PetscObject)A)->comm, PETSC_ERR_SUP, "Operation only valid for Mat(Nest)-Vec(Nest) combinations");
53d8588912SDave May     PetscFunctionReturn(0);
54d8588912SDave May   }
55d8588912SDave May   PetscFunctionReturn(0);
56d8588912SDave May }
57d8588912SDave May 
58d8588912SDave May /*
59d8588912SDave May  This function is called every time we insert a sub matrix the Nest.
60d8588912SDave May  It ensures that every Nest along row r, and col c has the same dimensions
61d8588912SDave May  as the submat being inserted.
62d8588912SDave May */
63d8588912SDave May #undef __FUNCT__
64d8588912SDave May #define __FUNCT__ "PETSc_MatNest_CheckConsistency"
65063a28d4SJed Brown PETSC_UNUSED
66d8588912SDave May static PetscErrorCode PETSc_MatNest_CheckConsistency(Mat A,Mat submat,PetscInt r,PetscInt c)
67d8588912SDave May {
68d8588912SDave May   Mat_Nest       *b = (Mat_Nest*)A->data;
69d8588912SDave May   PetscInt       i,j;
70d8588912SDave May   PetscInt       nr,nc;
71d8588912SDave May   PetscInt       sM,sN,M,N;
72d8588912SDave May   Mat            mat;
73d8588912SDave May   PetscErrorCode ierr;
74d8588912SDave May 
75d8588912SDave May   PetscFunctionBegin;
76d8588912SDave May   nr = b->nr;
77d8588912SDave May   nc = b->nc;
78d8588912SDave May   ierr = MatGetSize(submat,&sM,&sN);CHKERRQ(ierr);
79d8588912SDave May   for (i=0; i<nr; i++) {
80d8588912SDave May     mat = b->m[i][c];
81d8588912SDave May     if (mat) {
82d8588912SDave May       ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr);
83d8588912SDave May       /* Check columns match */
84d8588912SDave May       if (sN != N) {
85d8588912SDave May         SETERRQ3(((PetscObject)A)->comm,PETSC_ERR_SUP,"Inserted incompatible submatrix into Nest at (%D,%D). Submatrix must have %D rows",r,c,N );
86d8588912SDave May       }
87d8588912SDave May     }
88d8588912SDave May   }
89d8588912SDave May 
90d8588912SDave May   for (j=0; j<nc; j++) {
91d8588912SDave May     mat = b->m[r][j];
92d8588912SDave May     if (mat) {
93d8588912SDave May       ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr);
94d8588912SDave May       /* Check rows match */
95d8588912SDave May       if (sM != M) {
96d8588912SDave May         SETERRQ3(((PetscObject)A)->comm,PETSC_ERR_SUP,"Inserted incompatible submatrix into Nest at (%D,%D). Submatrix must have %D cols",r,c,M );
97d8588912SDave May       }
98d8588912SDave May     }
99d8588912SDave May   }
100d8588912SDave May   PetscFunctionReturn(0);
101d8588912SDave May }
102d8588912SDave May 
103d8588912SDave May /*
104d8588912SDave May  Checks if the row/col's contain a complete set of IS's.
105d8588912SDave May  Once they are filled, the offsets are computed. This saves having to update
106d8588912SDave May  the index set entries each time we insert something new.
107d8588912SDave May  */
108d8588912SDave May #undef __FUNCT__
109d8588912SDave May #define __FUNCT__ "PETSc_MatNest_UpdateStructure"
110063a28d4SJed Brown PETSC_UNUSED
111d8588912SDave May static PetscErrorCode PETSc_MatNest_UpdateStructure(Mat A,PetscInt ridx,PetscInt cidx)
112d8588912SDave May {
113d8588912SDave May   Mat_Nest       *b = (Mat_Nest*)A->data;
114d8588912SDave May   PetscInt       m,n,i,j;
115d8588912SDave May   PetscBool      fullrow,fullcol;
116d8588912SDave May   PetscErrorCode ierr;
117d8588912SDave May 
118d8588912SDave May   PetscFunctionBegin;
119d8588912SDave May   ierr = MatGetLocalSize(b->m[ridx][cidx],&m,&n);CHKERRQ(ierr);
120d8588912SDave May   b->row_len[ridx] = m;
121d8588912SDave May   b->col_len[cidx] = n;
122d8588912SDave May 
123d8588912SDave May   fullrow = PETSC_TRUE;
124d8588912SDave May   for (i=0; i<b->nr; i++) {
125d8588912SDave May     if (b->row_len[i]==-1) { fullrow = PETSC_FALSE; break; }
126d8588912SDave May   }
127f349c1fdSJed Brown   if ( (fullrow) && (!b->isglobal.row[0]) ){
128d8588912SDave May     PetscInt cnt = 0;
129d8588912SDave May     for (i=0; i<b->nr; i++) {
130f349c1fdSJed Brown       ierr = ISCreateStride(PETSC_COMM_SELF,b->row_len[i],cnt,1,&b->isglobal.row[i]);CHKERRQ(ierr);
131d8588912SDave May       cnt = cnt + b->row_len[i];
132d8588912SDave May     }
133d8588912SDave May   }
134d8588912SDave May 
135d8588912SDave May   fullcol = PETSC_TRUE;
136d8588912SDave May   for (j=0; j<b->nc; j++) {
137d8588912SDave May     if (b->col_len[j]==-1) { fullcol = PETSC_FALSE; break; }
138d8588912SDave May   }
139f349c1fdSJed Brown   if( (fullcol) && (!b->isglobal.col[0]) ){
140d8588912SDave May     PetscInt cnt = 0;
141d8588912SDave May     for (j=0; j<b->nc; j++) {
142f349c1fdSJed Brown       ierr = ISCreateStride(PETSC_COMM_SELF,b->col_len[j],cnt,1,&b->isglobal.col[j]);CHKERRQ(ierr);
143d8588912SDave May       cnt = cnt + b->col_len[j];
144d8588912SDave May     }
145d8588912SDave May   }
146d8588912SDave May   PetscFunctionReturn(0);
147d8588912SDave May }
148d8588912SDave May 
149d8588912SDave May /* operations */
150d8588912SDave May #undef __FUNCT__
151d8588912SDave May #define __FUNCT__ "MatMult_Nest"
152207556f9SJed Brown static PetscErrorCode MatMult_Nest(Mat A,Vec x,Vec y)
153d8588912SDave May {
154d8588912SDave May   Mat_Nest       *bA = (Mat_Nest*)A->data;
155207556f9SJed Brown   Vec            *bx = bA->right,*by = bA->left;
156207556f9SJed Brown   PetscInt       i,j,nr = bA->nr,nc = bA->nc;
157d8588912SDave May   PetscErrorCode ierr;
158d8588912SDave May 
159d8588912SDave May   PetscFunctionBegin;
160207556f9SJed Brown   for (i=0; i<nr; i++) {ierr = VecGetSubVector(y,bA->isglobal.row[i],&by[i]);CHKERRQ(ierr);}
161207556f9SJed Brown   for (i=0; i<nc; i++) {ierr = VecGetSubVector(x,bA->isglobal.col[i],&bx[i]);CHKERRQ(ierr);}
162207556f9SJed Brown   for (i=0; i<nr; i++) {
163d8588912SDave May     ierr = VecZeroEntries(by[i]);CHKERRQ(ierr);
164207556f9SJed Brown     for (j=0; j<nc; j++) {
165207556f9SJed Brown       if (!bA->m[i][j]) continue;
166d8588912SDave May       /* y[i] <- y[i] + A[i][j] * x[j] */
167d8588912SDave May       ierr = MatMultAdd(bA->m[i][j],bx[j],by[i],by[i]);CHKERRQ(ierr);
168d8588912SDave May     }
169d8588912SDave May   }
170207556f9SJed Brown   for (i=0; i<nr; i++) {ierr = VecRestoreSubVector(y,bA->isglobal.row[i],&by[i]);CHKERRQ(ierr);}
171207556f9SJed Brown   for (i=0; i<nc; i++) {ierr = VecRestoreSubVector(x,bA->isglobal.col[i],&bx[i]);CHKERRQ(ierr);}
172d8588912SDave May   PetscFunctionReturn(0);
173d8588912SDave May }
174d8588912SDave May 
175d8588912SDave May #undef __FUNCT__
1769194d70fSJed Brown #define __FUNCT__ "MatMultAdd_Nest"
1779194d70fSJed Brown static PetscErrorCode MatMultAdd_Nest(Mat A,Vec x,Vec y,Vec z)
1789194d70fSJed Brown {
1799194d70fSJed Brown   Mat_Nest       *bA = (Mat_Nest*)A->data;
1809194d70fSJed Brown   Vec            *bx = bA->right,*bz = bA->left;
1819194d70fSJed Brown   PetscInt       i,j,nr = bA->nr,nc = bA->nc;
1829194d70fSJed Brown   PetscErrorCode ierr;
1839194d70fSJed Brown 
1849194d70fSJed Brown   PetscFunctionBegin;
1859194d70fSJed Brown   for (i=0; i<nr; i++) {ierr = VecGetSubVector(z,bA->isglobal.row[i],&bz[i]);CHKERRQ(ierr);}
1869194d70fSJed Brown   for (i=0; i<nc; i++) {ierr = VecGetSubVector(x,bA->isglobal.col[i],&bx[i]);CHKERRQ(ierr);}
1879194d70fSJed Brown   for (i=0; i<nr; i++) {
1889194d70fSJed Brown     if (y != z) {
1899194d70fSJed Brown       Vec by;
1909194d70fSJed Brown       ierr = VecGetSubVector(y,bA->isglobal.row[i],&by);CHKERRQ(ierr);
1919194d70fSJed Brown       ierr = VecCopy(by,bz[i]);CHKERRQ(ierr);
1929194d70fSJed Brown       ierr = VecRestoreSubVector(y,bA->isglobal.col[j],&by);CHKERRQ(ierr);
1939194d70fSJed Brown     }
1949194d70fSJed Brown     for (j=0; j<nc; j++) {
1959194d70fSJed Brown       if (!bA->m[i][j]) continue;
1969194d70fSJed Brown       /* y[i] <- y[i] + A[i][j] * x[j] */
1979194d70fSJed Brown       ierr = MatMultAdd(bA->m[i][j],bx[j],bz[i],bz[i]);CHKERRQ(ierr);
1989194d70fSJed Brown     }
1999194d70fSJed Brown   }
2009194d70fSJed Brown   for (i=0; i<nr; i++) {ierr = VecRestoreSubVector(z,bA->isglobal.row[i],&bz[i]);CHKERRQ(ierr);}
2019194d70fSJed Brown   for (i=0; i<nc; i++) {ierr = VecRestoreSubVector(x,bA->isglobal.col[i],&bx[i]);CHKERRQ(ierr);}
2029194d70fSJed Brown   PetscFunctionReturn(0);
2039194d70fSJed Brown }
2049194d70fSJed Brown 
2059194d70fSJed Brown #undef __FUNCT__
206d8588912SDave May #define __FUNCT__ "MatMultTranspose_Nest"
207207556f9SJed Brown static PetscErrorCode MatMultTranspose_Nest(Mat A,Vec x,Vec y)
208d8588912SDave May {
209d8588912SDave May   Mat_Nest       *bA = (Mat_Nest*)A->data;
210207556f9SJed Brown   Vec            *bx = bA->left,*by = bA->right;
211207556f9SJed Brown   PetscInt       i,j,nr = bA->nr,nc = bA->nc;
212d8588912SDave May   PetscErrorCode ierr;
213d8588912SDave May 
214d8588912SDave May   PetscFunctionBegin;
215609e31cbSJed Brown   for (i=0; i<nr; i++) {ierr = VecGetSubVector(x,bA->isglobal.row[i],&bx[i]);CHKERRQ(ierr);}
216609e31cbSJed Brown   for (i=0; i<nc; i++) {ierr = VecGetSubVector(y,bA->isglobal.col[i],&by[i]);CHKERRQ(ierr);}
217207556f9SJed Brown   for (j=0; j<nc; j++) {
218609e31cbSJed Brown     ierr = VecZeroEntries(by[j]);CHKERRQ(ierr);
219609e31cbSJed Brown     for (i=0; i<nr; i++) {
220207556f9SJed Brown       if (!bA->m[j][i]) continue;
221609e31cbSJed Brown       /* y[j] <- y[j] + (A[i][j])^T * x[i] */
222609e31cbSJed Brown       ierr = MatMultTransposeAdd(bA->m[i][j],bx[i],by[j],by[j]);CHKERRQ(ierr);
223d8588912SDave May     }
224d8588912SDave May   }
225609e31cbSJed Brown   for (i=0; i<nr; i++) {ierr = VecRestoreSubVector(x,bA->isglobal.row[i],&bx[i]);CHKERRQ(ierr);}
226609e31cbSJed Brown   for (i=0; i<nc; i++) {ierr = VecRestoreSubVector(y,bA->isglobal.col[i],&by[i]);CHKERRQ(ierr);}
227d8588912SDave May   PetscFunctionReturn(0);
228d8588912SDave May }
229d8588912SDave May 
230d8588912SDave May #undef __FUNCT__
2319194d70fSJed Brown #define __FUNCT__ "MatMultTransposeAdd_Nest"
2329194d70fSJed Brown static PetscErrorCode MatMultTransposeAdd_Nest(Mat A,Vec x,Vec y,Vec z)
2339194d70fSJed Brown {
2349194d70fSJed Brown   Mat_Nest       *bA = (Mat_Nest*)A->data;
2359194d70fSJed Brown   Vec            *bx = bA->left,*bz = bA->right;
2369194d70fSJed Brown   PetscInt       i,j,nr = bA->nr,nc = bA->nc;
2379194d70fSJed Brown   PetscErrorCode ierr;
2389194d70fSJed Brown 
2399194d70fSJed Brown   PetscFunctionBegin;
2409194d70fSJed Brown   for (i=0; i<nr; i++) {ierr = VecGetSubVector(x,bA->isglobal.row[i],&bx[i]);CHKERRQ(ierr);}
2419194d70fSJed Brown   for (i=0; i<nc; i++) {ierr = VecGetSubVector(z,bA->isglobal.col[i],&bz[i]);CHKERRQ(ierr);}
2429194d70fSJed Brown   for (j=0; j<nc; j++) {
2439194d70fSJed Brown     if (y != z) {
2449194d70fSJed Brown       Vec by;
2459194d70fSJed Brown       ierr = VecGetSubVector(y,bA->isglobal.col[j],&by);CHKERRQ(ierr);
2469194d70fSJed Brown       ierr = VecCopy(by,bz[j]);CHKERRQ(ierr);
2479194d70fSJed Brown       ierr = VecRestoreSubVector(y,bA->isglobal.col[j],&by);CHKERRQ(ierr);
2489194d70fSJed Brown     }
2499194d70fSJed Brown     for (i=0; i<nr; i++) {
2509194d70fSJed Brown       if (!bA->m[j][i]) continue;
2519194d70fSJed Brown       /* z[j] <- y[j] + (A[i][j])^T * x[i] */
2529194d70fSJed Brown       ierr = MatMultTransposeAdd(bA->m[i][j],bx[i],bz[j],bz[j]);CHKERRQ(ierr);
2539194d70fSJed Brown     }
2549194d70fSJed Brown   }
2559194d70fSJed Brown   for (i=0; i<nr; i++) {ierr = VecRestoreSubVector(x,bA->isglobal.row[i],&bx[i]);CHKERRQ(ierr);}
2569194d70fSJed Brown   for (i=0; i<nc; i++) {ierr = VecRestoreSubVector(z,bA->isglobal.col[i],&bz[i]);CHKERRQ(ierr);}
2579194d70fSJed Brown   PetscFunctionReturn(0);
2589194d70fSJed Brown }
2599194d70fSJed Brown 
2609194d70fSJed Brown #undef __FUNCT__
261e2d7f03fSJed Brown #define __FUNCT__ "MatNestDestroyISList"
262e2d7f03fSJed Brown static PetscErrorCode MatNestDestroyISList(PetscInt n,IS **list)
263e2d7f03fSJed Brown {
264e2d7f03fSJed Brown   PetscErrorCode ierr;
265e2d7f03fSJed Brown   IS             *lst = *list;
266e2d7f03fSJed Brown   PetscInt       i;
267e2d7f03fSJed Brown 
268e2d7f03fSJed Brown   PetscFunctionBegin;
269e2d7f03fSJed Brown   if (!lst) PetscFunctionReturn(0);
2706bf464f9SBarry Smith   for (i=0; i<n; i++) if (lst[i]) {ierr = ISDestroy(&lst[i]);CHKERRQ(ierr);}
271e2d7f03fSJed Brown   ierr = PetscFree(lst);CHKERRQ(ierr);
272e2d7f03fSJed Brown   *list = PETSC_NULL;
273e2d7f03fSJed Brown   PetscFunctionReturn(0);
274e2d7f03fSJed Brown }
275e2d7f03fSJed Brown 
276e2d7f03fSJed Brown #undef __FUNCT__
277d8588912SDave May #define __FUNCT__ "MatDestroy_Nest"
278207556f9SJed Brown static PetscErrorCode MatDestroy_Nest(Mat A)
279d8588912SDave May {
280d8588912SDave May   Mat_Nest       *vs = (Mat_Nest*)A->data;
281d8588912SDave May   PetscInt       i,j;
282d8588912SDave May   PetscErrorCode ierr;
283d8588912SDave May 
284d8588912SDave May   PetscFunctionBegin;
285d8588912SDave May   /* release the matrices and the place holders */
286e2d7f03fSJed Brown   ierr = MatNestDestroyISList(vs->nr,&vs->isglobal.row);CHKERRQ(ierr);
287e2d7f03fSJed Brown   ierr = MatNestDestroyISList(vs->nc,&vs->isglobal.col);CHKERRQ(ierr);
288e2d7f03fSJed Brown   ierr = MatNestDestroyISList(vs->nr,&vs->islocal.row);CHKERRQ(ierr);
289e2d7f03fSJed Brown   ierr = MatNestDestroyISList(vs->nc,&vs->islocal.col);CHKERRQ(ierr);
290d8588912SDave May 
291d8588912SDave May   ierr = PetscFree(vs->row_len);CHKERRQ(ierr);
292d8588912SDave May   ierr = PetscFree(vs->col_len);CHKERRQ(ierr);
293d8588912SDave May 
294207556f9SJed Brown   ierr = PetscFree2(vs->left,vs->right);CHKERRQ(ierr);
295207556f9SJed Brown 
296d8588912SDave May   /* release the matrices and the place holders */
297d8588912SDave May   if (vs->m) {
298d8588912SDave May     for (i=0; i<vs->nr; i++) {
299d8588912SDave May       for (j=0; j<vs->nc; j++) {
3006bf464f9SBarry Smith         ierr = MatDestroy(&vs->m[i][j]);CHKERRQ(ierr);
301d8588912SDave May       }
302d8588912SDave May       ierr = PetscFree( vs->m[i] );CHKERRQ(ierr);
303d8588912SDave May     }
304d8588912SDave May     ierr = PetscFree(vs->m);CHKERRQ(ierr);
305d8588912SDave May   }
306bf0cc555SLisandro Dalcin   ierr = PetscFree(A->data);CHKERRQ(ierr);
307d8588912SDave May 
308c8883902SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatNestGetSubMat_C",   "",0);CHKERRQ(ierr);
3090782ca92SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatNestSetSubMat_C",   "",0);CHKERRQ(ierr);
310c8883902SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatNestGetSubMats_C",  "",0);CHKERRQ(ierr);
311c8883902SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatNestGetSize_C",     "",0);CHKERRQ(ierr);
312c8883902SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatNestSetVecType_C",  "",0);CHKERRQ(ierr);
313c8883902SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatNestSetSubMats_C",   "",0);CHKERRQ(ierr);
314d8588912SDave May   PetscFunctionReturn(0);
315d8588912SDave May }
316d8588912SDave May 
317d8588912SDave May #undef __FUNCT__
318d8588912SDave May #define __FUNCT__ "MatAssemblyBegin_Nest"
319207556f9SJed Brown static PetscErrorCode MatAssemblyBegin_Nest(Mat A,MatAssemblyType type)
320d8588912SDave May {
321d8588912SDave May   Mat_Nest       *vs = (Mat_Nest*)A->data;
322d8588912SDave May   PetscInt       i,j;
323d8588912SDave May   PetscErrorCode ierr;
324d8588912SDave May 
325d8588912SDave May   PetscFunctionBegin;
326d8588912SDave May   for (i=0; i<vs->nr; i++) {
327d8588912SDave May     for (j=0; j<vs->nc; j++) {
328d8588912SDave May       if (vs->m[i][j]) { ierr = MatAssemblyBegin(vs->m[i][j],type);CHKERRQ(ierr); }
329d8588912SDave May     }
330d8588912SDave May   }
331d8588912SDave May   PetscFunctionReturn(0);
332d8588912SDave May }
333d8588912SDave May 
334d8588912SDave May #undef __FUNCT__
335d8588912SDave May #define __FUNCT__ "MatAssemblyEnd_Nest"
336207556f9SJed Brown static PetscErrorCode MatAssemblyEnd_Nest(Mat A, MatAssemblyType type)
337d8588912SDave May {
338d8588912SDave May   Mat_Nest       *vs = (Mat_Nest*)A->data;
339d8588912SDave May   PetscInt       i,j;
340d8588912SDave May   PetscErrorCode ierr;
341d8588912SDave May 
342d8588912SDave May   PetscFunctionBegin;
343d8588912SDave May   for (i=0; i<vs->nr; i++) {
344d8588912SDave May     for (j=0; j<vs->nc; j++) {
345d8588912SDave May       if (vs->m[i][j]) { ierr = MatAssemblyEnd(vs->m[i][j],type);CHKERRQ(ierr); }
346d8588912SDave May     }
347d8588912SDave May   }
348d8588912SDave May   PetscFunctionReturn(0);
349d8588912SDave May }
350d8588912SDave May 
351d8588912SDave May #undef __FUNCT__
352f349c1fdSJed Brown #define __FUNCT__ "MatNestFindNonzeroSubMatRow"
353f349c1fdSJed Brown static PetscErrorCode MatNestFindNonzeroSubMatRow(Mat A,PetscInt row,Mat *B)
354d8588912SDave May {
355207556f9SJed Brown   PetscErrorCode ierr;
356f349c1fdSJed Brown   Mat_Nest       *vs = (Mat_Nest*)A->data;
357f349c1fdSJed Brown   PetscInt       j;
358f349c1fdSJed Brown   Mat            sub;
359d8588912SDave May 
360d8588912SDave May   PetscFunctionBegin;
3618188e55aSJed Brown   sub = (row < vs->nc) ? vs->m[row][row] : PETSC_NULL; /* Prefer to find on the diagonal */
362f349c1fdSJed Brown   for (j=0; !sub && j<vs->nc; j++) sub = vs->m[row][j];
3638188e55aSJed Brown   if (sub) {ierr = MatPreallocated(sub);CHKERRQ(ierr);} /* Ensure that the sizes are available */
364f349c1fdSJed Brown   *B = sub;
365f349c1fdSJed Brown   PetscFunctionReturn(0);
366d8588912SDave May }
367d8588912SDave May 
368f349c1fdSJed Brown #undef __FUNCT__
369f349c1fdSJed Brown #define __FUNCT__ "MatNestFindNonzeroSubMatCol"
370f349c1fdSJed Brown static PetscErrorCode MatNestFindNonzeroSubMatCol(Mat A,PetscInt col,Mat *B)
371f349c1fdSJed Brown {
372207556f9SJed Brown   PetscErrorCode ierr;
373f349c1fdSJed Brown   Mat_Nest       *vs = (Mat_Nest*)A->data;
374f349c1fdSJed Brown   PetscInt       i;
375f349c1fdSJed Brown   Mat            sub;
376f349c1fdSJed Brown 
377f349c1fdSJed Brown   PetscFunctionBegin;
3788188e55aSJed Brown   sub = (col < vs->nr) ? vs->m[col][col] : PETSC_NULL; /* Prefer to find on the diagonal */
379f349c1fdSJed Brown   for (i=0; !sub && i<vs->nr; i++) sub = vs->m[i][col];
3808188e55aSJed Brown   if (sub) {ierr = MatPreallocated(sub);CHKERRQ(ierr);} /* Ensure that the sizes are available */
381f349c1fdSJed Brown   *B = sub;
382f349c1fdSJed Brown   PetscFunctionReturn(0);
383d8588912SDave May }
384d8588912SDave May 
385f349c1fdSJed Brown #undef __FUNCT__
386f349c1fdSJed Brown #define __FUNCT__ "MatNestFindIS"
387f349c1fdSJed Brown static PetscErrorCode MatNestFindIS(Mat A,PetscInt n,const IS list[],IS is,PetscInt *found)
388f349c1fdSJed Brown {
389f349c1fdSJed Brown   PetscErrorCode ierr;
390f349c1fdSJed Brown   PetscInt       i;
391f349c1fdSJed Brown   PetscBool      flg;
392f349c1fdSJed Brown 
393f349c1fdSJed Brown   PetscFunctionBegin;
394f349c1fdSJed Brown   PetscValidPointer(list,3);
395f349c1fdSJed Brown   PetscValidHeaderSpecific(is,IS_CLASSID,4);
396f349c1fdSJed Brown   PetscValidIntPointer(found,5);
397f349c1fdSJed Brown   *found = -1;
398f349c1fdSJed Brown   for (i=0; i<n; i++) {
399207556f9SJed Brown     if (!list[i]) continue;
400f349c1fdSJed Brown     ierr = ISEqual(list[i],is,&flg);CHKERRQ(ierr);
401f349c1fdSJed Brown     if (flg) {
402f349c1fdSJed Brown       *found = i;
403f349c1fdSJed Brown       PetscFunctionReturn(0);
404f349c1fdSJed Brown     }
405f349c1fdSJed Brown   }
406f349c1fdSJed Brown   SETERRQ(((PetscObject)A)->comm,PETSC_ERR_ARG_INCOMP,"Could not find index set");
407f349c1fdSJed Brown   PetscFunctionReturn(0);
408f349c1fdSJed Brown }
409f349c1fdSJed Brown 
410f349c1fdSJed Brown #undef __FUNCT__
4118188e55aSJed Brown #define __FUNCT__ "MatNestGetRow"
4128188e55aSJed Brown /* Get a block row as a new MatNest */
4138188e55aSJed Brown static PetscErrorCode MatNestGetRow(Mat A,PetscInt row,Mat *B)
4148188e55aSJed Brown {
4158188e55aSJed Brown   Mat_Nest       *vs = (Mat_Nest*)A->data;
4168188e55aSJed Brown   char           keyname[256];
4178188e55aSJed Brown   PetscErrorCode ierr;
4188188e55aSJed Brown 
4198188e55aSJed Brown   PetscFunctionBegin;
4208188e55aSJed Brown   *B = PETSC_NULL;
4218188e55aSJed Brown   ierr = PetscSNPrintf(keyname,sizeof keyname,"NestRow_%D",row);CHKERRQ(ierr);
4228188e55aSJed Brown   ierr = PetscObjectQuery((PetscObject)A,keyname,(PetscObject*)B);CHKERRQ(ierr);
4238188e55aSJed Brown   if (*B) PetscFunctionReturn(0);
4248188e55aSJed Brown 
4258188e55aSJed Brown   ierr = MatCreateNest(((PetscObject)A)->comm,1,PETSC_NULL,vs->nc,vs->isglobal.col,vs->m[row],B);CHKERRQ(ierr);
4268188e55aSJed Brown   (*B)->assembled = A->assembled;
4278188e55aSJed Brown   ierr = PetscObjectCompose((PetscObject)A,keyname,(PetscObject)*B);CHKERRQ(ierr);
4288188e55aSJed Brown   ierr = PetscObjectDereference((PetscObject)*B);CHKERRQ(ierr); /* Leave the only remaining reference in the composition */
4298188e55aSJed Brown   PetscFunctionReturn(0);
4308188e55aSJed Brown }
4318188e55aSJed Brown 
4328188e55aSJed Brown #undef __FUNCT__
433f349c1fdSJed Brown #define __FUNCT__ "MatNestFindSubMat"
434f349c1fdSJed Brown static PetscErrorCode MatNestFindSubMat(Mat A,struct MatNestISPair *is,IS isrow,IS iscol,Mat *B)
435f349c1fdSJed Brown {
436f349c1fdSJed Brown   Mat_Nest       *vs = (Mat_Nest*)A->data;
4378188e55aSJed Brown   PetscErrorCode ierr;
438*6b3a5b13SJed Brown   PetscInt       row,col;
4398188e55aSJed Brown   PetscBool      same,isFullCol;
440f349c1fdSJed Brown 
441f349c1fdSJed Brown   PetscFunctionBegin;
4428188e55aSJed Brown   /* Check if full column space. This is a hack */
4438188e55aSJed Brown   isFullCol = PETSC_FALSE;
4448188e55aSJed Brown   ierr = PetscTypeCompare((PetscObject)iscol,ISSTRIDE,&same);CHKERRQ(ierr);
4458188e55aSJed Brown   if (same) {
4468188e55aSJed Brown     PetscInt n,first,step;
4478188e55aSJed Brown     ierr = ISStrideGetInfo(iscol,&first,&step);CHKERRQ(ierr);
4488188e55aSJed Brown     ierr = ISGetLocalSize(iscol,&n);CHKERRQ(ierr);
4498188e55aSJed Brown     if (A->cmap->n == n && A->cmap->rstart == first && step == 1) isFullCol = PETSC_TRUE;
4508188e55aSJed Brown   }
4518188e55aSJed Brown 
4528188e55aSJed Brown   if (isFullCol) {
4538188e55aSJed Brown     PetscInt row;
4548188e55aSJed Brown     ierr = MatNestFindIS(A,vs->nr,is->row,isrow,&row);CHKERRQ(ierr);
4558188e55aSJed Brown     ierr = MatNestGetRow(A,row,B);CHKERRQ(ierr);
4568188e55aSJed Brown   } else {
457f349c1fdSJed Brown     ierr = MatNestFindIS(A,vs->nr,is->row,isrow,&row);CHKERRQ(ierr);
458f349c1fdSJed Brown     ierr = MatNestFindIS(A,vs->nc,is->col,iscol,&col);CHKERRQ(ierr);
459f349c1fdSJed Brown     *B = vs->m[row][col];
4608188e55aSJed Brown   }
461f349c1fdSJed Brown   PetscFunctionReturn(0);
462f349c1fdSJed Brown }
463f349c1fdSJed Brown 
464f349c1fdSJed Brown #undef __FUNCT__
465f349c1fdSJed Brown #define __FUNCT__ "MatGetSubMatrix_Nest"
466f349c1fdSJed Brown static PetscErrorCode MatGetSubMatrix_Nest(Mat A,IS isrow,IS iscol,MatReuse reuse,Mat *B)
467f349c1fdSJed Brown {
468f349c1fdSJed Brown   PetscErrorCode ierr;
469f349c1fdSJed Brown   Mat_Nest       *vs = (Mat_Nest*)A->data;
470f349c1fdSJed Brown   Mat            sub;
471f349c1fdSJed Brown 
472f349c1fdSJed Brown   PetscFunctionBegin;
473f349c1fdSJed Brown   ierr = MatNestFindSubMat(A,&vs->isglobal,isrow,iscol,&sub);CHKERRQ(ierr);
474f349c1fdSJed Brown   switch (reuse) {
475f349c1fdSJed Brown   case MAT_INITIAL_MATRIX:
4767874fa86SDave May     if (sub) { ierr = PetscObjectReference((PetscObject)sub);CHKERRQ(ierr); }
477f349c1fdSJed Brown     *B = sub;
478f349c1fdSJed Brown     break;
479f349c1fdSJed Brown   case MAT_REUSE_MATRIX:
480f349c1fdSJed Brown     if (sub != *B) SETERRQ(((PetscObject)A)->comm,PETSC_ERR_ARG_WRONGSTATE,"Submatrix was not used before in this call");
481f349c1fdSJed Brown     break;
482f349c1fdSJed Brown   case MAT_IGNORE_MATRIX:       /* Nothing to do */
483f349c1fdSJed Brown     break;
484f349c1fdSJed Brown   }
485f349c1fdSJed Brown   PetscFunctionReturn(0);
486f349c1fdSJed Brown }
487f349c1fdSJed Brown 
488f349c1fdSJed Brown #undef __FUNCT__
489f349c1fdSJed Brown #define __FUNCT__ "MatGetLocalSubMatrix_Nest"
490f349c1fdSJed Brown PetscErrorCode MatGetLocalSubMatrix_Nest(Mat A,IS isrow,IS iscol,Mat *B)
491f349c1fdSJed Brown {
492f349c1fdSJed Brown   PetscErrorCode ierr;
493f349c1fdSJed Brown   Mat_Nest       *vs = (Mat_Nest*)A->data;
494f349c1fdSJed Brown   Mat            sub;
495f349c1fdSJed Brown 
496f349c1fdSJed Brown   PetscFunctionBegin;
497f349c1fdSJed Brown   ierr = MatNestFindSubMat(A,&vs->islocal,isrow,iscol,&sub);CHKERRQ(ierr);
498f349c1fdSJed Brown   /* We allow the submatrix to be NULL, perhaps it would be better for the user to return an empty matrix instead */
499f349c1fdSJed Brown   if (sub) {ierr = PetscObjectReference((PetscObject)sub);CHKERRQ(ierr);}
500f349c1fdSJed Brown   *B = sub;
501d8588912SDave May   PetscFunctionReturn(0);
502d8588912SDave May }
503d8588912SDave May 
504d8588912SDave May #undef __FUNCT__
505d8588912SDave May #define __FUNCT__ "MatRestoreLocalSubMatrix_Nest"
506207556f9SJed Brown static PetscErrorCode MatRestoreLocalSubMatrix_Nest(Mat A,IS isrow,IS iscol,Mat *B)
507d8588912SDave May {
508d8588912SDave May   PetscErrorCode ierr;
509f349c1fdSJed Brown   Mat_Nest       *vs = (Mat_Nest*)A->data;
510f349c1fdSJed Brown   Mat            sub;
511d8588912SDave May 
512d8588912SDave May   PetscFunctionBegin;
513f349c1fdSJed Brown   ierr = MatNestFindSubMat(A,&vs->islocal,isrow,iscol,&sub);CHKERRQ(ierr);
514f349c1fdSJed Brown   if (*B != sub) SETERRQ(((PetscObject)A)->comm,PETSC_ERR_ARG_WRONGSTATE,"Local submatrix has not been gotten");
515f349c1fdSJed Brown   if (sub) {
516f349c1fdSJed Brown     if (((PetscObject)sub)->refct <= 1) SETERRQ(((PetscObject)A)->comm,PETSC_ERR_ARG_WRONGSTATE,"Local submatrix has had reference count decremented too many times");
5176bf464f9SBarry Smith     ierr = MatDestroy(B);CHKERRQ(ierr);
518d8588912SDave May   }
519d8588912SDave May   PetscFunctionReturn(0);
520d8588912SDave May }
521d8588912SDave May 
522d8588912SDave May #undef __FUNCT__
5237874fa86SDave May #define __FUNCT__ "MatGetDiagonal_Nest"
5247874fa86SDave May static PetscErrorCode MatGetDiagonal_Nest(Mat A,Vec v)
5257874fa86SDave May {
5267874fa86SDave May   Mat_Nest       *bA = (Mat_Nest*)A->data;
5277874fa86SDave May   Vec            *bdiag;
5287874fa86SDave May   PetscInt       i;
5297874fa86SDave May   PetscErrorCode ierr;
5307874fa86SDave May 
5317874fa86SDave May   PetscFunctionBegin;
532a0769a71SSatish Balay   /*  ierr = MatGetVecs_Nest(A,&diag,PETSC_NULL);CHKERRQ(ierr); */
533a0769a71SSatish Balay   /*  ierr = VecNestGetSubVecs(diag,PETSC_NULL,&bdiag);CHKERRQ(ierr); */
5347874fa86SDave May   ierr = VecNestGetSubVecs(v,PETSC_NULL,&bdiag);CHKERRQ(ierr);
5357874fa86SDave May   for (i=0; i<bA->nr; i++) {
5367874fa86SDave May     if (bA->m[i][i]) {
5377874fa86SDave May       ierr = MatGetDiagonal(bA->m[i][i],bdiag[i]);CHKERRQ(ierr);
5387874fa86SDave May     } else {
5397874fa86SDave May       ierr = VecSet(bdiag[i],1.0);CHKERRQ(ierr);
5407874fa86SDave May     }
5417874fa86SDave May   }
5427874fa86SDave May   PetscFunctionReturn(0);
5437874fa86SDave May }
5447874fa86SDave May 
5457874fa86SDave May #undef __FUNCT__
5467874fa86SDave May #define __FUNCT__ "MatGetDiagonal_Nest2"
5477874fa86SDave May static PetscErrorCode MatGetDiagonal_Nest2(Mat A,Vec v)
5487874fa86SDave May {
5497874fa86SDave May   Mat_Nest       *bA = (Mat_Nest*)A->data;
5507874fa86SDave May   Vec            diag,*bdiag;
5517874fa86SDave May   VecScatter     *vscat;
5527874fa86SDave May   PetscInt       i;
5537874fa86SDave May   PetscErrorCode ierr;
5547874fa86SDave May 
5557874fa86SDave May   PetscFunctionBegin;
5567874fa86SDave May   ierr = MatGetVecs_Nest(A,&diag,PETSC_NULL);CHKERRQ(ierr);
5577874fa86SDave May   ierr = MatGetDiagonal_Nest(A,diag);CHKERRQ(ierr);
5587874fa86SDave May 
5597874fa86SDave May   /* scatter diag into v */
5607874fa86SDave May   ierr = VecNestGetSubVecs(diag,PETSC_NULL,&bdiag);CHKERRQ(ierr);
5617874fa86SDave May   ierr = PetscMalloc( sizeof(VecScatter) * bA->nr, &vscat );CHKERRQ(ierr);
5627874fa86SDave May   for (i=0; i<bA->nr; i++) {
5637874fa86SDave May     ierr = VecScatterCreate(v,bA->isglobal.row[i], bdiag[i],PETSC_NULL,&vscat[i]);CHKERRQ(ierr);
5647874fa86SDave May     ierr = VecScatterBegin(vscat[i],bdiag[i],v,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5657874fa86SDave May   }
5667874fa86SDave May   for (i=0; i<bA->nr; i++) {
5677874fa86SDave May     ierr = VecScatterEnd(vscat[i],bdiag[i],v,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5687874fa86SDave May   }
5697874fa86SDave May   for (i=0; i<bA->nr; i++) {
5706bf464f9SBarry Smith     ierr = VecScatterDestroy(&vscat[i]);CHKERRQ(ierr);
5717874fa86SDave May   }
5727874fa86SDave May   ierr = PetscFree(vscat);CHKERRQ(ierr);
5736bf464f9SBarry Smith   ierr = VecDestroy(&diag);CHKERRQ(ierr);
5747874fa86SDave May   PetscFunctionReturn(0);
5757874fa86SDave May }
5767874fa86SDave May 
5777874fa86SDave May #undef __FUNCT__
5787874fa86SDave May #define __FUNCT__ "MatDiagonalScale_Nest"
5797874fa86SDave May static PetscErrorCode MatDiagonalScale_Nest(Mat A,Vec l,Vec r)
5807874fa86SDave May {
5817874fa86SDave May   Mat_Nest       *bA = (Mat_Nest*)A->data;
5827874fa86SDave May   Vec            *bl,*br;
5837874fa86SDave May   PetscInt       i,j;
5847874fa86SDave May   PetscErrorCode ierr;
5857874fa86SDave May 
5867874fa86SDave May   PetscFunctionBegin;
5877874fa86SDave May   ierr = VecNestGetSubVecs(l,PETSC_NULL,&bl);CHKERRQ(ierr);
5887874fa86SDave May   ierr = VecNestGetSubVecs(r,PETSC_NULL,&br);CHKERRQ(ierr);
5897874fa86SDave May   for (i=0; i<bA->nr; i++) {
5907874fa86SDave May     for (j=0; j<bA->nc; j++) {
5917874fa86SDave May       if (bA->m[i][j]) {
5927874fa86SDave May         ierr = MatDiagonalScale(bA->m[i][j],bl[i],br[j]);CHKERRQ(ierr);
5937874fa86SDave May       }
5947874fa86SDave May     }
5957874fa86SDave May   }
5967874fa86SDave May   PetscFunctionReturn(0);
5977874fa86SDave May }
5987874fa86SDave May 
5997874fa86SDave May #undef __FUNCT__
6007874fa86SDave May #define __FUNCT__ "MatDiagonalScale_Nest2"
6017874fa86SDave May static PetscErrorCode MatDiagonalScale_Nest2(Mat A,Vec l,Vec r)
6027874fa86SDave May {
6037874fa86SDave May   Mat_Nest       *bA = (Mat_Nest*)A->data;
6047874fa86SDave May   Vec            bl,br,*ble,*bre;
6057874fa86SDave May   VecScatter     *vscatl,*vscatr;
6067874fa86SDave May   PetscInt       i;
6077874fa86SDave May   PetscErrorCode ierr;
6087874fa86SDave May 
6097874fa86SDave May   PetscFunctionBegin;
6107874fa86SDave May   /* scatter l,r into bl,br */
6117874fa86SDave May   ierr = MatGetVecs_Nest(A,&bl,&br);CHKERRQ(ierr);
6127874fa86SDave May   ierr = VecNestGetSubVecs(bl,PETSC_NULL,&ble);CHKERRQ(ierr);
6137874fa86SDave May   ierr = VecNestGetSubVecs(br,PETSC_NULL,&bre);CHKERRQ(ierr);
6147874fa86SDave May 
6157874fa86SDave May   /* row */
6167874fa86SDave May   ierr = PetscMalloc( sizeof(VecScatter) * bA->nr, &vscatl );CHKERRQ(ierr);
6177874fa86SDave May   for (i=0; i<bA->nr; i++) {
6187874fa86SDave May     ierr = VecScatterCreate(l,bA->isglobal.row[i], ble[i],PETSC_NULL,&vscatl[i]);CHKERRQ(ierr);
6197874fa86SDave May     ierr = VecScatterBegin(vscatl[i],l,ble[i],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6207874fa86SDave May   }
6217874fa86SDave May   for (i=0; i<bA->nr; i++) {
6227874fa86SDave May     ierr = VecScatterEnd(vscatl[i],l,ble[i],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6237874fa86SDave May   }
6247874fa86SDave May   /* col */
6257874fa86SDave May   ierr = PetscMalloc( sizeof(VecScatter) * bA->nc, &vscatr );CHKERRQ(ierr);
6267874fa86SDave May   for (i=0; i<bA->nc; i++) {
6277874fa86SDave May     ierr = VecScatterCreate(r,bA->isglobal.col[i], bre[i],PETSC_NULL,&vscatr[i]);CHKERRQ(ierr);
6287874fa86SDave May     ierr = VecScatterBegin(vscatr[i],l,bre[i],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6297874fa86SDave May   }
6307874fa86SDave May   for (i=0; i<bA->nc; i++) {
6317874fa86SDave May     ierr = VecScatterEnd(vscatr[i],r,bre[i],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6327874fa86SDave May   }
6337874fa86SDave May 
6347874fa86SDave May   ierr = MatDiagonalScale_Nest(A,bl,br);CHKERRQ(ierr);
6357874fa86SDave May 
6367874fa86SDave May   for (i=0; i<bA->nr; i++) {
6376bf464f9SBarry Smith     ierr = VecScatterDestroy(&vscatl[i]);CHKERRQ(ierr);
6387874fa86SDave May   }
6397874fa86SDave May   for (i=0; i<bA->nc; i++) {
6406bf464f9SBarry Smith     ierr = VecScatterDestroy(&vscatr[i]);CHKERRQ(ierr);
6417874fa86SDave May   }
6427874fa86SDave May   ierr = PetscFree(vscatl);CHKERRQ(ierr);
6437874fa86SDave May   ierr = PetscFree(vscatr);CHKERRQ(ierr);
6446bf464f9SBarry Smith   ierr = VecDestroy(&bl);CHKERRQ(ierr);
6456bf464f9SBarry Smith   ierr = VecDestroy(&br);CHKERRQ(ierr);
6467874fa86SDave May   PetscFunctionReturn(0);
6477874fa86SDave May }
6487874fa86SDave May 
6497874fa86SDave May #undef __FUNCT__
650d8588912SDave May #define __FUNCT__ "MatGetVecs_Nest"
651207556f9SJed Brown static PetscErrorCode MatGetVecs_Nest(Mat A,Vec *right,Vec *left)
652d8588912SDave May {
653d8588912SDave May   Mat_Nest       *bA = (Mat_Nest*)A->data;
654d8588912SDave May   Vec            *L,*R;
655d8588912SDave May   MPI_Comm       comm;
656d8588912SDave May   PetscInt       i,j;
657d8588912SDave May   PetscErrorCode ierr;
658d8588912SDave May 
659d8588912SDave May   PetscFunctionBegin;
660d8588912SDave May   comm = ((PetscObject)A)->comm;
661d8588912SDave May   if (right) {
662d8588912SDave May     /* allocate R */
663d8588912SDave May     ierr = PetscMalloc( sizeof(Vec) * bA->nc, &R );CHKERRQ(ierr);
664d8588912SDave May     /* Create the right vectors */
665d8588912SDave May     for (j=0; j<bA->nc; j++) {
666d8588912SDave May       for (i=0; i<bA->nr; i++) {
667d8588912SDave May         if (bA->m[i][j]) {
668d8588912SDave May           ierr = MatGetVecs(bA->m[i][j],&R[j],PETSC_NULL);CHKERRQ(ierr);
669d8588912SDave May           break;
670d8588912SDave May         }
671d8588912SDave May       }
672d8588912SDave May       if (i==bA->nr) {
673d8588912SDave May         /* have an empty column */
674d8588912SDave May         SETERRQ( ((PetscObject)A)->comm, PETSC_ERR_ARG_WRONG, "Mat(Nest) contains a null column.");
675d8588912SDave May       }
676d8588912SDave May     }
677f349c1fdSJed Brown     ierr = VecCreateNest(comm,bA->nc,bA->isglobal.col,R,right);CHKERRQ(ierr);
678d8588912SDave May     /* hand back control to the nest vector */
679d8588912SDave May     for (j=0; j<bA->nc; j++) {
6806bf464f9SBarry Smith       ierr = VecDestroy(&R[j]);CHKERRQ(ierr);
681d8588912SDave May     }
682d8588912SDave May     ierr = PetscFree(R);CHKERRQ(ierr);
683d8588912SDave May   }
684d8588912SDave May 
685d8588912SDave May   if (left) {
686d8588912SDave May     /* allocate L */
687d8588912SDave May     ierr = PetscMalloc( sizeof(Vec) * bA->nr, &L );CHKERRQ(ierr);
688d8588912SDave May     /* Create the left vectors */
689d8588912SDave May     for (i=0; i<bA->nr; i++) {
690d8588912SDave May       for (j=0; j<bA->nc; j++) {
691d8588912SDave May         if (bA->m[i][j]) {
692d8588912SDave May           ierr = MatGetVecs(bA->m[i][j],PETSC_NULL,&L[i]);CHKERRQ(ierr);
693d8588912SDave May           break;
694d8588912SDave May         }
695d8588912SDave May       }
696d8588912SDave May       if (j==bA->nc) {
697d8588912SDave May         /* have an empty row */
698d8588912SDave May         SETERRQ( ((PetscObject)A)->comm, PETSC_ERR_ARG_WRONG, "Mat(Nest) contains a null row.");
699d8588912SDave May       }
700d8588912SDave May     }
701d8588912SDave May 
702f349c1fdSJed Brown     ierr = VecCreateNest(comm,bA->nr,bA->isglobal.row,L,left);CHKERRQ(ierr);
703d8588912SDave May     for (i=0; i<bA->nr; i++) {
7046bf464f9SBarry Smith       ierr = VecDestroy(&L[i]);CHKERRQ(ierr);
705d8588912SDave May     }
706d8588912SDave May 
707d8588912SDave May     ierr = PetscFree(L);CHKERRQ(ierr);
708d8588912SDave May   }
709d8588912SDave May   PetscFunctionReturn(0);
710d8588912SDave May }
711d8588912SDave May 
712d8588912SDave May #undef __FUNCT__
713d8588912SDave May #define __FUNCT__ "MatView_Nest"
714207556f9SJed Brown static PetscErrorCode MatView_Nest(Mat A,PetscViewer viewer)
715d8588912SDave May {
716d8588912SDave May   Mat_Nest       *bA = (Mat_Nest*)A->data;
717d8588912SDave May   PetscBool      isascii;
718d8588912SDave May   PetscInt       i,j;
719d8588912SDave May   PetscErrorCode ierr;
720d8588912SDave May 
721d8588912SDave May   PetscFunctionBegin;
722d8588912SDave May   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
723d8588912SDave May   if (isascii) {
724d8588912SDave May 
725d8588912SDave May     PetscViewerASCIIPrintf(viewer,"Matrix object: \n" );
726d8588912SDave May     PetscViewerASCIIPushTab( viewer );    /* push0 */
727d8588912SDave May     PetscViewerASCIIPrintf( viewer, "type=nest, rows=%d, cols=%d \n",bA->nr,bA->nc);
728d8588912SDave May 
729d8588912SDave May     PetscViewerASCIIPrintf(viewer,"MatNest structure: \n" );
730d8588912SDave May     for (i=0; i<bA->nr; i++) {
731d8588912SDave May       for (j=0; j<bA->nc; j++) {
732d8588912SDave May         const MatType type;
733d8588912SDave May         const char *name;
734d8588912SDave May         PetscInt NR,NC;
735d8588912SDave May         PetscBool isNest = PETSC_FALSE;
736d8588912SDave May 
737d8588912SDave May         if (!bA->m[i][j]) {
738d8588912SDave May           PetscViewerASCIIPrintf( viewer, "(%D,%D) : PETSC_NULL \n",i,j);
739d8588912SDave May           continue;
740d8588912SDave May         }
741d8588912SDave May         ierr = MatGetSize(bA->m[i][j],&NR,&NC);CHKERRQ(ierr);
742d8588912SDave May         ierr = MatGetType( bA->m[i][j], &type );CHKERRQ(ierr);
743d8588912SDave May         name = ((PetscObject)bA->m[i][j])->prefix;
744d8588912SDave May         ierr = PetscTypeCompare((PetscObject)bA->m[i][j],MATNEST,&isNest);CHKERRQ(ierr);
745d8588912SDave May 
746d8588912SDave May         PetscViewerASCIIPrintf( viewer, "(%D,%D) : name=\"%s\", type=%s, rows=%D, cols=%D \n",i,j,name,type,NR,NC);
747d8588912SDave May 
748d8588912SDave May         if (isNest) {
749d8588912SDave May           PetscViewerASCIIPushTab( viewer );  /* push1 */
750d8588912SDave May           ierr = MatView( bA->m[i][j], viewer );CHKERRQ(ierr);
751d8588912SDave May           PetscViewerASCIIPopTab(viewer);    /* pop1 */
752d8588912SDave May         }
753d8588912SDave May       }
754d8588912SDave May     }
755d8588912SDave May     PetscViewerASCIIPopTab(viewer);    /* pop0 */
756d8588912SDave May   }
757d8588912SDave May   PetscFunctionReturn(0);
758d8588912SDave May }
759d8588912SDave May 
760d8588912SDave May #undef __FUNCT__
761d8588912SDave May #define __FUNCT__ "MatZeroEntries_Nest"
762207556f9SJed Brown static PetscErrorCode MatZeroEntries_Nest(Mat A)
763d8588912SDave May {
764d8588912SDave May   Mat_Nest       *bA = (Mat_Nest*)A->data;
765d8588912SDave May   PetscInt       i,j;
766d8588912SDave May   PetscErrorCode ierr;
767d8588912SDave May 
768d8588912SDave May   PetscFunctionBegin;
769d8588912SDave May   for (i=0; i<bA->nr; i++) {
770d8588912SDave May     for (j=0; j<bA->nc; j++) {
771d8588912SDave May       if (!bA->m[i][j]) continue;
772d8588912SDave May       ierr = MatZeroEntries(bA->m[i][j]);CHKERRQ(ierr);
773d8588912SDave May     }
774d8588912SDave May   }
775d8588912SDave May   PetscFunctionReturn(0);
776d8588912SDave May }
777d8588912SDave May 
778d8588912SDave May #undef __FUNCT__
779d8588912SDave May #define __FUNCT__ "MatDuplicate_Nest"
780207556f9SJed Brown static PetscErrorCode MatDuplicate_Nest(Mat A,MatDuplicateOption op,Mat *B)
781d8588912SDave May {
782d8588912SDave May   Mat_Nest       *bA = (Mat_Nest*)A->data;
783841e96a3SJed Brown   Mat            *b;
784841e96a3SJed Brown   PetscInt       i,j,nr = bA->nr,nc = bA->nc;
785d8588912SDave May   PetscErrorCode ierr;
786d8588912SDave May 
787d8588912SDave May   PetscFunctionBegin;
788841e96a3SJed Brown   ierr = PetscMalloc(nr*nc*sizeof(Mat),&b);CHKERRQ(ierr);
789841e96a3SJed Brown   for (i=0; i<nr; i++) {
790841e96a3SJed Brown     for (j=0; j<nc; j++) {
791841e96a3SJed Brown       if (bA->m[i][j]) {
792841e96a3SJed Brown         ierr = MatDuplicate(bA->m[i][j],op,&b[i*nc+j]);CHKERRQ(ierr);
793841e96a3SJed Brown       } else {
794841e96a3SJed Brown         b[i*nc+j] = PETSC_NULL;
795d8588912SDave May       }
796d8588912SDave May     }
797d8588912SDave May   }
798f349c1fdSJed Brown   ierr = MatCreateNest(((PetscObject)A)->comm,nr,bA->isglobal.row,nc,bA->isglobal.col,b,B);CHKERRQ(ierr);
799841e96a3SJed Brown   /* Give the new MatNest exclusive ownership */
800841e96a3SJed Brown   for (i=0; i<nr*nc; i++) {
8016bf464f9SBarry Smith     ierr = MatDestroy(&b[i]);CHKERRQ(ierr);
802d8588912SDave May   }
803d8588912SDave May   ierr = PetscFree(b);CHKERRQ(ierr);
804d8588912SDave May 
805841e96a3SJed Brown   ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
806841e96a3SJed Brown   ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
807d8588912SDave May   PetscFunctionReturn(0);
808d8588912SDave May }
809d8588912SDave May 
810d8588912SDave May /* nest api */
811d8588912SDave May EXTERN_C_BEGIN
812d8588912SDave May #undef __FUNCT__
813d8588912SDave May #define __FUNCT__ "MatNestGetSubMat_Nest"
814d8588912SDave May PetscErrorCode MatNestGetSubMat_Nest(Mat A,PetscInt idxm,PetscInt jdxm,Mat *mat)
815d8588912SDave May {
816d8588912SDave May   Mat_Nest *bA = (Mat_Nest*)A->data;
817d8588912SDave May   PetscFunctionBegin;
818d8588912SDave May   if (idxm >= bA->nr) SETERRQ2(((PetscObject)A)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",idxm,bA->nr-1);
819d8588912SDave May   if (jdxm >= bA->nc) SETERRQ2(((PetscObject)A)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Col too large: row %D max %D",jdxm,bA->nc-1);
820d8588912SDave May   *mat = bA->m[idxm][jdxm];
821d8588912SDave May   PetscFunctionReturn(0);
822d8588912SDave May }
823d8588912SDave May EXTERN_C_END
824d8588912SDave May 
825d8588912SDave May #undef __FUNCT__
826d8588912SDave May #define __FUNCT__ "MatNestGetSubMat"
827d8588912SDave May /*@C
828d8588912SDave May  MatNestGetSubMat - Returns a single, sub-matrix from a nest matrix.
829d8588912SDave May 
830d8588912SDave May  Not collective
831d8588912SDave May 
832d8588912SDave May  Input Parameters:
833629881c0SJed Brown +   A  - nest matrix
834d8588912SDave May .   idxm - index of the matrix within the nest matrix
835629881c0SJed Brown -   jdxm - index of the matrix within the nest matrix
836d8588912SDave May 
837d8588912SDave May  Output Parameter:
838d8588912SDave May .   sub - matrix at index idxm,jdxm within the nest matrix
839d8588912SDave May 
840d8588912SDave May  Level: developer
841d8588912SDave May 
842d8588912SDave May .seealso: MatNestGetSize(), MatNestGetSubMats()
843d8588912SDave May @*/
8447087cfbeSBarry Smith PetscErrorCode  MatNestGetSubMat(Mat A,PetscInt idxm,PetscInt jdxm,Mat *sub)
845d8588912SDave May {
846699a902aSJed Brown   PetscErrorCode ierr;
847d8588912SDave May 
848d8588912SDave May   PetscFunctionBegin;
849699a902aSJed Brown   ierr = PetscUseMethod(A,"MatNestGetSubMat_C",(Mat,PetscInt,PetscInt,Mat*),(A,idxm,jdxm,sub));CHKERRQ(ierr);
850d8588912SDave May   PetscFunctionReturn(0);
851d8588912SDave May }
852d8588912SDave May 
853d8588912SDave May EXTERN_C_BEGIN
854d8588912SDave May #undef __FUNCT__
8550782ca92SJed Brown #define __FUNCT__ "MatNestSetSubMat_Nest"
8560782ca92SJed Brown PetscErrorCode MatNestSetSubMat_Nest(Mat A,PetscInt idxm,PetscInt jdxm,Mat mat)
8570782ca92SJed Brown {
8580782ca92SJed Brown   Mat_Nest *bA = (Mat_Nest*)A->data;
8590782ca92SJed Brown   PetscInt m,n,M,N,mi,ni,Mi,Ni;
8600782ca92SJed Brown   PetscErrorCode ierr;
8610782ca92SJed Brown 
8620782ca92SJed Brown   PetscFunctionBegin;
8630782ca92SJed Brown   if (idxm >= bA->nr) SETERRQ2(((PetscObject)A)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",idxm,bA->nr-1);
8640782ca92SJed Brown   if (jdxm >= bA->nc) SETERRQ2(((PetscObject)A)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Col too large: row %D max %D",jdxm,bA->nc-1);
8650782ca92SJed Brown   ierr = MatGetLocalSize(mat,&m,&n);CHKERRQ(ierr);
8660782ca92SJed Brown   ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr);
8670782ca92SJed Brown   ierr = ISGetLocalSize(bA->isglobal.row[idxm],&mi);CHKERRQ(ierr);
8680782ca92SJed Brown   ierr = ISGetSize(bA->isglobal.row[idxm],&Mi);CHKERRQ(ierr);
8690782ca92SJed Brown   ierr = ISGetLocalSize(bA->isglobal.col[jdxm],&ni);CHKERRQ(ierr);
8700782ca92SJed Brown   ierr = ISGetSize(bA->isglobal.col[jdxm],&Ni);CHKERRQ(ierr);
8710782ca92SJed 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);
8720782ca92SJed 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);
8730782ca92SJed Brown   ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr);
8740782ca92SJed Brown   ierr = MatDestroy(&bA->m[idxm][jdxm]);CHKERRQ(ierr);
8750782ca92SJed Brown   bA->m[idxm][jdxm] = mat;
8760782ca92SJed Brown   PetscFunctionReturn(0);
8770782ca92SJed Brown }
8780782ca92SJed Brown EXTERN_C_END
8790782ca92SJed Brown 
8800782ca92SJed Brown #undef __FUNCT__
8810782ca92SJed Brown #define __FUNCT__ "MatNestSetSubMat"
8820782ca92SJed Brown /*@C
8830782ca92SJed Brown  MatNestSetSubMat - Set a single submatrix in the nest matrix.
8840782ca92SJed Brown 
8850782ca92SJed Brown  Logically collective on the submatrix communicator
8860782ca92SJed Brown 
8870782ca92SJed Brown  Input Parameters:
8880782ca92SJed Brown +   A  - nest matrix
8890782ca92SJed Brown .   idxm - index of the matrix within the nest matrix
8900782ca92SJed Brown .   jdxm - index of the matrix within the nest matrix
8910782ca92SJed Brown -   sub - matrix at index idxm,jdxm within the nest matrix
8920782ca92SJed Brown 
8930782ca92SJed Brown  Notes:
8940782ca92SJed Brown  The new submatrix must have the same size and communicator as that block of the nest.
8950782ca92SJed Brown 
8960782ca92SJed Brown  This increments the reference count of the submatrix.
8970782ca92SJed Brown 
8980782ca92SJed Brown  Level: developer
8990782ca92SJed Brown 
9000782ca92SJed Brown .seealso: MatNestSetSubMats(), MatNestGetSubMat()
9010782ca92SJed Brown @*/
9020782ca92SJed Brown PetscErrorCode  MatNestSetSubMat(Mat A,PetscInt idxm,PetscInt jdxm,Mat sub)
9030782ca92SJed Brown {
9040782ca92SJed Brown   PetscErrorCode ierr;
9050782ca92SJed Brown 
9060782ca92SJed Brown   PetscFunctionBegin;
9070782ca92SJed Brown   ierr = PetscUseMethod(A,"MatNestSetSubMat_C",(Mat,PetscInt,PetscInt,Mat),(A,idxm,jdxm,sub));CHKERRQ(ierr);
9080782ca92SJed Brown   PetscFunctionReturn(0);
9090782ca92SJed Brown }
9100782ca92SJed Brown 
9110782ca92SJed Brown EXTERN_C_BEGIN
9120782ca92SJed Brown #undef __FUNCT__
913d8588912SDave May #define __FUNCT__ "MatNestGetSubMats_Nest"
914d8588912SDave May PetscErrorCode MatNestGetSubMats_Nest(Mat A,PetscInt *M,PetscInt *N,Mat ***mat)
915d8588912SDave May {
916d8588912SDave May   Mat_Nest *bA = (Mat_Nest*)A->data;
917d8588912SDave May   PetscFunctionBegin;
918d8588912SDave May   if (M)   { *M   = bA->nr; }
919d8588912SDave May   if (N)   { *N   = bA->nc; }
920d8588912SDave May   if (mat) { *mat = bA->m;  }
921d8588912SDave May   PetscFunctionReturn(0);
922d8588912SDave May }
923d8588912SDave May EXTERN_C_END
924d8588912SDave May 
925d8588912SDave May #undef __FUNCT__
926d8588912SDave May #define __FUNCT__ "MatNestGetSubMats"
927d8588912SDave May /*@C
928d8588912SDave May  MatNestGetSubMats - Returns the entire two dimensional array of matrices defining a nest matrix.
929d8588912SDave May 
930d8588912SDave May  Not collective
931d8588912SDave May 
932d8588912SDave May  Input Parameters:
933629881c0SJed Brown .   A  - nest matrix
934d8588912SDave May 
935d8588912SDave May  Output Parameter:
936629881c0SJed Brown +   M - number of rows in the nest matrix
937d8588912SDave May .   N - number of cols in the nest matrix
938629881c0SJed Brown -   mat - 2d array of matrices
939d8588912SDave May 
940d8588912SDave May  Notes:
941d8588912SDave May 
942d8588912SDave May  The user should not free the array mat.
943d8588912SDave May 
944d8588912SDave May  Level: developer
945d8588912SDave May 
946d8588912SDave May .seealso: MatNestGetSize(), MatNestGetSubMat()
947d8588912SDave May @*/
9487087cfbeSBarry Smith PetscErrorCode  MatNestGetSubMats(Mat A,PetscInt *M,PetscInt *N,Mat ***mat)
949d8588912SDave May {
950699a902aSJed Brown   PetscErrorCode ierr;
951d8588912SDave May 
952d8588912SDave May   PetscFunctionBegin;
953699a902aSJed Brown   ierr = PetscUseMethod(A,"MatNestGetSubMats_C",(Mat,PetscInt*,PetscInt*,Mat***),(A,M,N,mat));CHKERRQ(ierr);
954d8588912SDave May   PetscFunctionReturn(0);
955d8588912SDave May }
956d8588912SDave May 
957d8588912SDave May EXTERN_C_BEGIN
958d8588912SDave May #undef __FUNCT__
959d8588912SDave May #define __FUNCT__ "MatNestGetSize_Nest"
9607087cfbeSBarry Smith PetscErrorCode  MatNestGetSize_Nest(Mat A,PetscInt *M,PetscInt *N)
961d8588912SDave May {
962d8588912SDave May   Mat_Nest  *bA = (Mat_Nest*)A->data;
963d8588912SDave May 
964d8588912SDave May   PetscFunctionBegin;
965d8588912SDave May   if (M) { *M  = bA->nr; }
966d8588912SDave May   if (N) { *N  = bA->nc; }
967d8588912SDave May   PetscFunctionReturn(0);
968d8588912SDave May }
969d8588912SDave May EXTERN_C_END
970d8588912SDave May 
971d8588912SDave May #undef __FUNCT__
972d8588912SDave May #define __FUNCT__ "MatNestGetSize"
973d8588912SDave May /*@C
974d8588912SDave May  MatNestGetSize - Returns the size of the nest matrix.
975d8588912SDave May 
976d8588912SDave May  Not collective
977d8588912SDave May 
978d8588912SDave May  Input Parameters:
979d8588912SDave May .   A  - nest matrix
980d8588912SDave May 
981d8588912SDave May  Output Parameter:
982629881c0SJed Brown +   M - number of rows in the nested mat
983629881c0SJed Brown -   N - number of cols in the nested mat
984d8588912SDave May 
985d8588912SDave May  Notes:
986d8588912SDave May 
987d8588912SDave May  Level: developer
988d8588912SDave May 
989d8588912SDave May .seealso: MatNestGetSubMat(), MatNestGetSubMats()
990d8588912SDave May @*/
9917087cfbeSBarry Smith PetscErrorCode  MatNestGetSize(Mat A,PetscInt *M,PetscInt *N)
992d8588912SDave May {
993699a902aSJed Brown   PetscErrorCode ierr;
994d8588912SDave May 
995d8588912SDave May   PetscFunctionBegin;
996699a902aSJed Brown   ierr = PetscUseMethod(A,"MatNestGetSize_C",(Mat,PetscInt*,PetscInt*),(A,M,N));CHKERRQ(ierr);
997d8588912SDave May   PetscFunctionReturn(0);
998d8588912SDave May }
999d8588912SDave May 
1000207556f9SJed Brown EXTERN_C_BEGIN
1001207556f9SJed Brown #undef __FUNCT__
1002207556f9SJed Brown #define __FUNCT__ "MatNestSetVecType_Nest"
10037087cfbeSBarry Smith PetscErrorCode  MatNestSetVecType_Nest(Mat A,const VecType vtype)
1004207556f9SJed Brown {
1005207556f9SJed Brown   PetscErrorCode ierr;
1006207556f9SJed Brown   PetscBool      flg;
1007207556f9SJed Brown 
1008207556f9SJed Brown   PetscFunctionBegin;
1009207556f9SJed Brown   ierr = PetscStrcmp(vtype,VECNEST,&flg);CHKERRQ(ierr);
1010207556f9SJed Brown   /* In reality, this only distinguishes VECNEST and "other" */
1011207556f9SJed Brown   A->ops->getvecs       = flg ? MatGetVecs_Nest       : 0;
10127874fa86SDave May   A->ops->getdiagonal   = flg ? MatGetDiagonal_Nest   : 0;
10137874fa86SDave May   A->ops->diagonalscale = flg ? MatDiagonalScale_Nest : 0;
10147874fa86SDave May 
1015207556f9SJed Brown  PetscFunctionReturn(0);
1016207556f9SJed Brown }
1017207556f9SJed Brown EXTERN_C_END
1018207556f9SJed Brown 
1019207556f9SJed Brown #undef __FUNCT__
1020207556f9SJed Brown #define __FUNCT__ "MatNestSetVecType"
1021207556f9SJed Brown /*@C
1022207556f9SJed Brown  MatNestSetVecType - Sets the type of Vec returned by MatGetVecs()
1023207556f9SJed Brown 
1024207556f9SJed Brown  Not collective
1025207556f9SJed Brown 
1026207556f9SJed Brown  Input Parameters:
1027207556f9SJed Brown +  A  - nest matrix
1028207556f9SJed Brown -  vtype - type to use for creating vectors
1029207556f9SJed Brown 
1030207556f9SJed Brown  Notes:
1031207556f9SJed Brown 
1032207556f9SJed Brown  Level: developer
1033207556f9SJed Brown 
1034207556f9SJed Brown .seealso: MatGetVecs()
1035207556f9SJed Brown @*/
10367087cfbeSBarry Smith PetscErrorCode  MatNestSetVecType(Mat A,const VecType vtype)
1037207556f9SJed Brown {
1038207556f9SJed Brown   PetscErrorCode ierr;
1039207556f9SJed Brown 
1040207556f9SJed Brown   PetscFunctionBegin;
1041207556f9SJed Brown   ierr = PetscTryMethod(A,"MatNestSetVecType_C",(Mat,const VecType),(A,vtype));CHKERRQ(ierr);
1042207556f9SJed Brown   PetscFunctionReturn(0);
1043207556f9SJed Brown }
1044207556f9SJed Brown 
1045c8883902SJed Brown EXTERN_C_BEGIN
1046d8588912SDave May #undef __FUNCT__
1047c8883902SJed Brown #define __FUNCT__ "MatNestSetSubMats_Nest"
1048c8883902SJed Brown PetscErrorCode MatNestSetSubMats_Nest(Mat A,PetscInt nr,const IS is_row[],PetscInt nc,const IS is_col[],const Mat a[])
1049d8588912SDave May {
1050c8883902SJed Brown   Mat_Nest       *s = (Mat_Nest*)A->data;
1051c8883902SJed Brown   PetscInt       i,j,m,n,M,N;
1052d8588912SDave May   PetscErrorCode ierr;
1053d8588912SDave May 
1054d8588912SDave May   PetscFunctionBegin;
1055c8883902SJed Brown   s->nr = nr;
1056c8883902SJed Brown   s->nc = nc;
1057d8588912SDave May 
1058c8883902SJed Brown   /* Create space for submatrices */
1059c8883902SJed Brown   ierr = PetscMalloc(sizeof(Mat*)*nr,&s->m);CHKERRQ(ierr);
1060c8883902SJed Brown   for (i=0; i<nr; i++) {
1061c8883902SJed Brown     ierr = PetscMalloc(sizeof(Mat)*nc,&s->m[i]);CHKERRQ(ierr);
1062d8588912SDave May   }
1063c8883902SJed Brown   for (i=0; i<nr; i++) {
1064c8883902SJed Brown     for (j=0; j<nc; j++) {
1065c8883902SJed Brown       s->m[i][j] = a[i*nc+j];
1066c8883902SJed Brown       if (a[i*nc+j]) {
1067c8883902SJed Brown         ierr = PetscObjectReference((PetscObject)a[i*nc+j]);CHKERRQ(ierr);
1068d8588912SDave May       }
1069d8588912SDave May     }
1070d8588912SDave May   }
1071d8588912SDave May 
10728188e55aSJed Brown   ierr = MatSetUp_NestIS_Private(A,nr,is_row,nc,is_col);CHKERRQ(ierr);
1073d8588912SDave May 
1074c8883902SJed Brown   ierr = PetscMalloc(sizeof(PetscInt)*nr,&s->row_len);CHKERRQ(ierr);
1075c8883902SJed Brown   ierr = PetscMalloc(sizeof(PetscInt)*nc,&s->col_len);CHKERRQ(ierr);
1076c8883902SJed Brown   for (i=0; i<nr; i++) s->row_len[i]=-1;
1077c8883902SJed Brown   for (j=0; j<nc; j++) s->col_len[j]=-1;
1078d8588912SDave May 
10798188e55aSJed Brown   ierr = MatNestGetSizes_Private(A,&m,&n,&M,&N);CHKERRQ(ierr);
1080d8588912SDave May 
1081c8883902SJed Brown   ierr = PetscLayoutSetSize(A->rmap,M);CHKERRQ(ierr);
1082c8883902SJed Brown   ierr = PetscLayoutSetLocalSize(A->rmap,m);CHKERRQ(ierr);
1083c8883902SJed Brown   ierr = PetscLayoutSetBlockSize(A->rmap,1);CHKERRQ(ierr);
1084c8883902SJed Brown   ierr = PetscLayoutSetSize(A->cmap,N);CHKERRQ(ierr);
1085c8883902SJed Brown   ierr = PetscLayoutSetLocalSize(A->cmap,n);CHKERRQ(ierr);
1086c8883902SJed Brown   ierr = PetscLayoutSetBlockSize(A->cmap,1);CHKERRQ(ierr);
1087c8883902SJed Brown 
1088c8883902SJed Brown   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
1089c8883902SJed Brown   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
1090c8883902SJed Brown 
1091c8883902SJed Brown   ierr = PetscMalloc2(nr,Vec,&s->left,nc,Vec,&s->right);CHKERRQ(ierr);
1092c8883902SJed Brown   ierr = PetscMemzero(s->left,nr*sizeof(Vec));CHKERRQ(ierr);
1093c8883902SJed Brown   ierr = PetscMemzero(s->right,nc*sizeof(Vec));CHKERRQ(ierr);
1094d8588912SDave May   PetscFunctionReturn(0);
1095d8588912SDave May }
1096c8883902SJed Brown EXTERN_C_END
1097d8588912SDave May 
1098c8883902SJed Brown #undef __FUNCT__
1099c8883902SJed Brown #define __FUNCT__ "MatNestSetSubMats"
1100c8883902SJed Brown /*@
1101c8883902SJed Brown    MatNestSetSubMats - Sets the nested submatrices
1102c8883902SJed Brown 
1103c8883902SJed Brown    Collective on Mat
1104c8883902SJed Brown 
1105c8883902SJed Brown    Input Parameter:
1106c8883902SJed Brown +  N - nested matrix
1107c8883902SJed Brown .  nr - number of nested row blocks
1108c8883902SJed Brown .  is_row - index sets for each nested row block, or PETSC_NULL to make contiguous
1109c8883902SJed Brown .  nc - number of nested column blocks
1110c8883902SJed Brown .  is_col - index sets for each nested column block, or PETSC_NULL to make contiguous
1111c8883902SJed Brown -  a - row-aligned array of nr*nc submatrices, empty submatrices can be passed using PETSC_NULL
1112c8883902SJed Brown 
1113c8883902SJed Brown    Level: advanced
1114c8883902SJed Brown 
1115c8883902SJed Brown .seealso: MatCreateNest(), MATNEST
1116c8883902SJed Brown @*/
1117c8883902SJed Brown PetscErrorCode MatNestSetSubMats(Mat A,PetscInt nr,const IS is_row[],PetscInt nc,const IS is_col[],const Mat a[])
1118c8883902SJed Brown {
1119c8883902SJed Brown   PetscErrorCode ierr;
1120c8883902SJed Brown   PetscInt i;
1121c8883902SJed Brown 
1122c8883902SJed Brown   PetscFunctionBegin;
1123c8883902SJed Brown   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
1124c8883902SJed Brown   if (nr < 0) SETERRQ(((PetscObject)A)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Number of rows cannot be negative");
1125c8883902SJed Brown   if (nr && is_row) {
1126c8883902SJed Brown     PetscValidPointer(is_row,3);
1127c8883902SJed Brown     for (i=0; i<nr; i++) PetscValidHeaderSpecific(is_row[i],IS_CLASSID,3);
1128c8883902SJed Brown   }
1129c8883902SJed Brown   if (nc < 0) SETERRQ(((PetscObject)A)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Number of columns cannot be negative");
11301664e352SJed Brown   if (nc && is_col) {
1131c8883902SJed Brown     PetscValidPointer(is_col,5);
1132c8883902SJed Brown     for (i=0; i<nr; i++) PetscValidHeaderSpecific(is_col[i],IS_CLASSID,5);
1133c8883902SJed Brown   }
1134c8883902SJed Brown   if (nr*nc) PetscValidPointer(a,6);
1135c8883902SJed 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);
1136c8883902SJed Brown   PetscFunctionReturn(0);
1137c8883902SJed Brown }
1138d8588912SDave May 
1139d8588912SDave May /* If an IS was provided, there is nothing Nest needs to do, otherwise Nest will build a strided IS */
1140d8588912SDave May /*
1141d8588912SDave May   nprocessors = NP
1142d8588912SDave May   Nest x^T = ( (g_0,g_1,...g_nprocs-1), (h_0,h_1,...h_NP-1) )
1143d8588912SDave May        proc 0: => (g_0,h_0,)
1144d8588912SDave May        proc 1: => (g_1,h_1,)
1145d8588912SDave May        ...
1146d8588912SDave May        proc nprocs-1: => (g_NP-1,h_NP-1,)
1147d8588912SDave May 
1148d8588912SDave May             proc 0:                      proc 1:                    proc nprocs-1:
1149d8588912SDave May     is[0] = ( 0,1,2,...,nlocal(g_0)-1 )  ( 0,1,...,nlocal(g_1)-1 )  ( 0,1,...,nlocal(g_NP-1) )
1150d8588912SDave May 
1151d8588912SDave May             proc 0:
1152d8588912SDave May     is[1] = ( nlocal(g_0),nlocal(g_0)+1,...,nlocal(g_0)+nlocal(h_0)-1 )
1153d8588912SDave May             proc 1:
1154d8588912SDave May     is[1] = ( nlocal(g_1),nlocal(g_1)+1,...,nlocal(g_1)+nlocal(h_1)-1 )
1155d8588912SDave May 
1156d8588912SDave May             proc NP-1:
1157d8588912SDave May     is[1] = ( nlocal(g_NP-1),nlocal(g_NP-1)+1,...,nlocal(g_NP-1)+nlocal(h_NP-1)-1 )
1158d8588912SDave May */
1159d8588912SDave May #undef __FUNCT__
1160d8588912SDave May #define __FUNCT__ "MatSetUp_NestIS_Private"
1161841e96a3SJed Brown static PetscErrorCode MatSetUp_NestIS_Private(Mat A,PetscInt nr,const IS is_row[],PetscInt nc,const IS is_col[])
1162d8588912SDave May {
1163e2d7f03fSJed Brown   Mat_Nest       *vs = (Mat_Nest*)A->data;
11648188e55aSJed Brown   PetscInt       i,j,offset,n,nsum,bs;
1165d8588912SDave May   PetscErrorCode ierr;
11662ae74bdbSJed Brown   Mat            sub;
1167d8588912SDave May 
1168d8588912SDave May   PetscFunctionBegin;
11698188e55aSJed Brown   ierr = PetscMalloc(sizeof(IS)*nr,&vs->isglobal.row);CHKERRQ(ierr);
11708188e55aSJed Brown   ierr = PetscMalloc(sizeof(IS)*nc,&vs->isglobal.col);CHKERRQ(ierr);
1171d8588912SDave May   if (is_row) { /* valid IS is passed in */
1172d8588912SDave May     /* refs on is[] are incremeneted */
1173e2d7f03fSJed Brown     for (i=0; i<vs->nr; i++) {
1174d8588912SDave May       ierr = PetscObjectReference((PetscObject)is_row[i]);CHKERRQ(ierr);
1175e2d7f03fSJed Brown       vs->isglobal.row[i] = is_row[i];
1176d8588912SDave May     }
11772ae74bdbSJed Brown   } else {                      /* Create the ISs by inspecting sizes of a submatrix in each row */
11788188e55aSJed Brown     nsum = 0;
11798188e55aSJed Brown     for (i=0; i<vs->nr; i++) {  /* Add up the local sizes to compute the aggregate offset */
11808188e55aSJed Brown       ierr = MatNestFindNonzeroSubMatRow(A,i,&sub);CHKERRQ(ierr);
11818188e55aSJed Brown       if (!sub) SETERRQ1(((PetscObject)A)->comm,PETSC_ERR_ARG_WRONG,"No nonzero submatrix in row %D",i);
11828188e55aSJed Brown       ierr = MatGetLocalSize(sub,&n,PETSC_NULL);CHKERRQ(ierr);
11838188e55aSJed Brown       if (n < 0) SETERRQ(((PetscObject)A)->comm,PETSC_ERR_ARG_WRONGSTATE,"Sizes have not yet been set for submatrix");
11848188e55aSJed Brown       nsum += n;
11858188e55aSJed Brown     }
11868188e55aSJed Brown     offset = 0;
11878188e55aSJed Brown     ierr = MPI_Exscan(&nsum,&offset,1,MPIU_INT,MPI_SUM,((PetscObject)A)->comm);CHKERRQ(ierr);
1188e2d7f03fSJed Brown     for (i=0; i<vs->nr; i++) {
1189f349c1fdSJed Brown       ierr = MatNestFindNonzeroSubMatRow(A,i,&sub);CHKERRQ(ierr);
11902ae74bdbSJed Brown       ierr = MatGetLocalSize(sub,&n,PETSC_NULL);CHKERRQ(ierr);
11912ae74bdbSJed Brown       ierr = MatGetBlockSize(sub,&bs);CHKERRQ(ierr);
1192e2d7f03fSJed Brown       ierr = ISCreateStride(((PetscObject)sub)->comm,n,offset,1,&vs->isglobal.row[i]);CHKERRQ(ierr);
1193e2d7f03fSJed Brown       ierr = ISSetBlockSize(vs->isglobal.row[i],bs);CHKERRQ(ierr);
11942ae74bdbSJed Brown       offset += n;
1195d8588912SDave May     }
1196d8588912SDave May   }
1197d8588912SDave May 
1198d8588912SDave May   if (is_col) { /* valid IS is passed in */
1199d8588912SDave May     /* refs on is[] are incremeneted */
1200e2d7f03fSJed Brown     for (j=0; j<vs->nc; j++) {
1201d8588912SDave May       ierr = PetscObjectReference((PetscObject)is_col[j]);CHKERRQ(ierr);
1202e2d7f03fSJed Brown       vs->isglobal.col[j] = is_col[j];
1203d8588912SDave May     }
12042ae74bdbSJed Brown   } else {                      /* Create the ISs by inspecting sizes of a submatrix in each column */
12052ae74bdbSJed Brown     offset = A->cmap->rstart;
12068188e55aSJed Brown     nsum = 0;
12078188e55aSJed Brown     for (j=0; j<vs->nc; j++) {
12088188e55aSJed Brown       ierr = MatNestFindNonzeroSubMatCol(A,j,&sub);CHKERRQ(ierr);
12098188e55aSJed Brown       if (!sub) SETERRQ1(((PetscObject)A)->comm,PETSC_ERR_ARG_WRONG,"No nonzero submatrix in column %D",i);
12108188e55aSJed Brown       ierr = MatGetLocalSize(sub,PETSC_NULL,&n);CHKERRQ(ierr);
12118188e55aSJed Brown       if (n < 0) SETERRQ(((PetscObject)A)->comm,PETSC_ERR_ARG_WRONGSTATE,"Sizes have not yet been set for submatrix");
12128188e55aSJed Brown       nsum += n;
12138188e55aSJed Brown     }
12148188e55aSJed Brown     offset = 0;
12158188e55aSJed Brown     ierr = MPI_Exscan(&nsum,&offset,1,MPIU_INT,MPI_SUM,((PetscObject)A)->comm);CHKERRQ(ierr);
1216e2d7f03fSJed Brown     for (j=0; j<vs->nc; j++) {
1217f349c1fdSJed Brown       ierr = MatNestFindNonzeroSubMatCol(A,j,&sub);CHKERRQ(ierr);
12182ae74bdbSJed Brown       ierr = MatGetLocalSize(sub,PETSC_NULL,&n);CHKERRQ(ierr);
12192ae74bdbSJed Brown       ierr = MatGetBlockSize(sub,&bs);CHKERRQ(ierr);
1220e2d7f03fSJed Brown       ierr = ISCreateStride(((PetscObject)sub)->comm,n,offset,1,&vs->isglobal.col[j]);CHKERRQ(ierr);
1221e2d7f03fSJed Brown       ierr = ISSetBlockSize(vs->isglobal.col[j],bs);CHKERRQ(ierr);
12222ae74bdbSJed Brown       offset += n;
1223d8588912SDave May     }
1224d8588912SDave May   }
1225e2d7f03fSJed Brown 
1226e2d7f03fSJed Brown   /* Set up the local ISs */
1227e2d7f03fSJed Brown   ierr = PetscMalloc(vs->nr*sizeof(IS),&vs->islocal.row);CHKERRQ(ierr);
1228e2d7f03fSJed Brown   ierr = PetscMalloc(vs->nc*sizeof(IS),&vs->islocal.col);CHKERRQ(ierr);
1229e2d7f03fSJed Brown   for (i=0,offset=0; i<vs->nr; i++) {
1230e2d7f03fSJed Brown     IS                     isloc;
12318188e55aSJed Brown     ISLocalToGlobalMapping rmap = PETSC_NULL;
1232e2d7f03fSJed Brown     PetscInt               nlocal,bs;
1233e2d7f03fSJed Brown     ierr = MatNestFindNonzeroSubMatRow(A,i,&sub);CHKERRQ(ierr);
12348188e55aSJed Brown     if (sub) {ierr = MatGetLocalToGlobalMapping(sub,&rmap,PETSC_NULL);CHKERRQ(ierr);}
1235207556f9SJed Brown     if (rmap) {
1236e2d7f03fSJed Brown       ierr = MatGetBlockSize(sub,&bs);CHKERRQ(ierr);
1237e2d7f03fSJed Brown       ierr = ISLocalToGlobalMappingGetSize(rmap,&nlocal);CHKERRQ(ierr);
1238e2d7f03fSJed Brown       ierr = ISCreateStride(PETSC_COMM_SELF,nlocal,offset,1,&isloc);CHKERRQ(ierr);
1239e2d7f03fSJed Brown       ierr = ISSetBlockSize(isloc,bs);CHKERRQ(ierr);
1240207556f9SJed Brown     } else {
1241207556f9SJed Brown       nlocal = 0;
1242207556f9SJed Brown       isloc  = PETSC_NULL;
1243207556f9SJed Brown     }
1244e2d7f03fSJed Brown     vs->islocal.row[i] = isloc;
1245e2d7f03fSJed Brown     offset += nlocal;
1246e2d7f03fSJed Brown   }
12478188e55aSJed Brown   for (i=0,offset=0; i<vs->nc; i++) {
1248e2d7f03fSJed Brown     IS                     isloc;
12498188e55aSJed Brown     ISLocalToGlobalMapping cmap = PETSC_NULL;
1250e2d7f03fSJed Brown     PetscInt               nlocal,bs;
1251e2d7f03fSJed Brown     ierr = MatNestFindNonzeroSubMatCol(A,i,&sub);CHKERRQ(ierr);
12528188e55aSJed Brown     if (sub) {ierr = MatGetLocalToGlobalMapping(sub,PETSC_NULL,&cmap);CHKERRQ(ierr);}
1253207556f9SJed Brown     if (cmap) {
1254e2d7f03fSJed Brown       ierr = MatGetBlockSize(sub,&bs);CHKERRQ(ierr);
1255e2d7f03fSJed Brown       ierr = ISLocalToGlobalMappingGetSize(cmap,&nlocal);CHKERRQ(ierr);
1256e2d7f03fSJed Brown       ierr = ISCreateStride(PETSC_COMM_SELF,nlocal,offset,1,&isloc);CHKERRQ(ierr);
1257e2d7f03fSJed Brown       ierr = ISSetBlockSize(isloc,bs);CHKERRQ(ierr);
1258207556f9SJed Brown     } else {
1259207556f9SJed Brown       nlocal = 0;
1260207556f9SJed Brown       isloc  = PETSC_NULL;
1261207556f9SJed Brown     }
1262e2d7f03fSJed Brown     vs->islocal.col[i] = isloc;
1263e2d7f03fSJed Brown     offset += nlocal;
1264e2d7f03fSJed Brown   }
12650189643fSJed Brown 
12660189643fSJed Brown #if defined(PETSC_USE_DEBUG)
12670189643fSJed Brown   for (i=0; i<vs->nr; i++) {
12680189643fSJed Brown     for (j=0; j<vs->nc; j++) {
12690189643fSJed Brown       PetscInt m,n,M,N,mi,ni,Mi,Ni;
12700189643fSJed Brown       Mat B = vs->m[i][j];
12710189643fSJed Brown       if (!B) continue;
12720189643fSJed Brown       ierr = MatGetSize(B,&M,&N);CHKERRQ(ierr);
12730189643fSJed Brown       ierr = MatGetLocalSize(B,&m,&n);CHKERRQ(ierr);
12740189643fSJed Brown       ierr = ISGetSize(vs->isglobal.row[i],&Mi);CHKERRQ(ierr);
12750189643fSJed Brown       ierr = ISGetSize(vs->isglobal.col[j],&Ni);CHKERRQ(ierr);
12760189643fSJed Brown       ierr = ISGetLocalSize(vs->isglobal.row[i],&mi);CHKERRQ(ierr);
12770189643fSJed Brown       ierr = ISGetLocalSize(vs->isglobal.col[j],&ni);CHKERRQ(ierr);
12780189643fSJed 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);
12790189643fSJed 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);
12800189643fSJed Brown     }
12810189643fSJed Brown   }
12820189643fSJed Brown #endif
1283d8588912SDave May   PetscFunctionReturn(0);
1284d8588912SDave May }
1285d8588912SDave May 
1286d8588912SDave May #undef __FUNCT__
1287d8588912SDave May #define __FUNCT__ "MatCreateNest"
1288659c6bb0SJed Brown /*@
1289659c6bb0SJed Brown    MatCreateNest - Creates a new matrix containing several nested submatrices, each stored separately
1290659c6bb0SJed Brown 
1291659c6bb0SJed Brown    Collective on Mat
1292659c6bb0SJed Brown 
1293659c6bb0SJed Brown    Input Parameter:
1294659c6bb0SJed Brown +  comm - Communicator for the new Mat
1295659c6bb0SJed Brown .  nr - number of nested row blocks
1296659c6bb0SJed Brown .  is_row - index sets for each nested row block, or PETSC_NULL to make contiguous
1297659c6bb0SJed Brown .  nc - number of nested column blocks
1298659c6bb0SJed Brown .  is_col - index sets for each nested column block, or PETSC_NULL to make contiguous
1299659c6bb0SJed Brown -  a - row-aligned array of nr*nc submatrices, empty submatrices can be passed using PETSC_NULL
1300659c6bb0SJed Brown 
1301659c6bb0SJed Brown    Output Parameter:
1302659c6bb0SJed Brown .  B - new matrix
1303659c6bb0SJed Brown 
1304659c6bb0SJed Brown    Level: advanced
1305659c6bb0SJed Brown 
1306659c6bb0SJed Brown .seealso: MatCreate(), VecCreateNest(), DMGetMatrix(), MATNEST
1307659c6bb0SJed Brown @*/
13087087cfbeSBarry Smith PetscErrorCode MatCreateNest(MPI_Comm comm,PetscInt nr,const IS is_row[],PetscInt nc,const IS is_col[],const Mat a[],Mat *B)
1309d8588912SDave May {
1310d8588912SDave May   Mat            A;
1311d8588912SDave May   PetscErrorCode ierr;
1312d8588912SDave May 
1313d8588912SDave May   PetscFunctionBegin;
1314c8883902SJed Brown   *B = 0;
1315d8588912SDave May   ierr = MatCreate(comm,&A);CHKERRQ(ierr);
1316c8883902SJed Brown   ierr = MatSetType(A,MATNEST);CHKERRQ(ierr);
1317c8883902SJed Brown   ierr = MatNestSetSubMats(A,nr,is_row,nc,is_col,a);CHKERRQ(ierr);
1318d8588912SDave May   *B = A;
1319d8588912SDave May   PetscFunctionReturn(0);
1320d8588912SDave May }
1321659c6bb0SJed Brown 
1322659c6bb0SJed Brown /*MC
1323659c6bb0SJed Brown   MATNEST - MATNEST = "nest" - Matrix type consisting of nested submatrices, each stored separately.
1324659c6bb0SJed Brown 
1325659c6bb0SJed Brown   Level: intermediate
1326659c6bb0SJed Brown 
1327659c6bb0SJed Brown   Notes:
1328659c6bb0SJed Brown   This matrix type permits scalable use of PCFieldSplit and avoids the large memory costs of extracting submatrices.
1329659c6bb0SJed Brown   It allows the use of symmetric and block formats for parts of multi-physics simulations.
1330659c6bb0SJed Brown   It is usually used with DMComposite and DMGetMatrix()
1331659c6bb0SJed Brown 
1332659c6bb0SJed Brown .seealso: MatCreate(), MatType, MatCreateNest()
1333659c6bb0SJed Brown M*/
1334c8883902SJed Brown EXTERN_C_BEGIN
1335c8883902SJed Brown #undef __FUNCT__
1336c8883902SJed Brown #define __FUNCT__ "MatCreate_Nest"
1337c8883902SJed Brown PetscErrorCode MatCreate_Nest(Mat A)
1338c8883902SJed Brown {
1339c8883902SJed Brown   Mat_Nest       *s;
1340c8883902SJed Brown   PetscErrorCode ierr;
1341c8883902SJed Brown 
1342c8883902SJed Brown   PetscFunctionBegin;
1343c8883902SJed Brown   ierr = PetscNewLog(A,Mat_Nest,&s);CHKERRQ(ierr);
1344c8883902SJed Brown   A->data         = (void*)s;
1345c8883902SJed Brown   s->nr = s->nc   = -1;
1346c8883902SJed Brown   s->m            = PETSC_NULL;
1347c8883902SJed Brown 
1348c8883902SJed Brown   ierr = PetscMemzero(A->ops,sizeof(*A->ops));CHKERRQ(ierr);
1349c8883902SJed Brown   A->ops->mult                  = MatMult_Nest;
13509194d70fSJed Brown   A->ops->multadd               = MatMultAdd_Nest;
1351c8883902SJed Brown   A->ops->multtranspose         = MatMultTranspose_Nest;
13529194d70fSJed Brown   A->ops->multtransposeadd      = MatMultTransposeAdd_Nest;
1353c8883902SJed Brown   A->ops->assemblybegin         = MatAssemblyBegin_Nest;
1354c8883902SJed Brown   A->ops->assemblyend           = MatAssemblyEnd_Nest;
1355c8883902SJed Brown   A->ops->zeroentries           = MatZeroEntries_Nest;
1356c8883902SJed Brown   A->ops->duplicate             = MatDuplicate_Nest;
1357c8883902SJed Brown   A->ops->getsubmatrix          = MatGetSubMatrix_Nest;
1358c8883902SJed Brown   A->ops->destroy               = MatDestroy_Nest;
1359c8883902SJed Brown   A->ops->view                  = MatView_Nest;
1360c8883902SJed Brown   A->ops->getvecs               = 0; /* Use VECNEST by calling MatNestSetVecType(A,VECNEST) */
1361c8883902SJed Brown   A->ops->getlocalsubmatrix     = MatGetLocalSubMatrix_Nest;
1362c8883902SJed Brown   A->ops->restorelocalsubmatrix = MatRestoreLocalSubMatrix_Nest;
13637874fa86SDave May   A->ops->getdiagonal           = MatGetDiagonal_Nest2; /* VECNEST version activated by calling MatNestSetVecType(A,VECNEST) */
13647874fa86SDave May   A->ops->diagonalscale         = MatDiagonalScale_Nest2; /* VECNEST version activated by calling MatNestSetVecType(A,VECNEST) */
1365c8883902SJed Brown 
1366c8883902SJed Brown   A->spptr        = 0;
1367c8883902SJed Brown   A->same_nonzero = PETSC_FALSE;
1368c8883902SJed Brown   A->assembled    = PETSC_FALSE;
1369c8883902SJed Brown 
1370c8883902SJed Brown   /* expose Nest api's */
1371c8883902SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatNestGetSubMat_C",   "MatNestGetSubMat_Nest",   MatNestGetSubMat_Nest);CHKERRQ(ierr);
13720782ca92SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatNestSetSubMat_C",   "MatNestSetSubMat_Nest",   MatNestSetSubMat_Nest);CHKERRQ(ierr);
1373c8883902SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatNestGetSubMats_C",  "MatNestGetSubMats_Nest",  MatNestGetSubMats_Nest);CHKERRQ(ierr);
1374c8883902SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatNestGetSize_C",     "MatNestGetSize_Nest",     MatNestGetSize_Nest);CHKERRQ(ierr);
1375c8883902SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatNestSetVecType_C",  "MatNestSetVecType_Nest",  MatNestSetVecType_Nest);CHKERRQ(ierr);
1376c8883902SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatNestSetSubMats_C",  "MatNestSetSubMats_Nest",  MatNestSetSubMats_Nest);CHKERRQ(ierr);
1377c8883902SJed Brown 
1378c8883902SJed Brown   ierr = PetscObjectChangeTypeName((PetscObject)A,MATNEST);CHKERRQ(ierr);
1379c8883902SJed Brown   PetscFunctionReturn(0);
1380c8883902SJed Brown }
138186e80854SHong Zhang EXTERN_C_END
1382