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