xref: /petsc/src/ksp/pc/impls/bjacobi/bjacobi.c (revision 4482741e5b2e2bbc854fb1f8dba65221386520f2)
1 /*$Id: bjacobi.c,v 1.160 2001/08/07 03:03:35 balay Exp $*/
2 /*
3    Defines a block Jacobi preconditioner.
4 */
5 #include "src/mat/matimpl.h"
6 #include "src/ksp/pc/pcimpl.h"              /*I "petscpc.h" I*/
7 #include "src/ksp/pc/impls/bjacobi/bjacobi.h"
8 
9 static int PCSetUp_BJacobi_Singleblock(PC,Mat,Mat);
10 static int PCSetUp_BJacobi_Multiblock(PC,Mat,Mat);
11 
12 #undef __FUNCT__
13 #define __FUNCT__ "PCSetUp_BJacobi"
14 static int PCSetUp_BJacobi(PC pc)
15 {
16   PC_BJacobi      *jac = (PC_BJacobi*)pc->data;
17   Mat             mat = pc->mat,pmat = pc->pmat;
18   int             ierr,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   int 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  isascii,isstring;
227   PetscViewer sviewer;
228 
229   PetscFunctionBegin;
230   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);CHKERRQ(ierr);
231   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_STRING,&isstring);CHKERRQ(ierr);
232   if (isascii) {
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 int 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 int 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 int PCBJacobiSetTotalBlocks_BJacobi(PC pc,int blocks,int *lens)
316 {
317   PC_BJacobi *jac = (PC_BJacobi*)pc->data;
318   int        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 int 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 int PCBJacobiSetLocalBlocks_BJacobi(PC pc,int blocks,const int lens[])
353 {
354   PC_BJacobi *jac;
355   int        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 int 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 int PCBJacobiSetUseTrueLocal(PC pc)
417 {
418   int 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 int PCBJacobiGetSubKSP(PC pc,int *n_local,int *first_local,KSP *ksp[])
461 {
462   int 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 int PCBJacobiSetTotalBlocks(PC pc,int blocks,const int lens[])
502 {
503   int 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 int PCBJacobiGetTotalBlocks(PC pc, int *blocks, const int *lens[])
537 {
538   int 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 int PCBJacobiSetLocalBlocks(PC pc,int blocks,const int lens[])
573 {
574   int 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 int PCBJacobiGetLocalBlocks(PC pc, int *blocks, const int *lens[])
609 {
610   int 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 int 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 int 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   int                    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 int PCSetUpOnBlocks_BJacobi_Singleblock(PC pc)
738 {
739   int                    ierr;
740   PC_BJacobi             *jac = (PC_BJacobi*)pc->data;
741   PC_BJacobi_Singleblock *bjac = (PC_BJacobi_Singleblock*)jac->data;
742 
743   PetscFunctionBegin;
744   ierr = KSPSetRhs(jac->ksp[0],bjac->x);CHKERRQ(ierr);
745   ierr = KSPSetSolution(jac->ksp[0],bjac->y);CHKERRQ(ierr);
746   ierr = KSPSetUp(jac->ksp[0]);CHKERRQ(ierr);
747   PetscFunctionReturn(0);
748 }
749 
750 #undef __FUNCT__
751 #define __FUNCT__ "PCApply_BJacobi_Singleblock"
752 int PCApply_BJacobi_Singleblock(PC pc,Vec x,Vec y)
753 {
754   int                    ierr;
755   PC_BJacobi             *jac = (PC_BJacobi*)pc->data;
756   PC_BJacobi_Singleblock *bjac = (PC_BJacobi_Singleblock*)jac->data;
757   PetscScalar            *x_array,*y_array;
758 
759   PetscFunctionBegin;
760   /*
761       The VecPlaceArray() is to avoid having to copy the
762     y vector into the bjac->x vector. The reason for
763     the bjac->x vector is that we need a sequential vector
764     for the sequential solve.
765   */
766   ierr = VecGetArray(x,&x_array);CHKERRQ(ierr);
767   ierr = VecGetArray(y,&y_array);CHKERRQ(ierr);
768   ierr = VecPlaceArray(bjac->x,x_array);CHKERRQ(ierr);
769   ierr = VecPlaceArray(bjac->y,y_array);CHKERRQ(ierr);
770   ierr = KSPSolve(jac->ksp[0]);CHKERRQ(ierr);
771   ierr = VecRestoreArray(x,&x_array);CHKERRQ(ierr);
772   ierr = VecRestoreArray(y,&y_array);CHKERRQ(ierr);
773   PetscFunctionReturn(0);
774 }
775 
776 #undef __FUNCT__
777 #define __FUNCT__ "PCApplySymmetricLeft_BJacobi_Singleblock"
778 int PCApplySymmetricLeft_BJacobi_Singleblock(PC pc,Vec x,Vec y)
779 {
780   int                    ierr;
781   PC_BJacobi             *jac = (PC_BJacobi*)pc->data;
782   PC_BJacobi_Singleblock *bjac = (PC_BJacobi_Singleblock*)jac->data;
783   PetscScalar            *x_array,*y_array;
784   PC                     subpc;
785 
786   PetscFunctionBegin;
787   /*
788       The VecPlaceArray() is to avoid having to copy the
789     y vector into the bjac->x vector. The reason for
790     the bjac->x vector is that we need a sequential vector
791     for the sequential solve.
792   */
793   ierr = VecGetArray(x,&x_array);CHKERRQ(ierr);
794   ierr = VecGetArray(y,&y_array);CHKERRQ(ierr);
795   ierr = VecPlaceArray(bjac->x,x_array);CHKERRQ(ierr);
796   ierr = VecPlaceArray(bjac->y,y_array);CHKERRQ(ierr);
797 
798   /* apply the symmetric left portion of the inner PC operator */
799   /* note this by-passes the inner KSP and its options completely */
800 
801   ierr = KSPGetPC(jac->ksp[0],&subpc);CHKERRQ(ierr);
802   ierr = PCApplySymmetricLeft(subpc,bjac->x,bjac->y);CHKERRQ(ierr);
803 
804   ierr = VecRestoreArray(x,&x_array);CHKERRQ(ierr);
805   ierr = VecRestoreArray(y,&y_array);CHKERRQ(ierr);
806   PetscFunctionReturn(0);
807 }
808 
809 #undef __FUNCT__
810 #define __FUNCT__ "PCApplySymmetricRight_BJacobi_Singleblock"
811 int PCApplySymmetricRight_BJacobi_Singleblock(PC pc,Vec x,Vec y)
812 {
813   int                    ierr;
814   PC_BJacobi             *jac = (PC_BJacobi*)pc->data;
815   PC_BJacobi_Singleblock *bjac = (PC_BJacobi_Singleblock*)jac->data;
816   PetscScalar            *x_array,*y_array;
817   PC                     subpc;
818 
819   PetscFunctionBegin;
820   /*
821       The VecPlaceArray() is to avoid having to copy the
822     y vector into the bjac->x vector. The reason for
823     the bjac->x vector is that we need a sequential vector
824     for the sequential solve.
825   */
826   ierr = VecGetArray(x,&x_array);CHKERRQ(ierr);
827   ierr = VecGetArray(y,&y_array);CHKERRQ(ierr);
828   ierr = VecPlaceArray(bjac->x,x_array);CHKERRQ(ierr);
829   ierr = VecPlaceArray(bjac->y,y_array);CHKERRQ(ierr);
830 
831   /* apply the symmetric right portion of the inner PC operator */
832   /* note this by-passes the inner KSP and its options completely */
833 
834   ierr = KSPGetPC(jac->ksp[0],&subpc);CHKERRQ(ierr);
835   ierr = PCApplySymmetricRight(subpc,bjac->x,bjac->y);CHKERRQ(ierr);
836 
837   ierr = VecRestoreArray(x,&x_array);CHKERRQ(ierr);
838   ierr = VecRestoreArray(y,&y_array);CHKERRQ(ierr);
839   PetscFunctionReturn(0);
840 }
841 
842 #undef __FUNCT__
843 #define __FUNCT__ "PCApplyTranspose_BJacobi_Singleblock"
844 int PCApplyTranspose_BJacobi_Singleblock(PC pc,Vec x,Vec y)
845 {
846   int                    ierr;
847   PC_BJacobi             *jac = (PC_BJacobi*)pc->data;
848   PC_BJacobi_Singleblock *bjac = (PC_BJacobi_Singleblock*)jac->data;
849   PetscScalar            *x_array,*y_array;
850 
851   PetscFunctionBegin;
852   /*
853       The VecPlaceArray() is to avoid having to copy the
854     y vector into the bjac->x vector. The reason for
855     the bjac->x vector is that we need a sequential vector
856     for the sequential solve.
857   */
858   ierr = VecGetArray(x,&x_array);CHKERRQ(ierr);
859   ierr = VecGetArray(y,&y_array);CHKERRQ(ierr);
860   ierr = VecPlaceArray(bjac->x,x_array);CHKERRQ(ierr);
861   ierr = VecPlaceArray(bjac->y,y_array);CHKERRQ(ierr);
862   ierr = KSPSolveTranspose(jac->ksp[0]);CHKERRQ(ierr);
863   ierr = VecRestoreArray(x,&x_array);CHKERRQ(ierr);
864   ierr = VecRestoreArray(y,&y_array);CHKERRQ(ierr);
865   PetscFunctionReturn(0);
866 }
867 
868 #undef __FUNCT__
869 #define __FUNCT__ "PCSetUp_BJacobi_Singleblock"
870 static int PCSetUp_BJacobi_Singleblock(PC pc,Mat mat,Mat pmat)
871 {
872   PC_BJacobi             *jac = (PC_BJacobi*)pc->data;
873   int                    ierr,m;
874   KSP                   ksp;
875   Vec                    x,y;
876   PC_BJacobi_Singleblock *bjac;
877   PC                     subpc;
878 
879   PetscFunctionBegin;
880 
881   /* set default direct solver with no Krylov method */
882   if (!pc->setupcalled) {
883     char *prefix;
884     ierr = KSPCreate(PETSC_COMM_SELF,&ksp);CHKERRQ(ierr);
885     PetscLogObjectParent(pc,ksp);
886     ierr = KSPSetType(ksp,KSPPREONLY);CHKERRQ(ierr);
887     ierr = KSPGetPC(ksp,&subpc);CHKERRQ(ierr);
888     ierr = PCSetType(subpc,PCILU);CHKERRQ(ierr);
889     ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr);
890     ierr = KSPSetOptionsPrefix(ksp,prefix);CHKERRQ(ierr);
891     ierr = KSPAppendOptionsPrefix(ksp,"sub_");CHKERRQ(ierr);
892     ierr = KSPSetFromOptions(ksp);CHKERRQ(ierr);
893     /*
894       The reason we need to generate these vectors is to serve
895       as the right-hand side and solution vector for the solve on the
896       block. We do not need to allocate space for the vectors since
897       that is provided via VecPlaceArray() just before the call to
898       KSPSolve() on the block.
899     */
900     ierr = MatGetSize(pmat,&m,&m);CHKERRQ(ierr);
901     ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,m,PETSC_NULL,&x);CHKERRQ(ierr);
902     ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,m,PETSC_NULL,&y);CHKERRQ(ierr);
903     PetscLogObjectParent(pc,x);
904     PetscLogObjectParent(pc,y);
905 
906     pc->ops->destroy             = PCDestroy_BJacobi_Singleblock;
907     pc->ops->apply               = PCApply_BJacobi_Singleblock;
908     pc->ops->applysymmetricleft  = PCApplySymmetricLeft_BJacobi_Singleblock;
909     pc->ops->applysymmetricright = PCApplySymmetricRight_BJacobi_Singleblock;
910     pc->ops->applytranspose      = PCApplyTranspose_BJacobi_Singleblock;
911     pc->ops->setuponblocks       = PCSetUpOnBlocks_BJacobi_Singleblock;
912 
913     ierr = PetscMalloc(sizeof(PC_BJacobi_Singleblock),&bjac);CHKERRQ(ierr);
914     PetscLogObjectMemory(pc,sizeof(PC_BJacobi_Singleblock));
915     bjac->x      = x;
916     bjac->y      = y;
917 
918     ierr = PetscMalloc(sizeof(KSP),&jac->ksp);CHKERRQ(ierr);
919     jac->ksp[0] = ksp;
920     jac->data    = (void*)bjac;
921   } else {
922     ksp = jac->ksp[0];
923     bjac = (PC_BJacobi_Singleblock *)jac->data;
924   }
925   if (jac->use_true_local) {
926     ierr = KSPSetOperators(ksp,mat,pmat,pc->flag);CHKERRQ(ierr);
927   }  else {
928     ierr = KSPSetOperators(ksp,pmat,pmat,pc->flag);CHKERRQ(ierr);
929   }
930   PetscFunctionReturn(0);
931 }
932 
933 /* ---------------------------------------------------------------------------------------------*/
934 
935 #undef __FUNCT__
936 #define __FUNCT__ "PCDestroy_BJacobi_Multiblock"
937 int PCDestroy_BJacobi_Multiblock(PC pc)
938 {
939   PC_BJacobi            *jac = (PC_BJacobi*)pc->data;
940   PC_BJacobi_Multiblock *bjac = (PC_BJacobi_Multiblock*)jac->data;
941   int                   i,ierr;
942 
943   PetscFunctionBegin;
944   ierr = MatDestroyMatrices(jac->n_local,&bjac->pmat);CHKERRQ(ierr);
945   if (jac->use_true_local) {
946     ierr = MatDestroyMatrices(jac->n_local,&bjac->mat);CHKERRQ(ierr);
947   }
948 
949   /*
950         If the on processor block had to be generated via a MatGetDiagonalBlock()
951      that creates a copy (for example MPIBDiag matrices do), this frees the space
952   */
953   if (jac->tp_mat) {
954     ierr = MatDestroy(jac->tp_mat);CHKERRQ(ierr);
955   }
956   if (jac->tp_pmat) {
957     ierr = MatDestroy(jac->tp_pmat);CHKERRQ(ierr);
958   }
959 
960   for (i=0; i<jac->n_local; i++) {
961     ierr = KSPDestroy(jac->ksp[i]);CHKERRQ(ierr);
962     ierr = VecDestroy(bjac->x[i]);CHKERRQ(ierr);
963     ierr = VecDestroy(bjac->y[i]);CHKERRQ(ierr);
964     ierr = ISDestroy(bjac->is[i]);CHKERRQ(ierr);
965   }
966   ierr = PetscFree(jac->ksp);CHKERRQ(ierr);
967   ierr = PetscFree(bjac->x);CHKERRQ(ierr);
968   ierr = PetscFree(bjac->starts);CHKERRQ(ierr);
969   ierr = PetscFree(bjac->is);CHKERRQ(ierr);
970   ierr = PetscFree(bjac);CHKERRQ(ierr);
971   if (jac->l_lens) {ierr = PetscFree(jac->l_lens);CHKERRQ(ierr);}
972   if (jac->g_lens) {ierr = PetscFree(jac->g_lens);CHKERRQ(ierr);}
973   ierr = PetscFree(jac);CHKERRQ(ierr);
974   PetscFunctionReturn(0);
975 }
976 
977 #undef __FUNCT__
978 #define __FUNCT__ "PCSetUpOnBlocks_BJacobi_Multiblock"
979 int PCSetUpOnBlocks_BJacobi_Multiblock(PC pc)
980 {
981   PC_BJacobi            *jac = (PC_BJacobi*)pc->data;
982   int                   ierr,i,n_local = jac->n_local;
983   PC_BJacobi_Multiblock *bjac = (PC_BJacobi_Multiblock*)jac->data;
984 
985   PetscFunctionBegin;
986   for (i=0; i<n_local; i++) {
987     ierr = KSPSetRhs(jac->ksp[i],bjac->x[i]);CHKERRQ(ierr);
988     ierr = KSPSetSolution(jac->ksp[i],bjac->y[i]);CHKERRQ(ierr);
989     ierr = KSPSetUp(jac->ksp[i]);CHKERRQ(ierr);
990   }
991   PetscFunctionReturn(0);
992 }
993 
994 /*
995       Preconditioner for block Jacobi
996 */
997 #undef __FUNCT__
998 #define __FUNCT__ "PCApply_BJacobi_Multiblock"
999 int PCApply_BJacobi_Multiblock(PC pc,Vec x,Vec y)
1000 {
1001   PC_BJacobi            *jac = (PC_BJacobi*)pc->data;
1002   int                   ierr,i,n_local = jac->n_local;
1003   PC_BJacobi_Multiblock *bjac = (PC_BJacobi_Multiblock*)jac->data;
1004   PetscScalar           *xin,*yin;
1005   static PetscTruth     flag = PETSC_TRUE;
1006   static int            SUBKspSolve;
1007 
1008   PetscFunctionBegin;
1009   if (flag) {
1010     ierr = PetscLogEventRegister(&SUBKspSolve,"SubKspSolve",KSP_COOKIE);CHKERRQ(ierr);
1011     flag = PETSC_FALSE;
1012   }
1013   ierr = VecGetArray(x,&xin);CHKERRQ(ierr);
1014   ierr = VecGetArray(y,&yin);CHKERRQ(ierr);
1015   for (i=0; i<n_local; i++) {
1016     /*
1017        To avoid copying the subvector from x into a workspace we instead
1018        make the workspace vector array point to the subpart of the array of
1019        the global vector.
1020     */
1021     ierr = VecPlaceArray(bjac->x[i],xin+bjac->starts[i]);CHKERRQ(ierr);
1022     ierr = VecPlaceArray(bjac->y[i],yin+bjac->starts[i]);CHKERRQ(ierr);
1023 
1024     ierr = PetscLogEventBegin(SUBKspSolve,jac->ksp[i],bjac->x[i],bjac->y[i],0);CHKERRQ(ierr);
1025     ierr = KSPSolve(jac->ksp[i]);CHKERRQ(ierr);
1026     ierr = PetscLogEventEnd(SUBKspSolve,jac->ksp[i],bjac->x[i],bjac->y[i],0);CHKERRQ(ierr);
1027   }
1028   ierr = VecRestoreArray(x,&xin);CHKERRQ(ierr);
1029   ierr = VecRestoreArray(y,&yin);CHKERRQ(ierr);
1030   PetscFunctionReturn(0);
1031 }
1032 
1033 /*
1034       Preconditioner for block Jacobi
1035 */
1036 #undef __FUNCT__
1037 #define __FUNCT__ "PCApplyTranspose_BJacobi_Multiblock"
1038 int PCApplyTranspose_BJacobi_Multiblock(PC pc,Vec x,Vec y)
1039 {
1040   PC_BJacobi            *jac = (PC_BJacobi*)pc->data;
1041   int                   ierr,i,n_local = jac->n_local;
1042   PC_BJacobi_Multiblock *bjac = (PC_BJacobi_Multiblock*)jac->data;
1043   PetscScalar           *xin,*yin;
1044   static PetscTruth     flag = PETSC_TRUE;
1045   static int            SUBKspSolve;
1046 
1047   PetscFunctionBegin;
1048   if (flag) {
1049     ierr = PetscLogEventRegister(&SUBKspSolve,"SubKspSolveTranspose",KSP_COOKIE);CHKERRQ(ierr);
1050     flag = PETSC_FALSE;
1051   }
1052   ierr = VecGetArray(x,&xin);CHKERRQ(ierr);
1053   ierr = VecGetArray(y,&yin);CHKERRQ(ierr);
1054   for (i=0; i<n_local; i++) {
1055     /*
1056        To avoid copying the subvector from x into a workspace we instead
1057        make the workspace vector array point to the subpart of the array of
1058        the global vector.
1059     */
1060     ierr = VecPlaceArray(bjac->x[i],xin+bjac->starts[i]);CHKERRQ(ierr);
1061     ierr = VecPlaceArray(bjac->y[i],yin+bjac->starts[i]);CHKERRQ(ierr);
1062 
1063     ierr = PetscLogEventBegin(SUBKspSolve,jac->ksp[i],bjac->x[i],bjac->y[i],0);CHKERRQ(ierr);
1064     ierr = KSPSolveTranspose(jac->ksp[i]);CHKERRQ(ierr);
1065     ierr = PetscLogEventEnd(SUBKspSolve,jac->ksp[i],bjac->x[i],bjac->y[i],0);CHKERRQ(ierr);
1066   }
1067   ierr = VecRestoreArray(x,&xin);CHKERRQ(ierr);
1068   ierr = VecRestoreArray(y,&yin);CHKERRQ(ierr);
1069   PetscFunctionReturn(0);
1070 }
1071 
1072 #undef __FUNCT__
1073 #define __FUNCT__ "PCSetUp_BJacobi_Multiblock"
1074 static int PCSetUp_BJacobi_Multiblock(PC pc,Mat mat,Mat pmat)
1075 {
1076   PC_BJacobi             *jac = (PC_BJacobi*)pc->data;
1077   int                    ierr,m,n_local,N,M,start,i;
1078   char                   *prefix,*pprefix,*mprefix;
1079   KSP                    ksp;
1080   Vec                    x,y;
1081   PC_BJacobi_Multiblock  *bjac = (PC_BJacobi_Multiblock*)jac->data;
1082   PC                     subpc;
1083   IS                     is;
1084   MatReuse               scall = MAT_REUSE_MATRIX;
1085 
1086   PetscFunctionBegin;
1087   ierr = MatGetLocalSize(pc->pmat,&M,&N);CHKERRQ(ierr);
1088 
1089   n_local = jac->n_local;
1090 
1091   if (jac->use_true_local) {
1092     if (mat->type != pmat->type) SETERRQ(PETSC_ERR_ARG_INCOMP,"Matrices not of same type");
1093   }
1094 
1095   /* set default direct solver with no Krylov method */
1096   if (!pc->setupcalled) {
1097     scall                  = MAT_INITIAL_MATRIX;
1098     pc->ops->destroy       = PCDestroy_BJacobi_Multiblock;
1099     pc->ops->apply         = PCApply_BJacobi_Multiblock;
1100     pc->ops->applytranspose= PCApplyTranspose_BJacobi_Multiblock;
1101     pc->ops->setuponblocks = PCSetUpOnBlocks_BJacobi_Multiblock;
1102 
1103     ierr = PetscMalloc(sizeof(PC_BJacobi_Multiblock),&bjac);CHKERRQ(ierr);
1104     PetscLogObjectMemory(pc,sizeof(PC_BJacobi_Multiblock));
1105     ierr = PetscMalloc(n_local*sizeof(KSP),&jac->ksp);CHKERRQ(ierr);
1106     PetscLogObjectMemory(pc,sizeof(n_local*sizeof(KSP)));
1107     ierr = PetscMalloc(2*n_local*sizeof(Vec),&bjac->x);CHKERRQ(ierr);
1108     PetscLogObjectMemory(pc,sizeof(2*n_local*sizeof(Vec)));
1109     bjac->y      = bjac->x + n_local;
1110     ierr = PetscMalloc(n_local*sizeof(PetscScalar),&bjac->starts);CHKERRQ(ierr);
1111     PetscLogObjectMemory(pc,sizeof(n_local*sizeof(PetscScalar)));
1112 
1113     jac->data    = (void*)bjac;
1114     ierr = PetscMalloc(n_local*sizeof(IS),&bjac->is);CHKERRQ(ierr);
1115     PetscLogObjectMemory(pc,sizeof(n_local*sizeof(IS)));
1116 
1117     start = 0;
1118     for (i=0; i<n_local; i++) {
1119       ierr = KSPCreate(PETSC_COMM_SELF,&ksp);CHKERRQ(ierr);
1120       PetscLogObjectParent(pc,ksp);
1121       ierr = KSPSetType(ksp,KSPPREONLY);CHKERRQ(ierr);
1122       ierr = KSPGetPC(ksp,&subpc);CHKERRQ(ierr);
1123       ierr = PCSetType(subpc,PCILU);CHKERRQ(ierr);
1124       ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr);
1125       ierr = KSPSetOptionsPrefix(ksp,prefix);CHKERRQ(ierr);
1126       ierr = KSPAppendOptionsPrefix(ksp,"sub_");CHKERRQ(ierr);
1127       ierr = KSPSetFromOptions(ksp);CHKERRQ(ierr);
1128 
1129       m = jac->l_lens[i];
1130 
1131       /*
1132       The reason we need to generate these vectors is to serve
1133       as the right-hand side and solution vector for the solve on the
1134       block. We do not need to allocate space for the vectors since
1135       that is provided via VecPlaceArray() just before the call to
1136       KSPSolve() on the block.
1137 
1138       */
1139       ierr = VecCreateSeq(PETSC_COMM_SELF,m,&x);CHKERRQ(ierr);
1140       ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,m,PETSC_NULL,&y);CHKERRQ(ierr);
1141       PetscLogObjectParent(pc,x);
1142       PetscLogObjectParent(pc,y);
1143       bjac->x[i]      = x;
1144       bjac->y[i]      = y;
1145       bjac->starts[i] = start;
1146       jac->ksp[i]    = ksp;
1147 
1148       ierr = ISCreateStride(PETSC_COMM_SELF,m,start,1,&is);CHKERRQ(ierr);
1149       bjac->is[i] = is;
1150       PetscLogObjectParent(pc,is);
1151 
1152       start += m;
1153     }
1154   } else {
1155     bjac = (PC_BJacobi_Multiblock*)jac->data;
1156     /*
1157        Destroy the blocks from the previous iteration
1158     */
1159     if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
1160       ierr = MatDestroyMatrices(n_local,&bjac->pmat);CHKERRQ(ierr);
1161       if (jac->use_true_local) {
1162         ierr = MatDestroyMatrices(n_local,&bjac->mat);CHKERRQ(ierr);
1163       }
1164       scall = MAT_INITIAL_MATRIX;
1165     }
1166   }
1167 
1168   ierr = MatGetSubMatrices(pmat,n_local,bjac->is,bjac->is,scall,&bjac->pmat);CHKERRQ(ierr);
1169   if (jac->use_true_local) {
1170     ierr = PetscObjectGetOptionsPrefix((PetscObject)mat,&mprefix);CHKERRQ(ierr);
1171     ierr = MatGetSubMatrices(mat,n_local,bjac->is,bjac->is,scall,&bjac->mat);CHKERRQ(ierr);
1172   }
1173   /* Return control to the user so that the submatrices can be modified (e.g., to apply
1174      different boundary conditions for the submatrices than for the global problem) */
1175   ierr = PCModifySubMatrices(pc,n_local,bjac->is,bjac->is,bjac->pmat,pc->modifysubmatricesP);CHKERRQ(ierr);
1176 
1177   ierr = PetscObjectGetOptionsPrefix((PetscObject)pmat,&pprefix);CHKERRQ(ierr);
1178   for (i=0; i<n_local; i++) {
1179     PetscLogObjectParent(pc,bjac->pmat[i]);
1180     ierr = PetscObjectSetOptionsPrefix((PetscObject)bjac->pmat[i],pprefix);CHKERRQ(ierr);
1181     if (jac->use_true_local) {
1182       PetscLogObjectParent(pc,bjac->mat[i]);
1183       ierr = PetscObjectSetOptionsPrefix((PetscObject)bjac->mat[i],mprefix);CHKERRQ(ierr);
1184       ierr = KSPSetOperators(jac->ksp[i],bjac->mat[i],bjac->pmat[i],pc->flag);CHKERRQ(ierr);
1185     } else {
1186       ierr = KSPSetOperators(jac->ksp[i],bjac->pmat[i],bjac->pmat[i],pc->flag);CHKERRQ(ierr);
1187     }
1188   }
1189 
1190   PetscFunctionReturn(0);
1191 }
1192 
1193 
1194 
1195 
1196 
1197 
1198 
1199 
1200 
1201 
1202