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