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