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