xref: /petsc/src/ksp/pc/impls/bjacobi/bjacobi.c (revision d172c84b7da0a47fed8c9ccbc9dfdecdae586ec8)
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) {ierr = PCBJacobiSetTotalBlocks(pc,blocks,NULL);CHKERRQ(ierr);}
168   ierr = PetscOptionsInt("-pc_bjacobi_local_blocks","Local number of blocks","PCBJacobiSetLocalBlocks",jac->n_local,&blocks,&flg);CHKERRQ(ierr);
169   if (flg) {ierr = PCBJacobiSetLocalBlocks(pc,blocks,NULL);CHKERRQ(ierr);}
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    Options Database Key:
457 .  -pc_bjacobi_local_blocks <blocks> - Sets the number of local blocks
458 
459    Note:
460    Currently only a limited number of blocking configurations are supported.
461 
462    Level: intermediate
463 
464 .keywords: PC, set, number, Jacobi, local, blocks
465 
466 .seealso: PCSetUseAmat(), PCBJacobiSetTotalBlocks()
467 @*/
468 PetscErrorCode  PCBJacobiSetLocalBlocks(PC pc,PetscInt blocks,const PetscInt lens[])
469 {
470   PetscErrorCode ierr;
471 
472   PetscFunctionBegin;
473   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
474   if (blocks < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Must have nonegative blocks");
475   ierr = PetscTryMethod(pc,"PCBJacobiSetLocalBlocks_C",(PC,PetscInt,const PetscInt []),(pc,blocks,lens));CHKERRQ(ierr);
476   PetscFunctionReturn(0);
477 }
478 
479 /*@C
480    PCBJacobiGetLocalBlocks - Gets the local number of blocks for the block
481    Jacobi preconditioner.
482 
483    Not Collective
484 
485    Input Parameters:
486 +  pc - the preconditioner context
487 .  blocks - the number of blocks
488 -  lens - [optional] integer array containing size of each block
489 
490    Note:
491    Currently only a limited number of blocking configurations are supported.
492 
493    Level: intermediate
494 
495 .keywords: PC, get, number, Jacobi, local, blocks
496 
497 .seealso: PCSetUseAmat(), PCBJacobiGetTotalBlocks()
498 @*/
499 PetscErrorCode  PCBJacobiGetLocalBlocks(PC pc, PetscInt *blocks, const PetscInt *lens[])
500 {
501   PetscErrorCode ierr;
502 
503   PetscFunctionBegin;
504   PetscValidHeaderSpecific(pc, PC_CLASSID,1);
505   PetscValidIntPointer(blocks,2);
506   ierr = PetscUseMethod(pc,"PCBJacobiGetLocalBlocks_C",(PC,PetscInt*, const PetscInt *[]),(pc,blocks,lens));CHKERRQ(ierr);
507   PetscFunctionReturn(0);
508 }
509 
510 /* -----------------------------------------------------------------------------------*/
511 
512 /*MC
513    PCBJACOBI - Use block Jacobi preconditioning, each block is (approximately) solved with
514            its own KSP object.
515 
516    Options Database Keys:
517 +  -pc_use_amat - use Amat to apply block of operator in inner Krylov method
518 -  -pc_bjacobi_blocks <n> - use n total blocks
519 
520    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.
521 
522      To set options on the solvers for each block append -sub_ to all the KSP, KSP, and PC
523         options database keys. For example, -sub_pc_type ilu -sub_pc_factor_levels 1 -sub_ksp_type preonly
524 
525      To set the options on the solvers separate for each block call PCBJacobiGetSubKSP()
526          and set the options directly on the resulting KSP object (you can access its PC
527          KSPGetPC())
528 
529      For GPU-based vectors (CUDA, CUSP, ViennaCL) it is recommended to use exactly one block per MPI process for best
530          performance.  Different block partitioning may lead to additional data transfers
531          between host and GPU that lead to degraded performance.
532 
533      The options prefix for each block is sub_, for example -sub_pc_type lu.
534 
535      When multiple processes share a single block, each block encompasses exactly all the unknowns owned its set of processes.
536 
537    Level: beginner
538 
539    Concepts: block Jacobi
540 
541 .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
542            PCASM, PCSetUseAmat(), PCGetUseAmat(), PCBJacobiGetSubKSP(), PCBJacobiSetTotalBlocks(),
543            PCBJacobiSetLocalBlocks(), PCSetModifySubmatrices()
544 M*/
545 
546 PETSC_EXTERN PetscErrorCode PCCreate_BJacobi(PC pc)
547 {
548   PetscErrorCode ierr;
549   PetscMPIInt    rank;
550   PC_BJacobi     *jac;
551 
552   PetscFunctionBegin;
553   ierr = PetscNewLog(pc,&jac);CHKERRQ(ierr);
554   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
555 
556   pc->ops->apply           = 0;
557   pc->ops->applytranspose  = 0;
558   pc->ops->setup           = PCSetUp_BJacobi;
559   pc->ops->destroy         = PCDestroy_BJacobi;
560   pc->ops->setfromoptions  = PCSetFromOptions_BJacobi;
561   pc->ops->view            = PCView_BJacobi;
562   pc->ops->applyrichardson = 0;
563 
564   pc->data               = (void*)jac;
565   jac->n                 = -1;
566   jac->n_local           = -1;
567   jac->first_local       = rank;
568   jac->ksp               = 0;
569   jac->same_local_solves = PETSC_TRUE;
570   jac->g_lens            = 0;
571   jac->l_lens            = 0;
572   jac->psubcomm          = 0;
573 
574   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBJacobiGetSubKSP_C",PCBJacobiGetSubKSP_BJacobi);CHKERRQ(ierr);
575   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBJacobiSetTotalBlocks_C",PCBJacobiSetTotalBlocks_BJacobi);CHKERRQ(ierr);
576   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBJacobiGetTotalBlocks_C",PCBJacobiGetTotalBlocks_BJacobi);CHKERRQ(ierr);
577   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBJacobiSetLocalBlocks_C",PCBJacobiSetLocalBlocks_BJacobi);CHKERRQ(ierr);
578   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBJacobiGetLocalBlocks_C",PCBJacobiGetLocalBlocks_BJacobi);CHKERRQ(ierr);
579   PetscFunctionReturn(0);
580 }
581 
582 /* --------------------------------------------------------------------------------------------*/
583 /*
584         These are for a single block per processor; works for AIJ, BAIJ; Seq and MPI
585 */
586 static PetscErrorCode PCReset_BJacobi_Singleblock(PC pc)
587 {
588   PC_BJacobi             *jac  = (PC_BJacobi*)pc->data;
589   PC_BJacobi_Singleblock *bjac = (PC_BJacobi_Singleblock*)jac->data;
590   PetscErrorCode         ierr;
591 
592   PetscFunctionBegin;
593   ierr = KSPReset(jac->ksp[0]);CHKERRQ(ierr);
594   ierr = VecDestroy(&bjac->x);CHKERRQ(ierr);
595   ierr = VecDestroy(&bjac->y);CHKERRQ(ierr);
596   PetscFunctionReturn(0);
597 }
598 
599 static PetscErrorCode PCDestroy_BJacobi_Singleblock(PC pc)
600 {
601   PC_BJacobi             *jac  = (PC_BJacobi*)pc->data;
602   PC_BJacobi_Singleblock *bjac = (PC_BJacobi_Singleblock*)jac->data;
603   PetscErrorCode         ierr;
604 
605   PetscFunctionBegin;
606   ierr = PCReset_BJacobi_Singleblock(pc);CHKERRQ(ierr);
607   ierr = KSPDestroy(&jac->ksp[0]);CHKERRQ(ierr);
608   ierr = PetscFree(jac->ksp);CHKERRQ(ierr);
609   ierr = PetscFree(jac->l_lens);CHKERRQ(ierr);
610   ierr = PetscFree(jac->g_lens);CHKERRQ(ierr);
611   ierr = PetscFree(bjac);CHKERRQ(ierr);
612   ierr = PetscFree(pc->data);CHKERRQ(ierr);
613   PetscFunctionReturn(0);
614 }
615 
616 static PetscErrorCode PCSetUpOnBlocks_BJacobi_Singleblock(PC pc)
617 {
618   PetscErrorCode     ierr;
619   PC_BJacobi         *jac = (PC_BJacobi*)pc->data;
620   KSP                subksp = jac->ksp[0];
621   KSPConvergedReason reason;
622 
623   PetscFunctionBegin;
624   ierr = KSPSetUp(subksp);CHKERRQ(ierr);
625   ierr = KSPGetConvergedReason(subksp,&reason);CHKERRQ(ierr);
626   if (reason == KSP_DIVERGED_PCSETUP_FAILED) {
627     pc->failedreason = PC_SUBPC_ERROR;
628   }
629   PetscFunctionReturn(0);
630 }
631 
632 static PetscErrorCode PCApply_BJacobi_Singleblock(PC pc,Vec x,Vec y)
633 {
634   PetscErrorCode         ierr;
635   PC_BJacobi             *jac  = (PC_BJacobi*)pc->data;
636   PC_BJacobi_Singleblock *bjac = (PC_BJacobi_Singleblock*)jac->data;
637 
638   PetscFunctionBegin;
639   ierr = VecGetLocalVectorRead(x, bjac->x);CHKERRQ(ierr);
640   ierr = VecGetLocalVector(y, bjac->y);CHKERRQ(ierr);
641  /* Since the inner KSP matrix may point directly to the diagonal block of an MPI matrix the inner
642      matrix may change even if the outter KSP/PC has not updated the preconditioner, this will trigger a rebuild
643      of the inner preconditioner automatically unless we pass down the outter preconditioners reuse flag.*/
644   ierr = KSPSetReusePreconditioner(jac->ksp[0],pc->reusepreconditioner);CHKERRQ(ierr);
645   ierr = KSPSolve(jac->ksp[0],bjac->x,bjac->y);CHKERRQ(ierr);
646   ierr = VecRestoreLocalVectorRead(x, bjac->x);CHKERRQ(ierr);
647   ierr = VecRestoreLocalVector(y, bjac->y);CHKERRQ(ierr);
648   PetscFunctionReturn(0);
649 }
650 
651 static PetscErrorCode PCApplySymmetricLeft_BJacobi_Singleblock(PC pc,Vec x,Vec y)
652 {
653   PetscErrorCode         ierr;
654   PC_BJacobi             *jac  = (PC_BJacobi*)pc->data;
655   PC_BJacobi_Singleblock *bjac = (PC_BJacobi_Singleblock*)jac->data;
656   PetscScalar            *y_array;
657   const PetscScalar      *x_array;
658   PC                     subpc;
659 
660   PetscFunctionBegin;
661   /*
662       The VecPlaceArray() is to avoid having to copy the
663     y vector into the bjac->x vector. The reason for
664     the bjac->x vector is that we need a sequential vector
665     for the sequential solve.
666   */
667   ierr = VecGetArrayRead(x,&x_array);CHKERRQ(ierr);
668   ierr = VecGetArray(y,&y_array);CHKERRQ(ierr);
669   ierr = VecPlaceArray(bjac->x,x_array);CHKERRQ(ierr);
670   ierr = VecPlaceArray(bjac->y,y_array);CHKERRQ(ierr);
671   /* apply the symmetric left portion of the inner PC operator */
672   /* note this by-passes the inner KSP and its options completely */
673   ierr = KSPGetPC(jac->ksp[0],&subpc);CHKERRQ(ierr);
674   ierr = PCApplySymmetricLeft(subpc,bjac->x,bjac->y);CHKERRQ(ierr);
675   ierr = VecResetArray(bjac->x);CHKERRQ(ierr);
676   ierr = VecResetArray(bjac->y);CHKERRQ(ierr);
677   ierr = VecRestoreArrayRead(x,&x_array);CHKERRQ(ierr);
678   ierr = VecRestoreArray(y,&y_array);CHKERRQ(ierr);
679   PetscFunctionReturn(0);
680 }
681 
682 static PetscErrorCode PCApplySymmetricRight_BJacobi_Singleblock(PC pc,Vec x,Vec y)
683 {
684   PetscErrorCode         ierr;
685   PC_BJacobi             *jac  = (PC_BJacobi*)pc->data;
686   PC_BJacobi_Singleblock *bjac = (PC_BJacobi_Singleblock*)jac->data;
687   PetscScalar            *y_array;
688   const PetscScalar      *x_array;
689   PC                     subpc;
690 
691   PetscFunctionBegin;
692   /*
693       The VecPlaceArray() is to avoid having to copy the
694     y vector into the bjac->x vector. The reason for
695     the bjac->x vector is that we need a sequential vector
696     for the sequential solve.
697   */
698   ierr = VecGetArrayRead(x,&x_array);CHKERRQ(ierr);
699   ierr = VecGetArray(y,&y_array);CHKERRQ(ierr);
700   ierr = VecPlaceArray(bjac->x,x_array);CHKERRQ(ierr);
701   ierr = VecPlaceArray(bjac->y,y_array);CHKERRQ(ierr);
702 
703   /* apply the symmetric right portion of the inner PC operator */
704   /* note this by-passes the inner KSP and its options completely */
705 
706   ierr = KSPGetPC(jac->ksp[0],&subpc);CHKERRQ(ierr);
707   ierr = PCApplySymmetricRight(subpc,bjac->x,bjac->y);CHKERRQ(ierr);
708 
709   ierr = VecRestoreArrayRead(x,&x_array);CHKERRQ(ierr);
710   ierr = VecRestoreArray(y,&y_array);CHKERRQ(ierr);
711   PetscFunctionReturn(0);
712 }
713 
714 static PetscErrorCode PCApplyTranspose_BJacobi_Singleblock(PC pc,Vec x,Vec y)
715 {
716   PetscErrorCode         ierr;
717   PC_BJacobi             *jac  = (PC_BJacobi*)pc->data;
718   PC_BJacobi_Singleblock *bjac = (PC_BJacobi_Singleblock*)jac->data;
719   PetscScalar            *y_array;
720   const PetscScalar      *x_array;
721 
722   PetscFunctionBegin;
723   /*
724       The VecPlaceArray() is to avoid having to copy the
725     y vector into the bjac->x vector. The reason for
726     the bjac->x vector is that we need a sequential vector
727     for the sequential solve.
728   */
729   ierr = VecGetArrayRead(x,&x_array);CHKERRQ(ierr);
730   ierr = VecGetArray(y,&y_array);CHKERRQ(ierr);
731   ierr = VecPlaceArray(bjac->x,x_array);CHKERRQ(ierr);
732   ierr = VecPlaceArray(bjac->y,y_array);CHKERRQ(ierr);
733   ierr = KSPSolveTranspose(jac->ksp[0],bjac->x,bjac->y);CHKERRQ(ierr);
734   ierr = VecResetArray(bjac->x);CHKERRQ(ierr);
735   ierr = VecResetArray(bjac->y);CHKERRQ(ierr);
736   ierr = VecRestoreArrayRead(x,&x_array);CHKERRQ(ierr);
737   ierr = VecRestoreArray(y,&y_array);CHKERRQ(ierr);
738   PetscFunctionReturn(0);
739 }
740 
741 static PetscErrorCode PCSetUp_BJacobi_Singleblock(PC pc,Mat mat,Mat pmat)
742 {
743   PC_BJacobi             *jac = (PC_BJacobi*)pc->data;
744   PetscErrorCode         ierr;
745   PetscInt               m;
746   KSP                    ksp;
747   PC_BJacobi_Singleblock *bjac;
748   PetscBool              wasSetup = PETSC_TRUE;
749 #if defined(PETSC_HAVE_CUSP) || defined(PETSC_HAVE_VECCUDA) || defined(PETSC_HAVE_VIENNACL)
750   PetscBool              is_gpumatrix = PETSC_FALSE;
751 #endif
752 
753   PetscFunctionBegin;
754   if (!pc->setupcalled) {
755     const char *prefix;
756 
757     if (!jac->ksp) {
758       wasSetup = PETSC_FALSE;
759 
760       ierr = KSPCreate(PETSC_COMM_SELF,&ksp);CHKERRQ(ierr);
761       ierr = KSPSetErrorIfNotConverged(ksp,pc->erroriffailure);CHKERRQ(ierr);
762       ierr = PetscObjectIncrementTabLevel((PetscObject)ksp,(PetscObject)pc,1);CHKERRQ(ierr);
763       ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)ksp);CHKERRQ(ierr);
764       ierr = KSPSetType(ksp,KSPPREONLY);CHKERRQ(ierr);
765       ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr);
766       ierr = KSPSetOptionsPrefix(ksp,prefix);CHKERRQ(ierr);
767       ierr = KSPAppendOptionsPrefix(ksp,"sub_");CHKERRQ(ierr);
768 
769       pc->ops->reset               = PCReset_BJacobi_Singleblock;
770       pc->ops->destroy             = PCDestroy_BJacobi_Singleblock;
771       pc->ops->apply               = PCApply_BJacobi_Singleblock;
772       pc->ops->applysymmetricleft  = PCApplySymmetricLeft_BJacobi_Singleblock;
773       pc->ops->applysymmetricright = PCApplySymmetricRight_BJacobi_Singleblock;
774       pc->ops->applytranspose      = PCApplyTranspose_BJacobi_Singleblock;
775       pc->ops->setuponblocks       = PCSetUpOnBlocks_BJacobi_Singleblock;
776 
777       ierr        = PetscMalloc1(1,&jac->ksp);CHKERRQ(ierr);
778       jac->ksp[0] = ksp;
779 
780       ierr      = PetscNewLog(pc,&bjac);CHKERRQ(ierr);
781       jac->data = (void*)bjac;
782     } else {
783       ksp  = jac->ksp[0];
784       bjac = (PC_BJacobi_Singleblock*)jac->data;
785     }
786 
787     /*
788       The reason we need to generate these vectors is to serve
789       as the right-hand side and solution vector for the solve on the
790       block. We do not need to allocate space for the vectors since
791       that is provided via VecPlaceArray() just before the call to
792       KSPSolve() on the block.
793     */
794     ierr = MatGetSize(pmat,&m,&m);CHKERRQ(ierr);
795     ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,1,m,NULL,&bjac->x);CHKERRQ(ierr);
796     ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,1,m,NULL,&bjac->y);CHKERRQ(ierr);
797 #if defined(PETSC_HAVE_CUSP)
798     ierr = PetscObjectTypeCompareAny((PetscObject)pmat,&is_gpumatrix,MATAIJCUSP,MATSEQAIJCUSP,MATMPIAIJCUSP,"");CHKERRQ(ierr);
799     if (is_gpumatrix) {
800       ierr = VecSetType(bjac->x,VECCUSP);CHKERRQ(ierr);
801       ierr = VecSetType(bjac->y,VECCUSP);CHKERRQ(ierr);
802     }
803 #elif defined(PETSC_HAVE_VECCUDA)
804     ierr = PetscObjectTypeCompareAny((PetscObject)pmat,&is_gpumatrix,MATAIJCUSPARSE,MATSEQAIJCUSPARSE,MATMPIAIJCUSPARSE,"");CHKERRQ(ierr);
805     if (is_gpumatrix) {
806       ierr = VecSetType(bjac->x,VECCUDA);CHKERRQ(ierr);
807       ierr = VecSetType(bjac->y,VECCUDA);CHKERRQ(ierr);
808     }
809 #elif defined(PETSC_HAVE_VIENNACL)
810     ierr = PetscObjectTypeCompareAny((PetscObject)pmat,&is_gpumatrix,MATAIJVIENNACL,MATSEQAIJVIENNACL,MATMPIAIJVIENNACL,"");CHKERRQ(ierr);
811     if (is_gpumatrix) {
812       ierr = VecSetType(bjac->x,VECVIENNACL);CHKERRQ(ierr);
813       ierr = VecSetType(bjac->y,VECVIENNACL);CHKERRQ(ierr);
814     }
815 #endif
816     ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)bjac->x);CHKERRQ(ierr);
817     ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)bjac->y);CHKERRQ(ierr);
818   } else {
819     ksp  = jac->ksp[0];
820     bjac = (PC_BJacobi_Singleblock*)jac->data;
821   }
822   if (pc->useAmat) {
823     ierr = KSPSetOperators(ksp,mat,pmat);CHKERRQ(ierr);
824   } else {
825     ierr = KSPSetOperators(ksp,pmat,pmat);CHKERRQ(ierr);
826   }
827   if (!wasSetup && pc->setfromoptionscalled) {
828     /* If PCSetFromOptions_BJacobi is called later, KSPSetFromOptions will be called at that time. */
829     ierr = KSPSetFromOptions(ksp);CHKERRQ(ierr);
830   }
831   PetscFunctionReturn(0);
832 }
833 
834 /* ---------------------------------------------------------------------------------------------*/
835 static PetscErrorCode PCReset_BJacobi_Multiblock(PC pc)
836 {
837   PC_BJacobi            *jac  = (PC_BJacobi*)pc->data;
838   PC_BJacobi_Multiblock *bjac = (PC_BJacobi_Multiblock*)jac->data;
839   PetscErrorCode        ierr;
840   PetscInt              i;
841 
842   PetscFunctionBegin;
843   if (bjac && bjac->pmat) {
844     ierr = MatDestroyMatrices(jac->n_local,&bjac->pmat);CHKERRQ(ierr);
845     if (pc->useAmat) {
846       ierr = MatDestroyMatrices(jac->n_local,&bjac->mat);CHKERRQ(ierr);
847     }
848   }
849 
850   for (i=0; i<jac->n_local; i++) {
851     ierr = KSPReset(jac->ksp[i]);CHKERRQ(ierr);
852     if (bjac && bjac->x) {
853       ierr = VecDestroy(&bjac->x[i]);CHKERRQ(ierr);
854       ierr = VecDestroy(&bjac->y[i]);CHKERRQ(ierr);
855       ierr = ISDestroy(&bjac->is[i]);CHKERRQ(ierr);
856     }
857   }
858   ierr = PetscFree(jac->l_lens);CHKERRQ(ierr);
859   ierr = PetscFree(jac->g_lens);CHKERRQ(ierr);
860   PetscFunctionReturn(0);
861 }
862 
863 static PetscErrorCode PCDestroy_BJacobi_Multiblock(PC pc)
864 {
865   PC_BJacobi            *jac  = (PC_BJacobi*)pc->data;
866   PC_BJacobi_Multiblock *bjac = (PC_BJacobi_Multiblock*)jac->data;
867   PetscErrorCode        ierr;
868   PetscInt              i;
869 
870   PetscFunctionBegin;
871   ierr = PCReset_BJacobi_Multiblock(pc);CHKERRQ(ierr);
872   if (bjac) {
873     ierr = PetscFree2(bjac->x,bjac->y);CHKERRQ(ierr);
874     ierr = PetscFree(bjac->starts);CHKERRQ(ierr);
875     ierr = PetscFree(bjac->is);CHKERRQ(ierr);
876   }
877   ierr = PetscFree(jac->data);CHKERRQ(ierr);
878   for (i=0; i<jac->n_local; i++) {
879     ierr = KSPDestroy(&jac->ksp[i]);CHKERRQ(ierr);
880   }
881   ierr = PetscFree(jac->ksp);CHKERRQ(ierr);
882   ierr = PetscFree(pc->data);CHKERRQ(ierr);
883   PetscFunctionReturn(0);
884 }
885 
886 static PetscErrorCode PCSetUpOnBlocks_BJacobi_Multiblock(PC pc)
887 {
888   PC_BJacobi         *jac = (PC_BJacobi*)pc->data;
889   PetscErrorCode     ierr;
890   PetscInt           i,n_local = jac->n_local;
891   KSPConvergedReason reason;
892 
893   PetscFunctionBegin;
894   for (i=0; i<n_local; i++) {
895     ierr = KSPSetUp(jac->ksp[i]);CHKERRQ(ierr);
896     ierr = KSPGetConvergedReason(jac->ksp[i],&reason);CHKERRQ(ierr);
897     if (reason == KSP_DIVERGED_PCSETUP_FAILED) {
898       pc->failedreason = PC_SUBPC_ERROR;
899     }
900   }
901   PetscFunctionReturn(0);
902 }
903 
904 /*
905       Preconditioner for block Jacobi
906 */
907 static PetscErrorCode PCApply_BJacobi_Multiblock(PC pc,Vec x,Vec y)
908 {
909   PC_BJacobi            *jac = (PC_BJacobi*)pc->data;
910   PetscErrorCode        ierr;
911   PetscInt              i,n_local = jac->n_local;
912   PC_BJacobi_Multiblock *bjac = (PC_BJacobi_Multiblock*)jac->data;
913   PetscScalar           *yin;
914   const PetscScalar     *xin;
915 
916   PetscFunctionBegin;
917   ierr = VecGetArrayRead(x,&xin);CHKERRQ(ierr);
918   ierr = VecGetArray(y,&yin);CHKERRQ(ierr);
919   for (i=0; i<n_local; i++) {
920     /*
921        To avoid copying the subvector from x into a workspace we instead
922        make the workspace vector array point to the subpart of the array of
923        the global vector.
924     */
925     ierr = VecPlaceArray(bjac->x[i],xin+bjac->starts[i]);CHKERRQ(ierr);
926     ierr = VecPlaceArray(bjac->y[i],yin+bjac->starts[i]);CHKERRQ(ierr);
927 
928     ierr = PetscLogEventBegin(PC_ApplyOnBlocks,jac->ksp[i],bjac->x[i],bjac->y[i],0);CHKERRQ(ierr);
929     ierr = KSPSolve(jac->ksp[i],bjac->x[i],bjac->y[i]);CHKERRQ(ierr);
930     ierr = PetscLogEventEnd(PC_ApplyOnBlocks,jac->ksp[i],bjac->x[i],bjac->y[i],0);CHKERRQ(ierr);
931 
932     ierr = VecResetArray(bjac->x[i]);CHKERRQ(ierr);
933     ierr = VecResetArray(bjac->y[i]);CHKERRQ(ierr);
934   }
935   ierr = VecRestoreArrayRead(x,&xin);CHKERRQ(ierr);
936   ierr = VecRestoreArray(y,&yin);CHKERRQ(ierr);
937   PetscFunctionReturn(0);
938 }
939 
940 /*
941       Preconditioner for block Jacobi
942 */
943 static PetscErrorCode PCApplyTranspose_BJacobi_Multiblock(PC pc,Vec x,Vec y)
944 {
945   PC_BJacobi            *jac = (PC_BJacobi*)pc->data;
946   PetscErrorCode        ierr;
947   PetscInt              i,n_local = jac->n_local;
948   PC_BJacobi_Multiblock *bjac = (PC_BJacobi_Multiblock*)jac->data;
949   PetscScalar           *yin;
950   const PetscScalar     *xin;
951 
952   PetscFunctionBegin;
953   ierr = VecGetArrayRead(x,&xin);CHKERRQ(ierr);
954   ierr = VecGetArray(y,&yin);CHKERRQ(ierr);
955   for (i=0; i<n_local; i++) {
956     /*
957        To avoid copying the subvector from x into a workspace we instead
958        make the workspace vector array point to the subpart of the array of
959        the global vector.
960     */
961     ierr = VecPlaceArray(bjac->x[i],xin+bjac->starts[i]);CHKERRQ(ierr);
962     ierr = VecPlaceArray(bjac->y[i],yin+bjac->starts[i]);CHKERRQ(ierr);
963 
964     ierr = PetscLogEventBegin(PC_ApplyTransposeOnBlocks,jac->ksp[i],bjac->x[i],bjac->y[i],0);CHKERRQ(ierr);
965     ierr = KSPSolveTranspose(jac->ksp[i],bjac->x[i],bjac->y[i]);CHKERRQ(ierr);
966     ierr = PetscLogEventEnd(PC_ApplyTransposeOnBlocks,jac->ksp[i],bjac->x[i],bjac->y[i],0);CHKERRQ(ierr);
967 
968     ierr = VecResetArray(bjac->x[i]);CHKERRQ(ierr);
969     ierr = VecResetArray(bjac->y[i]);CHKERRQ(ierr);
970   }
971   ierr = VecRestoreArrayRead(x,&xin);CHKERRQ(ierr);
972   ierr = VecRestoreArray(y,&yin);CHKERRQ(ierr);
973   PetscFunctionReturn(0);
974 }
975 
976 static PetscErrorCode PCSetUp_BJacobi_Multiblock(PC pc,Mat mat,Mat pmat)
977 {
978   PC_BJacobi            *jac = (PC_BJacobi*)pc->data;
979   PetscErrorCode        ierr;
980   PetscInt              m,n_local,N,M,start,i;
981   const char            *prefix,*pprefix,*mprefix;
982   KSP                   ksp;
983   Vec                   x,y;
984   PC_BJacobi_Multiblock *bjac = (PC_BJacobi_Multiblock*)jac->data;
985   PC                    subpc;
986   IS                    is;
987   MatReuse              scall;
988 #if defined(PETSC_HAVE_CUSP) || defined(PETSC_HAVE_VECCUDA) || defined(PETSC_HAVE_VIENNACL)
989   PetscBool              is_gpumatrix = PETSC_FALSE;
990 #endif
991 
992   PetscFunctionBegin;
993   ierr = MatGetLocalSize(pc->pmat,&M,&N);CHKERRQ(ierr);
994 
995   n_local = jac->n_local;
996 
997   if (pc->useAmat) {
998     PetscBool same;
999     ierr = PetscObjectTypeCompare((PetscObject)mat,((PetscObject)pmat)->type_name,&same);CHKERRQ(ierr);
1000     if (!same) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_INCOMP,"Matrices not of same type");
1001   }
1002 
1003   if (!pc->setupcalled) {
1004     scall = MAT_INITIAL_MATRIX;
1005 
1006     if (!jac->ksp) {
1007       pc->ops->reset         = PCReset_BJacobi_Multiblock;
1008       pc->ops->destroy       = PCDestroy_BJacobi_Multiblock;
1009       pc->ops->apply         = PCApply_BJacobi_Multiblock;
1010       pc->ops->applytranspose= PCApplyTranspose_BJacobi_Multiblock;
1011       pc->ops->setuponblocks = PCSetUpOnBlocks_BJacobi_Multiblock;
1012 
1013       ierr = PetscNewLog(pc,&bjac);CHKERRQ(ierr);
1014       ierr = PetscMalloc1(n_local,&jac->ksp);CHKERRQ(ierr);
1015       ierr = PetscLogObjectMemory((PetscObject)pc,sizeof(n_local*sizeof(KSP)));CHKERRQ(ierr);
1016       ierr = PetscMalloc2(n_local,&bjac->x,n_local,&bjac->y);CHKERRQ(ierr);
1017       ierr = PetscMalloc1(n_local,&bjac->starts);CHKERRQ(ierr);
1018       ierr = PetscLogObjectMemory((PetscObject)pc,sizeof(n_local*sizeof(PetscScalar)));CHKERRQ(ierr);
1019 
1020       jac->data = (void*)bjac;
1021       ierr      = PetscMalloc1(n_local,&bjac->is);CHKERRQ(ierr);
1022       ierr      = PetscLogObjectMemory((PetscObject)pc,sizeof(n_local*sizeof(IS)));CHKERRQ(ierr);
1023 
1024       for (i=0; i<n_local; i++) {
1025         ierr = KSPCreate(PETSC_COMM_SELF,&ksp);CHKERRQ(ierr);
1026         ierr = KSPSetErrorIfNotConverged(ksp,pc->erroriffailure);CHKERRQ(ierr);
1027         ierr = PetscObjectIncrementTabLevel((PetscObject)ksp,(PetscObject)pc,1);CHKERRQ(ierr);
1028         ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)ksp);CHKERRQ(ierr);
1029         ierr = KSPSetType(ksp,KSPPREONLY);CHKERRQ(ierr);
1030         ierr = KSPGetPC(ksp,&subpc);CHKERRQ(ierr);
1031         ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr);
1032         ierr = KSPSetOptionsPrefix(ksp,prefix);CHKERRQ(ierr);
1033         ierr = KSPAppendOptionsPrefix(ksp,"sub_");CHKERRQ(ierr);
1034 
1035         jac->ksp[i] = ksp;
1036       }
1037     } else {
1038       bjac = (PC_BJacobi_Multiblock*)jac->data;
1039     }
1040 
1041     start = 0;
1042     for (i=0; i<n_local; i++) {
1043       m = jac->l_lens[i];
1044       /*
1045       The reason we need to generate these vectors is to serve
1046       as the right-hand side and solution vector for the solve on the
1047       block. We do not need to allocate space for the vectors since
1048       that is provided via VecPlaceArray() just before the call to
1049       KSPSolve() on the block.
1050 
1051       */
1052       ierr = VecCreateSeq(PETSC_COMM_SELF,m,&x);CHKERRQ(ierr);
1053       ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,1,m,NULL,&y);CHKERRQ(ierr);
1054 #if defined(PETSC_HAVE_CUSP)
1055       ierr = PetscObjectTypeCompareAny((PetscObject)pmat,&is_gpumatrix,MATAIJCUSP,MATSEQAIJCUSP,MATMPIAIJCUSP,"");CHKERRQ(ierr);
1056       if (is_gpumatrix) {
1057         ierr = VecSetType(x,VECCUSP);CHKERRQ(ierr);
1058         ierr = VecSetType(y,VECCUSP);CHKERRQ(ierr);
1059       }
1060 #elif defined(PETSC_HAVE_VECCUDA)
1061       ierr = PetscObjectTypeCompareAny((PetscObject)pmat,&is_gpumatrix,MATAIJCUSPARSE,MATSEQAIJCUSPARSE,MATMPIAIJCUSPARSE,"");CHKERRQ(ierr);
1062       if (is_gpumatrix) {
1063         ierr = VecSetType(x,VECCUDA);CHKERRQ(ierr);
1064         ierr = VecSetType(y,VECCUDA);CHKERRQ(ierr);
1065       }
1066 #elif defined(PETSC_HAVE_VIENNACL)
1067       ierr = PetscObjectTypeCompareAny((PetscObject)pmat,&is_gpumatrix,MATAIJVIENNACL,MATSEQAIJVIENNACL,MATMPIAIJVIENNACL,"");CHKERRQ(ierr);
1068       if (is_gpumatrix) {
1069         ierr = VecSetType(x,VECVIENNACL);CHKERRQ(ierr);
1070         ierr = VecSetType(y,VECVIENNACL);CHKERRQ(ierr);
1071       }
1072 #endif
1073       ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)x);CHKERRQ(ierr);
1074       ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)y);CHKERRQ(ierr);
1075 
1076       bjac->x[i]      = x;
1077       bjac->y[i]      = y;
1078       bjac->starts[i] = start;
1079 
1080       ierr        = ISCreateStride(PETSC_COMM_SELF,m,start,1,&is);CHKERRQ(ierr);
1081       bjac->is[i] = is;
1082       ierr        = PetscLogObjectParent((PetscObject)pc,(PetscObject)is);CHKERRQ(ierr);
1083 
1084       start += m;
1085     }
1086   } else {
1087     bjac = (PC_BJacobi_Multiblock*)jac->data;
1088     /*
1089        Destroy the blocks from the previous iteration
1090     */
1091     if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
1092       ierr = MatDestroyMatrices(n_local,&bjac->pmat);CHKERRQ(ierr);
1093       if (pc->useAmat) {
1094         ierr = MatDestroyMatrices(n_local,&bjac->mat);CHKERRQ(ierr);
1095       }
1096       scall = MAT_INITIAL_MATRIX;
1097     } else scall = MAT_REUSE_MATRIX;
1098   }
1099 
1100   ierr = MatCreateSubMatrices(pmat,n_local,bjac->is,bjac->is,scall,&bjac->pmat);CHKERRQ(ierr);
1101   if (pc->useAmat) {
1102     ierr = PetscObjectGetOptionsPrefix((PetscObject)mat,&mprefix);CHKERRQ(ierr);
1103     ierr = MatCreateSubMatrices(mat,n_local,bjac->is,bjac->is,scall,&bjac->mat);CHKERRQ(ierr);
1104   }
1105   /* Return control to the user so that the submatrices can be modified (e.g., to apply
1106      different boundary conditions for the submatrices than for the global problem) */
1107   ierr = PCModifySubMatrices(pc,n_local,bjac->is,bjac->is,bjac->pmat,pc->modifysubmatricesP);CHKERRQ(ierr);
1108 
1109   ierr = PetscObjectGetOptionsPrefix((PetscObject)pmat,&pprefix);CHKERRQ(ierr);
1110   for (i=0; i<n_local; i++) {
1111     ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)bjac->pmat[i]);CHKERRQ(ierr);
1112     ierr = PetscObjectSetOptionsPrefix((PetscObject)bjac->pmat[i],pprefix);CHKERRQ(ierr);
1113     if (pc->useAmat) {
1114       ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)bjac->mat[i]);CHKERRQ(ierr);
1115       ierr = PetscObjectSetOptionsPrefix((PetscObject)bjac->mat[i],mprefix);CHKERRQ(ierr);
1116       ierr = KSPSetOperators(jac->ksp[i],bjac->mat[i],bjac->pmat[i]);CHKERRQ(ierr);
1117     } else {
1118       ierr = KSPSetOperators(jac->ksp[i],bjac->pmat[i],bjac->pmat[i]);CHKERRQ(ierr);
1119     }
1120     if (pc->setfromoptionscalled) {
1121       ierr = KSPSetFromOptions(jac->ksp[i]);CHKERRQ(ierr);
1122     }
1123   }
1124   PetscFunctionReturn(0);
1125 }
1126 
1127 /* ---------------------------------------------------------------------------------------------*/
1128 /*
1129       These are for a single block with multiple processes;
1130 */
1131 static PetscErrorCode PCReset_BJacobi_Multiproc(PC pc)
1132 {
1133   PC_BJacobi           *jac   = (PC_BJacobi*)pc->data;
1134   PC_BJacobi_Multiproc *mpjac = (PC_BJacobi_Multiproc*)jac->data;
1135   PetscErrorCode       ierr;
1136 
1137   PetscFunctionBegin;
1138   ierr = VecDestroy(&mpjac->ysub);CHKERRQ(ierr);
1139   ierr = VecDestroy(&mpjac->xsub);CHKERRQ(ierr);
1140   ierr = MatDestroy(&mpjac->submats);CHKERRQ(ierr);
1141   if (jac->ksp) {ierr = KSPReset(jac->ksp[0]);CHKERRQ(ierr);}
1142   PetscFunctionReturn(0);
1143 }
1144 
1145 static PetscErrorCode PCDestroy_BJacobi_Multiproc(PC pc)
1146 {
1147   PC_BJacobi           *jac   = (PC_BJacobi*)pc->data;
1148   PC_BJacobi_Multiproc *mpjac = (PC_BJacobi_Multiproc*)jac->data;
1149   PetscErrorCode       ierr;
1150 
1151   PetscFunctionBegin;
1152   ierr = PCReset_BJacobi_Multiproc(pc);CHKERRQ(ierr);
1153   ierr = KSPDestroy(&jac->ksp[0]);CHKERRQ(ierr);
1154   ierr = PetscFree(jac->ksp);CHKERRQ(ierr);
1155   ierr = PetscSubcommDestroy(&mpjac->psubcomm);CHKERRQ(ierr);
1156 
1157   ierr = PetscFree(mpjac);CHKERRQ(ierr);
1158   ierr = PetscFree(pc->data);CHKERRQ(ierr);
1159   PetscFunctionReturn(0);
1160 }
1161 
1162 static PetscErrorCode PCApply_BJacobi_Multiproc(PC pc,Vec x,Vec y)
1163 {
1164   PC_BJacobi           *jac   = (PC_BJacobi*)pc->data;
1165   PC_BJacobi_Multiproc *mpjac = (PC_BJacobi_Multiproc*)jac->data;
1166   PetscErrorCode       ierr;
1167   PetscScalar          *yarray;
1168   const PetscScalar    *xarray;
1169   KSPConvergedReason   reason;
1170 
1171   PetscFunctionBegin;
1172   /* place x's and y's local arrays into xsub and ysub */
1173   ierr = VecGetArrayRead(x,&xarray);CHKERRQ(ierr);
1174   ierr = VecGetArray(y,&yarray);CHKERRQ(ierr);
1175   ierr = VecPlaceArray(mpjac->xsub,xarray);CHKERRQ(ierr);
1176   ierr = VecPlaceArray(mpjac->ysub,yarray);CHKERRQ(ierr);
1177 
1178   /* apply preconditioner on each matrix block */
1179   ierr = PetscLogEventBegin(PC_ApplyOnBlocks,jac->ksp[0],mpjac->xsub,mpjac->ysub,0);CHKERRQ(ierr);
1180   ierr = KSPSolve(jac->ksp[0],mpjac->xsub,mpjac->ysub);CHKERRQ(ierr);
1181   ierr = PetscLogEventEnd(PC_ApplyOnBlocks,jac->ksp[0],mpjac->xsub,mpjac->ysub,0);CHKERRQ(ierr);
1182   ierr = KSPGetConvergedReason(jac->ksp[0],&reason);CHKERRQ(ierr);
1183   if (reason == KSP_DIVERGED_PCSETUP_FAILED) {
1184     pc->failedreason = PC_SUBPC_ERROR;
1185   }
1186 
1187   ierr = VecResetArray(mpjac->xsub);CHKERRQ(ierr);
1188   ierr = VecResetArray(mpjac->ysub);CHKERRQ(ierr);
1189   ierr = VecRestoreArrayRead(x,&xarray);CHKERRQ(ierr);
1190   ierr = VecRestoreArray(y,&yarray);CHKERRQ(ierr);
1191   PetscFunctionReturn(0);
1192 }
1193 
1194 static PetscErrorCode PCSetUp_BJacobi_Multiproc(PC pc)
1195 {
1196   PC_BJacobi           *jac   = (PC_BJacobi*)pc->data;
1197   PC_BJacobi_Multiproc *mpjac = (PC_BJacobi_Multiproc*)jac->data;
1198   PetscErrorCode       ierr;
1199   PetscInt             m,n;
1200   MPI_Comm             comm,subcomm=0;
1201   const char           *prefix;
1202   PetscBool            wasSetup = PETSC_TRUE;
1203 #if defined(PETSC_HAVE_CUSP) || defined(PETSC_HAVE_VECCUDA) || defined(PETSC_HAVE_VIENNACL)
1204   PetscBool              is_gpumatrix = PETSC_FALSE;
1205 #endif
1206 
1207 
1208   PetscFunctionBegin;
1209   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
1210   if (jac->n_local > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Only a single block in a subcommunicator is supported");
1211   jac->n_local = 1; /* currently only a single block is supported for a subcommunicator */
1212   if (!pc->setupcalled) {
1213     wasSetup  = PETSC_FALSE;
1214     ierr      = PetscNewLog(pc,&mpjac);CHKERRQ(ierr);
1215     jac->data = (void*)mpjac;
1216 
1217     /* initialize datastructure mpjac */
1218     if (!jac->psubcomm) {
1219       /* Create default contiguous subcommunicatiors if user does not provide them */
1220       ierr = PetscSubcommCreate(comm,&jac->psubcomm);CHKERRQ(ierr);
1221       ierr = PetscSubcommSetNumber(jac->psubcomm,jac->n);CHKERRQ(ierr);
1222       ierr = PetscSubcommSetType(jac->psubcomm,PETSC_SUBCOMM_CONTIGUOUS);CHKERRQ(ierr);
1223       ierr = PetscLogObjectMemory((PetscObject)pc,sizeof(PetscSubcomm));CHKERRQ(ierr);
1224     }
1225     mpjac->psubcomm = jac->psubcomm;
1226     subcomm         = PetscSubcommChild(mpjac->psubcomm);
1227 
1228     /* Get matrix blocks of pmat */
1229     ierr = MatGetMultiProcBlock(pc->pmat,subcomm,MAT_INITIAL_MATRIX,&mpjac->submats);CHKERRQ(ierr);
1230 
1231     /* create a new PC that processors in each subcomm have copy of */
1232     ierr = PetscMalloc1(1,&jac->ksp);CHKERRQ(ierr);
1233     ierr = KSPCreate(subcomm,&jac->ksp[0]);CHKERRQ(ierr);
1234     ierr = KSPSetErrorIfNotConverged(jac->ksp[0],pc->erroriffailure);CHKERRQ(ierr);
1235     ierr = PetscObjectIncrementTabLevel((PetscObject)jac->ksp[0],(PetscObject)pc,1);CHKERRQ(ierr);
1236     ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)jac->ksp[0]);CHKERRQ(ierr);
1237     ierr = KSPSetOperators(jac->ksp[0],mpjac->submats,mpjac->submats);CHKERRQ(ierr);
1238     ierr = KSPGetPC(jac->ksp[0],&mpjac->pc);CHKERRQ(ierr);
1239 
1240     ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr);
1241     ierr = KSPSetOptionsPrefix(jac->ksp[0],prefix);CHKERRQ(ierr);
1242     ierr = KSPAppendOptionsPrefix(jac->ksp[0],"sub_");CHKERRQ(ierr);
1243     /*
1244       PetscMPIInt rank,subsize,subrank;
1245       ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
1246       ierr = MPI_Comm_size(subcomm,&subsize);CHKERRQ(ierr);
1247       ierr = MPI_Comm_rank(subcomm,&subrank);CHKERRQ(ierr);
1248 
1249       ierr = MatGetLocalSize(mpjac->submats,&m,NULL);CHKERRQ(ierr);
1250       ierr = MatGetSize(mpjac->submats,&n,NULL);CHKERRQ(ierr);
1251       ierr = PetscSynchronizedPrintf(comm,"[%d], sub-size %d,sub-rank %d\n",rank,subsize,subrank);
1252       ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
1253     */
1254 
1255     /* create dummy vectors xsub and ysub */
1256     ierr = MatGetLocalSize(mpjac->submats,&m,&n);CHKERRQ(ierr);
1257     ierr = VecCreateMPIWithArray(subcomm,1,n,PETSC_DECIDE,NULL,&mpjac->xsub);CHKERRQ(ierr);
1258     ierr = VecCreateMPIWithArray(subcomm,1,m,PETSC_DECIDE,NULL,&mpjac->ysub);CHKERRQ(ierr);
1259 #if defined(PETSC_HAVE_CUSP)
1260     ierr = PetscObjectTypeCompareAny((PetscObject)mpjac->submats,&is_gpumatrix,MATAIJCUSP,MATMPIAIJCUSP,"");CHKERRQ(ierr);
1261     if (is_gpumatrix) {
1262       ierr = VecSetType(mpjac->xsub,VECMPICUSP);CHKERRQ(ierr);
1263       ierr = VecSetType(mpjac->ysub,VECMPICUSP);CHKERRQ(ierr);
1264     }
1265 #elif defined(PETSC_HAVE_VECCUDA)
1266     ierr = PetscObjectTypeCompareAny((PetscObject)mpjac->submats,&is_gpumatrix,MATAIJCUSPARSE,MATMPIAIJCUSPARSE,"");CHKERRQ(ierr);
1267     if (is_gpumatrix) {
1268       ierr = VecSetType(mpjac->xsub,VECMPICUDA);CHKERRQ(ierr);
1269       ierr = VecSetType(mpjac->ysub,VECMPICUDA);CHKERRQ(ierr);
1270     }
1271 #elif defined(PETSC_HAVE_VIENNACL)
1272     ierr = PetscObjectTypeCompareAny((PetscObject)mpjac->submats,&is_gpumatrix,MATAIJVIENNACL,MATMPIAIJVIENNACL,"");CHKERRQ(ierr);
1273     if (is_gpumatrix) {
1274       ierr = VecSetType(mpjac->xsub,VECMPIVIENNACL);CHKERRQ(ierr);
1275       ierr = VecSetType(mpjac->ysub,VECMPIVIENNACL);CHKERRQ(ierr);
1276     }
1277 #endif
1278     ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)mpjac->xsub);CHKERRQ(ierr);
1279     ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)mpjac->ysub);CHKERRQ(ierr);
1280 
1281     pc->ops->reset   = PCReset_BJacobi_Multiproc;
1282     pc->ops->destroy = PCDestroy_BJacobi_Multiproc;
1283     pc->ops->apply   = PCApply_BJacobi_Multiproc;
1284   } else { /* pc->setupcalled */
1285     subcomm = PetscSubcommChild(mpjac->psubcomm);
1286     if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
1287       /* destroy old matrix blocks, then get new matrix blocks */
1288       if (mpjac->submats) {ierr = MatDestroy(&mpjac->submats);CHKERRQ(ierr);}
1289       ierr = MatGetMultiProcBlock(pc->pmat,subcomm,MAT_INITIAL_MATRIX,&mpjac->submats);CHKERRQ(ierr);
1290     } else {
1291       ierr = MatGetMultiProcBlock(pc->pmat,subcomm,MAT_REUSE_MATRIX,&mpjac->submats);CHKERRQ(ierr);
1292     }
1293     ierr = KSPSetOperators(jac->ksp[0],mpjac->submats,mpjac->submats);CHKERRQ(ierr);
1294   }
1295 
1296   if (!wasSetup && pc->setfromoptionscalled) {
1297     ierr = KSPSetFromOptions(jac->ksp[0]);CHKERRQ(ierr);
1298   }
1299   PetscFunctionReturn(0);
1300 }
1301