xref: /petsc/src/ksp/pc/impls/bddc/bddc.c (revision 1cf9b2375b21bbd252d6a780c47a40d91538aeab)
1 /* TODOLIST
2 
3    Solvers
4    - Add support for cholesky for coarse solver (similar to local solvers)
5    - Propagate ksp prefixes for solvers to mat objects?
6 
7    User interface
8    - ** DM attached to pc?
9 
10    Debugging output
11    - * Better management of verbosity levels of debugging output
12 
13    Extra
14    - *** Is it possible to work with PCBDDCGraph on boundary indices only (less memory consumed)?
15    - BDDC with MG framework?
16 
17    FETIDP
18    - Move FETIDP code to its own classes
19 
20    MATIS related operations contained in BDDC code
21    - Provide general case for subassembling
22 
23 */
24 
25 #include <../src/ksp/pc/impls/bddc/bddc.h> /*I "petscpc.h" I*/  /* includes for fortran wrappers */
26 #include <../src/ksp/pc/impls/bddc/bddcprivate.h>
27 #include <petscblaslapack.h>
28 
29 /* temporarily declare it */
30 PetscErrorCode PCApply_BDDC(PC,Vec,Vec);
31 
32 /* -------------------------------------------------------------------------- */
33 #undef __FUNCT__
34 #define __FUNCT__ "PCSetFromOptions_BDDC"
35 PetscErrorCode PCSetFromOptions_BDDC(PetscOptions *PetscOptionsObject,PC pc)
36 {
37   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
38   PetscErrorCode ierr;
39 
40   PetscFunctionBegin;
41   ierr = PetscOptionsHead(PetscOptionsObject,"BDDC options");CHKERRQ(ierr);
42   /* Verbose debugging */
43   ierr = PetscOptionsInt("-pc_bddc_check_level","Verbose output for PCBDDC (intended for debug)","none",pcbddc->dbg_flag,&pcbddc->dbg_flag,NULL);CHKERRQ(ierr);
44   /* Primal space cumstomization */
45   ierr = PetscOptionsBool("-pc_bddc_use_local_mat_graph","Use or not adjacency graph of local mat for interface analysis","none",pcbddc->use_local_adj,&pcbddc->use_local_adj,NULL);CHKERRQ(ierr);
46   ierr = PetscOptionsBool("-pc_bddc_use_vertices","Use or not corner dofs in coarse space","none",pcbddc->use_vertices,&pcbddc->use_vertices,NULL);CHKERRQ(ierr);
47   ierr = PetscOptionsBool("-pc_bddc_use_edges","Use or not edge constraints in coarse space","none",pcbddc->use_edges,&pcbddc->use_edges,NULL);CHKERRQ(ierr);
48   ierr = PetscOptionsBool("-pc_bddc_use_faces","Use or not face constraints in coarse space","none",pcbddc->use_faces,&pcbddc->use_faces,NULL);CHKERRQ(ierr);
49   ierr = PetscOptionsBool("-pc_bddc_use_true_nnsp","Use near null space attached to the matrix without modifications","none",pcbddc->use_nnsp_true,&pcbddc->use_nnsp_true,NULL);CHKERRQ(ierr);
50   ierr = PetscOptionsBool("-pc_bddc_use_qr_single","Use QR factorization for single constraints on cc (QR is used when multiple constraints are present)","none",pcbddc->use_qr_single,&pcbddc->use_qr_single,NULL);CHKERRQ(ierr);
51   /* Change of basis */
52   ierr = PetscOptionsBool("-pc_bddc_use_change_of_basis","Use or not internal change of basis on local edge nodes","none",pcbddc->use_change_of_basis,&pcbddc->use_change_of_basis,NULL);CHKERRQ(ierr);
53   ierr = PetscOptionsBool("-pc_bddc_use_change_on_faces","Use or not internal change of basis on local face nodes","none",pcbddc->use_change_on_faces,&pcbddc->use_change_on_faces,NULL);CHKERRQ(ierr);
54   if (!pcbddc->use_change_of_basis) {
55     pcbddc->use_change_on_faces = PETSC_FALSE;
56   }
57   /* Switch between M_2 (default) and M_3 preconditioners (as defined by C. Dohrmann in the ref. article) */
58   ierr = PetscOptionsBool("-pc_bddc_switch_static","Switch on static condensation ops around the interface preconditioner","none",pcbddc->switch_static,&pcbddc->switch_static,NULL);CHKERRQ(ierr);
59   ierr = PetscOptionsInt("-pc_bddc_coarse_redistribute","Number of procs where to redistribute coarse problem","none",pcbddc->redistribute_coarse,&pcbddc->redistribute_coarse,NULL);CHKERRQ(ierr);
60   ierr = PetscOptionsInt("-pc_bddc_coarsening_ratio","Set coarsening ratio used in multilevel coarsening","none",pcbddc->coarsening_ratio,&pcbddc->coarsening_ratio,NULL);CHKERRQ(ierr);
61   ierr = PetscOptionsInt("-pc_bddc_levels","Set maximum number of levels for multilevel","none",pcbddc->max_levels,&pcbddc->max_levels,NULL);CHKERRQ(ierr);
62   ierr = PetscOptionsBool("-pc_bddc_use_coarse_estimates","Use estimated eigenvalues for coarse problem","none",pcbddc->use_coarse_estimates,&pcbddc->use_coarse_estimates,NULL);CHKERRQ(ierr);
63   ierr = PetscOptionsBool("-pc_bddc_use_deluxe_scaling","Use deluxe scaling for BDDC","none",pcbddc->use_deluxe_scaling,&pcbddc->use_deluxe_scaling,NULL);CHKERRQ(ierr);
64   ierr = PetscOptionsBool("-pc_bddc_schur_rebuild","Whether or not the interface graph for Schur principal minors has to be rebuilt (i.e. define the interface without any adjacency)","none",pcbddc->sub_schurs_rebuild,&pcbddc->sub_schurs_rebuild,NULL);CHKERRQ(ierr);
65   ierr = PetscOptionsInt("-pc_bddc_schur_layers","Number of dofs' layers for the computation of principal minors (i.e. -1 uses all dofs)","none",pcbddc->sub_schurs_layers,&pcbddc->sub_schurs_layers,NULL);CHKERRQ(ierr);
66   ierr = PetscOptionsBool("-pc_bddc_schur_use_useradj","Whether or not the CSR graph specified by the user should be used for computing successive layers (default is to use adj of local mat)","none",pcbddc->sub_schurs_use_useradj,&pcbddc->sub_schurs_use_useradj,NULL);CHKERRQ(ierr);
67   ierr = PetscOptionsBool("-pc_bddc_deluxe_faster","Faster application of deluxe scaling (requires extra work during setup)","none",pcbddc->faster_deluxe,&pcbddc->faster_deluxe,NULL);CHKERRQ(ierr);
68   ierr = PetscOptionsReal("-pc_bddc_adaptive_threshold","Threshold to be used for adaptive selection of constraints","none",pcbddc->adaptive_threshold,&pcbddc->adaptive_threshold,NULL);CHKERRQ(ierr);
69   ierr = PetscOptionsInt("-pc_bddc_adaptive_nmin","Minimum number of constraints per connected components","none",pcbddc->adaptive_nmin,&pcbddc->adaptive_nmin,NULL);CHKERRQ(ierr);
70   ierr = PetscOptionsInt("-pc_bddc_adaptive_nmax","Maximum number of constraints per connected components","none",pcbddc->adaptive_nmax,&pcbddc->adaptive_nmax,NULL);CHKERRQ(ierr);
71   ierr = PetscOptionsBool("-pc_bddc_symmetric","Symmetric computation of primal basis functions","none",pcbddc->symmetric_primal,&pcbddc->symmetric_primal,NULL);CHKERRQ(ierr);
72   ierr = PetscOptionsInt("-pc_bddc_coarse_adj","Number of processors where to map the coarse adjacency list","none",pcbddc->coarse_adj_red,&pcbddc->coarse_adj_red,NULL);CHKERRQ(ierr);
73   ierr = PetscOptionsBool("-pc_bddc_benign_trick","Apply the benign subspace trick to a class of saddle point problems","none",pcbddc->benign_saddle_point,&pcbddc->benign_saddle_point,NULL);CHKERRQ(ierr);
74   ierr = PetscOptionsBool("-pc_bddc_detect_disconnected","Detects disconnected subdomains","none",pcbddc->detect_disconnected,&pcbddc->detect_disconnected,NULL);CHKERRQ(ierr);
75   ierr = PetscOptionsTail();CHKERRQ(ierr);
76   PetscFunctionReturn(0);
77 }
78 /* -------------------------------------------------------------------------- */
79 #undef __FUNCT__
80 #define __FUNCT__ "PCBDDCSetChangeOfBasisMat_BDDC"
81 static PetscErrorCode PCBDDCSetChangeOfBasisMat_BDDC(PC pc, Mat change)
82 {
83   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
84   PetscErrorCode ierr;
85 
86   PetscFunctionBegin;
87   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
88   ierr = PetscObjectReference((PetscObject)change);CHKERRQ(ierr);
89   pcbddc->user_ChangeOfBasisMatrix = change;
90   PetscFunctionReturn(0);
91 }
92 #undef __FUNCT__
93 #define __FUNCT__ "PCBDDCSetChangeOfBasisMat"
94 /*@
95  PCBDDCSetChangeOfBasisMat - Set user defined change of basis for dofs
96 
97    Collective on PC
98 
99    Input Parameters:
100 +  pc - the preconditioning context
101 -  change - the change of basis matrix
102 
103    Level: intermediate
104 
105    Notes:
106 
107 .seealso: PCBDDC
108 @*/
109 PetscErrorCode PCBDDCSetChangeOfBasisMat(PC pc, Mat change)
110 {
111   PetscErrorCode ierr;
112 
113   PetscFunctionBegin;
114   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
115   PetscValidHeaderSpecific(change,MAT_CLASSID,2);
116   PetscCheckSameComm(pc,1,change,2);
117   if (pc->mat) {
118     PetscInt rows_c,cols_c,rows,cols;
119     ierr = MatGetSize(pc->mat,&rows,&cols);CHKERRQ(ierr);
120     ierr = MatGetSize(change,&rows_c,&cols_c);CHKERRQ(ierr);
121     if (rows_c != rows) {
122       SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of rows for change of basis matrix! %d != %d",rows_c,rows);
123     }
124     if (cols_c != cols) {
125       SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of columns for change of basis matrix! %d != %d",cols_c,cols);
126     }
127     ierr = MatGetLocalSize(pc->mat,&rows,&cols);CHKERRQ(ierr);
128     ierr = MatGetLocalSize(change,&rows_c,&cols_c);CHKERRQ(ierr);
129     if (rows_c != rows) {
130       SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of local rows for change of basis matrix! %d != %d",rows_c,rows);
131     }
132     if (cols_c != cols) {
133       SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of local columns for change of basis matrix! %d != %d",cols_c,cols);
134     }
135   }
136   ierr = PetscTryMethod(pc,"PCBDDCSetChangeOfBasisMat_C",(PC,Mat),(pc,change));CHKERRQ(ierr);
137   PetscFunctionReturn(0);
138 }
139 /* -------------------------------------------------------------------------- */
140 #undef __FUNCT__
141 #define __FUNCT__ "PCBDDCSetPrimalVerticesLocalIS_BDDC"
142 static PetscErrorCode PCBDDCSetPrimalVerticesLocalIS_BDDC(PC pc, IS PrimalVertices)
143 {
144   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
145   PetscErrorCode ierr;
146 
147   PetscFunctionBegin;
148   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
149   ierr = PetscObjectReference((PetscObject)PrimalVertices);CHKERRQ(ierr);
150   pcbddc->user_primal_vertices = PrimalVertices;
151   PetscFunctionReturn(0);
152 }
153 #undef __FUNCT__
154 #define __FUNCT__ "PCBDDCSetPrimalVerticesLocalIS"
155 /*@
156  PCBDDCSetPrimalVerticesLocalIS - Set additional user defined primal vertices in PCBDDC
157 
158    Collective
159 
160    Input Parameters:
161 +  pc - the preconditioning context
162 -  PrimalVertices - index set of primal vertices in local numbering (can be empty)
163 
164    Level: intermediate
165 
166    Notes:
167 
168 .seealso: PCBDDC
169 @*/
170 PetscErrorCode PCBDDCSetPrimalVerticesLocalIS(PC pc, IS PrimalVertices)
171 {
172   PetscErrorCode ierr;
173 
174   PetscFunctionBegin;
175   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
176   PetscValidHeaderSpecific(PrimalVertices,IS_CLASSID,2);
177   PetscCheckSameComm(pc,1,PrimalVertices,2);
178   ierr = PetscTryMethod(pc,"PCBDDCSetPrimalVerticesLocalIS_C",(PC,IS),(pc,PrimalVertices));CHKERRQ(ierr);
179   PetscFunctionReturn(0);
180 }
181 /* -------------------------------------------------------------------------- */
182 #undef __FUNCT__
183 #define __FUNCT__ "PCBDDCSetCoarseningRatio_BDDC"
184 static PetscErrorCode PCBDDCSetCoarseningRatio_BDDC(PC pc,PetscInt k)
185 {
186   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
187 
188   PetscFunctionBegin;
189   pcbddc->coarsening_ratio = k;
190   PetscFunctionReturn(0);
191 }
192 
193 #undef __FUNCT__
194 #define __FUNCT__ "PCBDDCSetCoarseningRatio"
195 /*@
196  PCBDDCSetCoarseningRatio - Set coarsening ratio used in multilevel
197 
198    Logically collective on PC
199 
200    Input Parameters:
201 +  pc - the preconditioning context
202 -  k - coarsening ratio (H/h at the coarser level)
203 
204    Options Database Keys:
205 .    -pc_bddc_coarsening_ratio
206 
207    Level: intermediate
208 
209    Notes:
210      Approximatively k subdomains at the finer level will be aggregated into a single subdomain at the coarser level
211 
212 .seealso: PCBDDC, PCBDDCSetLevels()
213 @*/
214 PetscErrorCode PCBDDCSetCoarseningRatio(PC pc,PetscInt k)
215 {
216   PetscErrorCode ierr;
217 
218   PetscFunctionBegin;
219   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
220   PetscValidLogicalCollectiveInt(pc,k,2);
221   ierr = PetscTryMethod(pc,"PCBDDCSetCoarseningRatio_C",(PC,PetscInt),(pc,k));CHKERRQ(ierr);
222   PetscFunctionReturn(0);
223 }
224 
225 /* The following functions (PCBDDCSetUseExactDirichlet PCBDDCSetLevel) are not public */
226 #undef __FUNCT__
227 #define __FUNCT__ "PCBDDCSetUseExactDirichlet_BDDC"
228 static PetscErrorCode PCBDDCSetUseExactDirichlet_BDDC(PC pc,PetscBool flg)
229 {
230   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
231 
232   PetscFunctionBegin;
233   pcbddc->use_exact_dirichlet_trick = flg;
234   PetscFunctionReturn(0);
235 }
236 
237 #undef __FUNCT__
238 #define __FUNCT__ "PCBDDCSetUseExactDirichlet"
239 PetscErrorCode PCBDDCSetUseExactDirichlet(PC pc,PetscBool flg)
240 {
241   PetscErrorCode ierr;
242 
243   PetscFunctionBegin;
244   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
245   PetscValidLogicalCollectiveBool(pc,flg,2);
246   ierr = PetscTryMethod(pc,"PCBDDCSetUseExactDirichlet_C",(PC,PetscBool),(pc,flg));CHKERRQ(ierr);
247   PetscFunctionReturn(0);
248 }
249 
250 #undef __FUNCT__
251 #define __FUNCT__ "PCBDDCSetLevel_BDDC"
252 static PetscErrorCode PCBDDCSetLevel_BDDC(PC pc,PetscInt level)
253 {
254   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
255 
256   PetscFunctionBegin;
257   pcbddc->current_level = level;
258   PetscFunctionReturn(0);
259 }
260 
261 #undef __FUNCT__
262 #define __FUNCT__ "PCBDDCSetLevel"
263 PetscErrorCode PCBDDCSetLevel(PC pc,PetscInt level)
264 {
265   PetscErrorCode ierr;
266 
267   PetscFunctionBegin;
268   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
269   PetscValidLogicalCollectiveInt(pc,level,2);
270   ierr = PetscTryMethod(pc,"PCBDDCSetLevel_C",(PC,PetscInt),(pc,level));CHKERRQ(ierr);
271   PetscFunctionReturn(0);
272 }
273 
274 #undef __FUNCT__
275 #define __FUNCT__ "PCBDDCSetLevels_BDDC"
276 static PetscErrorCode PCBDDCSetLevels_BDDC(PC pc,PetscInt levels)
277 {
278   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
279 
280   PetscFunctionBegin;
281   pcbddc->max_levels = levels;
282   PetscFunctionReturn(0);
283 }
284 
285 #undef __FUNCT__
286 #define __FUNCT__ "PCBDDCSetLevels"
287 /*@
288  PCBDDCSetLevels - Sets the maximum number of levels for multilevel
289 
290    Logically collective on PC
291 
292    Input Parameters:
293 +  pc - the preconditioning context
294 -  levels - the maximum number of levels (max 9)
295 
296    Options Database Keys:
297 .    -pc_bddc_levels
298 
299    Level: intermediate
300 
301    Notes:
302      Default value is 0, i.e. traditional one-level BDDC
303 
304 .seealso: PCBDDC, PCBDDCSetCoarseningRatio()
305 @*/
306 PetscErrorCode PCBDDCSetLevels(PC pc,PetscInt levels)
307 {
308   PetscErrorCode ierr;
309 
310   PetscFunctionBegin;
311   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
312   PetscValidLogicalCollectiveInt(pc,levels,2);
313   if (levels > 99) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Maximum number of levels for bddc is 99\n");
314   ierr = PetscTryMethod(pc,"PCBDDCSetLevels_C",(PC,PetscInt),(pc,levels));CHKERRQ(ierr);
315   PetscFunctionReturn(0);
316 }
317 /* -------------------------------------------------------------------------- */
318 
319 #undef __FUNCT__
320 #define __FUNCT__ "PCBDDCSetNullSpace_BDDC"
321 static PetscErrorCode PCBDDCSetNullSpace_BDDC(PC pc,MatNullSpace NullSpace)
322 {
323   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
324   PetscErrorCode ierr;
325 
326   PetscFunctionBegin;
327   ierr = PetscObjectReference((PetscObject)NullSpace);CHKERRQ(ierr);
328   ierr = MatNullSpaceDestroy(&pcbddc->NullSpace);CHKERRQ(ierr);
329   pcbddc->NullSpace = NullSpace;
330   PetscFunctionReturn(0);
331 }
332 
333 #undef __FUNCT__
334 #define __FUNCT__ "PCBDDCSetNullSpace"
335 /*@
336  PCBDDCSetNullSpace - Set nullspace for BDDC operator
337 
338    Logically collective on PC and MatNullSpace
339 
340    Input Parameters:
341 +  pc - the preconditioning context
342 -  NullSpace - Null space of the linear operator to be preconditioned (Pmat)
343 
344    Level: intermediate
345 
346    Notes:
347 
348 .seealso: PCBDDC
349 @*/
350 PetscErrorCode PCBDDCSetNullSpace(PC pc,MatNullSpace NullSpace)
351 {
352   PetscErrorCode ierr;
353 
354   PetscFunctionBegin;
355   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
356   PetscValidHeaderSpecific(NullSpace,MAT_NULLSPACE_CLASSID,2);
357   PetscCheckSameComm(pc,1,NullSpace,2);
358   ierr = PetscTryMethod(pc,"PCBDDCSetNullSpace_C",(PC,MatNullSpace),(pc,NullSpace));CHKERRQ(ierr);
359   PetscFunctionReturn(0);
360 }
361 /* -------------------------------------------------------------------------- */
362 
363 #undef __FUNCT__
364 #define __FUNCT__ "PCBDDCSetDirichletBoundaries_BDDC"
365 static PetscErrorCode PCBDDCSetDirichletBoundaries_BDDC(PC pc,IS DirichletBoundaries)
366 {
367   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
368   PetscErrorCode ierr;
369 
370   PetscFunctionBegin;
371   /* last user setting takes precendence -> destroy any other customization */
372   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
373   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
374   ierr = PetscObjectReference((PetscObject)DirichletBoundaries);CHKERRQ(ierr);
375   pcbddc->DirichletBoundaries = DirichletBoundaries;
376   pcbddc->recompute_topography = PETSC_TRUE;
377   PetscFunctionReturn(0);
378 }
379 
380 #undef __FUNCT__
381 #define __FUNCT__ "PCBDDCSetDirichletBoundaries"
382 /*@
383  PCBDDCSetDirichletBoundaries - Set IS defining Dirichlet boundaries for the global problem.
384 
385    Collective
386 
387    Input Parameters:
388 +  pc - the preconditioning context
389 -  DirichletBoundaries - parallel IS defining the Dirichlet boundaries
390 
391    Level: intermediate
392 
393    Notes:
394      Provide the information if you used MatZeroRows/Columns routines. Any process can list any global node
395 
396 .seealso: PCBDDC, PCBDDCSetDirichletBoundariesLocal(), MatZeroRows(), MatZeroRowsColumns()
397 @*/
398 PetscErrorCode PCBDDCSetDirichletBoundaries(PC pc,IS DirichletBoundaries)
399 {
400   PetscErrorCode ierr;
401 
402   PetscFunctionBegin;
403   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
404   PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2);
405   PetscCheckSameComm(pc,1,DirichletBoundaries,2);
406   ierr = PetscTryMethod(pc,"PCBDDCSetDirichletBoundaries_C",(PC,IS),(pc,DirichletBoundaries));CHKERRQ(ierr);
407   PetscFunctionReturn(0);
408 }
409 /* -------------------------------------------------------------------------- */
410 
411 #undef __FUNCT__
412 #define __FUNCT__ "PCBDDCSetDirichletBoundariesLocal_BDDC"
413 static PetscErrorCode PCBDDCSetDirichletBoundariesLocal_BDDC(PC pc,IS DirichletBoundaries)
414 {
415   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
416   PetscErrorCode ierr;
417 
418   PetscFunctionBegin;
419   /* last user setting takes precendence -> destroy any other customization */
420   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
421   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
422   ierr = PetscObjectReference((PetscObject)DirichletBoundaries);CHKERRQ(ierr);
423   pcbddc->DirichletBoundariesLocal = DirichletBoundaries;
424   pcbddc->recompute_topography = PETSC_TRUE;
425   PetscFunctionReturn(0);
426 }
427 
428 #undef __FUNCT__
429 #define __FUNCT__ "PCBDDCSetDirichletBoundariesLocal"
430 /*@
431  PCBDDCSetDirichletBoundariesLocal - Set IS defining Dirichlet boundaries for the global problem in local ordering.
432 
433    Collective
434 
435    Input Parameters:
436 +  pc - the preconditioning context
437 -  DirichletBoundaries - parallel IS defining the Dirichlet boundaries (in local ordering)
438 
439    Level: intermediate
440 
441    Notes:
442 
443 .seealso: PCBDDC, PCBDDCSetDirichletBoundaries(), MatZeroRows(), MatZeroRowsColumns()
444 @*/
445 PetscErrorCode PCBDDCSetDirichletBoundariesLocal(PC pc,IS DirichletBoundaries)
446 {
447   PetscErrorCode ierr;
448 
449   PetscFunctionBegin;
450   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
451   PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2);
452   PetscCheckSameComm(pc,1,DirichletBoundaries,2);
453   ierr = PetscTryMethod(pc,"PCBDDCSetDirichletBoundariesLocal_C",(PC,IS),(pc,DirichletBoundaries));CHKERRQ(ierr);
454   PetscFunctionReturn(0);
455 }
456 /* -------------------------------------------------------------------------- */
457 
458 #undef __FUNCT__
459 #define __FUNCT__ "PCBDDCSetNeumannBoundaries_BDDC"
460 static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc,IS NeumannBoundaries)
461 {
462   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
463   PetscErrorCode ierr;
464 
465   PetscFunctionBegin;
466   /* last user setting takes precendence -> destroy any other customization */
467   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
468   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
469   ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr);
470   pcbddc->NeumannBoundaries = NeumannBoundaries;
471   pcbddc->recompute_topography = PETSC_TRUE;
472   PetscFunctionReturn(0);
473 }
474 
475 #undef __FUNCT__
476 #define __FUNCT__ "PCBDDCSetNeumannBoundaries"
477 /*@
478  PCBDDCSetNeumannBoundaries - Set IS defining Neumann boundaries for the global problem.
479 
480    Collective
481 
482    Input Parameters:
483 +  pc - the preconditioning context
484 -  NeumannBoundaries - parallel IS defining the Neumann boundaries
485 
486    Level: intermediate
487 
488    Notes:
489      Any process can list any global node
490 
491 .seealso: PCBDDC, PCBDDCSetNeumannBoundariesLocal()
492 @*/
493 PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc,IS NeumannBoundaries)
494 {
495   PetscErrorCode ierr;
496 
497   PetscFunctionBegin;
498   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
499   PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2);
500   PetscCheckSameComm(pc,1,NeumannBoundaries,2);
501   ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundaries_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr);
502   PetscFunctionReturn(0);
503 }
504 /* -------------------------------------------------------------------------- */
505 
506 #undef __FUNCT__
507 #define __FUNCT__ "PCBDDCSetNeumannBoundariesLocal_BDDC"
508 static PetscErrorCode PCBDDCSetNeumannBoundariesLocal_BDDC(PC pc,IS NeumannBoundaries)
509 {
510   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
511   PetscErrorCode ierr;
512 
513   PetscFunctionBegin;
514   /* last user setting takes precendence -> destroy any other customization */
515   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
516   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
517   ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr);
518   pcbddc->NeumannBoundariesLocal = NeumannBoundaries;
519   pcbddc->recompute_topography = PETSC_TRUE;
520   PetscFunctionReturn(0);
521 }
522 
523 #undef __FUNCT__
524 #define __FUNCT__ "PCBDDCSetNeumannBoundariesLocal"
525 /*@
526  PCBDDCSetNeumannBoundariesLocal - Set IS defining Neumann boundaries for the global problem in local ordering.
527 
528    Collective
529 
530    Input Parameters:
531 +  pc - the preconditioning context
532 -  NeumannBoundaries - parallel IS defining the subdomain part of Neumann boundaries (in local ordering)
533 
534    Level: intermediate
535 
536    Notes:
537 
538 .seealso: PCBDDC, PCBDDCSetNeumannBoundaries()
539 @*/
540 PetscErrorCode PCBDDCSetNeumannBoundariesLocal(PC pc,IS NeumannBoundaries)
541 {
542   PetscErrorCode ierr;
543 
544   PetscFunctionBegin;
545   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
546   PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2);
547   PetscCheckSameComm(pc,1,NeumannBoundaries,2);
548   ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundariesLocal_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr);
549   PetscFunctionReturn(0);
550 }
551 /* -------------------------------------------------------------------------- */
552 
553 #undef __FUNCT__
554 #define __FUNCT__ "PCBDDCGetDirichletBoundaries_BDDC"
555 static PetscErrorCode PCBDDCGetDirichletBoundaries_BDDC(PC pc,IS *DirichletBoundaries)
556 {
557   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
558 
559   PetscFunctionBegin;
560   *DirichletBoundaries = pcbddc->DirichletBoundaries;
561   PetscFunctionReturn(0);
562 }
563 
564 #undef __FUNCT__
565 #define __FUNCT__ "PCBDDCGetDirichletBoundaries"
566 /*@
567  PCBDDCGetDirichletBoundaries - Get parallel IS for Dirichlet boundaries
568 
569    Collective
570 
571    Input Parameters:
572 .  pc - the preconditioning context
573 
574    Output Parameters:
575 .  DirichletBoundaries - index set defining the Dirichlet boundaries
576 
577    Level: intermediate
578 
579    Notes:
580      The IS returned (if any) is the same passed in earlier by the user with PCBDDCSetDirichletBoundaries
581 
582 .seealso: PCBDDC
583 @*/
584 PetscErrorCode PCBDDCGetDirichletBoundaries(PC pc,IS *DirichletBoundaries)
585 {
586   PetscErrorCode ierr;
587 
588   PetscFunctionBegin;
589   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
590   ierr = PetscUseMethod(pc,"PCBDDCGetDirichletBoundaries_C",(PC,IS*),(pc,DirichletBoundaries));CHKERRQ(ierr);
591   PetscFunctionReturn(0);
592 }
593 /* -------------------------------------------------------------------------- */
594 
595 #undef __FUNCT__
596 #define __FUNCT__ "PCBDDCGetDirichletBoundariesLocal_BDDC"
597 static PetscErrorCode PCBDDCGetDirichletBoundariesLocal_BDDC(PC pc,IS *DirichletBoundaries)
598 {
599   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
600 
601   PetscFunctionBegin;
602   *DirichletBoundaries = pcbddc->DirichletBoundariesLocal;
603   PetscFunctionReturn(0);
604 }
605 
606 #undef __FUNCT__
607 #define __FUNCT__ "PCBDDCGetDirichletBoundariesLocal"
608 /*@
609  PCBDDCGetDirichletBoundariesLocal - Get parallel IS for Dirichlet boundaries (in local ordering)
610 
611    Collective
612 
613    Input Parameters:
614 .  pc - the preconditioning context
615 
616    Output Parameters:
617 .  DirichletBoundaries - index set defining the subdomain part of Dirichlet boundaries
618 
619    Level: intermediate
620 
621    Notes:
622      The IS returned could be the same passed in earlier by the user (if provided with PCBDDCSetDirichletBoundariesLocal) or a global-to-local map of the global IS (if provided with PCBDDCSetDirichletBoundaries).
623           In the latter case, the IS will be available after PCSetUp.
624 
625 .seealso: PCBDDC
626 @*/
627 PetscErrorCode PCBDDCGetDirichletBoundariesLocal(PC pc,IS *DirichletBoundaries)
628 {
629   PetscErrorCode ierr;
630 
631   PetscFunctionBegin;
632   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
633   ierr = PetscUseMethod(pc,"PCBDDCGetDirichletBoundariesLocal_C",(PC,IS*),(pc,DirichletBoundaries));CHKERRQ(ierr);
634   PetscFunctionReturn(0);
635 }
636 /* -------------------------------------------------------------------------- */
637 
638 #undef __FUNCT__
639 #define __FUNCT__ "PCBDDCGetNeumannBoundaries_BDDC"
640 static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc,IS *NeumannBoundaries)
641 {
642   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
643 
644   PetscFunctionBegin;
645   *NeumannBoundaries = pcbddc->NeumannBoundaries;
646   PetscFunctionReturn(0);
647 }
648 
649 #undef __FUNCT__
650 #define __FUNCT__ "PCBDDCGetNeumannBoundaries"
651 /*@
652  PCBDDCGetNeumannBoundaries - Get parallel IS for Neumann boundaries
653 
654    Collective
655 
656    Input Parameters:
657 .  pc - the preconditioning context
658 
659    Output Parameters:
660 .  NeumannBoundaries - index set defining the Neumann boundaries
661 
662    Level: intermediate
663 
664    Notes:
665      The IS returned (if any) is the same passed in earlier by the user with PCBDDCSetNeumannBoundaries
666 
667 .seealso: PCBDDC
668 @*/
669 PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc,IS *NeumannBoundaries)
670 {
671   PetscErrorCode ierr;
672 
673   PetscFunctionBegin;
674   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
675   ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundaries_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr);
676   PetscFunctionReturn(0);
677 }
678 /* -------------------------------------------------------------------------- */
679 
680 #undef __FUNCT__
681 #define __FUNCT__ "PCBDDCGetNeumannBoundariesLocal_BDDC"
682 static PetscErrorCode PCBDDCGetNeumannBoundariesLocal_BDDC(PC pc,IS *NeumannBoundaries)
683 {
684   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
685 
686   PetscFunctionBegin;
687   *NeumannBoundaries = pcbddc->NeumannBoundariesLocal;
688   PetscFunctionReturn(0);
689 }
690 
691 #undef __FUNCT__
692 #define __FUNCT__ "PCBDDCGetNeumannBoundariesLocal"
693 /*@
694  PCBDDCGetNeumannBoundariesLocal - Get parallel IS for Neumann boundaries (in local ordering)
695 
696    Collective
697 
698    Input Parameters:
699 .  pc - the preconditioning context
700 
701    Output Parameters:
702 .  NeumannBoundaries - index set defining the subdomain part of Neumann boundaries
703 
704    Level: intermediate
705 
706    Notes:
707      The IS returned could be the same passed in earlier by the user (if provided with PCBDDCSetNeumannBoundariesLocal) or a global-to-local map of the global IS (if provided with PCBDDCSetNeumannBoundaries).
708           In the latter case, the IS will be available after PCSetUp.
709 
710 .seealso: PCBDDC
711 @*/
712 PetscErrorCode PCBDDCGetNeumannBoundariesLocal(PC pc,IS *NeumannBoundaries)
713 {
714   PetscErrorCode ierr;
715 
716   PetscFunctionBegin;
717   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
718   ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundariesLocal_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr);
719   PetscFunctionReturn(0);
720 }
721 /* -------------------------------------------------------------------------- */
722 
723 #undef __FUNCT__
724 #define __FUNCT__ "PCBDDCSetLocalAdjacencyGraph_BDDC"
725 static PetscErrorCode PCBDDCSetLocalAdjacencyGraph_BDDC(PC pc, PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode)
726 {
727   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
728   PCBDDCGraph    mat_graph = pcbddc->mat_graph;
729   PetscErrorCode ierr;
730 
731   PetscFunctionBegin;
732   /* free old CSR */
733   ierr = PCBDDCGraphResetCSR(mat_graph);CHKERRQ(ierr);
734   /* TODO: PCBDDCGraphSetAdjacency */
735   /* get CSR into graph structure */
736   if (copymode == PETSC_COPY_VALUES) {
737     ierr = PetscMalloc1(nvtxs+1,&mat_graph->xadj);CHKERRQ(ierr);
738     ierr = PetscMalloc1(xadj[nvtxs],&mat_graph->adjncy);CHKERRQ(ierr);
739     ierr = PetscMemcpy(mat_graph->xadj,xadj,(nvtxs+1)*sizeof(PetscInt));CHKERRQ(ierr);
740     ierr = PetscMemcpy(mat_graph->adjncy,adjncy,xadj[nvtxs]*sizeof(PetscInt));CHKERRQ(ierr);
741   } else if (copymode == PETSC_OWN_POINTER) {
742     mat_graph->xadj = (PetscInt*)xadj;
743     mat_graph->adjncy = (PetscInt*)adjncy;
744   }
745   mat_graph->nvtxs_csr = nvtxs;
746   PetscFunctionReturn(0);
747 }
748 
749 #undef __FUNCT__
750 #define __FUNCT__ "PCBDDCSetLocalAdjacencyGraph"
751 /*@
752  PCBDDCSetLocalAdjacencyGraph - Set adjacency structure (CSR graph) of the local matrix
753 
754    Not collective
755 
756    Input Parameters:
757 +  pc - the preconditioning context
758 .  nvtxs - number of local vertices of the graph (i.e., the size of the local problem)
759 .  xadj, adjncy - the CSR graph
760 -  copymode - either PETSC_COPY_VALUES or PETSC_OWN_POINTER.
761 
762    Level: intermediate
763 
764    Notes:
765 
766 .seealso: PCBDDC,PetscCopyMode
767 @*/
768 PetscErrorCode PCBDDCSetLocalAdjacencyGraph(PC pc,PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode)
769 {
770   void (*f)(void) = 0;
771   PetscErrorCode ierr;
772 
773   PetscFunctionBegin;
774   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
775   PetscValidIntPointer(xadj,3);
776   PetscValidIntPointer(adjncy,4);
777   if (copymode != PETSC_COPY_VALUES && copymode != PETSC_OWN_POINTER) {
778     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported copy mode %d in %s\n",copymode,__FUNCT__);
779   }
780   ierr = PetscTryMethod(pc,"PCBDDCSetLocalAdjacencyGraph_C",(PC,PetscInt,const PetscInt[],const PetscInt[],PetscCopyMode),(pc,nvtxs,xadj,adjncy,copymode));CHKERRQ(ierr);
781   /* free arrays if PCBDDC is not the PC type */
782   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",&f);CHKERRQ(ierr);
783   if (!f && copymode == PETSC_OWN_POINTER) {
784     ierr = PetscFree(xadj);CHKERRQ(ierr);
785     ierr = PetscFree(adjncy);CHKERRQ(ierr);
786   }
787   PetscFunctionReturn(0);
788 }
789 /* -------------------------------------------------------------------------- */
790 
791 #undef __FUNCT__
792 #define __FUNCT__ "PCBDDCSetDofsSplittingLocal_BDDC"
793 static PetscErrorCode PCBDDCSetDofsSplittingLocal_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
794 {
795   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
796   PetscInt i;
797   PetscErrorCode ierr;
798 
799   PetscFunctionBegin;
800   /* Destroy ISes if they were already set */
801   for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
802     ierr = ISDestroy(&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
803   }
804   ierr = PetscFree(pcbddc->ISForDofsLocal);CHKERRQ(ierr);
805   /* last user setting takes precendence -> destroy any other customization */
806   for (i=0;i<pcbddc->n_ISForDofs;i++) {
807     ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
808   }
809   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
810   pcbddc->n_ISForDofs = 0;
811   /* allocate space then set */
812   if (n_is) {
813     ierr = PetscMalloc1(n_is,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
814   }
815   for (i=0;i<n_is;i++) {
816     ierr = PetscObjectReference((PetscObject)ISForDofs[i]);CHKERRQ(ierr);
817     pcbddc->ISForDofsLocal[i]=ISForDofs[i];
818   }
819   pcbddc->n_ISForDofsLocal=n_is;
820   if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE;
821   pcbddc->recompute_topography = PETSC_TRUE;
822   PetscFunctionReturn(0);
823 }
824 
825 #undef __FUNCT__
826 #define __FUNCT__ "PCBDDCSetDofsSplittingLocal"
827 /*@
828  PCBDDCSetDofsSplittingLocal - Set index sets defining fields of the local subdomain matrix
829 
830    Collective
831 
832    Input Parameters:
833 +  pc - the preconditioning context
834 .  n_is - number of index sets defining the fields
835 -  ISForDofs - array of IS describing the fields in local ordering
836 
837    Level: intermediate
838 
839    Notes:
840      n_is should be the same among processes. Not all nodes need to be listed: unlisted nodes will belong to the complement field.
841 
842 .seealso: PCBDDC
843 @*/
844 PetscErrorCode PCBDDCSetDofsSplittingLocal(PC pc,PetscInt n_is, IS ISForDofs[])
845 {
846   PetscInt       i;
847   PetscErrorCode ierr;
848 
849   PetscFunctionBegin;
850   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
851   PetscValidLogicalCollectiveInt(pc,n_is,2);
852   for (i=0;i<n_is;i++) {
853     PetscCheckSameComm(pc,1,ISForDofs[i],3);
854     PetscValidHeaderSpecific(ISForDofs[i],IS_CLASSID,3);
855   }
856   ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplittingLocal_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr);
857   PetscFunctionReturn(0);
858 }
859 /* -------------------------------------------------------------------------- */
860 
861 #undef __FUNCT__
862 #define __FUNCT__ "PCBDDCSetDofsSplitting_BDDC"
863 static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
864 {
865   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
866   PetscInt i;
867   PetscErrorCode ierr;
868 
869   PetscFunctionBegin;
870   /* Destroy ISes if they were already set */
871   for (i=0;i<pcbddc->n_ISForDofs;i++) {
872     ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
873   }
874   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
875   /* last user setting takes precendence -> destroy any other customization */
876   for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
877     ierr = ISDestroy(&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
878   }
879   ierr = PetscFree(pcbddc->ISForDofsLocal);CHKERRQ(ierr);
880   pcbddc->n_ISForDofsLocal = 0;
881   /* allocate space then set */
882   if (n_is) {
883     ierr = PetscMalloc1(n_is,&pcbddc->ISForDofs);CHKERRQ(ierr);
884   }
885   for (i=0;i<n_is;i++) {
886     ierr = PetscObjectReference((PetscObject)ISForDofs[i]);CHKERRQ(ierr);
887     pcbddc->ISForDofs[i]=ISForDofs[i];
888   }
889   pcbddc->n_ISForDofs=n_is;
890   if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE;
891   pcbddc->recompute_topography = PETSC_TRUE;
892   PetscFunctionReturn(0);
893 }
894 
895 #undef __FUNCT__
896 #define __FUNCT__ "PCBDDCSetDofsSplitting"
897 /*@
898  PCBDDCSetDofsSplitting - Set index sets defining fields of the global matrix
899 
900    Collective
901 
902    Input Parameters:
903 +  pc - the preconditioning context
904 .  n_is - number of index sets defining the fields
905 -  ISForDofs - array of IS describing the fields in global ordering
906 
907    Level: intermediate
908 
909    Notes:
910      Any process can list any global node. Not all nodes need to be listed: unlisted nodes will belong to the complement field.
911 
912 .seealso: PCBDDC
913 @*/
914 PetscErrorCode PCBDDCSetDofsSplitting(PC pc,PetscInt n_is, IS ISForDofs[])
915 {
916   PetscInt       i;
917   PetscErrorCode ierr;
918 
919   PetscFunctionBegin;
920   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
921   PetscValidLogicalCollectiveInt(pc,n_is,2);
922   for (i=0;i<n_is;i++) {
923     PetscCheckSameComm(pc,1,ISForDofs[i],3);
924     PetscValidHeaderSpecific(ISForDofs[i],IS_CLASSID,3);
925   }
926   ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplitting_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr);
927   PetscFunctionReturn(0);
928 }
929 
930 /* -------------------------------------------------------------------------- */
931 #undef __FUNCT__
932 #define __FUNCT__ "PCPreSolve_BDDC"
933 /* -------------------------------------------------------------------------- */
934 /*
935    PCPreSolve_BDDC - Changes the right hand side and (if necessary) the initial
936                      guess if a transformation of basis approach has been selected.
937 
938    Input Parameter:
939 +  pc - the preconditioner contex
940 
941    Application Interface Routine: PCPreSolve()
942 
943    Notes:
944      The interface routine PCPreSolve() is not usually called directly by
945    the user, but instead is called by KSPSolve().
946 */
947 static PetscErrorCode PCPreSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
948 {
949   PetscErrorCode ierr;
950   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
951   PC_IS          *pcis = (PC_IS*)(pc->data);
952   Vec            used_vec;
953   PetscBool      copy_rhs = PETSC_TRUE;
954   PetscBool      benign_correction_is_zero = PETSC_FALSE;
955   PetscBool      iscg;
956 
957   PetscFunctionBegin;
958   /* if we are working with cg, one dirichlet solve can be avoided during Krylov iterations */
959   if (ksp) {
960     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPCG,&iscg);CHKERRQ(ierr);
961     if (!iscg) {
962       ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
963     }
964   }
965   /* Creates parallel work vectors used in presolve */
966   if (!pcbddc->original_rhs) {
967     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs);CHKERRQ(ierr);
968   }
969   if (!pcbddc->temp_solution) {
970     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->temp_solution);CHKERRQ(ierr);
971   }
972 
973   if (x) {
974     ierr = PetscObjectReference((PetscObject)x);CHKERRQ(ierr);
975     used_vec = x;
976   } else { /* it can only happen when calling PCBDDCMatFETIDPGetRHS */
977     ierr = PetscObjectReference((PetscObject)pcbddc->temp_solution);CHKERRQ(ierr);
978     used_vec = pcbddc->temp_solution;
979     ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
980   }
981 
982   /* hack into ksp data structure since PCPreSolve comes earlier than setting to zero the guess in src/ksp/ksp/interface/itfunc.c */
983   if (ksp) {
984     /* store the flag for the initial guess since it will be restored back during PCPostSolve_BDDC */
985     ierr = KSPGetInitialGuessNonzero(ksp,&pcbddc->ksp_guess_nonzero);CHKERRQ(ierr);
986     if (!pcbddc->ksp_guess_nonzero) {
987       ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
988     }
989   }
990 
991   pcbddc->rhs_change = PETSC_FALSE;
992   /* Take into account zeroed rows -> change rhs and store solution removed */
993   if (rhs) {
994     IS dirIS = NULL;
995 
996     /* DirichletBoundariesLocal may not be consistent among neighbours; gets a dirichlet dofs IS from graph (may be cached) */
997     ierr = PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS);CHKERRQ(ierr);
998     if (dirIS) {
999       Mat_IS            *matis = (Mat_IS*)pc->pmat->data;
1000       PetscInt          dirsize,i,*is_indices;
1001       PetscScalar       *array_x;
1002       const PetscScalar *array_diagonal;
1003 
1004       ierr = MatGetDiagonal(pc->pmat,pcis->vec1_global);CHKERRQ(ierr);
1005       ierr = VecPointwiseDivide(pcis->vec1_global,rhs,pcis->vec1_global);CHKERRQ(ierr);
1006       ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1007       ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1008       ierr = VecScatterBegin(matis->rctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1009       ierr = VecScatterEnd(matis->rctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1010       ierr = ISGetLocalSize(dirIS,&dirsize);CHKERRQ(ierr);
1011       ierr = VecGetArray(pcis->vec1_N,&array_x);CHKERRQ(ierr);
1012       ierr = VecGetArrayRead(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr);
1013       ierr = ISGetIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1014       for (i=0; i<dirsize; i++) array_x[is_indices[i]] = array_diagonal[is_indices[i]];
1015       ierr = ISRestoreIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1016       ierr = VecRestoreArrayRead(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr);
1017       ierr = VecRestoreArray(pcis->vec1_N,&array_x);CHKERRQ(ierr);
1018       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1019       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1020       pcbddc->rhs_change = PETSC_TRUE;
1021       ierr = ISDestroy(&dirIS);CHKERRQ(ierr);
1022     }
1023   }
1024 
1025   /* remove the computed solution or the initial guess from the rhs */
1026   if (pcbddc->rhs_change || (ksp && pcbddc->ksp_guess_nonzero) ) {
1027     /* store the original rhs */
1028     if (copy_rhs) {
1029       ierr = VecCopy(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
1030       copy_rhs = PETSC_FALSE;
1031     }
1032     pcbddc->rhs_change = PETSC_TRUE;
1033     ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr);
1034     ierr = MatMultAdd(pc->mat,used_vec,rhs,rhs);CHKERRQ(ierr);
1035     ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr);
1036     ierr = VecCopy(used_vec,pcbddc->temp_solution);CHKERRQ(ierr);
1037     if (ksp) {
1038       ierr = KSPSetInitialGuessNonzero(ksp,PETSC_FALSE);CHKERRQ(ierr);
1039     }
1040   }
1041   ierr = VecDestroy(&used_vec);CHKERRQ(ierr);
1042 
1043   /* When using the benign trick: (TODO: what about FETI-DP?)
1044      - change rhs on pressures (iteration matrix is surely of type MATIS)
1045      - compute initial vector in benign space
1046   */
1047   if (rhs && pcbddc->benign_saddle_point) {
1048     Mat_IS   *matis = (Mat_IS*)(pc->mat->data);
1049     PetscInt i;
1050 
1051     /* store the original rhs */
1052     if (copy_rhs) {
1053       ierr = VecCopy(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
1054       copy_rhs = PETSC_FALSE;
1055     }
1056 
1057     /* now change (locally) the basis */
1058     ierr = VecScatterBegin(matis->rctx,rhs,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1059     ierr = VecScatterEnd(matis->rctx,rhs,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1060     if (pcbddc->benign_change) {
1061       Mat M;
1062 
1063       ierr = MatMultTranspose(pcbddc->benign_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
1064       ierr = VecScatterBegin(matis->rctx,pcis->vec2_N,rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1065       ierr = VecScatterEnd(matis->rctx,pcis->vec2_N,rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1066       /* change local iteration matrix TODO (case when mat == pmat) */
1067       ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
1068       ierr = MatPtAP(matis->A,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&M);CHKERRQ(ierr);
1069       ierr = MatSeqAIJCompress(M,&pcbddc->local_mat);CHKERRQ(ierr);
1070       ierr = MatDestroy(&M);CHKERRQ(ierr);
1071       ierr = MatDestroy(&pcbddc->benign_original_mat);CHKERRQ(ierr);
1072       ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
1073       pcbddc->benign_original_mat = matis->A;
1074       ierr = MatDestroy(&matis->A);CHKERRQ(ierr);
1075       ierr = PetscObjectReference((PetscObject)pcbddc->local_mat);CHKERRQ(ierr);
1076       matis->A = pcbddc->local_mat;
1077       ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
1078     } else {
1079       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1080       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1081     }
1082     pcbddc->rhs_change = PETSC_TRUE;
1083 
1084     /* compute u^*_h as in Xuemin Tu's thesis (see Section 4.8.1) */
1085     /* TODO: what about Stokes? */
1086     if (!pcbddc->benign_vec) {
1087       ierr = VecDuplicate(rhs,&pcbddc->benign_vec);CHKERRQ(ierr);
1088     }
1089     ierr = PetscMemzero(pcbddc->benign_p0,pcbddc->benign_n*sizeof(PetscScalar));CHKERRQ(ierr);
1090     if (pcbddc->benign_n) {
1091       const PetscScalar *array;
1092 
1093       ierr = VecGetArrayRead(pcis->vec2_N,&array);CHKERRQ(ierr);
1094       for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = array[pcbddc->benign_p0_lidx[i]];
1095       ierr = VecRestoreArrayRead(pcis->vec2_N,&array);CHKERRQ(ierr);
1096     }
1097     if (pcbddc->benign_null && iscg) { /* this is a workaround, need to understand more */
1098       PetscBool iszero_l = PETSC_TRUE;
1099       for (i=0;i<pcbddc->benign_n;i++) {
1100         iszero_l = (iszero_l && (PetscAbsScalar(pcbddc->benign_p0[i]) < PETSC_SMALL ? PETSC_TRUE : PETSC_FALSE));
1101       }
1102       ierr = MPI_Allreduce(&iszero_l,&benign_correction_is_zero,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
1103     }
1104     if (!benign_correction_is_zero) {
1105       ierr = VecSet(pcis->vec1_global,0.);CHKERRQ(ierr);
1106       ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_FALSE);CHKERRQ(ierr);
1107       ierr = PCApply_BDDC(pc,pcis->vec1_global,pcbddc->benign_vec);CHKERRQ(ierr);
1108       ierr = PetscMemzero(pcbddc->benign_p0,pcbddc->benign_n*sizeof(PetscScalar));CHKERRQ(ierr);
1109       ierr = PCBDDCBenignGetOrSetP0(pc,pcbddc->benign_vec,PETSC_FALSE);CHKERRQ(ierr);
1110     }
1111   }
1112 
1113   /* change rhs and iteration matrix if using the change of basis */
1114   if (pcbddc->ChangeOfBasisMatrix) {
1115     PCBDDCChange_ctx change_ctx;
1116 
1117     /* get change ctx */
1118     ierr = MatShellGetContext(pcbddc->new_global_mat,&change_ctx);CHKERRQ(ierr);
1119 
1120     /* set current iteration matrix inside change context (change of basis has been already set into the ctx during PCSetUp) */
1121     ierr = MatDestroy(&change_ctx->original_mat);CHKERRQ(ierr);
1122     ierr = PetscObjectReference((PetscObject)pc->mat);CHKERRQ(ierr);
1123     change_ctx->original_mat = pc->mat;
1124 
1125     /* change iteration matrix */
1126     ierr = MatDestroy(&pc->mat);CHKERRQ(ierr);
1127     ierr = PetscObjectReference((PetscObject)pcbddc->new_global_mat);CHKERRQ(ierr);
1128     pc->mat = pcbddc->new_global_mat;
1129 
1130     /* store the original rhs */
1131     if (copy_rhs) {
1132       ierr = VecCopy(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
1133       copy_rhs = PETSC_FALSE;
1134     }
1135 
1136     /* change rhs */
1137     ierr = MatMultTranspose(change_ctx->global_change,rhs,pcis->vec1_global);CHKERRQ(ierr);
1138     ierr = VecCopy(pcis->vec1_global,rhs);CHKERRQ(ierr);
1139     pcbddc->rhs_change = PETSC_TRUE;
1140   }
1141 
1142   /* remove non-benign solution from the rhs */
1143   if (pcbddc->benign_saddle_point) {
1144     /* store the original rhs */
1145     if (copy_rhs) {
1146       ierr = VecCopy(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
1147       copy_rhs = PETSC_FALSE;
1148     }
1149     if (benign_correction_is_zero) { /* still need to understand why it works great */
1150       ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
1151       ierr = PCApply_BDDC(pc,rhs,pcbddc->benign_vec);CHKERRQ(ierr);
1152     }
1153     ierr = VecScale(pcbddc->benign_vec,-1.0);CHKERRQ(ierr);
1154     ierr = MatMultAdd(pc->mat,pcbddc->benign_vec,rhs,rhs);CHKERRQ(ierr);
1155     pcbddc->rhs_change = PETSC_TRUE;
1156   }
1157 
1158   /* set initial guess if using PCG */
1159   if (x && pcbddc->use_exact_dirichlet_trick) {
1160     ierr = VecSet(x,0.0);CHKERRQ(ierr);
1161     ierr = VecScatterBegin(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1162     ierr = VecScatterEnd(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1163     ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
1164     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1165     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1166     if (ksp) {
1167       ierr = KSPSetInitialGuessNonzero(ksp,PETSC_TRUE);CHKERRQ(ierr);
1168     }
1169   }
1170   if (pcbddc->benign_null) {
1171     MatNullSpace null_space;
1172     Vec          nullv;
1173     PetscBool    isnull;
1174     PetscInt     i;
1175 
1176     for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = 1.;
1177     ierr = VecDuplicate(pcis->vec1_global,&nullv);CHKERRQ(ierr);
1178     ierr = VecSet(nullv,0.);CHKERRQ(ierr);
1179     ierr = PCBDDCBenignGetOrSetP0(pc,nullv,PETSC_FALSE);CHKERRQ(ierr);
1180     ierr = VecNormalize(nullv,NULL);CHKERRQ(ierr);
1181     ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)pc),PETSC_FALSE,1,&nullv,&null_space);CHKERRQ(ierr);
1182     ierr = MatNullSpaceTest(null_space,pc->mat,&isnull);CHKERRQ(ierr);
1183     if (isnull) {
1184       ierr = MatSetNullSpace(pc->mat,null_space);CHKERRQ(ierr);
1185     }
1186     ierr = MatNullSpaceDestroy(&null_space);CHKERRQ(ierr);
1187     ierr = VecDestroy(&nullv);CHKERRQ(ierr);
1188   }
1189 
1190 
1191   /* remove nullspace if present */
1192   if (ksp && x && pcbddc->NullSpace) {
1193     ierr = MatNullSpaceRemove(pcbddc->NullSpace,x);CHKERRQ(ierr);
1194     /* store the original rhs */
1195     if (copy_rhs) {
1196       ierr = VecCopy(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
1197       copy_rhs = PETSC_FALSE;
1198     }
1199     pcbddc->rhs_change = PETSC_TRUE;
1200     ierr = MatNullSpaceRemove(pcbddc->NullSpace,rhs);CHKERRQ(ierr);
1201   }
1202   PetscFunctionReturn(0);
1203 }
1204 
1205 /* -------------------------------------------------------------------------- */
1206 #undef __FUNCT__
1207 #define __FUNCT__ "PCPostSolve_BDDC"
1208 /* -------------------------------------------------------------------------- */
1209 /*
1210    PCPostSolve_BDDC - Changes the computed solution if a transformation of basis
1211                      approach has been selected. Also, restores rhs to its original state.
1212 
1213    Input Parameter:
1214 +  pc - the preconditioner contex
1215 
1216    Application Interface Routine: PCPostSolve()
1217 
1218    Notes:
1219      The interface routine PCPostSolve() is not usually called directly by
1220      the user, but instead is called by KSPSolve().
1221 */
1222 static PetscErrorCode PCPostSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
1223 {
1224   PetscErrorCode ierr;
1225   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1226 
1227   PetscFunctionBegin;
1228   if (pcbddc->ChangeOfBasisMatrix) {
1229     PCBDDCChange_ctx change_ctx;
1230 
1231     /* get change ctx */
1232     ierr = MatShellGetContext(pcbddc->new_global_mat,&change_ctx);CHKERRQ(ierr);
1233 
1234     /* restore iteration matrix */
1235     ierr = MatDestroy(&pc->mat);CHKERRQ(ierr);
1236     ierr = PetscObjectReference((PetscObject)change_ctx->original_mat);CHKERRQ(ierr);
1237     pc->mat = change_ctx->original_mat;
1238   }
1239 
1240   /* need to restore the local matrices */
1241   if (pcbddc->benign_change) {
1242     Mat_IS *matis = (Mat_IS*)pc->mat->data;
1243 
1244     ierr = MatDestroy(&matis->A);CHKERRQ(ierr);
1245     ierr = PetscObjectReference((PetscObject)pcbddc->benign_original_mat);CHKERRQ(ierr);
1246     matis->A = pcbddc->benign_original_mat;
1247     ierr = MatDestroy(&pcbddc->benign_original_mat);CHKERRQ(ierr);
1248   }
1249 
1250   /* get solution in original basis */
1251   if (x) {
1252     PC_IS *pcis = (PC_IS*)(pc->data);
1253 
1254     /* restore solution on pressures */
1255     if (pcbddc->benign_saddle_point) {
1256       Mat_IS *matis = (Mat_IS*)pc->mat->data;
1257 
1258       /* add non-benign solution */
1259       ierr = VecAXPY(x,-1.0,pcbddc->benign_vec);CHKERRQ(ierr);
1260 
1261       /* change basis on pressures for x */
1262       ierr = VecScatterBegin(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1263       ierr = VecScatterEnd(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1264       if (pcbddc->benign_change) {
1265         ierr = MatMult(pcbddc->benign_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
1266         ierr = VecScatterBegin(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1267         ierr = VecScatterEnd(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1268       } else {
1269         ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1270         ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1271       }
1272     }
1273 
1274     /* change basis on x */
1275     if (pcbddc->ChangeOfBasisMatrix) {
1276       PCBDDCChange_ctx change_ctx;
1277 
1278       ierr = MatShellGetContext(pcbddc->new_global_mat,&change_ctx);CHKERRQ(ierr);
1279       ierr = MatMult(change_ctx->global_change,x,pcis->vec1_global);CHKERRQ(ierr);
1280       ierr = VecCopy(pcis->vec1_global,x);CHKERRQ(ierr);
1281     }
1282   }
1283 
1284   /* add solution removed in presolve */
1285   if (x && pcbddc->rhs_change) {
1286     ierr = VecAXPY(x,1.0,pcbddc->temp_solution);CHKERRQ(ierr);
1287   }
1288 
1289   /* restore rhs to its original state */
1290   if (rhs && pcbddc->rhs_change) {
1291     ierr = VecCopy(pcbddc->original_rhs,rhs);CHKERRQ(ierr);
1292   }
1293   pcbddc->rhs_change = PETSC_FALSE;
1294 
1295   /* restore ksp guess state */
1296   if (ksp) {
1297     ierr = KSPSetInitialGuessNonzero(ksp,pcbddc->ksp_guess_nonzero);CHKERRQ(ierr);
1298   }
1299   PetscFunctionReturn(0);
1300 }
1301 /* -------------------------------------------------------------------------- */
1302 #undef __FUNCT__
1303 #define __FUNCT__ "PCSetUp_BDDC"
1304 /* -------------------------------------------------------------------------- */
1305 /*
1306    PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner
1307                   by setting data structures and options.
1308 
1309    Input Parameter:
1310 +  pc - the preconditioner context
1311 
1312    Application Interface Routine: PCSetUp()
1313 
1314    Notes:
1315      The interface routine PCSetUp() is not usually called directly by
1316      the user, but instead is called by PCApply() if necessary.
1317 */
1318 PetscErrorCode PCSetUp_BDDC(PC pc)
1319 {
1320   PetscErrorCode ierr;
1321   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
1322   Mat_IS*        matis;
1323   MatNullSpace   nearnullspace;
1324   IS             zerodiag = NULL;
1325   PetscInt       nrows,ncols;
1326   PetscBool      computetopography,computesolvers,computesubschurs;
1327   PetscBool      computeconstraintsmatrix;
1328   PetscBool      new_nearnullspace_provided,ismatis;
1329 
1330   PetscFunctionBegin;
1331   ierr = PetscObjectTypeCompare((PetscObject)pc->pmat,MATIS,&ismatis);CHKERRQ(ierr);
1332   if (!ismatis) {
1333     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"PCBDDC preconditioner requires matrix of type MATIS");
1334   }
1335   ierr = MatGetSize(pc->pmat,&nrows,&ncols);CHKERRQ(ierr);
1336   if (nrows != ncols) {
1337     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PCBDDC preconditioner requires a square preconditioning matrix");
1338   }
1339   matis = (Mat_IS*)pc->pmat->data;
1340   /* the following lines of code should be replaced by a better logic between PCIS, PCNN, PCBDDC and other future nonoverlapping preconditioners */
1341   /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup
1342      Also, BDDC directly build the Dirichlet problem */
1343   /* split work */
1344   if (pc->setupcalled) {
1345     if (pc->flag == SAME_NONZERO_PATTERN) {
1346       computetopography = PETSC_FALSE;
1347       computesolvers = PETSC_TRUE;
1348     } else { /* DIFFERENT_NONZERO_PATTERN */
1349       computetopography = PETSC_TRUE;
1350       computesolvers = PETSC_TRUE;
1351     }
1352   } else {
1353     computetopography = PETSC_TRUE;
1354     computesolvers = PETSC_TRUE;
1355   }
1356   if (pcbddc->recompute_topography) {
1357     computetopography = PETSC_TRUE;
1358   }
1359   computeconstraintsmatrix = PETSC_FALSE;
1360 
1361   /* check parameters' compatibility */
1362   if (pcbddc->adaptive_threshold > 0.0 && !pcbddc->use_deluxe_scaling) {
1363     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot compute adaptive constraints without deluxe scaling. Rerun with -pc_bddc_use_deluxe_scaling");
1364   }
1365   pcbddc->adaptive_selection = (PetscBool)(pcbddc->adaptive_threshold > 0.0 && pcbddc->use_deluxe_scaling);
1366   if (pcbddc->adaptive_selection) pcbddc->use_faces = PETSC_TRUE;
1367 
1368   computesubschurs = (PetscBool)(pcbddc->adaptive_selection || pcbddc->use_deluxe_scaling);
1369   if (pcbddc->faster_deluxe && pcbddc->adaptive_selection && pcbddc->use_change_of_basis) {
1370     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot compute faster deluxe if adaptivity and change of basis are both requested. Rerun with -pc_bddc_deluxe_faster false");
1371   }
1372 
1373   /* check if the iteration matrix is of type MATIS in case the benign trick has been requested */
1374   ierr = PetscObjectTypeCompare((PetscObject)pc->mat,MATIS,&ismatis);CHKERRQ(ierr);
1375   if (pcbddc->benign_saddle_point && !ismatis) {
1376     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"PCBDDC preconditioner with benign subspace trick requires the iteration matrix to be of type MATIS");
1377   }
1378 
1379   /* Get stdout for dbg */
1380   if (pcbddc->dbg_flag) {
1381     if (!pcbddc->dbg_viewer) {
1382       pcbddc->dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pc));
1383       ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
1384     }
1385     ierr = PetscViewerASCIIAddTab(pcbddc->dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
1386   }
1387 
1388   if (pcbddc->user_ChangeOfBasisMatrix) {
1389     /* use_change_of_basis flag is used to automatically compute a change of basis from constraints */
1390     pcbddc->use_change_of_basis = PETSC_FALSE;
1391     ierr = PCBDDCComputeLocalMatrix(pc,pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
1392   } else {
1393     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
1394     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
1395     pcbddc->local_mat = matis->A;
1396   }
1397 
1398   /* detect local disconnected subdomains if requested and not done before */
1399   if (pcbddc->detect_disconnected && !pcbddc->n_local_subs) {
1400     ierr = MatDetectDisconnectedComponents(pcbddc->local_mat,PETSC_FALSE,&pcbddc->n_local_subs,&pcbddc->local_subs);CHKERRQ(ierr);
1401   }
1402 
1403   /*
1404      change basis on local pressures (aka zerodiag dofs)
1405      This should come earlier then PCISSetUp for extracting the correct subdomain matrices
1406   */
1407   if (pcbddc->benign_saddle_point) {
1408     /* detect local saddle point and change the basis in pcbddc->local_mat */
1409     ierr = PCBDDCBenignDetectSaddlePoint(pc,&zerodiag);CHKERRQ(ierr);
1410     /* pop B0 mat from pcbddc->local_mat */
1411     ierr = PCBDDCBenignPopOrPushB0(pc,PETSC_TRUE);CHKERRQ(ierr);
1412   }
1413 
1414   /* propagate relevant information */
1415 #if !defined(PETSC_USE_COMPLEX) /* workaround for reals */
1416   if (matis->A->symmetric_set) {
1417     ierr = MatSetOption(pcbddc->local_mat,MAT_HERMITIAN,matis->A->symmetric);CHKERRQ(ierr);
1418   }
1419 #endif
1420   if (matis->A->symmetric_set) {
1421     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
1422   }
1423   if (matis->A->spd_set) {
1424     ierr = MatSetOption(pcbddc->local_mat,MAT_SPD,matis->A->spd);CHKERRQ(ierr);
1425   }
1426 
1427   /* Set up all the "iterative substructuring" common block without computing solvers */
1428   {
1429     Mat temp_mat;
1430 
1431     temp_mat = matis->A;
1432     matis->A = pcbddc->local_mat;
1433     ierr = PCISSetUp(pc,PETSC_FALSE);CHKERRQ(ierr);
1434     pcbddc->local_mat = matis->A;
1435     matis->A = temp_mat;
1436   }
1437 
1438   /* Analyze interface */
1439   if (computetopography) {
1440     ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
1441     computeconstraintsmatrix = PETSC_TRUE;
1442   }
1443 
1444   /* check existence of a divergence free extension, i.e.
1445      b(v_I,p_0) = 0 for all v_I (raise error if not).
1446      Also, check that PCBDDCBenignGetOrSetP0 works */
1447 #if defined(PETSC_USE_DEBUG)
1448   if (pcbddc->benign_saddle_point) {
1449     ierr = PCBDDCBenignCheck(pc,zerodiag);CHKERRQ(ierr);
1450   }
1451 #endif
1452   ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
1453 
1454   /* Setup local dirichlet solver ksp_D and sub_schurs solvers */
1455   if (computesolvers) {
1456     PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
1457 
1458     if (computesubschurs && computetopography) {
1459       ierr = PCBDDCInitSubSchurs(pc);CHKERRQ(ierr);
1460     }
1461     if (sub_schurs->use_mumps) {
1462       if (computesubschurs) {
1463         ierr = PCBDDCSetUpSubSchurs(pc);CHKERRQ(ierr);
1464       }
1465       ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr);
1466     } else {
1467       ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr);
1468       if (computesubschurs) {
1469         ierr = PCBDDCSetUpSubSchurs(pc);CHKERRQ(ierr);
1470       }
1471     }
1472     if (pcbddc->adaptive_selection) {
1473       ierr = PCBDDCAdaptiveSelection(pc);CHKERRQ(ierr);
1474       computeconstraintsmatrix = PETSC_TRUE;
1475     }
1476   }
1477 
1478   /* infer if NullSpace object attached to Mat via MatSetNearNullSpace has changed */
1479   new_nearnullspace_provided = PETSC_FALSE;
1480   ierr = MatGetNearNullSpace(pc->pmat,&nearnullspace);CHKERRQ(ierr);
1481   if (pcbddc->onearnullspace) { /* already used nearnullspace */
1482     if (!nearnullspace) { /* near null space attached to mat has been destroyed */
1483       new_nearnullspace_provided = PETSC_TRUE;
1484     } else {
1485       /* determine if the two nullspaces are different (should be lightweight) */
1486       if (nearnullspace != pcbddc->onearnullspace) {
1487         new_nearnullspace_provided = PETSC_TRUE;
1488       } else { /* maybe the user has changed the content of the nearnullspace so check vectors ObjectStateId */
1489         PetscInt         i;
1490         const Vec        *nearnullvecs;
1491         PetscObjectState state;
1492         PetscInt         nnsp_size;
1493         ierr = MatNullSpaceGetVecs(nearnullspace,NULL,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
1494         for (i=0;i<nnsp_size;i++) {
1495           ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&state);CHKERRQ(ierr);
1496           if (pcbddc->onearnullvecs_state[i] != state) {
1497             new_nearnullspace_provided = PETSC_TRUE;
1498             break;
1499           }
1500         }
1501       }
1502     }
1503   } else {
1504     if (!nearnullspace) { /* both nearnullspaces are null */
1505       new_nearnullspace_provided = PETSC_FALSE;
1506     } else { /* nearnullspace attached later */
1507       new_nearnullspace_provided = PETSC_TRUE;
1508     }
1509   }
1510 
1511   /* Setup constraints and related work vectors */
1512   /* reset primal space flags */
1513   pcbddc->new_primal_space = PETSC_FALSE;
1514   pcbddc->new_primal_space_local = PETSC_FALSE;
1515   if (computeconstraintsmatrix || new_nearnullspace_provided) {
1516     /* It also sets the primal space flags */
1517     ierr = PCBDDCConstraintsSetUp(pc);CHKERRQ(ierr);
1518     /* Allocate needed local vectors (which depends on quantities defined during ConstraintsSetUp) */
1519     ierr = PCBDDCSetUpLocalWorkVectors(pc);CHKERRQ(ierr);
1520   }
1521 
1522   if (computesolvers || pcbddc->new_primal_space) {
1523     if (pcbddc->use_change_of_basis) {
1524       PC_IS *pcis = (PC_IS*)(pc->data);
1525       Mat   temp_mat = NULL;
1526 
1527       if (pcbddc->benign_change) {
1528         /* insert B0 in pcbddc->local_mat */
1529         ierr = PCBDDCBenignPopOrPushB0(pc,PETSC_FALSE);CHKERRQ(ierr);
1530         /* swap local matrices */
1531         ierr = MatISGetLocalMat(pc->pmat,&temp_mat);CHKERRQ(ierr);
1532         ierr = PetscObjectReference((PetscObject)temp_mat);CHKERRQ(ierr);
1533         ierr = MatISSetLocalMat(pc->pmat,pcbddc->local_mat);CHKERRQ(ierr);
1534         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
1535       }
1536       ierr = PCBDDCComputeLocalMatrix(pc,pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
1537       if (pcbddc->benign_change) {
1538         /* restore original matrix */
1539         ierr = MatISSetLocalMat(pc->pmat,temp_mat);CHKERRQ(ierr);
1540         ierr = PetscObjectDereference((PetscObject)temp_mat);CHKERRQ(ierr);
1541         /* pop B0 from pcbddc->local_mat */
1542         ierr = PCBDDCBenignPopOrPushB0(pc,PETSC_TRUE);CHKERRQ(ierr);
1543       }
1544       /* get submatrices */
1545       ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr);
1546       ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr);
1547       ierr = MatDestroy(&pcis->A_BB);CHKERRQ(ierr);
1548       ierr = MatGetSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_BB);CHKERRQ(ierr);
1549       ierr = MatGetSubMatrix(pcbddc->local_mat,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_IB);CHKERRQ(ierr);
1550       ierr = MatGetSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&pcis->A_BI);CHKERRQ(ierr);
1551       /* set flag in pcis to not reuse submatrices during PCISCreate */
1552       pcis->reusesubmatrices = PETSC_FALSE;
1553     } else if (!pcbddc->user_ChangeOfBasisMatrix && !pcbddc->benign_change) {
1554       ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
1555       ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
1556       pcbddc->local_mat = matis->A;
1557     }
1558     /* SetUp coarse and local Neumann solvers */
1559     ierr = PCBDDCSetUpSolvers(pc);CHKERRQ(ierr);
1560     /* SetUp Scaling operator */
1561     ierr = PCBDDCScalingSetUp(pc);CHKERRQ(ierr);
1562   }
1563 
1564   if (pcbddc->dbg_flag) {
1565     ierr = PetscViewerASCIISubtractTab(pcbddc->dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
1566   }
1567   PetscFunctionReturn(0);
1568 }
1569 
1570 /* -------------------------------------------------------------------------- */
1571 /*
1572    PCApply_BDDC - Applies the BDDC operator to a vector.
1573 
1574    Input Parameters:
1575 +  pc - the preconditioner context
1576 -  r - input vector (global)
1577 
1578    Output Parameter:
1579 .  z - output vector (global)
1580 
1581    Application Interface Routine: PCApply()
1582  */
1583 #undef __FUNCT__
1584 #define __FUNCT__ "PCApply_BDDC"
1585 PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z)
1586 {
1587   PC_IS             *pcis = (PC_IS*)(pc->data);
1588   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
1589   PetscInt          n_B = pcis->n_B, n_D = pcis->n - n_B;
1590   PetscErrorCode    ierr;
1591   const PetscScalar one = 1.0;
1592   const PetscScalar m_one = -1.0;
1593   const PetscScalar zero = 0.0;
1594 
1595 /* This code is similar to that provided in nn.c for PCNN
1596    NN interface preconditioner changed to BDDC
1597    Added support for M_3 preconditioner in the reference article (code is active if pcbddc->switch_static == PETSC_TRUE) */
1598 
1599   PetscFunctionBegin;
1600   if (pcbddc->benign_saddle_point) { /* get p0 from r */
1601     ierr = PCBDDCBenignGetOrSetP0(pc,r,PETSC_TRUE);CHKERRQ(ierr);
1602   }
1603   if (!pcbddc->use_exact_dirichlet_trick) {
1604     ierr = VecCopy(r,z);CHKERRQ(ierr);
1605     /* First Dirichlet solve */
1606     ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1607     ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1608     /*
1609       Assembling right hand side for BDDC operator
1610       - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE)
1611       - pcis->vec1_B the interface part of the global vector z
1612     */
1613     if (n_D) {
1614       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
1615       ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
1616       if (pcbddc->switch_static) { ierr = MatMultAdd(pcis->A_II,pcis->vec2_D,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
1617       ierr = MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
1618     } else {
1619       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
1620     }
1621     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1622     ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1623     ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr);
1624   } else {
1625     if (pcbddc->switch_static) {
1626       ierr = VecSet(pcis->vec1_D,zero);CHKERRQ(ierr);
1627     }
1628     ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr);
1629   }
1630 
1631   /* Apply interface preconditioner
1632      input/output vecs: pcis->vec1_B and pcis->vec1_D */
1633   ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
1634 
1635   /* Apply transpose of partition of unity operator */
1636   ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr);
1637 
1638   /* Second Dirichlet solve and assembling of output */
1639   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1640   ierr = VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1641   if (n_B) {
1642     ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
1643     if (pcbddc->switch_static) { ierr = MatMultAdd(pcis->A_II,pcis->vec1_D,pcis->vec3_D,pcis->vec3_D);CHKERRQ(ierr); }
1644   } else if (pcbddc->switch_static) {
1645     ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec3_D);CHKERRQ(ierr);
1646   }
1647   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D);CHKERRQ(ierr);
1648 
1649   if (!pcbddc->use_exact_dirichlet_trick) {
1650     if (pcbddc->switch_static) {
1651       ierr = VecAXPBYPCZ(pcis->vec2_D,m_one,one,m_one,pcis->vec4_D,pcis->vec1_D);CHKERRQ(ierr);
1652     } else {
1653       ierr = VecAXPBY(pcis->vec2_D,m_one,m_one,pcis->vec4_D);CHKERRQ(ierr);
1654     }
1655     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1656     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1657   } else {
1658     if (pcbddc->switch_static) {
1659       ierr = VecAXPBY(pcis->vec4_D,one,m_one,pcis->vec1_D);CHKERRQ(ierr);
1660     } else {
1661       ierr = VecScale(pcis->vec4_D,m_one);CHKERRQ(ierr);
1662     }
1663     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1664     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1665   }
1666 
1667   if (pcbddc->benign_saddle_point) { /* set p0 (computed in PCBDDCApplyInterface) */
1668     ierr = PCBDDCBenignGetOrSetP0(pc,z,PETSC_FALSE);CHKERRQ(ierr);
1669   }
1670   PetscFunctionReturn(0);
1671 }
1672 
1673 /* -------------------------------------------------------------------------- */
1674 /*
1675    PCApplyTranspose_BDDC - Applies the transpose of the BDDC operator to a vector.
1676 
1677    Input Parameters:
1678 +  pc - the preconditioner context
1679 -  r - input vector (global)
1680 
1681    Output Parameter:
1682 .  z - output vector (global)
1683 
1684    Application Interface Routine: PCApplyTranspose()
1685  */
1686 #undef __FUNCT__
1687 #define __FUNCT__ "PCApplyTranspose_BDDC"
1688 PetscErrorCode PCApplyTranspose_BDDC(PC pc,Vec r,Vec z)
1689 {
1690   PC_IS             *pcis = (PC_IS*)(pc->data);
1691   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
1692   PetscInt          n_B = pcis->n_B, n_D = pcis->n - n_B;
1693   PetscErrorCode    ierr;
1694   const PetscScalar one = 1.0;
1695   const PetscScalar m_one = -1.0;
1696   const PetscScalar zero = 0.0;
1697 
1698   PetscFunctionBegin;
1699   if (pcbddc->benign_saddle_point) { /* get p0 from r */
1700     ierr = PCBDDCBenignGetOrSetP0(pc,r,PETSC_TRUE);CHKERRQ(ierr);
1701   }
1702   if (!pcbddc->use_exact_dirichlet_trick) {
1703     ierr = VecCopy(r,z);CHKERRQ(ierr);
1704     /* First Dirichlet solve */
1705     ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1706     ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1707     /*
1708       Assembling right hand side for BDDC operator
1709       - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE)
1710       - pcis->vec1_B the interface part of the global vector z
1711     */
1712     if (n_D) {
1713       ierr = KSPSolveTranspose(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
1714       ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
1715       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcis->A_II,pcis->vec2_D,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
1716       ierr = MatMultTranspose(pcis->A_IB,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
1717     } else {
1718       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
1719     }
1720     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1721     ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1722     ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr);
1723   } else {
1724     if (pcbddc->switch_static) {
1725       ierr = VecSet(pcis->vec1_D,zero);CHKERRQ(ierr);
1726     }
1727     ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr);
1728   }
1729 
1730   /* Apply interface preconditioner
1731      input/output vecs: pcis->vec1_B and pcis->vec1_D */
1732   ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_TRUE);CHKERRQ(ierr);
1733 
1734   /* Apply transpose of partition of unity operator */
1735   ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr);
1736 
1737   /* Second Dirichlet solve and assembling of output */
1738   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1739   ierr = VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1740   if (n_B) {
1741     ierr = MatMultTranspose(pcis->A_BI,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
1742     if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcis->A_II,pcis->vec1_D,pcis->vec3_D,pcis->vec3_D);CHKERRQ(ierr); }
1743   } else if (pcbddc->switch_static) {
1744     ierr = MatMultTranspose(pcis->A_II,pcis->vec1_D,pcis->vec3_D);CHKERRQ(ierr);
1745   }
1746   ierr = KSPSolveTranspose(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D);CHKERRQ(ierr);
1747   if (!pcbddc->use_exact_dirichlet_trick) {
1748     if (pcbddc->switch_static) {
1749       ierr = VecAXPBYPCZ(pcis->vec2_D,m_one,one,m_one,pcis->vec4_D,pcis->vec1_D);CHKERRQ(ierr);
1750     } else {
1751       ierr = VecAXPBY(pcis->vec2_D,m_one,m_one,pcis->vec4_D);CHKERRQ(ierr);
1752     }
1753     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1754     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1755   } else {
1756     if (pcbddc->switch_static) {
1757       ierr = VecAXPBY(pcis->vec4_D,one,m_one,pcis->vec1_D);CHKERRQ(ierr);
1758     } else {
1759       ierr = VecScale(pcis->vec4_D,m_one);CHKERRQ(ierr);
1760     }
1761     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1762     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1763   }
1764   if (pcbddc->benign_saddle_point) { /* set p0 (computed in PCBDDCApplyInterface) */
1765     ierr = PCBDDCBenignGetOrSetP0(pc,z,PETSC_FALSE);CHKERRQ(ierr);
1766   }
1767   PetscFunctionReturn(0);
1768 }
1769 /* -------------------------------------------------------------------------- */
1770 
1771 #undef __FUNCT__
1772 #define __FUNCT__ "PCDestroy_BDDC"
1773 PetscErrorCode PCDestroy_BDDC(PC pc)
1774 {
1775   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1776   PetscErrorCode ierr;
1777 
1778   PetscFunctionBegin;
1779   /* free data created by PCIS */
1780   ierr = PCISDestroy(pc);CHKERRQ(ierr);
1781   /* free BDDC custom data  */
1782   ierr = PCBDDCResetCustomization(pc);CHKERRQ(ierr);
1783   /* destroy objects related to topography */
1784   ierr = PCBDDCResetTopography(pc);CHKERRQ(ierr);
1785   /* free allocated graph structure */
1786   ierr = PetscFree(pcbddc->mat_graph);CHKERRQ(ierr);
1787   /* free allocated sub schurs structure */
1788   ierr = PetscFree(pcbddc->sub_schurs);CHKERRQ(ierr);
1789   /* destroy objects for scaling operator */
1790   ierr = PCBDDCScalingDestroy(pc);CHKERRQ(ierr);
1791   ierr = PetscFree(pcbddc->deluxe_ctx);CHKERRQ(ierr);
1792   /* free solvers stuff */
1793   ierr = PCBDDCResetSolvers(pc);CHKERRQ(ierr);
1794   /* free global vectors needed in presolve */
1795   ierr = VecDestroy(&pcbddc->temp_solution);CHKERRQ(ierr);
1796   ierr = VecDestroy(&pcbddc->original_rhs);CHKERRQ(ierr);
1797   /* free stuff for change of basis hooks */
1798   if (pcbddc->new_global_mat) {
1799     PCBDDCChange_ctx change_ctx;
1800     ierr = MatShellGetContext(pcbddc->new_global_mat,&change_ctx);CHKERRQ(ierr);
1801     ierr = MatDestroy(&change_ctx->original_mat);CHKERRQ(ierr);
1802     ierr = MatDestroy(&change_ctx->global_change);CHKERRQ(ierr);
1803     ierr = VecDestroyVecs(2,&change_ctx->work);CHKERRQ(ierr);
1804     ierr = PetscFree(change_ctx);CHKERRQ(ierr);
1805   }
1806   ierr = MatDestroy(&pcbddc->new_global_mat);CHKERRQ(ierr);
1807   /* remove functions */
1808   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",NULL);CHKERRQ(ierr);
1809   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",NULL);CHKERRQ(ierr);
1810   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",NULL);CHKERRQ(ierr);
1811   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",NULL);CHKERRQ(ierr);
1812   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",NULL);CHKERRQ(ierr);
1813   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",NULL);CHKERRQ(ierr);
1814   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNullSpace_C",NULL);CHKERRQ(ierr);
1815   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",NULL);CHKERRQ(ierr);
1816   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",NULL);CHKERRQ(ierr);
1817   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",NULL);CHKERRQ(ierr);
1818   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",NULL);CHKERRQ(ierr);
1819   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",NULL);CHKERRQ(ierr);
1820   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",NULL);CHKERRQ(ierr);
1821   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",NULL);CHKERRQ(ierr);
1822   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",NULL);CHKERRQ(ierr);
1823   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",NULL);CHKERRQ(ierr);
1824   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",NULL);CHKERRQ(ierr);
1825   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",NULL);CHKERRQ(ierr);
1826   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",NULL);CHKERRQ(ierr);
1827   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",NULL);CHKERRQ(ierr);
1828   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",NULL);CHKERRQ(ierr);
1829   /* Free the private data structure */
1830   ierr = PetscFree(pc->data);CHKERRQ(ierr);
1831   PetscFunctionReturn(0);
1832 }
1833 /* -------------------------------------------------------------------------- */
1834 
1835 #undef __FUNCT__
1836 #define __FUNCT__ "PCBDDCMatFETIDPGetRHS_BDDC"
1837 static PetscErrorCode PCBDDCMatFETIDPGetRHS_BDDC(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
1838 {
1839   FETIDPMat_ctx  mat_ctx;
1840   Vec            copy_standard_rhs;
1841   PC_IS*         pcis;
1842   PC_BDDC*       pcbddc;
1843   PetscErrorCode ierr;
1844 
1845   PetscFunctionBegin;
1846   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
1847   pcis = (PC_IS*)mat_ctx->pc->data;
1848   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
1849 
1850   /*
1851      change of basis for physical rhs if needed
1852      It also changes the rhs in case of dirichlet boundaries
1853      TODO: better management when FETIDP will have its own class
1854   */
1855   ierr = VecDuplicate(standard_rhs,&copy_standard_rhs);CHKERRQ(ierr);
1856   ierr = VecCopy(standard_rhs,copy_standard_rhs);CHKERRQ(ierr);
1857   ierr = PCPreSolve_BDDC(mat_ctx->pc,NULL,copy_standard_rhs,NULL);CHKERRQ(ierr);
1858   /* store vectors for computation of fetidp final solution */
1859   ierr = VecScatterBegin(pcis->global_to_D,copy_standard_rhs,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1860   ierr = VecScatterEnd(pcis->global_to_D,copy_standard_rhs,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1861   /* scale rhs since it should be unassembled */
1862   /* TODO use counter scaling? (also below) */
1863   ierr = VecScatterBegin(pcis->global_to_B,copy_standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1864   ierr = VecScatterEnd(pcis->global_to_B,copy_standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1865   /* Apply partition of unity */
1866   ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr);
1867   /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,copy_standard_rhs,mat_ctx->temp_solution_B);CHKERRQ(ierr); */
1868   if (!pcbddc->switch_static) {
1869     /* compute partially subassembled Schur complement right-hand side */
1870     ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
1871     ierr = MatMult(pcis->A_BI,pcis->vec1_D,pcis->vec1_B);CHKERRQ(ierr);
1872     ierr = VecAXPY(mat_ctx->temp_solution_B,-1.0,pcis->vec1_B);CHKERRQ(ierr);
1873     ierr = VecSet(copy_standard_rhs,0.0);CHKERRQ(ierr);
1874     ierr = VecScatterBegin(pcis->global_to_B,mat_ctx->temp_solution_B,copy_standard_rhs,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1875     ierr = VecScatterEnd(pcis->global_to_B,mat_ctx->temp_solution_B,copy_standard_rhs,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1876     /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,copy_standard_rhs,mat_ctx->temp_solution_B);CHKERRQ(ierr); */
1877     ierr = VecScatterBegin(pcis->global_to_B,copy_standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1878     ierr = VecScatterEnd(pcis->global_to_B,copy_standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1879     ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr);
1880   }
1881   ierr = VecDestroy(&copy_standard_rhs);CHKERRQ(ierr);
1882   /* BDDC rhs */
1883   ierr = VecCopy(mat_ctx->temp_solution_B,pcis->vec1_B);CHKERRQ(ierr);
1884   if (pcbddc->switch_static) {
1885     ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
1886   }
1887   /* apply BDDC */
1888   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE);CHKERRQ(ierr);
1889   /* Application of B_delta and assembling of rhs for fetidp fluxes */
1890   ierr = VecSet(fetidp_flux_rhs,0.0);CHKERRQ(ierr);
1891   ierr = MatMult(mat_ctx->B_delta,pcis->vec1_B,mat_ctx->lambda_local);CHKERRQ(ierr);
1892   ierr = VecScatterBegin(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1893   ierr = VecScatterEnd(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1894   PetscFunctionReturn(0);
1895 }
1896 
1897 #undef __FUNCT__
1898 #define __FUNCT__ "PCBDDCMatFETIDPGetRHS"
1899 /*@
1900  PCBDDCMatFETIDPGetRHS - Compute the right-hand side for FETI-DP linear system using the physical right-hand side
1901 
1902    Collective
1903 
1904    Input Parameters:
1905 +  fetidp_mat      - the FETI-DP matrix object obtained by a call to PCBDDCCreateFETIDPOperators
1906 -  standard_rhs    - the right-hand side of the original linear system
1907 
1908    Output Parameters:
1909 .  fetidp_flux_rhs - the right-hand side for the FETI-DP linear system
1910 
1911    Level: developer
1912 
1913    Notes:
1914 
1915 .seealso: PCBDDC, PCBDDCCreateFETIDPOperators, PCBDDCMatFETIDPGetSolution
1916 @*/
1917 PetscErrorCode PCBDDCMatFETIDPGetRHS(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
1918 {
1919   FETIDPMat_ctx  mat_ctx;
1920   PetscErrorCode ierr;
1921 
1922   PetscFunctionBegin;
1923   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
1924   ierr = PetscTryMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetRHS_C",(Mat,Vec,Vec),(fetidp_mat,standard_rhs,fetidp_flux_rhs));CHKERRQ(ierr);
1925   PetscFunctionReturn(0);
1926 }
1927 /* -------------------------------------------------------------------------- */
1928 
1929 #undef __FUNCT__
1930 #define __FUNCT__ "PCBDDCMatFETIDPGetSolution_BDDC"
1931 static PetscErrorCode PCBDDCMatFETIDPGetSolution_BDDC(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
1932 {
1933   FETIDPMat_ctx  mat_ctx;
1934   PC_IS*         pcis;
1935   PC_BDDC*       pcbddc;
1936   PetscErrorCode ierr;
1937 
1938   PetscFunctionBegin;
1939   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
1940   pcis = (PC_IS*)mat_ctx->pc->data;
1941   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
1942 
1943   /* apply B_delta^T */
1944   ierr = VecScatterBegin(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1945   ierr = VecScatterEnd  (mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1946   ierr = MatMultTranspose(mat_ctx->B_delta,mat_ctx->lambda_local,pcis->vec1_B);CHKERRQ(ierr);
1947   /* compute rhs for BDDC application */
1948   ierr = VecAYPX(pcis->vec1_B,-1.0,mat_ctx->temp_solution_B);CHKERRQ(ierr);
1949   if (pcbddc->switch_static) {
1950     ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
1951   }
1952   /* apply BDDC */
1953   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE);CHKERRQ(ierr);
1954   /* put values into standard global vector */
1955   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1956   ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1957   if (!pcbddc->switch_static) {
1958     /* compute values into the interior if solved for the partially subassembled Schur complement */
1959     ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec1_D);CHKERRQ(ierr);
1960     ierr = VecAXPY(mat_ctx->temp_solution_D,-1.0,pcis->vec1_D);CHKERRQ(ierr);
1961     ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
1962   }
1963   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec1_D,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1964   ierr = VecScatterEnd  (pcis->global_to_D,pcis->vec1_D,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1965   /* final change of basis if needed
1966      Is also sums the dirichlet part removed during RHS assembling */
1967   ierr = PCPostSolve_BDDC(mat_ctx->pc,NULL,NULL,standard_sol);CHKERRQ(ierr);
1968   PetscFunctionReturn(0);
1969 }
1970 
1971 #undef __FUNCT__
1972 #define __FUNCT__ "PCBDDCMatFETIDPGetSolution"
1973 /*@
1974  PCBDDCMatFETIDPGetSolution - Compute the physical solution using the solution of the FETI-DP linear system
1975 
1976    Collective
1977 
1978    Input Parameters:
1979 +  fetidp_mat      - the FETI-DP matrix obtained by a call to PCBDDCCreateFETIDPOperators
1980 -  fetidp_flux_sol - the solution of the FETI-DP linear system
1981 
1982    Output Parameters:
1983 .  standard_sol    - the solution defined on the physical domain
1984 
1985    Level: developer
1986 
1987    Notes:
1988 
1989 .seealso: PCBDDC, PCBDDCCreateFETIDPOperators, PCBDDCMatFETIDPGetRHS
1990 @*/
1991 PetscErrorCode PCBDDCMatFETIDPGetSolution(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
1992 {
1993   FETIDPMat_ctx  mat_ctx;
1994   PetscErrorCode ierr;
1995 
1996   PetscFunctionBegin;
1997   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
1998   ierr = PetscTryMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetSolution_C",(Mat,Vec,Vec),(fetidp_mat,fetidp_flux_sol,standard_sol));CHKERRQ(ierr);
1999   PetscFunctionReturn(0);
2000 }
2001 /* -------------------------------------------------------------------------- */
2002 
2003 extern PetscErrorCode FETIDPMatMult(Mat,Vec,Vec);
2004 extern PetscErrorCode FETIDPMatMultTranspose(Mat,Vec,Vec);
2005 extern PetscErrorCode PCBDDCDestroyFETIDPMat(Mat);
2006 extern PetscErrorCode FETIDPPCApply(PC,Vec,Vec);
2007 extern PetscErrorCode FETIDPPCApplyTranspose(PC,Vec,Vec);
2008 extern PetscErrorCode PCBDDCDestroyFETIDPPC(PC);
2009 
2010 #undef __FUNCT__
2011 #define __FUNCT__ "PCBDDCCreateFETIDPOperators_BDDC"
2012 static PetscErrorCode PCBDDCCreateFETIDPOperators_BDDC(PC pc, Mat *fetidp_mat, PC *fetidp_pc)
2013 {
2014 
2015   FETIDPMat_ctx  fetidpmat_ctx;
2016   Mat            newmat;
2017   FETIDPPC_ctx   fetidppc_ctx;
2018   PC             newpc;
2019   MPI_Comm       comm;
2020   PetscErrorCode ierr;
2021 
2022   PetscFunctionBegin;
2023   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
2024   /* FETIDP linear matrix */
2025   ierr = PCBDDCCreateFETIDPMatContext(pc,&fetidpmat_ctx);CHKERRQ(ierr);
2026   ierr = PCBDDCSetupFETIDPMatContext(fetidpmat_ctx);CHKERRQ(ierr);
2027   ierr = MatCreateShell(comm,PETSC_DECIDE,PETSC_DECIDE,fetidpmat_ctx->n_lambda,fetidpmat_ctx->n_lambda,fetidpmat_ctx,&newmat);CHKERRQ(ierr);
2028   ierr = MatShellSetOperation(newmat,MATOP_MULT,(void (*)(void))FETIDPMatMult);CHKERRQ(ierr);
2029   ierr = MatShellSetOperation(newmat,MATOP_MULT_TRANSPOSE,(void (*)(void))FETIDPMatMultTranspose);CHKERRQ(ierr);
2030   ierr = MatShellSetOperation(newmat,MATOP_DESTROY,(void (*)(void))PCBDDCDestroyFETIDPMat);CHKERRQ(ierr);
2031   ierr = MatSetUp(newmat);CHKERRQ(ierr);
2032   /* FETIDP preconditioner */
2033   ierr = PCBDDCCreateFETIDPPCContext(pc,&fetidppc_ctx);CHKERRQ(ierr);
2034   ierr = PCBDDCSetupFETIDPPCContext(newmat,fetidppc_ctx);CHKERRQ(ierr);
2035   ierr = PCCreate(comm,&newpc);CHKERRQ(ierr);
2036   ierr = PCSetType(newpc,PCSHELL);CHKERRQ(ierr);
2037   ierr = PCShellSetContext(newpc,fetidppc_ctx);CHKERRQ(ierr);
2038   ierr = PCShellSetApply(newpc,FETIDPPCApply);CHKERRQ(ierr);
2039   ierr = PCShellSetApplyTranspose(newpc,FETIDPPCApplyTranspose);CHKERRQ(ierr);
2040   ierr = PCShellSetDestroy(newpc,PCBDDCDestroyFETIDPPC);CHKERRQ(ierr);
2041   ierr = PCSetOperators(newpc,newmat,newmat);CHKERRQ(ierr);
2042   ierr = PCSetUp(newpc);CHKERRQ(ierr);
2043   /* return pointers for objects created */
2044   *fetidp_mat=newmat;
2045   *fetidp_pc=newpc;
2046   PetscFunctionReturn(0);
2047 }
2048 
2049 #undef __FUNCT__
2050 #define __FUNCT__ "PCBDDCCreateFETIDPOperators"
2051 /*@
2052  PCBDDCCreateFETIDPOperators - Create FETI-DP operators
2053 
2054    Collective
2055 
2056    Input Parameters:
2057 .  pc - the BDDC preconditioning context (setup should have been called before)
2058 
2059    Output Parameters:
2060 +  fetidp_mat - shell FETI-DP matrix object
2061 -  fetidp_pc  - shell Dirichlet preconditioner for FETI-DP matrix
2062 
2063    Options Database Keys:
2064 .    -fetidp_fullyredundant <false> - use or not a fully redundant set of Lagrange multipliers
2065 
2066    Level: developer
2067 
2068    Notes:
2069      Currently the only operations provided for FETI-DP matrix are MatMult and MatMultTranspose
2070 
2071 .seealso: PCBDDC, PCBDDCMatFETIDPGetRHS, PCBDDCMatFETIDPGetSolution
2072 @*/
2073 PetscErrorCode PCBDDCCreateFETIDPOperators(PC pc, Mat *fetidp_mat, PC *fetidp_pc)
2074 {
2075   PetscErrorCode ierr;
2076 
2077   PetscFunctionBegin;
2078   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2079   if (pc->setupcalled) {
2080     ierr = PetscUseMethod(pc,"PCBDDCCreateFETIDPOperators_C",(PC,Mat*,PC*),(pc,fetidp_mat,fetidp_pc));CHKERRQ(ierr);
2081   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"You must call PCSetup_BDDC() first \n");
2082   PetscFunctionReturn(0);
2083 }
2084 /* -------------------------------------------------------------------------- */
2085 /*MC
2086    PCBDDC - Balancing Domain Decomposition by Constraints.
2087 
2088    An implementation of the BDDC preconditioner based on
2089 
2090 .vb
2091    [1] C. R. Dohrmann. "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149-168, March 2007
2092    [2] A. Klawonn and O. B. Widlund. "Dual-Primal FETI Methods for Linear Elasticity", http://cs.nyu.edu/csweb/Research/TechReports/TR2004-855/TR2004-855.pdf
2093    [3] J. Mandel, B. Sousedik, C. R. Dohrmann. "Multispace and Multilevel BDDC", http://arxiv.org/abs/0712.3977
2094    [4] C. Pechstein and C. R. Dohrmann. "Modern domain decomposition methods BDDC, deluxe scaling, and an algebraic approach", Seminar talk, Linz, December 2013, http://people.ricam.oeaw.ac.at/c.pechstein/pechstein-bddc2013.pdf
2095 .ve
2096 
2097    The matrix to be preconditioned (Pmat) must be of type MATIS.
2098 
2099    Currently works with MATIS matrices with local matrices of type MATSEQAIJ, MATSEQBAIJ or MATSEQSBAIJ, either with real or complex numbers.
2100 
2101    It also works with unsymmetric and indefinite problems.
2102 
2103    Unlike 'conventional' interface preconditioners, PCBDDC iterates over all degrees of freedom, not just those on the interface. This allows the use of approximate solvers on the subdomains.
2104 
2105    Approximate local solvers are automatically adapted for singular linear problems (see [1]) if the user has provided the nullspace using PCBDDCSetNullSpace()
2106 
2107    Boundary nodes are split in vertices, edges and faces classes using information from the local to global mapping of dofs and the local connectivity graph of nodes. The latter can be customized by using PCBDDCSetLocalAdjacencyGraph()
2108    Additional information on dofs can be provided by using PCBDDCSetDofsSplitting(), PCBDDCSetDirichletBoundaries(), PCBDDCSetNeumannBoundaries(), and PCBDDCSetPrimalVerticesLocalIS()
2109 
2110    Constraints can be customized by attaching a MatNullSpace object to the MATIS matrix via MatSetNearNullSpace(). Non-singular modes are retained via SVD.
2111 
2112    Change of basis is performed similarly to [2] when requested. When more than one constraint is present on a single connected component (i.e. an edge or a face), a robust method based on local QR factorizations is used.
2113    User defined change of basis can be passed to PCBDDC by using PCBDDCSetChangeOfBasisMat()
2114 
2115    The PETSc implementation also supports multilevel BDDC [3]. Coarse grids are partitioned using a MatPartitioning object.
2116 
2117    Adaptive selection of primal constraints [4] is supported for SPD systems with high-contrast in the coefficients if MUMPS is present. Future versions of the code will also consider using MKL_PARDISO or PASTIX.
2118 
2119    An experimental interface to the FETI-DP method is available. FETI-DP operators could be created using PCBDDCCreateFETIDPOperators(). A stand-alone class for the FETI-DP method will be provided in the next releases.
2120    Deluxe scaling is not supported yet for FETI-DP.
2121 
2122    Options Database Keys (some of them, run with -h for a complete list):
2123 
2124 .    -pc_bddc_use_vertices <true> - use or not vertices in primal space
2125 .    -pc_bddc_use_edges <true> - use or not edges in primal space
2126 .    -pc_bddc_use_faces <false> - use or not faces in primal space
2127 .    -pc_bddc_symmetric <true> - symmetric computation of primal basis functions. Specify false for unsymmetric problems
2128 .    -pc_bddc_use_change_of_basis <false> - use change of basis approach (on edges only)
2129 .    -pc_bddc_use_change_on_faces <false> - use change of basis approach on faces if change of basis has been requested
2130 .    -pc_bddc_switch_static <false> - switches from M_2 (default) to M_3 operator (see reference article [1])
2131 .    -pc_bddc_levels <0> - maximum number of levels for multilevel
2132 .    -pc_bddc_coarsening_ratio <8> - number of subdomains which will be aggregated together at the coarser level (e.g. H/h ratio at the coarser level, significative only in the multilevel case)
2133 .    -pc_bddc_redistribute <0> - size of a subset of processors where the coarse problem will be remapped (the value is ignored if not at the coarsest level)
2134 .    -pc_bddc_use_deluxe_scaling <false> - use deluxe scaling
2135 .    -pc_bddc_schur_layers <-1> - select the economic version of deluxe scaling by specifying the number of layers (-1 corresponds to the original deluxe scaling)
2136 .    -pc_bddc_adaptive_threshold <0.0> - when a value greater than one is specified, adaptive selection of constraints is performed on edges and faces (requires deluxe scaling and MUMPS installed)
2137 -    -pc_bddc_check_level <0> - set verbosity level of debugging output
2138 
2139    Options for Dirichlet, Neumann or coarse solver can be set with
2140 .vb
2141       -pc_bddc_dirichlet_
2142       -pc_bddc_neumann_
2143       -pc_bddc_coarse_
2144 .ve
2145    e.g -pc_bddc_dirichlet_ksp_type richardson -pc_bddc_dirichlet_pc_type gamg. PCBDDC uses by default KPSPREONLY and PCLU.
2146 
2147    When using a multilevel approach, solvers' options at the N-th level (N > 1) can be specified as
2148 .vb
2149       -pc_bddc_dirichlet_lN_
2150       -pc_bddc_neumann_lN_
2151       -pc_bddc_coarse_lN_
2152 .ve
2153    Note that level number ranges from the finest (0) to the coarsest (N).
2154    In order to specify options for the BDDC operators at the coarser levels (and not for the solvers), prepend -pc_bddc_coarse_ or -pc_bddc_coarse_l to the option, e.g.
2155 .vb
2156      -pc_bddc_coarse_pc_bddc_adaptive_threshold 5 -pc_bddc_coarse_l1_pc_bddc_redistribute 3
2157 .ve
2158    will use a threshold of 5 for constraints' selection at the first coarse level and will redistribute the coarse problem of the first coarse level on 3 processors
2159 
2160    Level: intermediate
2161 
2162    Developer notes:
2163 
2164    Contributed by Stefano Zampini
2165 
2166 .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,  MATIS
2167 M*/
2168 
2169 #undef __FUNCT__
2170 #define __FUNCT__ "PCCreate_BDDC"
2171 PETSC_EXTERN PetscErrorCode PCCreate_BDDC(PC pc)
2172 {
2173   PetscErrorCode      ierr;
2174   PC_BDDC             *pcbddc;
2175 
2176   PetscFunctionBegin;
2177   /* Creates the private data structure for this preconditioner and attach it to the PC object. */
2178   ierr      = PetscNewLog(pc,&pcbddc);CHKERRQ(ierr);
2179   pc->data  = (void*)pcbddc;
2180 
2181   /* create PCIS data structure */
2182   ierr = PCISCreate(pc);CHKERRQ(ierr);
2183 
2184   /* BDDC customization */
2185   pcbddc->use_local_adj       = PETSC_TRUE;
2186   pcbddc->use_vertices        = PETSC_TRUE;
2187   pcbddc->use_edges           = PETSC_TRUE;
2188   pcbddc->use_faces           = PETSC_FALSE;
2189   pcbddc->use_change_of_basis = PETSC_FALSE;
2190   pcbddc->use_change_on_faces = PETSC_FALSE;
2191   pcbddc->switch_static       = PETSC_FALSE;
2192   pcbddc->use_nnsp_true       = PETSC_FALSE;
2193   pcbddc->use_qr_single       = PETSC_FALSE;
2194   pcbddc->symmetric_primal    = PETSC_TRUE;
2195   pcbddc->benign_saddle_point = PETSC_FALSE;
2196   pcbddc->dbg_flag            = 0;
2197   /* private */
2198   pcbddc->local_primal_size          = 0;
2199   pcbddc->local_primal_size_cc       = 0;
2200   pcbddc->local_primal_ref_node      = 0;
2201   pcbddc->local_primal_ref_mult      = 0;
2202   pcbddc->n_vertices                 = 0;
2203   pcbddc->primal_indices_local_idxs  = 0;
2204   pcbddc->recompute_topography       = PETSC_FALSE;
2205   pcbddc->coarse_size                = -1;
2206   pcbddc->new_primal_space           = PETSC_FALSE;
2207   pcbddc->new_primal_space_local     = PETSC_FALSE;
2208   pcbddc->global_primal_indices      = 0;
2209   pcbddc->onearnullspace             = 0;
2210   pcbddc->onearnullvecs_state        = 0;
2211   pcbddc->user_primal_vertices       = 0;
2212   pcbddc->NullSpace                  = 0;
2213   pcbddc->temp_solution              = 0;
2214   pcbddc->original_rhs               = 0;
2215   pcbddc->local_mat                  = 0;
2216   pcbddc->ChangeOfBasisMatrix        = 0;
2217   pcbddc->user_ChangeOfBasisMatrix   = 0;
2218   pcbddc->new_global_mat             = 0;
2219   pcbddc->coarse_vec                 = 0;
2220   pcbddc->coarse_ksp                 = 0;
2221   pcbddc->coarse_phi_B               = 0;
2222   pcbddc->coarse_phi_D               = 0;
2223   pcbddc->coarse_psi_B               = 0;
2224   pcbddc->coarse_psi_D               = 0;
2225   pcbddc->vec1_P                     = 0;
2226   pcbddc->vec1_R                     = 0;
2227   pcbddc->vec2_R                     = 0;
2228   pcbddc->local_auxmat1              = 0;
2229   pcbddc->local_auxmat2              = 0;
2230   pcbddc->R_to_B                     = 0;
2231   pcbddc->R_to_D                     = 0;
2232   pcbddc->ksp_D                      = 0;
2233   pcbddc->ksp_R                      = 0;
2234   pcbddc->NeumannBoundaries          = 0;
2235   pcbddc->NeumannBoundariesLocal     = 0;
2236   pcbddc->DirichletBoundaries        = 0;
2237   pcbddc->DirichletBoundariesLocal   = 0;
2238   pcbddc->user_provided_isfordofs    = PETSC_FALSE;
2239   pcbddc->n_ISForDofs                = 0;
2240   pcbddc->n_ISForDofsLocal           = 0;
2241   pcbddc->ISForDofs                  = 0;
2242   pcbddc->ISForDofsLocal             = 0;
2243   pcbddc->ConstraintMatrix           = 0;
2244   pcbddc->use_exact_dirichlet_trick  = PETSC_TRUE;
2245   pcbddc->coarse_loc_to_glob         = 0;
2246   pcbddc->coarsening_ratio           = 8;
2247   pcbddc->coarse_adj_red             = 0;
2248   pcbddc->current_level              = 0;
2249   pcbddc->max_levels                 = 0;
2250   pcbddc->use_coarse_estimates       = PETSC_FALSE;
2251   pcbddc->redistribute_coarse        = 0;
2252   pcbddc->coarse_subassembling       = 0;
2253   pcbddc->coarse_subassembling_init  = 0;
2254   pcbddc->detect_disconnected        = PETSC_FALSE;
2255   pcbddc->n_local_subs               = 0;
2256   pcbddc->local_subs                 = NULL;
2257 
2258   /* benign subspace trick */
2259   pcbddc->benign_change              = 0;
2260   pcbddc->benign_vec                 = 0;
2261   pcbddc->benign_original_mat        = 0;
2262   pcbddc->benign_sf                  = 0;
2263   pcbddc->benign_B0                  = 0;
2264   pcbddc->benign_n                   = 0;
2265   pcbddc->benign_p0                  = NULL;
2266   pcbddc->benign_p0_lidx             = NULL;
2267   pcbddc->benign_p0_gidx             = NULL;
2268   pcbddc->benign_null                = PETSC_FALSE;
2269 
2270   /* create local graph structure */
2271   ierr = PCBDDCGraphCreate(&pcbddc->mat_graph);CHKERRQ(ierr);
2272 
2273   /* scaling */
2274   pcbddc->work_scaling          = 0;
2275   pcbddc->use_deluxe_scaling    = PETSC_FALSE;
2276   pcbddc->faster_deluxe         = PETSC_FALSE;
2277 
2278   /* create sub schurs structure */
2279   ierr = PCBDDCSubSchursCreate(&pcbddc->sub_schurs);CHKERRQ(ierr);
2280   pcbddc->sub_schurs_rebuild     = PETSC_FALSE;
2281   pcbddc->sub_schurs_layers      = -1;
2282   pcbddc->sub_schurs_use_useradj = PETSC_FALSE;
2283 
2284   pcbddc->computed_rowadj = PETSC_FALSE;
2285 
2286   /* adaptivity */
2287   pcbddc->adaptive_threshold      = 0.0;
2288   pcbddc->adaptive_nmax           = 0;
2289   pcbddc->adaptive_nmin           = 0;
2290 
2291   /* function pointers */
2292   pc->ops->apply               = PCApply_BDDC;
2293   pc->ops->applytranspose      = PCApplyTranspose_BDDC;
2294   pc->ops->setup               = PCSetUp_BDDC;
2295   pc->ops->destroy             = PCDestroy_BDDC;
2296   pc->ops->setfromoptions      = PCSetFromOptions_BDDC;
2297   pc->ops->view                = 0;
2298   pc->ops->applyrichardson     = 0;
2299   pc->ops->applysymmetricleft  = 0;
2300   pc->ops->applysymmetricright = 0;
2301   pc->ops->presolve            = PCPreSolve_BDDC;
2302   pc->ops->postsolve           = PCPostSolve_BDDC;
2303 
2304   /* composing function */
2305   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",PCBDDCSetChangeOfBasisMat_BDDC);CHKERRQ(ierr);
2306   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",PCBDDCSetPrimalVerticesLocalIS_BDDC);CHKERRQ(ierr);
2307   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",PCBDDCSetCoarseningRatio_BDDC);CHKERRQ(ierr);
2308   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",PCBDDCSetLevel_BDDC);CHKERRQ(ierr);
2309   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",PCBDDCSetUseExactDirichlet_BDDC);CHKERRQ(ierr);
2310   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",PCBDDCSetLevels_BDDC);CHKERRQ(ierr);
2311   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNullSpace_C",PCBDDCSetNullSpace_BDDC);CHKERRQ(ierr);
2312   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",PCBDDCSetDirichletBoundaries_BDDC);CHKERRQ(ierr);
2313   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",PCBDDCSetDirichletBoundariesLocal_BDDC);CHKERRQ(ierr);
2314   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",PCBDDCSetNeumannBoundaries_BDDC);CHKERRQ(ierr);
2315   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",PCBDDCSetNeumannBoundariesLocal_BDDC);CHKERRQ(ierr);
2316   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",PCBDDCGetDirichletBoundaries_BDDC);CHKERRQ(ierr);
2317   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",PCBDDCGetDirichletBoundariesLocal_BDDC);CHKERRQ(ierr);
2318   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",PCBDDCGetNeumannBoundaries_BDDC);CHKERRQ(ierr);
2319   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",PCBDDCGetNeumannBoundariesLocal_BDDC);CHKERRQ(ierr);
2320   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",PCBDDCSetDofsSplitting_BDDC);CHKERRQ(ierr);
2321   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",PCBDDCSetDofsSplittingLocal_BDDC);CHKERRQ(ierr);
2322   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",PCBDDCSetLocalAdjacencyGraph_BDDC);CHKERRQ(ierr);
2323   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",PCBDDCCreateFETIDPOperators_BDDC);CHKERRQ(ierr);
2324   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",PCBDDCMatFETIDPGetRHS_BDDC);CHKERRQ(ierr);
2325   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",PCBDDCMatFETIDPGetSolution_BDDC);CHKERRQ(ierr);
2326   PetscFunctionReturn(0);
2327 }
2328 
2329