xref: /petsc/src/ksp/pc/impls/bddc/bddc.c (revision c8587f3400bb52e8a0bc75c0376dec77962410ff)
1 /* TODOLIST
2    DofSplitting and DM attached to pc?
3    Change SetNeumannBoundaries to SetNeumannBoundariesLocal and provide new SetNeumannBoundaries (same Dirichlet)
4    change how to deal with the coarse problem (PCBDDCSetCoarseEnvironment):
5      - simplify coarse problem structure -> PCBDDC or PCREDUDANT, nothing else -> same comm for all levels?
6      - remove coarse enums and allow use of PCBDDCGetCoarseKSP
7      - remove metis dependency -> use MatPartitioning for multilevel -> Assemble serial adjacency in PCBDDCAnalyzeInterface?
8    code refactoring:
9      - pick up better names for static functions
10    change options structure:
11      - insert BDDC into MG framework?
12    provide other ops? Ask to developers
13    remove all unused printf
14    man pages
15 */
16 
17 /* ----------------------------------------------------------------------------------------------------------------------------------------------
18    Implementation of BDDC preconditioner based on:
19    C. Dohrmann "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149-168, March 2007
20    ---------------------------------------------------------------------------------------------------------------------------------------------- */
21 
22 #include "bddc.h" /*I "petscpc.h" I*/  /* includes for fortran wrappers */
23 #include "bddcprivate.h"
24 #include <petscblaslapack.h>
25 
26 /* -------------------------------------------------------------------------- */
27 #undef __FUNCT__
28 #define __FUNCT__ "PCSetFromOptions_BDDC"
29 PetscErrorCode PCSetFromOptions_BDDC(PC pc)
30 {
31   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
32   PetscErrorCode ierr;
33 
34   PetscFunctionBegin;
35   ierr = PetscOptionsHead("BDDC options");CHKERRQ(ierr);
36   /* Verbose debugging of main data structures */
37   ierr = PetscOptionsInt("-pc_bddc_check_level"       ,"Verbose (debugging) output for PCBDDC"                       ,"none",pcbddc->dbg_flag      ,&pcbddc->dbg_flag      ,NULL);CHKERRQ(ierr);
38   /* Some customization for default primal space */
39   ierr = PetscOptionsBool("-pc_bddc_vertices_only"   ,"Use only vertices in coarse space (i.e. discard constraints)","none",pcbddc->vertices_flag   ,&pcbddc->vertices_flag   ,NULL);CHKERRQ(ierr);
40   ierr = PetscOptionsBool("-pc_bddc_constraints_only","Use only constraints in coarse space (i.e. discard vertices)","none",pcbddc->constraints_flag,&pcbddc->constraints_flag,NULL);CHKERRQ(ierr);
41   ierr = PetscOptionsBool("-pc_bddc_faces_only"      ,"Use only faces among constraints of coarse space (i.e. discard edges)"         ,"none",pcbddc->faces_flag      ,&pcbddc->faces_flag      ,NULL);CHKERRQ(ierr);
42   ierr = PetscOptionsBool("-pc_bddc_edges_only"      ,"Use only edges among constraints of coarse space (i.e. discard faces)"         ,"none",pcbddc->edges_flag      ,&pcbddc->edges_flag      ,NULL);CHKERRQ(ierr);
43   /* Coarse solver context */
44   static const char * const avail_coarse_problems[] = {"sequential","replicated","parallel","multilevel","CoarseProblemType","PC_BDDC_",0}; /*order of choiches depends on ENUM defined in bddc.h */
45   ierr = PetscOptionsEnum("-pc_bddc_coarse_problem_type","Set coarse problem type","none",avail_coarse_problems,(PetscEnum)pcbddc->coarse_problem_type,(PetscEnum*)&pcbddc->coarse_problem_type,NULL);CHKERRQ(ierr);
46   /* Two different application of BDDC to the whole set of dofs, internal and interface */
47   ierr = PetscOptionsBool("-pc_bddc_switch_preconditioning_type","Switch between M_2 (default) and M_3 preconditioners (as defined by Dohrmann)","none",pcbddc->inexact_prec_type,&pcbddc->inexact_prec_type,NULL);CHKERRQ(ierr);
48   ierr = PetscOptionsBool("-pc_bddc_use_change_of_basis","Use change of basis approach for primal space","none",pcbddc->use_change_of_basis,&pcbddc->use_change_of_basis,NULL);CHKERRQ(ierr);
49   ierr = PetscOptionsBool("-pc_bddc_use_change_on_faces","Use change of basis approach for face constraints","none",pcbddc->use_change_on_faces,&pcbddc->use_change_on_faces,NULL);CHKERRQ(ierr);
50   if (!pcbddc->use_change_of_basis) {
51     pcbddc->use_change_on_faces = PETSC_FALSE;
52   }
53   ierr = PetscOptionsInt("-pc_bddc_coarsening_ratio","Set coarsening ratio used in multilevel coarsening","none",pcbddc->coarsening_ratio,&pcbddc->coarsening_ratio,NULL);CHKERRQ(ierr);
54   ierr = PetscOptionsInt("-pc_bddc_max_levels","Set maximum number of levels for multilevel","none",pcbddc->max_levels,&pcbddc->max_levels,NULL);CHKERRQ(ierr);
55   ierr = PetscOptionsBool("-pc_bddc_use_deluxe_scaling","Use deluxe scaling for BDDC","none",pcbddc->use_deluxe_scaling,&pcbddc->use_deluxe_scaling,NULL);CHKERRQ(ierr);
56   ierr = PetscOptionsTail();CHKERRQ(ierr);
57   PetscFunctionReturn(0);
58 }
59 /* -------------------------------------------------------------------------- */
60 #undef __FUNCT__
61 #define __FUNCT__ "PCBDDCSetPrimalVerticesLocalIS_BDDC"
62 static PetscErrorCode PCBDDCSetPrimalVerticesLocalIS_BDDC(PC pc, IS PrimalVertices)
63 {
64   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
65   PetscErrorCode ierr;
66 
67   PetscFunctionBegin;
68   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
69   ierr = PetscObjectReference((PetscObject)PrimalVertices);CHKERRQ(ierr);
70   pcbddc->user_primal_vertices = PrimalVertices;
71   PetscFunctionReturn(0);
72 }
73 #undef __FUNCT__
74 #define __FUNCT__ "PCBDDCSetPrimalVerticesLocalIS"
75 /*@
76  PCBDDCSetPrimalVerticesLocalIS - Set user defined primal vertices in PCBDDC.
77 
78    Not collective
79 
80    Input Parameters:
81 +  pc - the preconditioning context
82 -  PrimalVertices - index sets of primal vertices in local numbering
83 
84    Level: intermediate
85 
86    Notes:
87 
88 .seealso: PCBDDC
89 @*/
90 PetscErrorCode PCBDDCSetPrimalVerticesLocalIS(PC pc, IS PrimalVertices)
91 {
92   PetscErrorCode ierr;
93 
94   PetscFunctionBegin;
95   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
96   PetscValidHeaderSpecific(PrimalVertices,IS_CLASSID,2);
97   ierr = PetscTryMethod(pc,"PCBDDCSetPrimalVerticesLocalIS_C",(PC,IS),(pc,PrimalVertices));CHKERRQ(ierr);
98   PetscFunctionReturn(0);
99 }
100 /* -------------------------------------------------------------------------- */
101 #undef __FUNCT__
102 #define __FUNCT__ "PCBDDCSetCoarseProblemType_BDDC"
103 static PetscErrorCode PCBDDCSetCoarseProblemType_BDDC(PC pc, CoarseProblemType CPT)
104 {
105   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
106 
107   PetscFunctionBegin;
108   pcbddc->coarse_problem_type = CPT;
109   PetscFunctionReturn(0);
110 }
111 
112 #undef __FUNCT__
113 #define __FUNCT__ "PCBDDCSetCoarseProblemType"
114 /*@
115  PCBDDCSetCoarseProblemType - Set coarse problem type in PCBDDC.
116 
117    Not collective
118 
119    Input Parameters:
120 +  pc - the preconditioning context
121 -  CoarseProblemType - pick a better name and explain what this is
122 
123    Level: intermediate
124 
125    Notes:
126    Not collective but all procs must call with same arguments.
127 
128 .seealso: PCBDDC
129 @*/
130 PetscErrorCode PCBDDCSetCoarseProblemType(PC pc, CoarseProblemType CPT)
131 {
132   PetscErrorCode ierr;
133 
134   PetscFunctionBegin;
135   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
136   ierr = PetscTryMethod(pc,"PCBDDCSetCoarseProblemType_C",(PC,CoarseProblemType),(pc,CPT));CHKERRQ(ierr);
137   PetscFunctionReturn(0);
138 }
139 /* -------------------------------------------------------------------------- */
140 #undef __FUNCT__
141 #define __FUNCT__ "PCBDDCSetCoarseningRatio_BDDC"
142 static PetscErrorCode PCBDDCSetCoarseningRatio_BDDC(PC pc,PetscInt k)
143 {
144   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
145 
146   PetscFunctionBegin;
147   pcbddc->coarsening_ratio=k;
148   PetscFunctionReturn(0);
149 }
150 
151 #undef __FUNCT__
152 #define __FUNCT__ "PCBDDCSetCoarseningRatio"
153 /*@
154  PCBDDCSetCoarseningRatio - Set coarsening ratio used in multilevel coarsening
155 
156    Logically collective on PC
157 
158    Input Parameters:
159 +  pc - the preconditioning context
160 -  k - coarsening ratio
161 
162    Approximatively k subdomains at the finer level will be aggregated into a single subdomain at the coarser level.
163 
164    Level: intermediate
165 
166    Notes:
167 
168 .seealso: PCBDDC
169 @*/
170 PetscErrorCode PCBDDCSetCoarseningRatio(PC pc,PetscInt k)
171 {
172   PetscErrorCode ierr;
173 
174   PetscFunctionBegin;
175   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
176   ierr = PetscTryMethod(pc,"PCBDDCSetCoarseningRatio_C",(PC,PetscInt),(pc,k));CHKERRQ(ierr);
177   PetscFunctionReturn(0);
178 }
179 /* -------------------------------------------------------------------------- */
180 
181 #undef __FUNCT__
182 #define __FUNCT__ "PCBDDCSetMaxLevels_BDDC"
183 static PetscErrorCode PCBDDCSetMaxLevels_BDDC(PC pc,PetscInt max_levels)
184 {
185   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
186 
187   PetscFunctionBegin;
188   pcbddc->max_levels=max_levels;
189   PetscFunctionReturn(0);
190 }
191 
192 #undef __FUNCT__
193 #define __FUNCT__ "PCBDDCSetMaxLevels"
194 /*@
195  PCBDDCSetMaxLevels - Sets the maximum number of levels within the multilevel approach.
196 
197    Logically collective on PC
198 
199    Input Parameters:
200 +  pc - the preconditioning context
201 -  max_levels - the maximum number of levels
202 
203    Default value is 1, i.e. coarse problem will be solved inexactly with one application
204    of PCBDDC preconditioner if the multilevel approach is requested.
205 
206    Level: intermediate
207 
208    Notes:
209 
210 .seealso: PCBDDC
211 @*/
212 PetscErrorCode PCBDDCSetMaxLevels(PC pc,PetscInt max_levels)
213 {
214   PetscErrorCode ierr;
215 
216   PetscFunctionBegin;
217   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
218   ierr = PetscTryMethod(pc,"PCBDDCSetMaxLevels_C",(PC,PetscInt),(pc,max_levels));CHKERRQ(ierr);
219   PetscFunctionReturn(0);
220 }
221 /* -------------------------------------------------------------------------- */
222 
223 #undef __FUNCT__
224 #define __FUNCT__ "PCBDDCSetNullSpace_BDDC"
225 static PetscErrorCode PCBDDCSetNullSpace_BDDC(PC pc,MatNullSpace NullSpace)
226 {
227   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
228   PetscErrorCode ierr;
229 
230   PetscFunctionBegin;
231   ierr = PetscObjectReference((PetscObject)NullSpace);CHKERRQ(ierr);
232   ierr = MatNullSpaceDestroy(&pcbddc->NullSpace);CHKERRQ(ierr);
233   pcbddc->NullSpace=NullSpace;
234   PetscFunctionReturn(0);
235 }
236 
237 #undef __FUNCT__
238 #define __FUNCT__ "PCBDDCSetNullSpace"
239 /*@
240  PCBDDCSetNullSpace - Set NullSpace of global operator of BDDC preconditioned mat.
241 
242    Logically collective on PC and MatNullSpace
243 
244    Input Parameters:
245 +  pc - the preconditioning context
246 -  NullSpace - Null space of the linear operator to be preconditioned.
247 
248    Level: intermediate
249 
250    Notes:
251 
252 .seealso: PCBDDC
253 @*/
254 PetscErrorCode PCBDDCSetNullSpace(PC pc,MatNullSpace NullSpace)
255 {
256   PetscErrorCode ierr;
257 
258   PetscFunctionBegin;
259   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
260   PetscValidHeaderSpecific(NullSpace,MAT_NULLSPACE_CLASSID,2);
261   ierr = PetscTryMethod(pc,"PCBDDCSetNullSpace_C",(PC,MatNullSpace),(pc,NullSpace));CHKERRQ(ierr);
262   PetscFunctionReturn(0);
263 }
264 /* -------------------------------------------------------------------------- */
265 
266 #undef __FUNCT__
267 #define __FUNCT__ "PCBDDCSetDirichletBoundaries_BDDC"
268 static PetscErrorCode PCBDDCSetDirichletBoundaries_BDDC(PC pc,IS DirichletBoundaries)
269 {
270   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
271   PetscErrorCode ierr;
272 
273   PetscFunctionBegin;
274   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
275   ierr = PetscObjectReference((PetscObject)DirichletBoundaries);CHKERRQ(ierr);
276   pcbddc->DirichletBoundaries=DirichletBoundaries;
277   PetscFunctionReturn(0);
278 }
279 
280 #undef __FUNCT__
281 #define __FUNCT__ "PCBDDCSetDirichletBoundaries"
282 /*@
283  PCBDDCSetDirichletBoundaries - Set index set defining subdomain part (in local ordering)
284                               of Dirichlet boundaries for the global problem.
285 
286    Not collective
287 
288    Input Parameters:
289 +  pc - the preconditioning context
290 -  DirichletBoundaries - sequential index set defining the subdomain part of Dirichlet boundaries (can be NULL)
291 
292    Level: intermediate
293 
294    Notes:
295 
296 .seealso: PCBDDC
297 @*/
298 PetscErrorCode PCBDDCSetDirichletBoundaries(PC pc,IS DirichletBoundaries)
299 {
300   PetscErrorCode ierr;
301 
302   PetscFunctionBegin;
303   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
304   PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2);
305   ierr = PetscTryMethod(pc,"PCBDDCSetDirichletBoundaries_C",(PC,IS),(pc,DirichletBoundaries));CHKERRQ(ierr);
306   PetscFunctionReturn(0);
307 }
308 /* -------------------------------------------------------------------------- */
309 
310 #undef __FUNCT__
311 #define __FUNCT__ "PCBDDCSetNeumannBoundaries_BDDC"
312 static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc,IS NeumannBoundaries)
313 {
314   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
315   PetscErrorCode ierr;
316 
317   PetscFunctionBegin;
318   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
319   ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr);
320   pcbddc->NeumannBoundaries=NeumannBoundaries;
321   PetscFunctionReturn(0);
322 }
323 
324 #undef __FUNCT__
325 #define __FUNCT__ "PCBDDCSetNeumannBoundaries"
326 /*@
327  PCBDDCSetNeumannBoundaries - Set index set defining subdomain part (in local ordering)
328                               of Neumann boundaries for the global problem.
329 
330    Not collective
331 
332    Input Parameters:
333 +  pc - the preconditioning context
334 -  NeumannBoundaries - sequential index set defining the subdomain part of Neumann boundaries (can be NULL)
335 
336    Level: intermediate
337 
338    Notes:
339 
340 .seealso: PCBDDC
341 @*/
342 PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc,IS NeumannBoundaries)
343 {
344   PetscErrorCode ierr;
345 
346   PetscFunctionBegin;
347   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
348   PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2);
349   ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundaries_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr);
350   PetscFunctionReturn(0);
351 }
352 /* -------------------------------------------------------------------------- */
353 
354 #undef __FUNCT__
355 #define __FUNCT__ "PCBDDCGetDirichletBoundaries_BDDC"
356 static PetscErrorCode PCBDDCGetDirichletBoundaries_BDDC(PC pc,IS *DirichletBoundaries)
357 {
358   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
359 
360   PetscFunctionBegin;
361   *DirichletBoundaries = pcbddc->DirichletBoundaries;
362   PetscFunctionReturn(0);
363 }
364 
365 #undef __FUNCT__
366 #define __FUNCT__ "PCBDDCGetDirichletBoundaries"
367 /*@
368  PCBDDCGetDirichletBoundaries - Get index set defining subdomain part (in local ordering)
369                                 of Dirichlet boundaries for the global problem.
370 
371    Not collective
372 
373    Input Parameters:
374 +  pc - the preconditioning context
375 
376    Output Parameters:
377 +  DirichletBoundaries - index set defining the subdomain part of Dirichlet boundaries
378 
379    Level: intermediate
380 
381    Notes:
382 
383 .seealso: PCBDDC
384 @*/
385 PetscErrorCode PCBDDCGetDirichletBoundaries(PC pc,IS *DirichletBoundaries)
386 {
387   PetscErrorCode ierr;
388 
389   PetscFunctionBegin;
390   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
391   ierr = PetscUseMethod(pc,"PCBDDCGetDirichletBoundaries_C",(PC,IS*),(pc,DirichletBoundaries));CHKERRQ(ierr);
392   PetscFunctionReturn(0);
393 }
394 /* -------------------------------------------------------------------------- */
395 
396 #undef __FUNCT__
397 #define __FUNCT__ "PCBDDCGetNeumannBoundaries_BDDC"
398 static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc,IS *NeumannBoundaries)
399 {
400   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
401 
402   PetscFunctionBegin;
403   *NeumannBoundaries = pcbddc->NeumannBoundaries;
404   PetscFunctionReturn(0);
405 }
406 
407 #undef __FUNCT__
408 #define __FUNCT__ "PCBDDCGetNeumannBoundaries"
409 /*@
410  PCBDDCGetNeumannBoundaries - Get index set defining subdomain part (in local ordering)
411                               of Neumann boundaries for the global problem.
412 
413    Not collective
414 
415    Input Parameters:
416 +  pc - the preconditioning context
417 
418    Output Parameters:
419 +  NeumannBoundaries - index set defining the subdomain part of Neumann boundaries
420 
421    Level: intermediate
422 
423    Notes:
424 
425 .seealso: PCBDDC
426 @*/
427 PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc,IS *NeumannBoundaries)
428 {
429   PetscErrorCode ierr;
430 
431   PetscFunctionBegin;
432   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
433   ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundaries_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr);
434   PetscFunctionReturn(0);
435 }
436 /* -------------------------------------------------------------------------- */
437 
438 #undef __FUNCT__
439 #define __FUNCT__ "PCBDDCSetLocalAdjacencyGraph_BDDC"
440 static PetscErrorCode PCBDDCSetLocalAdjacencyGraph_BDDC(PC pc, PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode)
441 {
442   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
443   PCBDDCGraph    mat_graph = pcbddc->mat_graph;
444   PetscErrorCode ierr;
445 
446   PetscFunctionBegin;
447   /* free old CSR */
448   ierr = PCBDDCGraphResetCSR(mat_graph);CHKERRQ(ierr);
449   /* TODO: PCBDDCGraphSetAdjacency */
450   /* get CSR into graph structure */
451   if (copymode == PETSC_COPY_VALUES) {
452     ierr = PetscMalloc((nvtxs+1)*sizeof(PetscInt),&mat_graph->xadj);CHKERRQ(ierr);
453     ierr = PetscMalloc(xadj[nvtxs]*sizeof(PetscInt),&mat_graph->adjncy);CHKERRQ(ierr);
454     ierr = PetscMemcpy(mat_graph->xadj,xadj,(nvtxs+1)*sizeof(PetscInt));CHKERRQ(ierr);
455     ierr = PetscMemcpy(mat_graph->adjncy,adjncy,xadj[nvtxs]*sizeof(PetscInt));CHKERRQ(ierr);
456   } else if (copymode == PETSC_OWN_POINTER) {
457     mat_graph->xadj = (PetscInt*)xadj;
458     mat_graph->adjncy = (PetscInt*)adjncy;
459   }
460   mat_graph->nvtxs_csr = nvtxs;
461   PetscFunctionReturn(0);
462 }
463 
464 #undef __FUNCT__
465 #define __FUNCT__ "PCBDDCSetLocalAdjacencyGraph"
466 /*@
467  PCBDDCSetLocalAdjacencyGraph - Set CSR graph of local matrix for use of PCBDDC.
468 
469    Not collective
470 
471    Input Parameters:
472 +  pc - the preconditioning context
473 -  nvtxs - number of local vertices of the graph
474 -  xadj, adjncy - the CSR graph
475 -  copymode - either PETSC_COPY_VALUES or PETSC_OWN_POINTER. In the former case the user must free the array passed in;
476                                                              in the latter case, memory must be obtained with PetscMalloc.
477 
478    Level: intermediate
479 
480    Notes:
481 
482 .seealso: PCBDDC
483 @*/
484 PetscErrorCode PCBDDCSetLocalAdjacencyGraph(PC pc,PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode)
485 {
486   void (*f)(void) = 0;
487   PetscErrorCode ierr;
488 
489   PetscFunctionBegin;
490   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
491   PetscValidIntPointer(xadj,3);
492   PetscValidIntPointer(xadj,4);
493   if (copymode != PETSC_COPY_VALUES && copymode != PETSC_OWN_POINTER) {
494     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported copy mode %d in %s\n",copymode,__FUNCT__);
495   }
496   ierr = PetscTryMethod(pc,"PCBDDCSetLocalAdjacencyGraph_C",(PC,PetscInt,const PetscInt[],const PetscInt[],PetscCopyMode),(pc,nvtxs,xadj,adjncy,copymode));CHKERRQ(ierr);
497   /* free arrays if PCBDDC is not the PC type */
498   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",&f);CHKERRQ(ierr);
499   if (!f && copymode == PETSC_OWN_POINTER) {
500     ierr = PetscFree(xadj);CHKERRQ(ierr);
501     ierr = PetscFree(adjncy);CHKERRQ(ierr);
502   }
503   PetscFunctionReturn(0);
504 }
505 /* -------------------------------------------------------------------------- */
506 
507 #undef __FUNCT__
508 #define __FUNCT__ "PCBDDCSetDofsSplitting_BDDC"
509 static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
510 {
511   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
512   PetscInt i;
513   PetscErrorCode ierr;
514 
515   PetscFunctionBegin;
516   /* Destroy ISes if they were already set */
517   for (i=0;i<pcbddc->n_ISForDofs;i++) {
518     ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
519   }
520   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
521   /* allocate space then set */
522   ierr = PetscMalloc(n_is*sizeof(IS),&pcbddc->ISForDofs);CHKERRQ(ierr);
523   for (i=0;i<n_is;i++) {
524     ierr = PetscObjectReference((PetscObject)ISForDofs[i]);CHKERRQ(ierr);
525     pcbddc->ISForDofs[i]=ISForDofs[i];
526   }
527   pcbddc->n_ISForDofs=n_is;
528   PetscFunctionReturn(0);
529 }
530 
531 #undef __FUNCT__
532 #define __FUNCT__ "PCBDDCSetDofsSplitting"
533 /*@
534  PCBDDCSetDofsSplitting - Set index sets defining fields of local mat.
535 
536    Not collective
537 
538    Input Parameters:
539 +  pc - the preconditioning context
540 -  n - number of index sets defining the fields
541 -  IS[] - array of IS describing the fields
542 
543    Level: intermediate
544 
545    Notes:
546 
547 .seealso: PCBDDC
548 @*/
549 PetscErrorCode PCBDDCSetDofsSplitting(PC pc,PetscInt n_is, IS ISForDofs[])
550 {
551   PetscErrorCode ierr;
552 
553   PetscFunctionBegin;
554   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
555   ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplitting_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr);
556   PetscFunctionReturn(0);
557 }
558 /* -------------------------------------------------------------------------- */
559 #undef __FUNCT__
560 #define __FUNCT__ "PCPreSolve_BDDC"
561 /* -------------------------------------------------------------------------- */
562 /*
563    PCPreSolve_BDDC - Changes the right hand side and (if necessary) the initial
564                      guess if a transformation of basis approach has been selected.
565 
566    Input Parameter:
567 +  pc - the preconditioner contex
568 
569    Application Interface Routine: PCPreSolve()
570 
571    Notes:
572    The interface routine PCPreSolve() is not usually called directly by
573    the user, but instead is called by KSPSolve().
574 */
575 static PetscErrorCode PCPreSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
576 {
577   PetscErrorCode ierr;
578   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
579   PC_IS          *pcis = (PC_IS*)(pc->data);
580   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
581   Mat            temp_mat;
582   IS             dirIS;
583   PetscInt       dirsize,i,*is_indices;
584   PetscScalar    *array_x,*array_diagonal;
585   Vec            used_vec;
586   PetscBool      guess_nonzero;
587 
588   PetscFunctionBegin;
589   /* Creates parallel work vectors used in presolve. */
590   if (!pcbddc->original_rhs) {
591     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs);CHKERRQ(ierr);
592   }
593   if (!pcbddc->temp_solution) {
594     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->temp_solution);CHKERRQ(ierr);
595   }
596   if (x) {
597     ierr = PetscObjectReference((PetscObject)x);CHKERRQ(ierr);
598     used_vec = x;
599   } else {
600     ierr = PetscObjectReference((PetscObject)pcbddc->temp_solution);CHKERRQ(ierr);
601     used_vec = pcbddc->temp_solution;
602     ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
603   }
604   /* hack into ksp data structure PCPreSolve comes earlier in src/ksp/ksp/interface/itfunc.c */
605   if (ksp) {
606     ierr = KSPGetInitialGuessNonzero(ksp,&guess_nonzero);CHKERRQ(ierr);
607     if ( !guess_nonzero ) {
608       ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
609     }
610   }
611 
612   if (rhs) { /* TODO: wiser handling of rhs removal, which is only needed in case of zeroed rows */
613     /* store the original rhs */
614     ierr = VecCopy(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
615 
616     /* Take into account zeroed rows -> change rhs and store solution removed */
617     ierr = MatGetDiagonal(pc->pmat,pcis->vec1_global);CHKERRQ(ierr);
618     ierr = VecPointwiseDivide(pcis->vec1_global,rhs,pcis->vec1_global);CHKERRQ(ierr);
619     ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
620     ierr = VecScatterEnd(matis->ctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
621     ierr = VecScatterBegin(matis->ctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
622     ierr = VecScatterEnd(matis->ctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
623     ierr = PCBDDCGetDirichletBoundaries(pc,&dirIS);CHKERRQ(ierr);
624     if (dirIS) {
625       ierr = ISGetSize(dirIS,&dirsize);CHKERRQ(ierr);
626       ierr = VecGetArray(pcis->vec1_N,&array_x);CHKERRQ(ierr);
627       ierr = VecGetArray(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr);
628       ierr = ISGetIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
629       for (i=0; i<dirsize; i++) array_x[is_indices[i]] = array_diagonal[is_indices[i]];
630       ierr = ISRestoreIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
631       ierr = VecRestoreArray(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr);
632       ierr = VecRestoreArray(pcis->vec1_N,&array_x);CHKERRQ(ierr);
633     }
634     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
635     ierr = VecScatterEnd(matis->ctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
636 
637     /* remove the computed solution from the rhs */
638     ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr);
639     ierr = MatMultAdd(pc->pmat,used_vec,rhs,rhs);CHKERRQ(ierr);
640     ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr);
641   }
642 
643   /* store partially computed solution and set initial guess */
644   if (x) {
645     ierr = VecCopy(used_vec,pcbddc->temp_solution);CHKERRQ(ierr);
646     ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
647     if (pcbddc->use_exact_dirichlet && !pcbddc->coarse_psi_B) {
648       ierr = VecScatterBegin(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
649       ierr = VecScatterEnd  (pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
650       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
651       ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
652       ierr = VecScatterEnd  (pcis->global_to_D,pcis->vec2_D,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
653       if (ksp) {
654         ierr = KSPSetInitialGuessNonzero(ksp,PETSC_TRUE);CHKERRQ(ierr);
655       }
656     }
657   }
658 
659   if (pcbddc->use_change_of_basis) {
660     /* swap pointers for local matrices */
661     temp_mat = matis->A;
662     matis->A = pcbddc->local_mat;
663     pcbddc->local_mat = temp_mat;
664   }
665   if (pcbddc->use_change_of_basis && rhs) {
666     /* Get local rhs and apply transformation of basis */
667     ierr = VecScatterBegin(pcis->global_to_B,rhs,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
668     ierr = VecScatterEnd  (pcis->global_to_B,rhs,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
669     /* from original basis to modified basis */
670     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
671     /* put back modified values into the global vec using INSERT_VALUES copy mode */
672     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec2_B,rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
673     ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec2_B,rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
674   }
675   if (ksp && pcbddc->NullSpace) {
676     ierr = MatNullSpaceRemove(pcbddc->NullSpace,used_vec);CHKERRQ(ierr);
677     ierr = MatNullSpaceRemove(pcbddc->NullSpace,rhs);CHKERRQ(ierr);
678   }
679   ierr = VecDestroy(&used_vec);CHKERRQ(ierr);
680   PetscFunctionReturn(0);
681 }
682 /* -------------------------------------------------------------------------- */
683 #undef __FUNCT__
684 #define __FUNCT__ "PCPostSolve_BDDC"
685 /* -------------------------------------------------------------------------- */
686 /*
687    PCPostSolve_BDDC - Changes the computed solution if a transformation of basis
688                      approach has been selected. Also, restores rhs to its original state.
689 
690    Input Parameter:
691 +  pc - the preconditioner contex
692 
693    Application Interface Routine: PCPostSolve()
694 
695    Notes:
696    The interface routine PCPostSolve() is not usually called directly by
697    the user, but instead is called by KSPSolve().
698 */
699 static PetscErrorCode PCPostSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
700 {
701   PetscErrorCode ierr;
702   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
703   PC_IS          *pcis   = (PC_IS*)(pc->data);
704   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
705   Mat            temp_mat;
706 
707   PetscFunctionBegin;
708   if (pcbddc->use_change_of_basis) {
709     /* swap pointers for local matrices */
710     temp_mat = matis->A;
711     matis->A = pcbddc->local_mat;
712     pcbddc->local_mat = temp_mat;
713   }
714   if (pcbddc->use_change_of_basis && x) {
715     /* Get Local boundary and apply transformation of basis to solution vector */
716     ierr = VecScatterBegin(pcis->global_to_B,x,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
717     ierr = VecScatterEnd  (pcis->global_to_B,x,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
718     /* from modified basis to original basis */
719     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
720     /* put back modified values into the global vec using INSERT_VALUES copy mode */
721     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec2_B,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
722     ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec2_B,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
723   }
724   /* add solution removed in presolve */
725   if (x) {
726     ierr = VecAXPY(x,1.0,pcbddc->temp_solution);CHKERRQ(ierr);
727   }
728   /* restore rhs to its original state */
729   if (rhs) {
730     ierr = VecCopy(pcbddc->original_rhs,rhs);CHKERRQ(ierr);
731   }
732   PetscFunctionReturn(0);
733 }
734 /* -------------------------------------------------------------------------- */
735 #undef __FUNCT__
736 #define __FUNCT__ "PCSetUp_BDDC"
737 /* -------------------------------------------------------------------------- */
738 /*
739    PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner
740                   by setting data structures and options.
741 
742    Input Parameter:
743 +  pc - the preconditioner context
744 
745    Application Interface Routine: PCSetUp()
746 
747    Notes:
748    The interface routine PCSetUp() is not usually called directly by
749    the user, but instead is called by PCApply() if necessary.
750 */
751 PetscErrorCode PCSetUp_BDDC(PC pc)
752 {
753   PetscErrorCode ierr;
754   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
755   MatStructure   flag;
756   PetscBool      computeis,computetopography,computesolvers;
757 
758   PetscFunctionBegin;
759   /* the following lines of code should be replaced by a better logic between PCIS, PCNN, PCBDDC and other nonoverlapping preconditioners */
760   /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup
761      So, we set to pcnone the Neumann problem of pcis in order to avoid unneeded computation
762      Also, we decide to directly build the (same) Dirichlet problem */
763   ierr = PetscOptionsSetValue("-is_localN_pc_type","none");CHKERRQ(ierr);
764   ierr = PetscOptionsSetValue("-is_localD_pc_type","none");CHKERRQ(ierr);
765   /* Get stdout for dbg */
766   if (pcbddc->dbg_flag && !pcbddc->dbg_viewer) {
767     ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)pc),&pcbddc->dbg_viewer);CHKERRQ(ierr);
768     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
769   }
770   /* first attempt to split work */
771   if (pc->setupcalled) {
772     computeis = PETSC_FALSE;
773     ierr = PCGetOperators(pc,NULL,NULL,&flag);CHKERRQ(ierr);
774     if (flag == SAME_PRECONDITIONER) {
775       computetopography = PETSC_FALSE;
776       computesolvers = PETSC_FALSE;
777     } else if (flag == SAME_NONZERO_PATTERN) {
778       computetopography = PETSC_FALSE;
779       computesolvers = PETSC_TRUE;
780     } else { /* DIFFERENT_NONZERO_PATTERN */
781       computetopography = PETSC_TRUE;
782       computesolvers = PETSC_TRUE;
783     }
784   } else {
785     computeis = PETSC_TRUE;
786     computetopography = PETSC_TRUE;
787     computesolvers = PETSC_TRUE;
788   }
789   /* Set up all the "iterative substructuring" common block */
790   if (computeis) {
791     ierr = PCISSetUp(pc);CHKERRQ(ierr);
792   }
793   /* Analyze interface and set up local constraint and change of basis matrices */
794   if (computetopography) {
795     /* reset data */
796     ierr = PCBDDCResetTopography(pc);CHKERRQ(ierr);
797     ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
798     ierr = PCBDDCConstraintsSetUp(pc);CHKERRQ(ierr);
799   }
800   if (computesolvers) {
801     /* reset data */
802     ierr = PCBDDCResetSolvers(pc);CHKERRQ(ierr);
803     ierr = PCBDDCScalingDestroy(pc);CHKERRQ(ierr);
804     /* Create coarse and local stuffs */
805     ierr = PCBDDCSetUpSolvers(pc);CHKERRQ(ierr);
806     ierr = PCBDDCScalingSetUp(pc);CHKERRQ(ierr);
807   }
808   PetscFunctionReturn(0);
809 }
810 
811 /* -------------------------------------------------------------------------- */
812 /*
813    PCApply_BDDC - Applies the BDDC preconditioner to a vector.
814 
815    Input Parameters:
816 .  pc - the preconditioner context
817 .  r - input vector (global)
818 
819    Output Parameter:
820 .  z - output vector (global)
821 
822    Application Interface Routine: PCApply()
823  */
824 #undef __FUNCT__
825 #define __FUNCT__ "PCApply_BDDC"
826 PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z)
827 {
828   PC_IS             *pcis = (PC_IS*)(pc->data);
829   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
830   PetscErrorCode    ierr;
831   const PetscScalar one = 1.0;
832   const PetscScalar m_one = -1.0;
833   const PetscScalar zero = 0.0;
834 
835 /* This code is similar to that provided in nn.c for PCNN
836    NN interface preconditioner changed to BDDC
837    Added support for M_3 preconditioner in the reference article (code is active if pcbddc->inexact_prec_type = PETSC_TRUE) */
838 
839   PetscFunctionBegin;
840   if (!pcbddc->use_exact_dirichlet || pcbddc->coarse_psi_B) {
841     /* First Dirichlet solve */
842     ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
843     ierr = VecScatterEnd  (pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
844     ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
845     /*
846       Assembling right hand side for BDDC operator
847       - pcis->vec1_D for the Dirichlet part (if needed, i.e. prec_flag=PETSC_TRUE)
848       - pcis->vec1_B the interface part of the global vector z
849     */
850     ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
851     ierr = MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
852     if (pcbddc->inexact_prec_type) { ierr = MatMultAdd(pcis->A_II,pcis->vec2_D,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
853     ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
854     ierr = VecCopy(r,z);CHKERRQ(ierr);
855     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
856     ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
857     ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr);
858   } else {
859     ierr = VecSet(pcis->vec1_D,zero);CHKERRQ(ierr);
860     ierr = VecSet(pcis->vec2_D,zero);CHKERRQ(ierr);
861     ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr);
862   }
863 
864   /* Apply interface preconditioner
865      input/output vecs: pcis->vec1_B and pcis->vec1_D */
866   ierr = PCBDDCApplyInterfacePreconditioner(pc);CHKERRQ(ierr);
867 
868   /* Apply transpose of partition of unity operator */
869   ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr);
870 
871   /* Second Dirichlet solve and assembling of output */
872   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
873   ierr = VecScatterEnd  (pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
874   ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
875   if (pcbddc->inexact_prec_type) { ierr = MatMultAdd(pcis->A_II,pcis->vec1_D,pcis->vec3_D,pcis->vec3_D);CHKERRQ(ierr); }
876   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec3_D,pcbddc->vec4_D);CHKERRQ(ierr);
877   ierr = VecScale(pcbddc->vec4_D,m_one);CHKERRQ(ierr);
878   if (pcbddc->inexact_prec_type) { ierr = VecAXPY (pcbddc->vec4_D,one,pcis->vec1_D);CHKERRQ(ierr); }
879   ierr = VecAXPY (pcis->vec2_D,one,pcbddc->vec4_D);CHKERRQ(ierr);
880   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
881   ierr = VecScatterEnd  (pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
882   PetscFunctionReturn(0);
883 }
884 /* -------------------------------------------------------------------------- */
885 
886 #undef __FUNCT__
887 #define __FUNCT__ "PCDestroy_BDDC"
888 PetscErrorCode PCDestroy_BDDC(PC pc)
889 {
890   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
891   PetscErrorCode ierr;
892 
893   PetscFunctionBegin;
894   /* free data created by PCIS */
895   ierr = PCISDestroy(pc);CHKERRQ(ierr);
896   /* free BDDC custom data  */
897   ierr = PCBDDCResetCustomization(pc);CHKERRQ(ierr);
898   /* destroy objects related to topography */
899   ierr = PCBDDCResetTopography(pc);CHKERRQ(ierr);
900   /* free allocated graph structure */
901   ierr = PetscFree(pcbddc->mat_graph);CHKERRQ(ierr);
902   /* free data for scaling operator */
903   ierr = PCBDDCScalingDestroy(pc);CHKERRQ(ierr);
904   /* free solvers stuff */
905   ierr = PCBDDCResetSolvers(pc);CHKERRQ(ierr);
906   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
907   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
908   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
909   /* free global vectors needed in presolve */
910   ierr = VecDestroy(&pcbddc->temp_solution);CHKERRQ(ierr);
911   ierr = VecDestroy(&pcbddc->original_rhs);CHKERRQ(ierr);
912   /* remove functions */
913   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",NULL);CHKERRQ(ierr);
914   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",NULL);CHKERRQ(ierr);
915   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetMaxLevels_C",NULL);CHKERRQ(ierr);
916   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNullSpace_C",NULL);CHKERRQ(ierr);
917   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",NULL);CHKERRQ(ierr);
918   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",NULL);CHKERRQ(ierr);
919   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",NULL);CHKERRQ(ierr);
920   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",NULL);CHKERRQ(ierr);
921   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseProblemType_C",NULL);CHKERRQ(ierr);
922   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",NULL);CHKERRQ(ierr);
923   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",NULL);CHKERRQ(ierr);
924   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",NULL);CHKERRQ(ierr);
925   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",NULL);CHKERRQ(ierr);
926   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",NULL);CHKERRQ(ierr);
927   /* Free the private data structure */
928   ierr = PetscFree(pc->data);CHKERRQ(ierr);
929   PetscFunctionReturn(0);
930 }
931 /* -------------------------------------------------------------------------- */
932 
933 #undef __FUNCT__
934 #define __FUNCT__ "PCBDDCMatFETIDPGetRHS_BDDC"
935 static PetscErrorCode PCBDDCMatFETIDPGetRHS_BDDC(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
936 {
937   FETIDPMat_ctx  mat_ctx;
938   PC_IS*         pcis;
939   PC_BDDC*       pcbddc;
940   PetscErrorCode ierr;
941 
942   PetscFunctionBegin;
943   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
944   pcis = (PC_IS*)mat_ctx->pc->data;
945   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
946 
947   /* change of basis for physical rhs if needed
948      It also changes the rhs in case of dirichlet boundaries */
949   ierr = PCPreSolve_BDDC(mat_ctx->pc,NULL,standard_rhs,NULL);CHKERRQ(ierr);
950   /* store vectors for computation of fetidp final solution */
951   ierr = VecScatterBegin(pcis->global_to_D,standard_rhs,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
952   ierr = VecScatterEnd(pcis->global_to_D,standard_rhs,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
953   /* scale rhs since it should be unassembled */
954   /* TODO use counter scaling? (also below) */
955   ierr = VecScatterBegin(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
956   ierr = VecScatterEnd(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
957   /* Apply partition of unity */
958   ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr);
959   /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,standard_rhs,mat_ctx->temp_solution_B);CHKERRQ(ierr); */
960   if (!pcbddc->inexact_prec_type) {
961     /* compute partially subassembled Schur complement right-hand side */
962     ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
963     ierr = MatMult(pcis->A_BI,pcis->vec1_D,pcis->vec1_B);CHKERRQ(ierr);
964     ierr = VecAXPY(mat_ctx->temp_solution_B,-1.0,pcis->vec1_B);CHKERRQ(ierr);
965     ierr = VecSet(standard_rhs,0.0);CHKERRQ(ierr);
966     ierr = VecScatterBegin(pcis->global_to_B,mat_ctx->temp_solution_B,standard_rhs,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
967     ierr = VecScatterEnd(pcis->global_to_B,mat_ctx->temp_solution_B,standard_rhs,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
968     /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,standard_rhs,mat_ctx->temp_solution_B);CHKERRQ(ierr); */
969     ierr = VecScatterBegin(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
970     ierr = VecScatterEnd(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
971     ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr);
972   }
973   /* BDDC rhs */
974   ierr = VecCopy(mat_ctx->temp_solution_B,pcis->vec1_B);CHKERRQ(ierr);
975   if (pcbddc->inexact_prec_type) {
976     ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
977   }
978   /* apply BDDC */
979   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc);CHKERRQ(ierr);
980   /* Application of B_delta and assembling of rhs for fetidp fluxes */
981   ierr = VecSet(fetidp_flux_rhs,0.0);CHKERRQ(ierr);
982   ierr = MatMult(mat_ctx->B_delta,pcis->vec1_B,mat_ctx->lambda_local);CHKERRQ(ierr);
983   ierr = VecScatterBegin(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
984   ierr = VecScatterEnd  (mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
985   /* restore original rhs */
986   ierr = VecCopy(pcbddc->original_rhs,standard_rhs);CHKERRQ(ierr);
987   PetscFunctionReturn(0);
988 }
989 
990 #undef __FUNCT__
991 #define __FUNCT__ "PCBDDCMatFETIDPGetRHS"
992 /*@
993  PCBDDCMatFETIDPGetRHS - Get rhs for FETIDP linear system.
994 
995    Collective
996 
997    Input Parameters:
998 +  fetidp_mat   - the FETIDP mat obtained by a call to PCBDDCCreateFETIDPOperators
999 +  standard_rhs - the rhs of your linear system
1000 
1001    Output Parameters:
1002 +  fetidp_flux_rhs   - the rhs of the FETIDP linear system
1003 
1004    Level: developer
1005 
1006    Notes:
1007 
1008 .seealso: PCBDDC
1009 @*/
1010 PetscErrorCode PCBDDCMatFETIDPGetRHS(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
1011 {
1012   FETIDPMat_ctx  mat_ctx;
1013   PetscErrorCode ierr;
1014 
1015   PetscFunctionBegin;
1016   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
1017   ierr = PetscTryMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetRHS_C",(Mat,Vec,Vec),(fetidp_mat,standard_rhs,fetidp_flux_rhs));CHKERRQ(ierr);
1018   PetscFunctionReturn(0);
1019 }
1020 /* -------------------------------------------------------------------------- */
1021 
1022 #undef __FUNCT__
1023 #define __FUNCT__ "PCBDDCMatFETIDPGetSolution_BDDC"
1024 static PetscErrorCode PCBDDCMatFETIDPGetSolution_BDDC(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
1025 {
1026   FETIDPMat_ctx  mat_ctx;
1027   PC_IS*         pcis;
1028   PC_BDDC*       pcbddc;
1029   PetscErrorCode ierr;
1030 
1031   PetscFunctionBegin;
1032   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
1033   pcis = (PC_IS*)mat_ctx->pc->data;
1034   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
1035 
1036   /* apply B_delta^T */
1037   ierr = VecScatterBegin(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1038   ierr = VecScatterEnd  (mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1039   ierr = MatMultTranspose(mat_ctx->B_delta,mat_ctx->lambda_local,pcis->vec1_B);CHKERRQ(ierr);
1040   /* compute rhs for BDDC application */
1041   ierr = VecAYPX(pcis->vec1_B,-1.0,mat_ctx->temp_solution_B);CHKERRQ(ierr);
1042   if (pcbddc->inexact_prec_type) {
1043     ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
1044   }
1045   /* apply BDDC */
1046   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc);CHKERRQ(ierr);
1047   /* put values into standard global vector */
1048   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1049   ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1050   if (!pcbddc->inexact_prec_type) {
1051     /* compute values into the interior if solved for the partially subassembled Schur complement */
1052     ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec1_D);CHKERRQ(ierr);
1053     ierr = VecAXPY(mat_ctx->temp_solution_D,-1.0,pcis->vec1_D);CHKERRQ(ierr);
1054     ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
1055   }
1056   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec1_D,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1057   ierr = VecScatterEnd  (pcis->global_to_D,pcis->vec1_D,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1058   /* final change of basis if needed
1059      Is also sums the dirichlet part removed during RHS assembling */
1060   ierr = PCPostSolve_BDDC(mat_ctx->pc,NULL,NULL,standard_sol);CHKERRQ(ierr);
1061   PetscFunctionReturn(0);
1062 }
1063 
1064 #undef __FUNCT__
1065 #define __FUNCT__ "PCBDDCMatFETIDPGetSolution"
1066 /*@
1067  PCBDDCMatFETIDPGetSolution - Get Solution for FETIDP linear system.
1068 
1069    Collective
1070 
1071    Input Parameters:
1072 +  fetidp_mat        - the FETIDP mat obtained by a call to PCBDDCCreateFETIDPOperators
1073 +  fetidp_flux_sol - the solution of the FETIDP linear system
1074 
1075    Output Parameters:
1076 +  standard_sol      - the solution on the global domain
1077 
1078    Level: developer
1079 
1080    Notes:
1081 
1082 .seealso: PCBDDC
1083 @*/
1084 PetscErrorCode PCBDDCMatFETIDPGetSolution(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
1085 {
1086   FETIDPMat_ctx  mat_ctx;
1087   PetscErrorCode ierr;
1088 
1089   PetscFunctionBegin;
1090   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
1091   ierr = PetscTryMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetSolution_C",(Mat,Vec,Vec),(fetidp_mat,fetidp_flux_sol,standard_sol));CHKERRQ(ierr);
1092   PetscFunctionReturn(0);
1093 }
1094 /* -------------------------------------------------------------------------- */
1095 
1096 extern PetscErrorCode FETIDPMatMult(Mat,Vec,Vec);
1097 extern PetscErrorCode PCBDDCDestroyFETIDPMat(Mat);
1098 extern PetscErrorCode FETIDPPCApply(PC,Vec,Vec);
1099 extern PetscErrorCode PCBDDCDestroyFETIDPPC(PC);
1100 
1101 #undef __FUNCT__
1102 #define __FUNCT__ "PCBDDCCreateFETIDPOperators_BDDC"
1103 static PetscErrorCode PCBDDCCreateFETIDPOperators_BDDC(PC pc, Mat *fetidp_mat, PC *fetidp_pc)
1104 {
1105 
1106   FETIDPMat_ctx  fetidpmat_ctx;
1107   Mat            newmat;
1108   FETIDPPC_ctx   fetidppc_ctx;
1109   PC             newpc;
1110   MPI_Comm       comm;
1111   PetscErrorCode ierr;
1112 
1113   PetscFunctionBegin;
1114   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
1115   /* FETIDP linear matrix */
1116   ierr = PCBDDCCreateFETIDPMatContext(pc,&fetidpmat_ctx);CHKERRQ(ierr);
1117   ierr = PCBDDCSetupFETIDPMatContext(fetidpmat_ctx);CHKERRQ(ierr);
1118   ierr = MatCreateShell(comm,PETSC_DECIDE,PETSC_DECIDE,fetidpmat_ctx->n_lambda,fetidpmat_ctx->n_lambda,fetidpmat_ctx,&newmat);CHKERRQ(ierr);
1119   ierr = MatShellSetOperation(newmat,MATOP_MULT,(void (*)(void))FETIDPMatMult);CHKERRQ(ierr);
1120   ierr = MatShellSetOperation(newmat,MATOP_DESTROY,(void (*)(void))PCBDDCDestroyFETIDPMat);CHKERRQ(ierr);
1121   ierr = MatSetUp(newmat);CHKERRQ(ierr);
1122   /* FETIDP preconditioner */
1123   ierr = PCBDDCCreateFETIDPPCContext(pc,&fetidppc_ctx);CHKERRQ(ierr);
1124   ierr = PCBDDCSetupFETIDPPCContext(newmat,fetidppc_ctx);CHKERRQ(ierr);
1125   ierr = PCCreate(comm,&newpc);CHKERRQ(ierr);
1126   ierr = PCSetType(newpc,PCSHELL);CHKERRQ(ierr);
1127   ierr = PCShellSetContext(newpc,fetidppc_ctx);CHKERRQ(ierr);
1128   ierr = PCShellSetApply(newpc,FETIDPPCApply);CHKERRQ(ierr);
1129   ierr = PCShellSetDestroy(newpc,PCBDDCDestroyFETIDPPC);CHKERRQ(ierr);
1130   ierr = PCSetOperators(newpc,newmat,newmat,SAME_PRECONDITIONER);CHKERRQ(ierr);
1131   ierr = PCSetUp(newpc);CHKERRQ(ierr);
1132   /* return pointers for objects created */
1133   *fetidp_mat=newmat;
1134   *fetidp_pc=newpc;
1135   PetscFunctionReturn(0);
1136 }
1137 
1138 #undef __FUNCT__
1139 #define __FUNCT__ "PCBDDCCreateFETIDPOperators"
1140 /*@
1141  PCBDDCCreateFETIDPOperators - Create operators for FETIDP.
1142 
1143    Collective
1144 
1145    Input Parameters:
1146 +  pc - the BDDC preconditioning context (setup must be already called)
1147 
1148    Level: developer
1149 
1150    Notes:
1151 
1152 .seealso: PCBDDC
1153 @*/
1154 PetscErrorCode PCBDDCCreateFETIDPOperators(PC pc, Mat *fetidp_mat, PC *fetidp_pc)
1155 {
1156   PetscErrorCode ierr;
1157 
1158   PetscFunctionBegin;
1159   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1160   if (pc->setupcalled) {
1161     ierr = PetscTryMethod(pc,"PCBDDCCreateFETIDPOperators_C",(PC,Mat*,PC*),(pc,fetidp_mat,fetidp_pc));CHKERRQ(ierr);
1162   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"You must call PCSetup_BDDC() first \n");
1163   PetscFunctionReturn(0);
1164 }
1165 /* -------------------------------------------------------------------------- */
1166 /*MC
1167    PCBDDC - Balancing Domain Decomposition by Constraints.
1168 
1169    Options Database Keys:
1170 .    -pcbddc ??? -
1171 
1172    Level: intermediate
1173 
1174    Notes: The matrix used with this preconditioner must be of type MATIS
1175 
1176           Unlike more 'conventional' interface preconditioners, this iterates over ALL the
1177           degrees of freedom, NOT just those on the interface (this allows the use of approximate solvers
1178           on the subdomains).
1179 
1180           Options for the coarse grid preconditioner can be set with -
1181           Options for the Dirichlet subproblem can be set with -
1182           Options for the Neumann subproblem can be set with -
1183 
1184    Contributed by Stefano Zampini
1185 
1186 .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,  MATIS
1187 M*/
1188 
1189 #undef __FUNCT__
1190 #define __FUNCT__ "PCCreate_BDDC"
1191 PETSC_EXTERN PetscErrorCode PCCreate_BDDC(PC pc)
1192 {
1193   PetscErrorCode      ierr;
1194   PC_BDDC             *pcbddc;
1195 
1196   PetscFunctionBegin;
1197   /* Creates the private data structure for this preconditioner and attach it to the PC object. */
1198   ierr      = PetscNewLog(pc,PC_BDDC,&pcbddc);CHKERRQ(ierr);
1199   pc->data  = (void*)pcbddc;
1200 
1201   /* create PCIS data structure */
1202   ierr = PCISCreate(pc);CHKERRQ(ierr);
1203 
1204   /* BDDC specific */
1205   pcbddc->user_primal_vertices       = 0;
1206   pcbddc->NullSpace                  = 0;
1207   pcbddc->temp_solution              = 0;
1208   pcbddc->original_rhs               = 0;
1209   pcbddc->local_mat                  = 0;
1210   pcbddc->ChangeOfBasisMatrix        = 0;
1211   pcbddc->use_change_of_basis        = PETSC_TRUE;
1212   pcbddc->use_change_on_faces        = PETSC_FALSE;
1213   pcbddc->coarse_vec                 = 0;
1214   pcbddc->coarse_rhs                 = 0;
1215   pcbddc->coarse_ksp                 = 0;
1216   pcbddc->coarse_phi_B               = 0;
1217   pcbddc->coarse_phi_D               = 0;
1218   pcbddc->coarse_psi_B               = 0;
1219   pcbddc->coarse_psi_D               = 0;
1220   pcbddc->vec1_P                     = 0;
1221   pcbddc->vec1_R                     = 0;
1222   pcbddc->vec2_R                     = 0;
1223   pcbddc->local_auxmat1              = 0;
1224   pcbddc->local_auxmat2              = 0;
1225   pcbddc->R_to_B                     = 0;
1226   pcbddc->R_to_D                     = 0;
1227   pcbddc->ksp_D                      = 0;
1228   pcbddc->ksp_R                      = 0;
1229   pcbddc->local_primal_indices       = 0;
1230   pcbddc->inexact_prec_type          = PETSC_FALSE;
1231   pcbddc->NeumannBoundaries          = 0;
1232   pcbddc->ISForDofs                  = 0;
1233   pcbddc->ConstraintMatrix           = 0;
1234   pcbddc->use_nnsp_true              = PETSC_FALSE;
1235   pcbddc->local_primal_sizes         = 0;
1236   pcbddc->local_primal_displacements = 0;
1237   pcbddc->coarse_loc_to_glob         = 0;
1238   pcbddc->dbg_flag                   = 0;
1239   pcbddc->coarsening_ratio           = 8;
1240   pcbddc->use_exact_dirichlet        = PETSC_TRUE;
1241   pcbddc->current_level              = 0;
1242   pcbddc->max_levels                 = 1;
1243   pcbddc->replicated_local_primal_indices = 0;
1244   pcbddc->replicated_local_primal_values  = 0;
1245 
1246   /* create local graph structure */
1247   ierr = PCBDDCGraphCreate(&pcbddc->mat_graph);CHKERRQ(ierr);
1248 
1249   /* scaling */
1250   pcbddc->use_deluxe_scaling         = PETSC_FALSE;
1251   pcbddc->work_scaling               = 0;
1252 
1253   /* function pointers */
1254   pc->ops->apply               = PCApply_BDDC;
1255   pc->ops->applytranspose      = 0;
1256   pc->ops->setup               = PCSetUp_BDDC;
1257   pc->ops->destroy             = PCDestroy_BDDC;
1258   pc->ops->setfromoptions      = PCSetFromOptions_BDDC;
1259   pc->ops->view                = 0;
1260   pc->ops->applyrichardson     = 0;
1261   pc->ops->applysymmetricleft  = 0;
1262   pc->ops->applysymmetricright = 0;
1263   pc->ops->presolve            = PCPreSolve_BDDC;
1264   pc->ops->postsolve           = PCPostSolve_BDDC;
1265 
1266   /* composing function */
1267   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",PCBDDCSetPrimalVerticesLocalIS_BDDC);CHKERRQ(ierr);
1268   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",PCBDDCSetCoarseningRatio_BDDC);CHKERRQ(ierr);
1269   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetMaxLevels_C",PCBDDCSetMaxLevels_BDDC);CHKERRQ(ierr);
1270   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNullSpace_C",PCBDDCSetNullSpace_BDDC);CHKERRQ(ierr);
1271   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",PCBDDCSetDirichletBoundaries_BDDC);CHKERRQ(ierr);
1272   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",PCBDDCSetNeumannBoundaries_BDDC);CHKERRQ(ierr);
1273   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",PCBDDCGetDirichletBoundaries_BDDC);CHKERRQ(ierr);
1274   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",PCBDDCGetNeumannBoundaries_BDDC);CHKERRQ(ierr);
1275   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseProblemType_C",PCBDDCSetCoarseProblemType_BDDC);CHKERRQ(ierr);
1276   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",PCBDDCSetDofsSplitting_BDDC);CHKERRQ(ierr);
1277   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",PCBDDCSetLocalAdjacencyGraph_BDDC);CHKERRQ(ierr);
1278   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",PCBDDCCreateFETIDPOperators_BDDC);CHKERRQ(ierr);
1279   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",PCBDDCMatFETIDPGetRHS_BDDC);CHKERRQ(ierr);
1280   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",PCBDDCMatFETIDPGetSolution_BDDC);CHKERRQ(ierr);
1281   PetscFunctionReturn(0);
1282 }
1283 
1284