xref: /petsc/src/ksp/pc/impls/bjacobi/bjacobi.c (revision fd7f7f7bf61ab351e0bc47bc8ec8a32e327db9eb)
1 
2 /*
3    Defines a block Jacobi preconditioner.
4 */
5 
6 #include <../src/ksp/pc/impls/bjacobi/bjacobi.h> /*I "petscpc.h" I*/
7 
8 static PetscErrorCode PCSetUp_BJacobi_Singleblock(PC,Mat,Mat);
9 static PetscErrorCode PCSetUp_BJacobi_Multiblock(PC,Mat,Mat);
10 static PetscErrorCode PCSetUp_BJacobi_Multiproc(PC);
11 
12 #undef __FUNCT__
13 #define __FUNCT__ "PCSetUp_BJacobi"
14 static PetscErrorCode PCSetUp_BJacobi(PC pc)
15 {
16   PC_BJacobi     *jac = (PC_BJacobi*)pc->data;
17   Mat            mat  = pc->mat,pmat = pc->pmat;
18   PetscErrorCode ierr,(*f)(Mat,Mat*);
19   PetscInt       N,M,start,i,sum,end;
20   PetscInt       bs,i_start=-1,i_end=-1;
21   PetscMPIInt    rank,size;
22   const char     *pprefix,*mprefix;
23 
24   PetscFunctionBegin;
25   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
26   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
27   ierr = MatGetLocalSize(pc->pmat,&M,&N);CHKERRQ(ierr);
28   ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr);
29 
30   if (jac->n > 0 && jac->n < size) {
31     ierr = PCSetUp_BJacobi_Multiproc(pc);CHKERRQ(ierr);
32     PetscFunctionReturn(0);
33   }
34 
35   /* --------------------------------------------------------------------------
36       Determines the number of blocks assigned to each processor
37   -----------------------------------------------------------------------------*/
38 
39   /*   local block count  given */
40   if (jac->n_local > 0 && jac->n < 0) {
41     ierr = MPIU_Allreduce(&jac->n_local,&jac->n,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
42     if (jac->l_lens) { /* check that user set these correctly */
43       sum = 0;
44       for (i=0; i<jac->n_local; i++) {
45         if (jac->l_lens[i]/bs*bs !=jac->l_lens[i]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat blocksize doesn't match block Jacobi layout");
46         sum += jac->l_lens[i];
47       }
48       if (sum != M) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local lens set incorrectly");
49     } else {
50       ierr = PetscMalloc1(jac->n_local,&jac->l_lens);CHKERRQ(ierr);
51       for (i=0; i<jac->n_local; i++) jac->l_lens[i] = bs*((M/bs)/jac->n_local + (((M/bs) % jac->n_local) > i));
52     }
53   } else if (jac->n > 0 && jac->n_local < 0) { /* global block count given */
54     /* global blocks given: determine which ones are local */
55     if (jac->g_lens) {
56       /* check if the g_lens is has valid entries */
57       for (i=0; i<jac->n; i++) {
58         if (!jac->g_lens[i]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Zero block not allowed");
59         if (jac->g_lens[i]/bs*bs != jac->g_lens[i]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat blocksize doesn't match block Jacobi layout");
60       }
61       if (size == 1) {
62         jac->n_local = jac->n;
63         ierr         = PetscMalloc1(jac->n_local,&jac->l_lens);CHKERRQ(ierr);
64         ierr         = PetscMemcpy(jac->l_lens,jac->g_lens,jac->n_local*sizeof(PetscInt));CHKERRQ(ierr);
65         /* check that user set these correctly */
66         sum = 0;
67         for (i=0; i<jac->n_local; i++) sum += jac->l_lens[i];
68         if (sum != M) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Global lens set incorrectly");
69       } else {
70         ierr = MatGetOwnershipRange(pc->pmat,&start,&end);CHKERRQ(ierr);
71         /* loop over blocks determing first one owned by me */
72         sum = 0;
73         for (i=0; i<jac->n+1; i++) {
74           if (sum == start) { i_start = i; goto start_1;}
75           if (i < jac->n) sum += jac->g_lens[i];
76         }
77         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Block sizes used in PCBJacobiSetTotalBlocks()\nare not compatible with parallel matrix layout");
78 start_1:
79         for (i=i_start; i<jac->n+1; i++) {
80           if (sum == end) { i_end = i; goto end_1; }
81           if (i < jac->n) sum += jac->g_lens[i];
82         }
83         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Block sizes used in PCBJacobiSetTotalBlocks()\nare not compatible with parallel matrix layout");
84 end_1:
85         jac->n_local = i_end - i_start;
86         ierr         = PetscMalloc1(jac->n_local,&jac->l_lens);CHKERRQ(ierr);
87         ierr         = PetscMemcpy(jac->l_lens,jac->g_lens+i_start,jac->n_local*sizeof(PetscInt));CHKERRQ(ierr);
88       }
89     } else { /* no global blocks given, determine then using default layout */
90       jac->n_local = jac->n/size + ((jac->n % size) > rank);
91       ierr         = PetscMalloc1(jac->n_local,&jac->l_lens);CHKERRQ(ierr);
92       for (i=0; i<jac->n_local; i++) {
93         jac->l_lens[i] = ((M/bs)/jac->n_local + (((M/bs) % jac->n_local) > i))*bs;
94         if (!jac->l_lens[i]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Too many blocks given");
95       }
96     }
97   } else if (jac->n < 0 && jac->n_local < 0) { /* no blocks given */
98     jac->n         = size;
99     jac->n_local   = 1;
100     ierr           = PetscMalloc1(1,&jac->l_lens);CHKERRQ(ierr);
101     jac->l_lens[0] = M;
102   } else { /* jac->n > 0 && jac->n_local > 0 */
103     if (!jac->l_lens) {
104       ierr = PetscMalloc1(jac->n_local,&jac->l_lens);CHKERRQ(ierr);
105       for (i=0; i<jac->n_local; i++) jac->l_lens[i] = bs*((M/bs)/jac->n_local + (((M/bs) % jac->n_local) > i));
106     }
107   }
108   if (jac->n_local < 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Number of blocks is less than number of processors");
109 
110   /* -------------------------
111       Determines mat and pmat
112   ---------------------------*/
113   ierr = PetscObjectQueryFunction((PetscObject)pc->mat,"MatGetDiagonalBlock_C",&f);CHKERRQ(ierr);
114   if (!f && size == 1) {
115     mat  = pc->mat;
116     pmat = pc->pmat;
117   } else {
118     if (pc->useAmat) {
119       /* use block from Amat matrix, not Pmat for local MatMult() */
120       ierr = MatGetDiagonalBlock(pc->mat,&mat);CHKERRQ(ierr);
121       /* make submatrix have same prefix as entire matrix */
122       ierr = PetscObjectGetOptionsPrefix((PetscObject)pc->mat,&mprefix);CHKERRQ(ierr);
123       ierr = PetscObjectSetOptionsPrefix((PetscObject)mat,mprefix);CHKERRQ(ierr);
124     }
125     if (pc->pmat != pc->mat || !pc->useAmat) {
126       ierr = MatGetDiagonalBlock(pc->pmat,&pmat);CHKERRQ(ierr);
127       /* make submatrix have same prefix as entire matrix */
128       ierr = PetscObjectGetOptionsPrefix((PetscObject)pc->pmat,&pprefix);CHKERRQ(ierr);
129       ierr = PetscObjectSetOptionsPrefix((PetscObject)pmat,pprefix);CHKERRQ(ierr);
130     } else pmat = mat;
131   }
132 
133   /* ------
134      Setup code depends on the number of blocks
135   */
136   if (jac->n_local == 1) {
137     ierr = PCSetUp_BJacobi_Singleblock(pc,mat,pmat);CHKERRQ(ierr);
138   } else {
139     ierr = PCSetUp_BJacobi_Multiblock(pc,mat,pmat);CHKERRQ(ierr);
140   }
141   PetscFunctionReturn(0);
142 }
143 
144 /* Default destroy, if it has never been setup */
145 #undef __FUNCT__
146 #define __FUNCT__ "PCDestroy_BJacobi"
147 static PetscErrorCode PCDestroy_BJacobi(PC pc)
148 {
149   PC_BJacobi     *jac = (PC_BJacobi*)pc->data;
150   PetscErrorCode ierr;
151 
152   PetscFunctionBegin;
153   ierr = PetscFree(jac->g_lens);CHKERRQ(ierr);
154   ierr = PetscFree(jac->l_lens);CHKERRQ(ierr);
155   ierr = PetscFree(pc->data);CHKERRQ(ierr);
156   PetscFunctionReturn(0);
157 }
158 
159 #undef __FUNCT__
160 #define __FUNCT__ "PCSetFromOptions_BJacobi"
161 
162 static PetscErrorCode PCSetFromOptions_BJacobi(PetscOptionItems *PetscOptionsObject,PC pc)
163 {
164   PC_BJacobi     *jac = (PC_BJacobi*)pc->data;
165   PetscErrorCode ierr;
166   PetscInt       blocks,i;
167   PetscBool      flg;
168 
169   PetscFunctionBegin;
170   ierr = PetscOptionsHead(PetscOptionsObject,"Block Jacobi options");CHKERRQ(ierr);
171   ierr = PetscOptionsInt("-pc_bjacobi_blocks","Total number of blocks","PCBJacobiSetTotalBlocks",jac->n,&blocks,&flg);CHKERRQ(ierr);
172   if (flg) {
173     ierr = PCBJacobiSetTotalBlocks(pc,blocks,NULL);CHKERRQ(ierr);
174   }
175   if (jac->ksp) {
176     /* The sub-KSP has already been set up (e.g., PCSetUp_BJacobi_Singleblock), but KSPSetFromOptions was not called
177      * unless we had already been called. */
178     for (i=0; i<jac->n_local; i++) {
179       ierr = KSPSetFromOptions(jac->ksp[i]);CHKERRQ(ierr);
180     }
181   }
182   ierr = PetscOptionsTail();CHKERRQ(ierr);
183   PetscFunctionReturn(0);
184 }
185 
186 #include <petscdraw.h>
187 #undef __FUNCT__
188 #define __FUNCT__ "PCView_BJacobi"
189 static PetscErrorCode PCView_BJacobi(PC pc,PetscViewer viewer)
190 {
191   PC_BJacobi           *jac   = (PC_BJacobi*)pc->data;
192   PC_BJacobi_Multiproc *mpjac = (PC_BJacobi_Multiproc*)jac->data;
193   PetscErrorCode       ierr;
194   PetscMPIInt          rank;
195   PetscInt             i;
196   PetscBool            iascii,isstring,isdraw;
197   PetscViewer          sviewer;
198 
199   PetscFunctionBegin;
200   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
201   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring);CHKERRQ(ierr);
202   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
203   if (iascii) {
204     if (pc->useAmat) {
205       ierr = PetscViewerASCIIPrintf(viewer,"  block Jacobi: using Amat local matrix, number of blocks = %D\n",jac->n);CHKERRQ(ierr);
206     }
207     ierr = PetscViewerASCIIPrintf(viewer,"  block Jacobi: number of blocks = %D\n",jac->n);CHKERRQ(ierr);
208     ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
209     if (jac->same_local_solves) {
210       ierr = PetscViewerASCIIPrintf(viewer,"  Local solve is same for all blocks, in the following KSP and PC objects:\n");CHKERRQ(ierr);
211       if (jac->ksp && !jac->psubcomm) {
212         ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
213         if (!rank) {
214           ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
215           ierr = KSPView(jac->ksp[0],sviewer);CHKERRQ(ierr);
216           ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
217         }
218         ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
219       } else if (mpjac && jac->ksp && mpjac->psubcomm) {
220         ierr = PetscViewerGetSubViewer(viewer,mpjac->psubcomm->child,&sviewer);CHKERRQ(ierr);
221         if (!mpjac->psubcomm->color) {
222           ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
223           ierr = KSPView(*(jac->ksp),sviewer);CHKERRQ(ierr);
224           ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
225         }
226         ierr = PetscViewerRestoreSubViewer(viewer,mpjac->psubcomm->child,&sviewer);CHKERRQ(ierr);
227       }
228     } else {
229       PetscInt n_global;
230       ierr = MPIU_Allreduce(&jac->n_local,&n_global,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
231       ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr);
232       ierr = PetscViewerASCIIPrintf(viewer,"  Local solve info for each block is in the following KSP and PC objects:\n");CHKERRQ(ierr);
233       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] number of local blocks = %D, first local block number = %D\n",
234                                                 rank,jac->n_local,jac->first_local);CHKERRQ(ierr);
235       ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
236       ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
237       for (i=0; i<jac->n_local; i++) {
238         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] local block number %D\n",rank,i);CHKERRQ(ierr);
239         ierr = KSPView(jac->ksp[i],sviewer);CHKERRQ(ierr);
240         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"- - - - - - - - - - - - - - - - - -\n");CHKERRQ(ierr);
241       }
242       ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
243       ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
244       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
245       ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr);
246     }
247   } else if (isstring) {
248     ierr = PetscViewerStringSPrintf(viewer," blks=%D",jac->n);CHKERRQ(ierr);
249     ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
250     if (jac->ksp) {ierr = KSPView(jac->ksp[0],sviewer);CHKERRQ(ierr);}
251     ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
252   } else if (isdraw) {
253     PetscDraw draw;
254     char      str[25];
255     PetscReal x,y,bottom,h;
256 
257     ierr   = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
258     ierr   = PetscDrawGetCurrentPoint(draw,&x,&y);CHKERRQ(ierr);
259     ierr   = PetscSNPrintf(str,25,"Number blocks %D",jac->n);CHKERRQ(ierr);
260     ierr   = PetscDrawStringBoxed(draw,x,y,PETSC_DRAW_RED,PETSC_DRAW_BLACK,str,NULL,&h);CHKERRQ(ierr);
261     bottom = y - h;
262     ierr   = PetscDrawPushCurrentPoint(draw,x,bottom);CHKERRQ(ierr);
263     /* warning the communicator on viewer is different then on ksp in parallel */
264     if (jac->ksp) {ierr = KSPView(jac->ksp[0],viewer);CHKERRQ(ierr);}
265     ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr);
266   }
267   PetscFunctionReturn(0);
268 }
269 
270 /* -------------------------------------------------------------------------------------*/
271 
272 #undef __FUNCT__
273 #define __FUNCT__ "PCBJacobiGetSubKSP_BJacobi"
274 static PetscErrorCode  PCBJacobiGetSubKSP_BJacobi(PC pc,PetscInt *n_local,PetscInt *first_local,KSP **ksp)
275 {
276   PC_BJacobi *jac = (PC_BJacobi*)pc->data;;
277 
278   PetscFunctionBegin;
279   if (!pc->setupcalled) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must call KSPSetUp() or PCSetUp() first");
280 
281   if (n_local) *n_local = jac->n_local;
282   if (first_local) *first_local = jac->first_local;
283   *ksp                   = jac->ksp;
284   jac->same_local_solves = PETSC_FALSE;        /* Assume that local solves are now different;
285                                                   not necessarily true though!  This flag is
286                                                   used only for PCView_BJacobi() */
287   PetscFunctionReturn(0);
288 }
289 
290 #undef __FUNCT__
291 #define __FUNCT__ "PCBJacobiSetTotalBlocks_BJacobi"
292 static PetscErrorCode  PCBJacobiSetTotalBlocks_BJacobi(PC pc,PetscInt blocks,PetscInt *lens)
293 {
294   PC_BJacobi     *jac = (PC_BJacobi*)pc->data;
295   PetscErrorCode ierr;
296 
297   PetscFunctionBegin;
298   if (pc->setupcalled > 0 && jac->n!=blocks) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ORDER,"Cannot alter number of blocks after PCSetUp()/KSPSetUp() has been called");
299   jac->n = blocks;
300   if (!lens) jac->g_lens = 0;
301   else {
302     ierr = PetscMalloc1(blocks,&jac->g_lens);CHKERRQ(ierr);
303     ierr = PetscLogObjectMemory((PetscObject)pc,blocks*sizeof(PetscInt));CHKERRQ(ierr);
304     ierr = PetscMemcpy(jac->g_lens,lens,blocks*sizeof(PetscInt));CHKERRQ(ierr);
305   }
306   PetscFunctionReturn(0);
307 }
308 
309 #undef __FUNCT__
310 #define __FUNCT__ "PCBJacobiGetTotalBlocks_BJacobi"
311 static PetscErrorCode  PCBJacobiGetTotalBlocks_BJacobi(PC pc, PetscInt *blocks, const PetscInt *lens[])
312 {
313   PC_BJacobi *jac = (PC_BJacobi*) pc->data;
314 
315   PetscFunctionBegin;
316   *blocks = jac->n;
317   if (lens) *lens = jac->g_lens;
318   PetscFunctionReturn(0);
319 }
320 
321 #undef __FUNCT__
322 #define __FUNCT__ "PCBJacobiSetLocalBlocks_BJacobi"
323 static PetscErrorCode  PCBJacobiSetLocalBlocks_BJacobi(PC pc,PetscInt blocks,const PetscInt lens[])
324 {
325   PC_BJacobi     *jac;
326   PetscErrorCode ierr;
327 
328   PetscFunctionBegin;
329   jac = (PC_BJacobi*)pc->data;
330 
331   jac->n_local = blocks;
332   if (!lens) jac->l_lens = 0;
333   else {
334     ierr = PetscMalloc1(blocks,&jac->l_lens);CHKERRQ(ierr);
335     ierr = PetscLogObjectMemory((PetscObject)pc,blocks*sizeof(PetscInt));CHKERRQ(ierr);
336     ierr = PetscMemcpy(jac->l_lens,lens,blocks*sizeof(PetscInt));CHKERRQ(ierr);
337   }
338   PetscFunctionReturn(0);
339 }
340 
341 #undef __FUNCT__
342 #define __FUNCT__ "PCBJacobiGetLocalBlocks_BJacobi"
343 static PetscErrorCode  PCBJacobiGetLocalBlocks_BJacobi(PC pc, PetscInt *blocks, const PetscInt *lens[])
344 {
345   PC_BJacobi *jac = (PC_BJacobi*) pc->data;
346 
347   PetscFunctionBegin;
348   *blocks = jac->n_local;
349   if (lens) *lens = jac->l_lens;
350   PetscFunctionReturn(0);
351 }
352 
353 /* -------------------------------------------------------------------------------------*/
354 
355 #undef __FUNCT__
356 #define __FUNCT__ "PCBJacobiGetSubKSP"
357 /*@C
358    PCBJacobiGetSubKSP - Gets the local KSP contexts for all blocks on
359    this processor.
360 
361    Note Collective
362 
363    Input Parameter:
364 .  pc - the preconditioner context
365 
366    Output Parameters:
367 +  n_local - the number of blocks on this processor, or NULL
368 .  first_local - the global number of the first block on this processor, or NULL
369 -  ksp - the array of KSP contexts
370 
371    Notes:
372    After PCBJacobiGetSubKSP() the array of KSP contexts is not to be freed.
373 
374    Currently for some matrix implementations only 1 block per processor
375    is supported.
376 
377    You must call KSPSetUp() or PCSetUp() before calling PCBJacobiGetSubKSP().
378 
379    Fortran Usage: You must pass in a KSP array that is large enough to contain all the local KSPs.
380       You can call PCBJacobiGetSubKSP(pc,nlocal,firstlocal,NULL_OBJECT,ierr) to determine how large the
381       KSP array must be.
382 
383    Level: advanced
384 
385 .keywords:  block, Jacobi, get, sub, KSP, context
386 
387 .seealso: PCBJacobiGetSubKSP()
388 @*/
389 PetscErrorCode  PCBJacobiGetSubKSP(PC pc,PetscInt *n_local,PetscInt *first_local,KSP *ksp[])
390 {
391   PetscErrorCode ierr;
392 
393   PetscFunctionBegin;
394   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
395   ierr = PetscUseMethod(pc,"PCBJacobiGetSubKSP_C",(PC,PetscInt*,PetscInt*,KSP **),(pc,n_local,first_local,ksp));CHKERRQ(ierr);
396   PetscFunctionReturn(0);
397 }
398 
399 #undef __FUNCT__
400 #define __FUNCT__ "PCBJacobiSetTotalBlocks"
401 /*@
402    PCBJacobiSetTotalBlocks - Sets the global number of blocks for the block
403    Jacobi preconditioner.
404 
405    Collective on PC
406 
407    Input Parameters:
408 +  pc - the preconditioner context
409 .  blocks - the number of blocks
410 -  lens - [optional] integer array containing the size of each block
411 
412    Options Database Key:
413 .  -pc_bjacobi_blocks <blocks> - Sets the number of global blocks
414 
415    Notes:
416    Currently only a limited number of blocking configurations are supported.
417    All processors sharing the PC must call this routine with the same data.
418 
419    Level: intermediate
420 
421 .keywords:  set, number, Jacobi, global, total, blocks
422 
423 .seealso: PCSetUseAmat(), PCBJacobiSetLocalBlocks()
424 @*/
425 PetscErrorCode  PCBJacobiSetTotalBlocks(PC pc,PetscInt blocks,const PetscInt lens[])
426 {
427   PetscErrorCode ierr;
428 
429   PetscFunctionBegin;
430   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
431   if (blocks <= 0) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Must have positive blocks");
432   ierr = PetscTryMethod(pc,"PCBJacobiSetTotalBlocks_C",(PC,PetscInt,const PetscInt[]),(pc,blocks,lens));CHKERRQ(ierr);
433   PetscFunctionReturn(0);
434 }
435 
436 #undef __FUNCT__
437 #define __FUNCT__ "PCBJacobiGetTotalBlocks"
438 /*@C
439    PCBJacobiGetTotalBlocks - Gets the global number of blocks for the block
440    Jacobi preconditioner.
441 
442    Not Collective
443 
444    Input Parameter:
445 .  pc - the preconditioner context
446 
447    Output parameters:
448 +  blocks - the number of blocks
449 -  lens - integer array containing the size of each block
450 
451    Level: intermediate
452 
453 .keywords:  get, number, Jacobi, global, total, blocks
454 
455 .seealso: PCSetUseAmat(), PCBJacobiGetLocalBlocks()
456 @*/
457 PetscErrorCode  PCBJacobiGetTotalBlocks(PC pc, PetscInt *blocks, const PetscInt *lens[])
458 {
459   PetscErrorCode ierr;
460 
461   PetscFunctionBegin;
462   PetscValidHeaderSpecific(pc, PC_CLASSID,1);
463   PetscValidIntPointer(blocks,2);
464   ierr = PetscUseMethod(pc,"PCBJacobiGetTotalBlocks_C",(PC,PetscInt*, const PetscInt *[]),(pc,blocks,lens));CHKERRQ(ierr);
465   PetscFunctionReturn(0);
466 }
467 
468 #undef __FUNCT__
469 #define __FUNCT__ "PCBJacobiSetLocalBlocks"
470 /*@
471    PCBJacobiSetLocalBlocks - Sets the local number of blocks for the block
472    Jacobi preconditioner.
473 
474    Not Collective
475 
476    Input Parameters:
477 +  pc - the preconditioner context
478 .  blocks - the number of blocks
479 -  lens - [optional] integer array containing size of each block
480 
481    Note:
482    Currently only a limited number of blocking configurations are supported.
483 
484    Level: intermediate
485 
486 .keywords: PC, set, number, Jacobi, local, blocks
487 
488 .seealso: PCSetUseAmat(), PCBJacobiSetTotalBlocks()
489 @*/
490 PetscErrorCode  PCBJacobiSetLocalBlocks(PC pc,PetscInt blocks,const PetscInt lens[])
491 {
492   PetscErrorCode ierr;
493 
494   PetscFunctionBegin;
495   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
496   if (blocks < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Must have nonegative blocks");
497   ierr = PetscTryMethod(pc,"PCBJacobiSetLocalBlocks_C",(PC,PetscInt,const PetscInt []),(pc,blocks,lens));CHKERRQ(ierr);
498   PetscFunctionReturn(0);
499 }
500 
501 #undef __FUNCT__
502 #define __FUNCT__ "PCBJacobiGetLocalBlocks"
503 /*@C
504    PCBJacobiGetLocalBlocks - Gets the local number of blocks for the block
505    Jacobi preconditioner.
506 
507    Not Collective
508 
509    Input Parameters:
510 +  pc - the preconditioner context
511 .  blocks - the number of blocks
512 -  lens - [optional] integer array containing size of each block
513 
514    Note:
515    Currently only a limited number of blocking configurations are supported.
516 
517    Level: intermediate
518 
519 .keywords: PC, get, number, Jacobi, local, blocks
520 
521 .seealso: PCSetUseAmat(), PCBJacobiGetTotalBlocks()
522 @*/
523 PetscErrorCode  PCBJacobiGetLocalBlocks(PC pc, PetscInt *blocks, const PetscInt *lens[])
524 {
525   PetscErrorCode ierr;
526 
527   PetscFunctionBegin;
528   PetscValidHeaderSpecific(pc, PC_CLASSID,1);
529   PetscValidIntPointer(blocks,2);
530   ierr = PetscUseMethod(pc,"PCBJacobiGetLocalBlocks_C",(PC,PetscInt*, const PetscInt *[]),(pc,blocks,lens));CHKERRQ(ierr);
531   PetscFunctionReturn(0);
532 }
533 
534 /* -----------------------------------------------------------------------------------*/
535 
536 /*MC
537    PCBJACOBI - Use block Jacobi preconditioning, each block is (approximately) solved with
538            its own KSP object.
539 
540    Options Database Keys:
541 .  -pc_use_amat - use Amat to apply block of operator in inner Krylov method
542 
543    Notes: Each processor can have one or more blocks, but a block cannot be shared by more
544      than one processor. Defaults to one block per processor.
545 
546      To set options on the solvers for each block append -sub_ to all the KSP, KSP, and PC
547         options database keys. For example, -sub_pc_type ilu -sub_pc_factor_levels 1 -sub_ksp_type preonly
548 
549      To set the options on the solvers separate for each block call PCBJacobiGetSubKSP()
550          and set the options directly on the resulting KSP object (you can access its PC
551          KSPGetPC())
552 
553      For CUSP vectors it is recommended to use exactly one block per MPI process for best
554          performance.  Different block partitioning may lead to additional data transfers
555          between host and GPU that lead to degraded performance.
556 
557    Level: beginner
558 
559    Concepts: block Jacobi
560 
561 
562 .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
563            PCASM, PCSetUseAmat(), PCGetUseAmat(), PCBJacobiGetSubKSP(), PCBJacobiSetTotalBlocks(),
564            PCBJacobiSetLocalBlocks(), PCSetModifySubmatrices()
565 M*/
566 
567 #undef __FUNCT__
568 #define __FUNCT__ "PCCreate_BJacobi"
569 PETSC_EXTERN PetscErrorCode PCCreate_BJacobi(PC pc)
570 {
571   PetscErrorCode ierr;
572   PetscMPIInt    rank;
573   PC_BJacobi     *jac;
574 
575   PetscFunctionBegin;
576   ierr = PetscNewLog(pc,&jac);CHKERRQ(ierr);
577   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
578 
579   pc->ops->apply           = 0;
580   pc->ops->applytranspose  = 0;
581   pc->ops->setup           = PCSetUp_BJacobi;
582   pc->ops->destroy         = PCDestroy_BJacobi;
583   pc->ops->setfromoptions  = PCSetFromOptions_BJacobi;
584   pc->ops->view            = PCView_BJacobi;
585   pc->ops->applyrichardson = 0;
586 
587   pc->data               = (void*)jac;
588   jac->n                 = -1;
589   jac->n_local           = -1;
590   jac->first_local       = rank;
591   jac->ksp               = 0;
592   jac->same_local_solves = PETSC_TRUE;
593   jac->g_lens            = 0;
594   jac->l_lens            = 0;
595   jac->psubcomm          = 0;
596 
597   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBJacobiGetSubKSP_C",PCBJacobiGetSubKSP_BJacobi);CHKERRQ(ierr);
598   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBJacobiSetTotalBlocks_C",PCBJacobiSetTotalBlocks_BJacobi);CHKERRQ(ierr);
599   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBJacobiGetTotalBlocks_C",PCBJacobiGetTotalBlocks_BJacobi);CHKERRQ(ierr);
600   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBJacobiSetLocalBlocks_C",PCBJacobiSetLocalBlocks_BJacobi);CHKERRQ(ierr);
601   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBJacobiGetLocalBlocks_C",PCBJacobiGetLocalBlocks_BJacobi);CHKERRQ(ierr);
602   PetscFunctionReturn(0);
603 }
604 
605 /* --------------------------------------------------------------------------------------------*/
606 /*
607         These are for a single block per processor; works for AIJ, BAIJ; Seq and MPI
608 */
609 #undef __FUNCT__
610 #define __FUNCT__ "PCReset_BJacobi_Singleblock"
611 static PetscErrorCode PCReset_BJacobi_Singleblock(PC pc)
612 {
613   PC_BJacobi             *jac  = (PC_BJacobi*)pc->data;
614   PC_BJacobi_Singleblock *bjac = (PC_BJacobi_Singleblock*)jac->data;
615   PetscErrorCode         ierr;
616 
617   PetscFunctionBegin;
618   ierr = KSPReset(jac->ksp[0]);CHKERRQ(ierr);
619   ierr = VecDestroy(&bjac->x);CHKERRQ(ierr);
620   ierr = VecDestroy(&bjac->y);CHKERRQ(ierr);
621   PetscFunctionReturn(0);
622 }
623 
624 #undef __FUNCT__
625 #define __FUNCT__ "PCDestroy_BJacobi_Singleblock"
626 static PetscErrorCode PCDestroy_BJacobi_Singleblock(PC pc)
627 {
628   PC_BJacobi             *jac  = (PC_BJacobi*)pc->data;
629   PC_BJacobi_Singleblock *bjac = (PC_BJacobi_Singleblock*)jac->data;
630   PetscErrorCode         ierr;
631 
632   PetscFunctionBegin;
633   ierr = PCReset_BJacobi_Singleblock(pc);CHKERRQ(ierr);
634   ierr = KSPDestroy(&jac->ksp[0]);CHKERRQ(ierr);
635   ierr = PetscFree(jac->ksp);CHKERRQ(ierr);
636   ierr = PetscFree(jac->l_lens);CHKERRQ(ierr);
637   ierr = PetscFree(jac->g_lens);CHKERRQ(ierr);
638   ierr = PetscFree(bjac);CHKERRQ(ierr);
639   ierr = PetscFree(pc->data);CHKERRQ(ierr);
640   PetscFunctionReturn(0);
641 }
642 
643 #undef __FUNCT__
644 #define __FUNCT__ "PCSetUpOnBlocks_BJacobi_Singleblock"
645 static PetscErrorCode PCSetUpOnBlocks_BJacobi_Singleblock(PC pc)
646 {
647   PetscErrorCode     ierr;
648   PC_BJacobi         *jac = (PC_BJacobi*)pc->data;
649   KSP                subksp = jac->ksp[0];
650   KSPConvergedReason reason;
651 
652   PetscFunctionBegin;
653   ierr = KSPSetUp(subksp);CHKERRQ(ierr);
654   ierr = KSPGetConvergedReason(subksp,&reason);CHKERRQ(ierr);
655   if (reason == KSP_DIVERGED_PCSETUP_FAILED) {
656     pc->failedreason = PC_SUBPC_ERROR;
657   }
658   PetscFunctionReturn(0);
659 }
660 
661 #undef __FUNCT__
662 #define __FUNCT__ "PCApply_BJacobi_Singleblock"
663 static PetscErrorCode PCApply_BJacobi_Singleblock(PC pc,Vec x,Vec y)
664 {
665   PetscErrorCode         ierr;
666   PC_BJacobi             *jac  = (PC_BJacobi*)pc->data;
667   PC_BJacobi_Singleblock *bjac = (PC_BJacobi_Singleblock*)jac->data;
668 
669   PetscFunctionBegin;
670   ierr = VecGetLocalVectorRead(x, bjac->x);CHKERRQ(ierr);
671   ierr = VecGetLocalVector(y, bjac->y);CHKERRQ(ierr);
672  /* Since the inner KSP matrix may point directly to the diagonal block of an MPI matrix the inner
673      matrix may change even if the outter KSP/PC has not updated the preconditioner, this will trigger a rebuild
674      of the inner preconditioner automatically unless we pass down the outter preconditioners reuse flag.*/
675   ierr = KSPSetReusePreconditioner(jac->ksp[0],pc->reusepreconditioner);CHKERRQ(ierr);
676   ierr = KSPSolve(jac->ksp[0],bjac->x,bjac->y);CHKERRQ(ierr);
677   ierr = VecRestoreLocalVectorRead(x, bjac->x);CHKERRQ(ierr);
678   ierr = VecRestoreLocalVector(y, bjac->y);CHKERRQ(ierr);
679   PetscFunctionReturn(0);
680 }
681 
682 #undef __FUNCT__
683 #define __FUNCT__ "PCApplySymmetricLeft_BJacobi_Singleblock"
684 static PetscErrorCode PCApplySymmetricLeft_BJacobi_Singleblock(PC pc,Vec x,Vec y)
685 {
686   PetscErrorCode         ierr;
687   PC_BJacobi             *jac  = (PC_BJacobi*)pc->data;
688   PC_BJacobi_Singleblock *bjac = (PC_BJacobi_Singleblock*)jac->data;
689   PetscScalar            *y_array;
690   const PetscScalar      *x_array;
691   PC                     subpc;
692 
693   PetscFunctionBegin;
694   /*
695       The VecPlaceArray() is to avoid having to copy the
696     y vector into the bjac->x vector. The reason for
697     the bjac->x vector is that we need a sequential vector
698     for the sequential solve.
699   */
700   ierr = VecGetArrayRead(x,&x_array);CHKERRQ(ierr);
701   ierr = VecGetArray(y,&y_array);CHKERRQ(ierr);
702   ierr = VecPlaceArray(bjac->x,x_array);CHKERRQ(ierr);
703   ierr = VecPlaceArray(bjac->y,y_array);CHKERRQ(ierr);
704   /* apply the symmetric left portion of the inner PC operator */
705   /* note this by-passes the inner KSP and its options completely */
706   ierr = KSPGetPC(jac->ksp[0],&subpc);CHKERRQ(ierr);
707   ierr = PCApplySymmetricLeft(subpc,bjac->x,bjac->y);CHKERRQ(ierr);
708   ierr = VecResetArray(bjac->x);CHKERRQ(ierr);
709   ierr = VecResetArray(bjac->y);CHKERRQ(ierr);
710   ierr = VecRestoreArrayRead(x,&x_array);CHKERRQ(ierr);
711   ierr = VecRestoreArray(y,&y_array);CHKERRQ(ierr);
712   PetscFunctionReturn(0);
713 }
714 
715 #undef __FUNCT__
716 #define __FUNCT__ "PCApplySymmetricRight_BJacobi_Singleblock"
717 static PetscErrorCode PCApplySymmetricRight_BJacobi_Singleblock(PC pc,Vec x,Vec y)
718 {
719   PetscErrorCode         ierr;
720   PC_BJacobi             *jac  = (PC_BJacobi*)pc->data;
721   PC_BJacobi_Singleblock *bjac = (PC_BJacobi_Singleblock*)jac->data;
722   PetscScalar            *y_array;
723   const PetscScalar      *x_array;
724   PC                     subpc;
725 
726   PetscFunctionBegin;
727   /*
728       The VecPlaceArray() is to avoid having to copy the
729     y vector into the bjac->x vector. The reason for
730     the bjac->x vector is that we need a sequential vector
731     for the sequential solve.
732   */
733   ierr = VecGetArrayRead(x,&x_array);CHKERRQ(ierr);
734   ierr = VecGetArray(y,&y_array);CHKERRQ(ierr);
735   ierr = VecPlaceArray(bjac->x,x_array);CHKERRQ(ierr);
736   ierr = VecPlaceArray(bjac->y,y_array);CHKERRQ(ierr);
737 
738   /* apply the symmetric right portion of the inner PC operator */
739   /* note this by-passes the inner KSP and its options completely */
740 
741   ierr = KSPGetPC(jac->ksp[0],&subpc);CHKERRQ(ierr);
742   ierr = PCApplySymmetricRight(subpc,bjac->x,bjac->y);CHKERRQ(ierr);
743 
744   ierr = VecRestoreArrayRead(x,&x_array);CHKERRQ(ierr);
745   ierr = VecRestoreArray(y,&y_array);CHKERRQ(ierr);
746   PetscFunctionReturn(0);
747 }
748 
749 #undef __FUNCT__
750 #define __FUNCT__ "PCApplyTranspose_BJacobi_Singleblock"
751 static PetscErrorCode PCApplyTranspose_BJacobi_Singleblock(PC pc,Vec x,Vec y)
752 {
753   PetscErrorCode         ierr;
754   PC_BJacobi             *jac  = (PC_BJacobi*)pc->data;
755   PC_BJacobi_Singleblock *bjac = (PC_BJacobi_Singleblock*)jac->data;
756   PetscScalar            *y_array;
757   const PetscScalar      *x_array;
758 
759   PetscFunctionBegin;
760   /*
761       The VecPlaceArray() is to avoid having to copy the
762     y vector into the bjac->x vector. The reason for
763     the bjac->x vector is that we need a sequential vector
764     for the sequential solve.
765   */
766   ierr = VecGetArrayRead(x,&x_array);CHKERRQ(ierr);
767   ierr = VecGetArray(y,&y_array);CHKERRQ(ierr);
768   ierr = VecPlaceArray(bjac->x,x_array);CHKERRQ(ierr);
769   ierr = VecPlaceArray(bjac->y,y_array);CHKERRQ(ierr);
770   ierr = KSPSolveTranspose(jac->ksp[0],bjac->x,bjac->y);CHKERRQ(ierr);
771   ierr = VecResetArray(bjac->x);CHKERRQ(ierr);
772   ierr = VecResetArray(bjac->y);CHKERRQ(ierr);
773   ierr = VecRestoreArrayRead(x,&x_array);CHKERRQ(ierr);
774   ierr = VecRestoreArray(y,&y_array);CHKERRQ(ierr);
775   PetscFunctionReturn(0);
776 }
777 
778 #undef __FUNCT__
779 #define __FUNCT__ "PCSetUp_BJacobi_Singleblock"
780 static PetscErrorCode PCSetUp_BJacobi_Singleblock(PC pc,Mat mat,Mat pmat)
781 {
782   PC_BJacobi             *jac = (PC_BJacobi*)pc->data;
783   PetscErrorCode         ierr;
784   PetscInt               m;
785   KSP                    ksp;
786   PC_BJacobi_Singleblock *bjac;
787   PetscBool              wasSetup = PETSC_TRUE;
788 
789   PetscFunctionBegin;
790   if (!pc->setupcalled) {
791     const char *prefix;
792 
793     if (!jac->ksp) {
794       wasSetup = PETSC_FALSE;
795 
796       ierr = KSPCreate(PETSC_COMM_SELF,&ksp);CHKERRQ(ierr);
797       ierr = KSPSetErrorIfNotConverged(ksp,pc->erroriffailure);CHKERRQ(ierr);
798       ierr = PetscObjectIncrementTabLevel((PetscObject)ksp,(PetscObject)pc,1);CHKERRQ(ierr);
799       ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)ksp);CHKERRQ(ierr);
800       ierr = KSPSetType(ksp,KSPPREONLY);CHKERRQ(ierr);
801       ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr);
802       ierr = KSPSetOptionsPrefix(ksp,prefix);CHKERRQ(ierr);
803       ierr = KSPAppendOptionsPrefix(ksp,"sub_");CHKERRQ(ierr);
804 
805       pc->ops->reset               = PCReset_BJacobi_Singleblock;
806       pc->ops->destroy             = PCDestroy_BJacobi_Singleblock;
807       pc->ops->apply               = PCApply_BJacobi_Singleblock;
808       pc->ops->applysymmetricleft  = PCApplySymmetricLeft_BJacobi_Singleblock;
809       pc->ops->applysymmetricright = PCApplySymmetricRight_BJacobi_Singleblock;
810       pc->ops->applytranspose      = PCApplyTranspose_BJacobi_Singleblock;
811       pc->ops->setuponblocks       = PCSetUpOnBlocks_BJacobi_Singleblock;
812 
813       ierr        = PetscMalloc1(1,&jac->ksp);CHKERRQ(ierr);
814       jac->ksp[0] = ksp;
815 
816       ierr      = PetscNewLog(pc,&bjac);CHKERRQ(ierr);
817       jac->data = (void*)bjac;
818     } else {
819       ksp  = jac->ksp[0];
820       bjac = (PC_BJacobi_Singleblock*)jac->data;
821     }
822 
823     /*
824       The reason we need to generate these vectors is to serve
825       as the right-hand side and solution vector for the solve on the
826       block. We do not need to allocate space for the vectors since
827       that is provided via VecPlaceArray() just before the call to
828       KSPSolve() on the block.
829     */
830     ierr = MatGetSize(pmat,&m,&m);CHKERRQ(ierr);
831     ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,1,m,NULL,&bjac->x);CHKERRQ(ierr);
832     ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,1,m,NULL,&bjac->y);CHKERRQ(ierr);
833 #if defined(PETSC_HAVE_CUSP)
834     ierr = VecSetType(bjac->x,VECCUSP);CHKERRQ(ierr);
835     ierr = VecSetType(bjac->y,VECCUSP);CHKERRQ(ierr);
836 #elif defined(PETSC_HAVE_VECCUDA)
837     ierr = VecSetType(bjac->x,VECCUDA);CHKERRQ(ierr);
838     ierr = VecSetType(bjac->y,VECCUDA);CHKERRQ(ierr);
839 #endif
840     ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)bjac->x);CHKERRQ(ierr);
841     ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)bjac->y);CHKERRQ(ierr);
842   } else {
843     ksp  = jac->ksp[0];
844     bjac = (PC_BJacobi_Singleblock*)jac->data;
845   }
846   if (pc->useAmat) {
847     ierr = KSPSetOperators(ksp,mat,pmat);CHKERRQ(ierr);
848   } else {
849     ierr = KSPSetOperators(ksp,pmat,pmat);CHKERRQ(ierr);
850   }
851   if (!wasSetup && pc->setfromoptionscalled) {
852     /* If PCSetFromOptions_BJacobi is called later, KSPSetFromOptions will be called at that time. */
853     ierr = KSPSetFromOptions(ksp);CHKERRQ(ierr);
854   }
855   PetscFunctionReturn(0);
856 }
857 
858 /* ---------------------------------------------------------------------------------------------*/
859 #undef __FUNCT__
860 #define __FUNCT__ "PCReset_BJacobi_Multiblock"
861 static PetscErrorCode PCReset_BJacobi_Multiblock(PC pc)
862 {
863   PC_BJacobi            *jac  = (PC_BJacobi*)pc->data;
864   PC_BJacobi_Multiblock *bjac = (PC_BJacobi_Multiblock*)jac->data;
865   PetscErrorCode        ierr;
866   PetscInt              i;
867 
868   PetscFunctionBegin;
869   if (bjac && bjac->pmat) {
870     ierr = MatDestroyMatrices(jac->n_local,&bjac->pmat);CHKERRQ(ierr);
871     if (pc->useAmat) {
872       ierr = MatDestroyMatrices(jac->n_local,&bjac->mat);CHKERRQ(ierr);
873     }
874   }
875 
876   for (i=0; i<jac->n_local; i++) {
877     ierr = KSPReset(jac->ksp[i]);CHKERRQ(ierr);
878     if (bjac && bjac->x) {
879       ierr = VecDestroy(&bjac->x[i]);CHKERRQ(ierr);
880       ierr = VecDestroy(&bjac->y[i]);CHKERRQ(ierr);
881       ierr = ISDestroy(&bjac->is[i]);CHKERRQ(ierr);
882     }
883   }
884   ierr = PetscFree(jac->l_lens);CHKERRQ(ierr);
885   ierr = PetscFree(jac->g_lens);CHKERRQ(ierr);
886   PetscFunctionReturn(0);
887 }
888 
889 #undef __FUNCT__
890 #define __FUNCT__ "PCDestroy_BJacobi_Multiblock"
891 static PetscErrorCode PCDestroy_BJacobi_Multiblock(PC pc)
892 {
893   PC_BJacobi            *jac  = (PC_BJacobi*)pc->data;
894   PC_BJacobi_Multiblock *bjac = (PC_BJacobi_Multiblock*)jac->data;
895   PetscErrorCode        ierr;
896   PetscInt              i;
897 
898   PetscFunctionBegin;
899   ierr = PCReset_BJacobi_Multiblock(pc);CHKERRQ(ierr);
900   if (bjac) {
901     ierr = PetscFree2(bjac->x,bjac->y);CHKERRQ(ierr);
902     ierr = PetscFree(bjac->starts);CHKERRQ(ierr);
903     ierr = PetscFree(bjac->is);CHKERRQ(ierr);
904   }
905   ierr = PetscFree(jac->data);CHKERRQ(ierr);
906   for (i=0; i<jac->n_local; i++) {
907     ierr = KSPDestroy(&jac->ksp[i]);CHKERRQ(ierr);
908   }
909   ierr = PetscFree(jac->ksp);CHKERRQ(ierr);
910   ierr = PetscFree(pc->data);CHKERRQ(ierr);
911   PetscFunctionReturn(0);
912 }
913 
914 #undef __FUNCT__
915 #define __FUNCT__ "PCSetUpOnBlocks_BJacobi_Multiblock"
916 static PetscErrorCode PCSetUpOnBlocks_BJacobi_Multiblock(PC pc)
917 {
918   PC_BJacobi         *jac = (PC_BJacobi*)pc->data;
919   PetscErrorCode     ierr;
920   PetscInt           i,n_local = jac->n_local;
921   KSPConvergedReason reason;
922 
923   PetscFunctionBegin;
924   for (i=0; i<n_local; i++) {
925     ierr = KSPSetUp(jac->ksp[i]);CHKERRQ(ierr);
926     ierr = KSPGetConvergedReason(jac->ksp[i],&reason);CHKERRQ(ierr);
927     if (reason == KSP_DIVERGED_PCSETUP_FAILED) {
928       pc->failedreason = PC_SUBPC_ERROR;
929     }
930   }
931   PetscFunctionReturn(0);
932 }
933 
934 /*
935       Preconditioner for block Jacobi
936 */
937 #undef __FUNCT__
938 #define __FUNCT__ "PCApply_BJacobi_Multiblock"
939 static PetscErrorCode PCApply_BJacobi_Multiblock(PC pc,Vec x,Vec y)
940 {
941   PC_BJacobi            *jac = (PC_BJacobi*)pc->data;
942   PetscErrorCode        ierr;
943   PetscInt              i,n_local = jac->n_local;
944   PC_BJacobi_Multiblock *bjac = (PC_BJacobi_Multiblock*)jac->data;
945   PetscScalar           *yin;
946   const PetscScalar     *xin;
947 
948   PetscFunctionBegin;
949   ierr = VecGetArrayRead(x,&xin);CHKERRQ(ierr);
950   ierr = VecGetArray(y,&yin);CHKERRQ(ierr);
951   for (i=0; i<n_local; i++) {
952     /*
953        To avoid copying the subvector from x into a workspace we instead
954        make the workspace vector array point to the subpart of the array of
955        the global vector.
956     */
957     ierr = VecPlaceArray(bjac->x[i],xin+bjac->starts[i]);CHKERRQ(ierr);
958     ierr = VecPlaceArray(bjac->y[i],yin+bjac->starts[i]);CHKERRQ(ierr);
959 
960     ierr = PetscLogEventBegin(PC_ApplyOnBlocks,jac->ksp[i],bjac->x[i],bjac->y[i],0);CHKERRQ(ierr);
961     ierr = KSPSolve(jac->ksp[i],bjac->x[i],bjac->y[i]);CHKERRQ(ierr);
962     ierr = PetscLogEventEnd(PC_ApplyOnBlocks,jac->ksp[i],bjac->x[i],bjac->y[i],0);CHKERRQ(ierr);
963 
964     ierr = VecResetArray(bjac->x[i]);CHKERRQ(ierr);
965     ierr = VecResetArray(bjac->y[i]);CHKERRQ(ierr);
966   }
967   ierr = VecRestoreArrayRead(x,&xin);CHKERRQ(ierr);
968   ierr = VecRestoreArray(y,&yin);CHKERRQ(ierr);
969   PetscFunctionReturn(0);
970 }
971 
972 /*
973       Preconditioner for block Jacobi
974 */
975 #undef __FUNCT__
976 #define __FUNCT__ "PCApplyTranspose_BJacobi_Multiblock"
977 static PetscErrorCode PCApplyTranspose_BJacobi_Multiblock(PC pc,Vec x,Vec y)
978 {
979   PC_BJacobi            *jac = (PC_BJacobi*)pc->data;
980   PetscErrorCode        ierr;
981   PetscInt              i,n_local = jac->n_local;
982   PC_BJacobi_Multiblock *bjac = (PC_BJacobi_Multiblock*)jac->data;
983   PetscScalar           *yin;
984   const PetscScalar     *xin;
985 
986   PetscFunctionBegin;
987   ierr = VecGetArrayRead(x,&xin);CHKERRQ(ierr);
988   ierr = VecGetArray(y,&yin);CHKERRQ(ierr);
989   for (i=0; i<n_local; i++) {
990     /*
991        To avoid copying the subvector from x into a workspace we instead
992        make the workspace vector array point to the subpart of the array of
993        the global vector.
994     */
995     ierr = VecPlaceArray(bjac->x[i],xin+bjac->starts[i]);CHKERRQ(ierr);
996     ierr = VecPlaceArray(bjac->y[i],yin+bjac->starts[i]);CHKERRQ(ierr);
997 
998     ierr = PetscLogEventBegin(PC_ApplyTransposeOnBlocks,jac->ksp[i],bjac->x[i],bjac->y[i],0);CHKERRQ(ierr);
999     ierr = KSPSolveTranspose(jac->ksp[i],bjac->x[i],bjac->y[i]);CHKERRQ(ierr);
1000     ierr = PetscLogEventEnd(PC_ApplyTransposeOnBlocks,jac->ksp[i],bjac->x[i],bjac->y[i],0);CHKERRQ(ierr);
1001 
1002     ierr = VecResetArray(bjac->x[i]);CHKERRQ(ierr);
1003     ierr = VecResetArray(bjac->y[i]);CHKERRQ(ierr);
1004   }
1005   ierr = VecRestoreArrayRead(x,&xin);CHKERRQ(ierr);
1006   ierr = VecRestoreArray(y,&yin);CHKERRQ(ierr);
1007   PetscFunctionReturn(0);
1008 }
1009 
1010 #undef __FUNCT__
1011 #define __FUNCT__ "PCSetUp_BJacobi_Multiblock"
1012 static PetscErrorCode PCSetUp_BJacobi_Multiblock(PC pc,Mat mat,Mat pmat)
1013 {
1014   PC_BJacobi            *jac = (PC_BJacobi*)pc->data;
1015   PetscErrorCode        ierr;
1016   PetscInt              m,n_local,N,M,start,i;
1017   const char            *prefix,*pprefix,*mprefix;
1018   KSP                   ksp;
1019   Vec                   x,y;
1020   PC_BJacobi_Multiblock *bjac = (PC_BJacobi_Multiblock*)jac->data;
1021   PC                    subpc;
1022   IS                    is;
1023   MatReuse              scall;
1024 
1025   PetscFunctionBegin;
1026   ierr = MatGetLocalSize(pc->pmat,&M,&N);CHKERRQ(ierr);
1027 
1028   n_local = jac->n_local;
1029 
1030   if (pc->useAmat) {
1031     PetscBool same;
1032     ierr = PetscObjectTypeCompare((PetscObject)mat,((PetscObject)pmat)->type_name,&same);CHKERRQ(ierr);
1033     if (!same) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_INCOMP,"Matrices not of same type");
1034   }
1035 
1036   if (!pc->setupcalled) {
1037     scall = MAT_INITIAL_MATRIX;
1038 
1039     if (!jac->ksp) {
1040       pc->ops->reset         = PCReset_BJacobi_Multiblock;
1041       pc->ops->destroy       = PCDestroy_BJacobi_Multiblock;
1042       pc->ops->apply         = PCApply_BJacobi_Multiblock;
1043       pc->ops->applytranspose= PCApplyTranspose_BJacobi_Multiblock;
1044       pc->ops->setuponblocks = PCSetUpOnBlocks_BJacobi_Multiblock;
1045 
1046       ierr = PetscNewLog(pc,&bjac);CHKERRQ(ierr);
1047       ierr = PetscMalloc1(n_local,&jac->ksp);CHKERRQ(ierr);
1048       ierr = PetscLogObjectMemory((PetscObject)pc,sizeof(n_local*sizeof(KSP)));CHKERRQ(ierr);
1049       ierr = PetscMalloc2(n_local,&bjac->x,n_local,&bjac->y);CHKERRQ(ierr);
1050       ierr = PetscMalloc1(n_local,&bjac->starts);CHKERRQ(ierr);
1051       ierr = PetscLogObjectMemory((PetscObject)pc,sizeof(n_local*sizeof(PetscScalar)));CHKERRQ(ierr);
1052 
1053       jac->data = (void*)bjac;
1054       ierr      = PetscMalloc1(n_local,&bjac->is);CHKERRQ(ierr);
1055       ierr      = PetscLogObjectMemory((PetscObject)pc,sizeof(n_local*sizeof(IS)));CHKERRQ(ierr);
1056 
1057       for (i=0; i<n_local; i++) {
1058         ierr = KSPCreate(PETSC_COMM_SELF,&ksp);CHKERRQ(ierr);
1059         ierr = KSPSetErrorIfNotConverged(ksp,pc->erroriffailure);CHKERRQ(ierr);
1060         ierr = PetscObjectIncrementTabLevel((PetscObject)ksp,(PetscObject)pc,1);CHKERRQ(ierr);
1061         ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)ksp);CHKERRQ(ierr);
1062         ierr = KSPSetType(ksp,KSPPREONLY);CHKERRQ(ierr);
1063         ierr = KSPGetPC(ksp,&subpc);CHKERRQ(ierr);
1064         ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr);
1065         ierr = KSPSetOptionsPrefix(ksp,prefix);CHKERRQ(ierr);
1066         ierr = KSPAppendOptionsPrefix(ksp,"sub_");CHKERRQ(ierr);
1067 
1068         jac->ksp[i] = ksp;
1069       }
1070     } else {
1071       bjac = (PC_BJacobi_Multiblock*)jac->data;
1072     }
1073 
1074     start = 0;
1075     for (i=0; i<n_local; i++) {
1076       m = jac->l_lens[i];
1077       /*
1078       The reason we need to generate these vectors is to serve
1079       as the right-hand side and solution vector for the solve on the
1080       block. We do not need to allocate space for the vectors since
1081       that is provided via VecPlaceArray() just before the call to
1082       KSPSolve() on the block.
1083 
1084       */
1085       ierr = VecCreateSeq(PETSC_COMM_SELF,m,&x);CHKERRQ(ierr);
1086       ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,1,m,NULL,&y);CHKERRQ(ierr);
1087 #if defined(PETSC_HAVE_CUSP)
1088       ierr = VecSetType(x,VECCUSP);CHKERRQ(ierr);
1089       ierr = VecSetType(y,VECCUSP);CHKERRQ(ierr);
1090 #elif defined(PETSC_HAVE_VECCUDA)
1091       ierr = VecSetType(x,VECCUDA);CHKERRQ(ierr);
1092       ierr = VecSetType(y,VECCUDA);CHKERRQ(ierr);
1093 #endif
1094       ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)x);CHKERRQ(ierr);
1095       ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)y);CHKERRQ(ierr);
1096 
1097       bjac->x[i]      = x;
1098       bjac->y[i]      = y;
1099       bjac->starts[i] = start;
1100 
1101       ierr        = ISCreateStride(PETSC_COMM_SELF,m,start,1,&is);CHKERRQ(ierr);
1102       bjac->is[i] = is;
1103       ierr        = PetscLogObjectParent((PetscObject)pc,(PetscObject)is);CHKERRQ(ierr);
1104 
1105       start += m;
1106     }
1107   } else {
1108     bjac = (PC_BJacobi_Multiblock*)jac->data;
1109     /*
1110        Destroy the blocks from the previous iteration
1111     */
1112     if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
1113       ierr = MatDestroyMatrices(n_local,&bjac->pmat);CHKERRQ(ierr);
1114       if (pc->useAmat) {
1115         ierr = MatDestroyMatrices(n_local,&bjac->mat);CHKERRQ(ierr);
1116       }
1117       scall = MAT_INITIAL_MATRIX;
1118     } else scall = MAT_REUSE_MATRIX;
1119   }
1120 
1121   ierr = MatGetSubMatrices(pmat,n_local,bjac->is,bjac->is,scall,&bjac->pmat);CHKERRQ(ierr);
1122   if (pc->useAmat) {
1123     ierr = PetscObjectGetOptionsPrefix((PetscObject)mat,&mprefix);CHKERRQ(ierr);
1124     ierr = MatGetSubMatrices(mat,n_local,bjac->is,bjac->is,scall,&bjac->mat);CHKERRQ(ierr);
1125   }
1126   /* Return control to the user so that the submatrices can be modified (e.g., to apply
1127      different boundary conditions for the submatrices than for the global problem) */
1128   ierr = PCModifySubMatrices(pc,n_local,bjac->is,bjac->is,bjac->pmat,pc->modifysubmatricesP);CHKERRQ(ierr);
1129 
1130   ierr = PetscObjectGetOptionsPrefix((PetscObject)pmat,&pprefix);CHKERRQ(ierr);
1131   for (i=0; i<n_local; i++) {
1132     ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)bjac->pmat[i]);CHKERRQ(ierr);
1133     ierr = PetscObjectSetOptionsPrefix((PetscObject)bjac->pmat[i],pprefix);CHKERRQ(ierr);
1134     if (pc->useAmat) {
1135       ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)bjac->mat[i]);CHKERRQ(ierr);
1136       ierr = PetscObjectSetOptionsPrefix((PetscObject)bjac->mat[i],mprefix);CHKERRQ(ierr);
1137       ierr = KSPSetOperators(jac->ksp[i],bjac->mat[i],bjac->pmat[i]);CHKERRQ(ierr);
1138     } else {
1139       ierr = KSPSetOperators(jac->ksp[i],bjac->pmat[i],bjac->pmat[i]);CHKERRQ(ierr);
1140     }
1141     if (pc->setfromoptionscalled) {
1142       ierr = KSPSetFromOptions(jac->ksp[i]);CHKERRQ(ierr);
1143     }
1144   }
1145   PetscFunctionReturn(0);
1146 }
1147 
1148 /* ---------------------------------------------------------------------------------------------*/
1149 /*
1150       These are for a single block with multiple processes;
1151 */
1152 #undef __FUNCT__
1153 #define __FUNCT__ "PCReset_BJacobi_Multiproc"
1154 static PetscErrorCode PCReset_BJacobi_Multiproc(PC pc)
1155 {
1156   PC_BJacobi           *jac   = (PC_BJacobi*)pc->data;
1157   PC_BJacobi_Multiproc *mpjac = (PC_BJacobi_Multiproc*)jac->data;
1158   PetscErrorCode       ierr;
1159 
1160   PetscFunctionBegin;
1161   ierr = VecDestroy(&mpjac->ysub);CHKERRQ(ierr);
1162   ierr = VecDestroy(&mpjac->xsub);CHKERRQ(ierr);
1163   ierr = MatDestroy(&mpjac->submats);CHKERRQ(ierr);
1164   if (jac->ksp) {ierr = KSPReset(jac->ksp[0]);CHKERRQ(ierr);}
1165   PetscFunctionReturn(0);
1166 }
1167 
1168 #undef __FUNCT__
1169 #define __FUNCT__ "PCDestroy_BJacobi_Multiproc"
1170 static PetscErrorCode PCDestroy_BJacobi_Multiproc(PC pc)
1171 {
1172   PC_BJacobi           *jac   = (PC_BJacobi*)pc->data;
1173   PC_BJacobi_Multiproc *mpjac = (PC_BJacobi_Multiproc*)jac->data;
1174   PetscErrorCode       ierr;
1175 
1176   PetscFunctionBegin;
1177   ierr = PCReset_BJacobi_Multiproc(pc);CHKERRQ(ierr);
1178   ierr = KSPDestroy(&jac->ksp[0]);CHKERRQ(ierr);
1179   ierr = PetscFree(jac->ksp);CHKERRQ(ierr);
1180   ierr = PetscSubcommDestroy(&mpjac->psubcomm);CHKERRQ(ierr);
1181 
1182   ierr = PetscFree(mpjac);CHKERRQ(ierr);
1183   ierr = PetscFree(pc->data);CHKERRQ(ierr);
1184   PetscFunctionReturn(0);
1185 }
1186 
1187 #undef __FUNCT__
1188 #define __FUNCT__ "PCApply_BJacobi_Multiproc"
1189 static PetscErrorCode PCApply_BJacobi_Multiproc(PC pc,Vec x,Vec y)
1190 {
1191   PC_BJacobi           *jac   = (PC_BJacobi*)pc->data;
1192   PC_BJacobi_Multiproc *mpjac = (PC_BJacobi_Multiproc*)jac->data;
1193   PetscErrorCode       ierr;
1194   PetscScalar          *yarray;
1195   const PetscScalar    *xarray;
1196   KSPConvergedReason   reason;
1197 
1198   PetscFunctionBegin;
1199   /* place x's and y's local arrays into xsub and ysub */
1200   ierr = VecGetArrayRead(x,&xarray);CHKERRQ(ierr);
1201   ierr = VecGetArray(y,&yarray);CHKERRQ(ierr);
1202   ierr = VecPlaceArray(mpjac->xsub,xarray);CHKERRQ(ierr);
1203   ierr = VecPlaceArray(mpjac->ysub,yarray);CHKERRQ(ierr);
1204 
1205   /* apply preconditioner on each matrix block */
1206   ierr = PetscLogEventBegin(PC_ApplyOnMproc,jac->ksp[0],mpjac->xsub,mpjac->ysub,0);CHKERRQ(ierr);
1207   ierr = KSPSolve(jac->ksp[0],mpjac->xsub,mpjac->ysub);CHKERRQ(ierr);
1208   ierr = PetscLogEventEnd(PC_ApplyOnMproc,jac->ksp[0],mpjac->xsub,mpjac->ysub,0);CHKERRQ(ierr);
1209   ierr = KSPGetConvergedReason(jac->ksp[0],&reason);CHKERRQ(ierr);
1210   if (reason == KSP_DIVERGED_PCSETUP_FAILED) {
1211     pc->failedreason = PC_SUBPC_ERROR;
1212   }
1213 
1214   ierr = VecResetArray(mpjac->xsub);CHKERRQ(ierr);
1215   ierr = VecResetArray(mpjac->ysub);CHKERRQ(ierr);
1216   ierr = VecRestoreArrayRead(x,&xarray);CHKERRQ(ierr);
1217   ierr = VecRestoreArray(y,&yarray);CHKERRQ(ierr);
1218   PetscFunctionReturn(0);
1219 }
1220 
1221 #undef __FUNCT__
1222 #define __FUNCT__ "PCSetUp_BJacobi_Multiproc"
1223 static PetscErrorCode PCSetUp_BJacobi_Multiproc(PC pc)
1224 {
1225   PC_BJacobi           *jac   = (PC_BJacobi*)pc->data;
1226   PC_BJacobi_Multiproc *mpjac = (PC_BJacobi_Multiproc*)jac->data;
1227   PetscErrorCode       ierr;
1228   PetscInt             m,n;
1229   MPI_Comm             comm,subcomm=0;
1230   const char           *prefix;
1231   PetscBool            wasSetup = PETSC_TRUE;
1232 
1233   PetscFunctionBegin;
1234   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
1235   if (jac->n_local > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Only a single block in a subcommunicator is supported");
1236   jac->n_local = 1; /* currently only a single block is supported for a subcommunicator */
1237   if (!pc->setupcalled) {
1238     wasSetup  = PETSC_FALSE;
1239     ierr      = PetscNewLog(pc,&mpjac);CHKERRQ(ierr);
1240     jac->data = (void*)mpjac;
1241 
1242     /* initialize datastructure mpjac */
1243     if (!jac->psubcomm) {
1244       /* Create default contiguous subcommunicatiors if user does not provide them */
1245       ierr = PetscSubcommCreate(comm,&jac->psubcomm);CHKERRQ(ierr);
1246       ierr = PetscSubcommSetNumber(jac->psubcomm,jac->n);CHKERRQ(ierr);
1247       ierr = PetscSubcommSetType(jac->psubcomm,PETSC_SUBCOMM_CONTIGUOUS);CHKERRQ(ierr);
1248       ierr = PetscLogObjectMemory((PetscObject)pc,sizeof(PetscSubcomm));CHKERRQ(ierr);
1249     }
1250     mpjac->psubcomm = jac->psubcomm;
1251     subcomm         = PetscSubcommChild(mpjac->psubcomm);
1252 
1253     /* Get matrix blocks of pmat */
1254     ierr = MatGetMultiProcBlock(pc->pmat,subcomm,MAT_INITIAL_MATRIX,&mpjac->submats);CHKERRQ(ierr);
1255 
1256     /* create a new PC that processors in each subcomm have copy of */
1257     ierr = PetscMalloc1(1,&jac->ksp);CHKERRQ(ierr);
1258     ierr = KSPCreate(subcomm,&jac->ksp[0]);CHKERRQ(ierr);
1259     ierr = KSPSetErrorIfNotConverged(jac->ksp[0],pc->erroriffailure);CHKERRQ(ierr);
1260     ierr = PetscObjectIncrementTabLevel((PetscObject)jac->ksp[0],(PetscObject)pc,1);CHKERRQ(ierr);
1261     ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)jac->ksp[0]);CHKERRQ(ierr);
1262     ierr = KSPSetOperators(jac->ksp[0],mpjac->submats,mpjac->submats);CHKERRQ(ierr);
1263     ierr = KSPGetPC(jac->ksp[0],&mpjac->pc);CHKERRQ(ierr);
1264 
1265     ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr);
1266     ierr = KSPSetOptionsPrefix(jac->ksp[0],prefix);CHKERRQ(ierr);
1267     ierr = KSPAppendOptionsPrefix(jac->ksp[0],"sub_");CHKERRQ(ierr);
1268     /*
1269       PetscMPIInt rank,subsize,subrank;
1270       ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
1271       ierr = MPI_Comm_size(subcomm,&subsize);CHKERRQ(ierr);
1272       ierr = MPI_Comm_rank(subcomm,&subrank);CHKERRQ(ierr);
1273 
1274       ierr = MatGetLocalSize(mpjac->submats,&m,NULL);CHKERRQ(ierr);
1275       ierr = MatGetSize(mpjac->submats,&n,NULL);CHKERRQ(ierr);
1276       ierr = PetscSynchronizedPrintf(comm,"[%d], sub-size %d,sub-rank %d\n",rank,subsize,subrank);
1277       ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
1278     */
1279 
1280     /* create dummy vectors xsub and ysub */
1281     ierr = MatGetLocalSize(mpjac->submats,&m,&n);CHKERRQ(ierr);
1282     ierr = VecCreateMPIWithArray(subcomm,1,n,PETSC_DECIDE,NULL,&mpjac->xsub);CHKERRQ(ierr);
1283     ierr = VecCreateMPIWithArray(subcomm,1,m,PETSC_DECIDE,NULL,&mpjac->ysub);CHKERRQ(ierr);
1284 #if defined(PETSC_HAVE_CUSP)
1285     ierr = VecSetType(mpjac->xsub,VECMPICUSP);CHKERRQ(ierr);
1286     ierr = VecSetType(mpjac->ysub,VECMPICUSP);CHKERRQ(ierr);
1287 #elif defined(PETSC_HAVE_VECCUDA)
1288     ierr = VecSetType(mpjac->xsub,VECMPICUDA);CHKERRQ(ierr);
1289     ierr = VecSetType(mpjac->ysub,VECMPICUDA);CHKERRQ(ierr);
1290 #endif
1291     ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)mpjac->xsub);CHKERRQ(ierr);
1292     ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)mpjac->ysub);CHKERRQ(ierr);
1293 
1294     pc->ops->reset   = PCReset_BJacobi_Multiproc;
1295     pc->ops->destroy = PCDestroy_BJacobi_Multiproc;
1296     pc->ops->apply   = PCApply_BJacobi_Multiproc;
1297   } else { /* pc->setupcalled */
1298     subcomm = PetscSubcommChild(mpjac->psubcomm);
1299     if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
1300       /* destroy old matrix blocks, then get new matrix blocks */
1301       if (mpjac->submats) {ierr = MatDestroy(&mpjac->submats);CHKERRQ(ierr);}
1302       ierr = MatGetMultiProcBlock(pc->pmat,subcomm,MAT_INITIAL_MATRIX,&mpjac->submats);CHKERRQ(ierr);
1303     } else {
1304       ierr = MatGetMultiProcBlock(pc->pmat,subcomm,MAT_REUSE_MATRIX,&mpjac->submats);CHKERRQ(ierr);
1305     }
1306     ierr = KSPSetOperators(jac->ksp[0],mpjac->submats,mpjac->submats);CHKERRQ(ierr);
1307   }
1308 
1309   if (!wasSetup && pc->setfromoptionscalled) {
1310     ierr = KSPSetFromOptions(jac->ksp[0]);CHKERRQ(ierr);
1311   }
1312   PetscFunctionReturn(0);
1313 }
1314