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