xref: /petsc/src/ksp/pc/impls/bddc/bddc.c (revision af25d912c737f21fca88746c26cd8b5ca8321f21)
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   if (pcbddc->adaptive_threshold > 0.0 && !pcbddc->use_deluxe_scaling) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot compute adaptive constraints without deluxe scaling. Rerun with -pc_bddc_use_deluxe_scaling");
1364   pcbddc->adaptive_selection = (PetscBool)(pcbddc->adaptive_threshold > 0.0 && pcbddc->use_deluxe_scaling);
1365   pcbddc->adaptive_userdefined = (PetscBool)(pcbddc->adaptive_selection && pcbddc->adaptive_userdefined);
1366   if (pcbddc->adaptive_selection) pcbddc->use_faces = PETSC_TRUE;
1367 
1368   computesubschurs = (PetscBool)(pcbddc->adaptive_selection || pcbddc->use_deluxe_scaling);
1369   if (pcbddc->faster_deluxe && pcbddc->adaptive_selection && pcbddc->use_change_of_basis) 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");
1370 
1371   if (pcbddc->switch_static) {
1372     PetscBool ismatis;
1373     ierr = PetscObjectTypeCompare((PetscObject)pc->mat,MATIS,&ismatis);CHKERRQ(ierr);
1374     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"When the static switch is one, the iteration matrix should be of type MATIS");
1375   }
1376 
1377   /* Get stdout for dbg */
1378   if (pcbddc->dbg_flag) {
1379     if (!pcbddc->dbg_viewer) {
1380       pcbddc->dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pc));
1381       ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
1382     }
1383     ierr = PetscViewerASCIIAddTab(pcbddc->dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
1384   }
1385 
1386   if (pcbddc->user_ChangeOfBasisMatrix) {
1387     /* use_change_of_basis flag is used to automatically compute a change of basis from constraints */
1388     pcbddc->use_change_of_basis = PETSC_FALSE;
1389     ierr = PCBDDCComputeLocalMatrix(pc,pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
1390   } else {
1391     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
1392     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
1393     pcbddc->local_mat = matis->A;
1394   }
1395 
1396   /* detect local disconnected subdomains if requested and not done before */
1397   if (pcbddc->detect_disconnected && !pcbddc->n_local_subs) {
1398     ierr = MatDetectDisconnectedComponents(pcbddc->local_mat,PETSC_FALSE,&pcbddc->n_local_subs,&pcbddc->local_subs);CHKERRQ(ierr);
1399   }
1400 
1401   /*
1402      Compute change of basis on local pressures (aka zerodiag dofs)
1403      This should come earlier then PCISSetUp for extracting the correct subdomain matrices
1404   */
1405   ierr = PCBDDCBenignShellMat(pc,PETSC_TRUE);CHKERRQ(ierr);
1406   if (pcbddc->benign_saddle_point) {
1407     PC_IS* pcis = (PC_IS*)pc->data;
1408 
1409     if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->use_change_of_basis || !computesubschurs) pcbddc->benign_change_explicit = PETSC_TRUE;
1410     /* detect local saddle point and change the basis in pcbddc->local_mat */
1411     ierr = PCBDDCBenignDetectSaddlePoint(pc,&zerodiag);CHKERRQ(ierr);
1412     /* pop B0 mat from local mat */
1413     ierr = PCBDDCBenignPopOrPushB0(pc,PETSC_TRUE);CHKERRQ(ierr);
1414     /* give pcis a hint to not reuse submatrices during PCISCreate */
1415     if (pc->flag == SAME_NONZERO_PATTERN && pcis->reusesubmatrices == PETSC_TRUE) {
1416       if (pcbddc->benign_n && (pcbddc->benign_change_explicit || pcbddc->dbg_flag)) {
1417         pcis->reusesubmatrices = PETSC_FALSE;
1418       } else {
1419         pcis->reusesubmatrices = PETSC_TRUE;
1420       }
1421     } else {
1422       pcis->reusesubmatrices = PETSC_FALSE;
1423     }
1424   }
1425   /* propagate relevant information */
1426 #if !defined(PETSC_USE_COMPLEX) /* workaround for reals */
1427   if (matis->A->symmetric_set) {
1428     ierr = MatSetOption(pcbddc->local_mat,MAT_HERMITIAN,matis->A->symmetric);CHKERRQ(ierr);
1429   }
1430 #endif
1431   if (matis->A->symmetric_set) {
1432     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
1433   }
1434   if (matis->A->spd_set) {
1435     ierr = MatSetOption(pcbddc->local_mat,MAT_SPD,matis->A->spd);CHKERRQ(ierr);
1436   }
1437 
1438   /* Set up all the "iterative substructuring" common block without computing solvers */
1439   {
1440     Mat temp_mat;
1441 
1442     temp_mat = matis->A;
1443     matis->A = pcbddc->local_mat;
1444     ierr = PCISSetUp(pc,PETSC_FALSE);CHKERRQ(ierr);
1445     pcbddc->local_mat = matis->A;
1446     matis->A = temp_mat;
1447   }
1448 
1449   /* Analyze interface */
1450   if (computetopography) {
1451     ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
1452     computeconstraintsmatrix = PETSC_TRUE;
1453   }
1454 
1455   /* check existence of a divergence free extension, i.e.
1456      b(v_I,p_0) = 0 for all v_I (raise error if not).
1457      Also, check that PCBDDCBenignGetOrSetP0 works */
1458 #if defined(PETSC_USE_DEBUG)
1459   if (pcbddc->benign_saddle_point) {
1460     ierr = PCBDDCBenignCheck(pc,zerodiag);CHKERRQ(ierr);
1461   }
1462 #endif
1463   ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
1464 
1465   /* Setup local dirichlet solver ksp_D and sub_schurs solvers */
1466   if (computesolvers) {
1467     PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
1468 
1469     if (computesubschurs && computetopography) {
1470       ierr = PCBDDCInitSubSchurs(pc);CHKERRQ(ierr);
1471     }
1472     if (sub_schurs->schur_explicit) {
1473       if (computesubschurs) {
1474         ierr = PCBDDCSetUpSubSchurs(pc);CHKERRQ(ierr);
1475       }
1476       ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr);
1477     } else {
1478       ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr);
1479       if (computesubschurs) {
1480         ierr = PCBDDCSetUpSubSchurs(pc);CHKERRQ(ierr);
1481       }
1482     }
1483     if (pcbddc->adaptive_selection) {
1484       ierr = PCBDDCAdaptiveSelection(pc);CHKERRQ(ierr);
1485       computeconstraintsmatrix = PETSC_TRUE;
1486     }
1487   }
1488 
1489   /* infer if NullSpace object attached to Mat via MatSetNearNullSpace has changed */
1490   new_nearnullspace_provided = PETSC_FALSE;
1491   ierr = MatGetNearNullSpace(pc->pmat,&nearnullspace);CHKERRQ(ierr);
1492   if (pcbddc->onearnullspace) { /* already used nearnullspace */
1493     if (!nearnullspace) { /* near null space attached to mat has been destroyed */
1494       new_nearnullspace_provided = PETSC_TRUE;
1495     } else {
1496       /* determine if the two nullspaces are different (should be lightweight) */
1497       if (nearnullspace != pcbddc->onearnullspace) {
1498         new_nearnullspace_provided = PETSC_TRUE;
1499       } else { /* maybe the user has changed the content of the nearnullspace so check vectors ObjectStateId */
1500         PetscInt         i;
1501         const Vec        *nearnullvecs;
1502         PetscObjectState state;
1503         PetscInt         nnsp_size;
1504         ierr = MatNullSpaceGetVecs(nearnullspace,NULL,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
1505         for (i=0;i<nnsp_size;i++) {
1506           ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&state);CHKERRQ(ierr);
1507           if (pcbddc->onearnullvecs_state[i] != state) {
1508             new_nearnullspace_provided = PETSC_TRUE;
1509             break;
1510           }
1511         }
1512       }
1513     }
1514   } else {
1515     if (!nearnullspace) { /* both nearnullspaces are null */
1516       new_nearnullspace_provided = PETSC_FALSE;
1517     } else { /* nearnullspace attached later */
1518       new_nearnullspace_provided = PETSC_TRUE;
1519     }
1520   }
1521 
1522   /* Setup constraints and related work vectors */
1523   /* reset primal space flags */
1524   pcbddc->new_primal_space = PETSC_FALSE;
1525   pcbddc->new_primal_space_local = PETSC_FALSE;
1526   if (computeconstraintsmatrix || new_nearnullspace_provided) {
1527     /* It also sets the primal space flags */
1528     ierr = PCBDDCConstraintsSetUp(pc);CHKERRQ(ierr);
1529     /* Allocate needed local vectors (which depends on quantities defined during ConstraintsSetUp) */
1530     ierr = PCBDDCSetUpLocalWorkVectors(pc);CHKERRQ(ierr);
1531   }
1532 
1533   if (computesolvers || pcbddc->new_primal_space) {
1534     if (pcbddc->use_change_of_basis) {
1535       PC_IS *pcis = (PC_IS*)(pc->data);
1536 
1537       ierr = PCBDDCComputeLocalMatrix(pc,pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
1538       if (pcbddc->benign_change) {
1539         ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
1540         /* pop B0 from pcbddc->local_mat */
1541         ierr = PCBDDCBenignPopOrPushB0(pc,PETSC_TRUE);CHKERRQ(ierr);
1542       }
1543       /* get submatrices */
1544       ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr);
1545       ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr);
1546       ierr = MatDestroy(&pcis->A_BB);CHKERRQ(ierr);
1547       ierr = MatGetSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_BB);CHKERRQ(ierr);
1548       ierr = MatGetSubMatrix(pcbddc->local_mat,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_IB);CHKERRQ(ierr);
1549       ierr = MatGetSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&pcis->A_BI);CHKERRQ(ierr);
1550       /* set flag in pcis to not reuse submatrices during PCISCreate */
1551       pcis->reusesubmatrices = PETSC_FALSE;
1552     } else if (!pcbddc->user_ChangeOfBasisMatrix && !pcbddc->benign_change) {
1553       ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
1554       ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
1555       pcbddc->local_mat = matis->A;
1556     }
1557     /* SetUp coarse and local Neumann solvers */
1558     ierr = PCBDDCSetUpSolvers(pc);CHKERRQ(ierr);
1559     /* SetUp Scaling operator */
1560     ierr = PCBDDCScalingSetUp(pc);CHKERRQ(ierr);
1561   }
1562   /* mark topography as done */
1563   pcbddc->recompute_topography = PETSC_FALSE;
1564 
1565   /* wrap pcis->A_IB and pcis->A_BI if we did not change explicitly the variables on the pressures */
1566   ierr = PCBDDCBenignShellMat(pc,PETSC_FALSE);CHKERRQ(ierr);
1567 
1568   if (pcbddc->dbg_flag) {
1569     ierr = PetscViewerASCIISubtractTab(pcbddc->dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
1570   }
1571   PetscFunctionReturn(0);
1572 }
1573 
1574 /* -------------------------------------------------------------------------- */
1575 /*
1576    PCApply_BDDC - Applies the BDDC operator to a vector.
1577 
1578    Input Parameters:
1579 +  pc - the preconditioner context
1580 -  r - input vector (global)
1581 
1582    Output Parameter:
1583 .  z - output vector (global)
1584 
1585    Application Interface Routine: PCApply()
1586  */
1587 #undef __FUNCT__
1588 #define __FUNCT__ "PCApply_BDDC"
1589 PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z)
1590 {
1591   PC_IS             *pcis = (PC_IS*)(pc->data);
1592   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
1593   PetscInt          n_B = pcis->n_B, n_D = pcis->n - n_B;
1594   PetscErrorCode    ierr;
1595   const PetscScalar one = 1.0;
1596   const PetscScalar m_one = -1.0;
1597   const PetscScalar zero = 0.0;
1598 
1599 /* This code is similar to that provided in nn.c for PCNN
1600    NN interface preconditioner changed to BDDC
1601    Added support for M_3 preconditioner in the reference article (code is active if pcbddc->switch_static == PETSC_TRUE) */
1602 
1603   PetscFunctionBegin;
1604   if (pcbddc->ChangeOfBasisMatrix) {
1605     Vec swap;
1606     ierr = VecCopy(r,pcbddc->work_change);CHKERRQ(ierr);
1607     swap = pcbddc->work_change;
1608     pcbddc->work_change = r;
1609     r = swap;
1610     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,r);CHKERRQ(ierr);
1611     /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */
1612     if (pcbddc->benign_apply_coarse_only && pcbddc->use_exact_dirichlet_trick && pcbddc->change_interior) {
1613       ierr = VecCopy(r,pcis->vec1_global);CHKERRQ(ierr);
1614       ierr = VecLockPush(pcis->vec1_global);CHKERRQ(ierr);
1615     }
1616   }
1617   if (pcbddc->benign_saddle_point) { /* get p0 from r */
1618     ierr = PCBDDCBenignGetOrSetP0(pc,r,PETSC_TRUE);CHKERRQ(ierr);
1619   }
1620   if (!pcbddc->use_exact_dirichlet_trick) {
1621     ierr = VecCopy(r,z);CHKERRQ(ierr);
1622     /* First Dirichlet solve */
1623     ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1624     ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1625     /*
1626       Assembling right hand side for BDDC operator
1627       - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE)
1628       - pcis->vec1_B the interface part of the global vector z
1629     */
1630     if (n_D) {
1631       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
1632       ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
1633       if (pcbddc->switch_static) {
1634         Mat_IS *matis = (Mat_IS*)(pc->mat->data);
1635 
1636         ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
1637         ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1638         ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1639         if (!pcbddc->switch_static_change) {
1640           ierr = MatMult(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
1641         } else {
1642           ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
1643           ierr = MatMult(matis->A,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr);
1644           ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
1645         }
1646         ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1647         ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1648         ierr = VecScatterBegin(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1649         ierr = VecScatterEnd(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1650       } else {
1651         ierr = MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
1652       }
1653     } else {
1654       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
1655     }
1656     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1657     ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1658     ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr);
1659   } else {
1660     if (!pcbddc->benign_apply_coarse_only) {
1661       ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr);
1662     }
1663   }
1664 
1665   /* Apply interface preconditioner
1666      input/output vecs: pcis->vec1_B and pcis->vec1_D */
1667   ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
1668 
1669   /* Apply transpose of partition of unity operator */
1670   ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr);
1671 
1672   /* Second Dirichlet solve and assembling of output */
1673   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1674   ierr = VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1675   if (n_B) {
1676     if (pcbddc->switch_static) {
1677       Mat_IS *matis = (Mat_IS*)(pc->mat->data);
1678 
1679       ierr = VecScatterBegin(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1680       ierr = VecScatterEnd(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1681       ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1682       ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1683       if (!pcbddc->switch_static_change) {
1684         ierr = MatMult(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
1685       } else {
1686         ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
1687         ierr = MatMult(matis->A,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr);
1688         ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
1689       }
1690       ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1691       ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1692     } else {
1693       ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
1694     }
1695   } else if (pcbddc->switch_static) { /* n_B is zero */
1696     Mat_IS *matis = (Mat_IS*)(pc->mat->data);
1697 
1698     if (!pcbddc->switch_static_change) {
1699       ierr = MatMult(matis->A,pcis->vec1_D,pcis->vec3_D);CHKERRQ(ierr);
1700     } else {
1701       ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_D,pcis->vec1_N);CHKERRQ(ierr);
1702       ierr = MatMult(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
1703       ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec2_N,pcis->vec3_D);CHKERRQ(ierr);
1704     }
1705   }
1706   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D);CHKERRQ(ierr);
1707 
1708   if (!pcbddc->use_exact_dirichlet_trick) {
1709     if (pcbddc->switch_static) {
1710       ierr = VecAXPBYPCZ(pcis->vec2_D,m_one,one,m_one,pcis->vec4_D,pcis->vec1_D);CHKERRQ(ierr);
1711     } else {
1712       ierr = VecAXPBY(pcis->vec2_D,m_one,m_one,pcis->vec4_D);CHKERRQ(ierr);
1713     }
1714     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1715     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1716   } else {
1717     if (pcbddc->switch_static) {
1718       ierr = VecAXPBY(pcis->vec4_D,one,m_one,pcis->vec1_D);CHKERRQ(ierr);
1719     } else {
1720       ierr = VecScale(pcis->vec4_D,m_one);CHKERRQ(ierr);
1721     }
1722     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1723     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1724   }
1725 
1726   if (pcbddc->benign_saddle_point) { /* set p0 (computed in PCBDDCApplyInterface) */
1727     if (pcbddc->benign_apply_coarse_only) {
1728       ierr = PetscMemzero(pcbddc->benign_p0,pcbddc->benign_n*sizeof(PetscScalar));CHKERRQ(ierr);
1729     }
1730     ierr = PCBDDCBenignGetOrSetP0(pc,z,PETSC_FALSE);CHKERRQ(ierr);
1731   }
1732   if (pcbddc->ChangeOfBasisMatrix) {
1733     Vec swap;
1734 
1735     swap = r;
1736     r = pcbddc->work_change;
1737     pcbddc->work_change = swap;
1738     ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr);
1739     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr);
1740   }
1741   PetscFunctionReturn(0);
1742 }
1743 
1744 /* -------------------------------------------------------------------------- */
1745 /*
1746    PCApplyTranspose_BDDC - Applies the transpose of the BDDC operator to a vector.
1747 
1748    Input Parameters:
1749 +  pc - the preconditioner context
1750 -  r - input vector (global)
1751 
1752    Output Parameter:
1753 .  z - output vector (global)
1754 
1755    Application Interface Routine: PCApplyTranspose()
1756  */
1757 #undef __FUNCT__
1758 #define __FUNCT__ "PCApplyTranspose_BDDC"
1759 PetscErrorCode PCApplyTranspose_BDDC(PC pc,Vec r,Vec z)
1760 {
1761   PC_IS             *pcis = (PC_IS*)(pc->data);
1762   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
1763   PetscInt          n_B = pcis->n_B, n_D = pcis->n - n_B;
1764   PetscErrorCode    ierr;
1765   const PetscScalar one = 1.0;
1766   const PetscScalar m_one = -1.0;
1767   const PetscScalar zero = 0.0;
1768 
1769   PetscFunctionBegin;
1770   if (pcbddc->ChangeOfBasisMatrix) {
1771     Vec swap;
1772     ierr = VecCopy(r,pcbddc->work_change);CHKERRQ(ierr);
1773     swap = pcbddc->work_change;
1774     pcbddc->work_change = r;
1775     r = swap;
1776     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,r);CHKERRQ(ierr);
1777   }
1778   if (pcbddc->benign_saddle_point) { /* get p0 from r */
1779     ierr = PCBDDCBenignGetOrSetP0(pc,r,PETSC_TRUE);CHKERRQ(ierr);
1780   }
1781   if (!pcbddc->use_exact_dirichlet_trick) {
1782     ierr = VecCopy(r,z);CHKERRQ(ierr);
1783     /* First Dirichlet solve */
1784     ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1785     ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1786     /*
1787       Assembling right hand side for BDDC operator
1788       - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE)
1789       - pcis->vec1_B the interface part of the global vector z
1790     */
1791     if (n_D) {
1792       ierr = KSPSolveTranspose(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
1793       ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
1794       if (pcbddc->switch_static) {
1795         Mat_IS *matis = (Mat_IS*)(pc->mat->data);
1796 
1797         ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
1798         ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1799         ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1800         if (!pcbddc->switch_static_change) {
1801           ierr = MatMultTranspose(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
1802         } else {
1803           ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
1804           ierr = MatMultTranspose(matis->A,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr);
1805           ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
1806         }
1807         ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1808         ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1809         ierr = VecScatterBegin(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1810         ierr = VecScatterEnd(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1811       } else {
1812         ierr = MatMultTranspose(pcis->A_IB,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
1813       }
1814     } else {
1815       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
1816     }
1817     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1818     ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1819     ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr);
1820   } else {
1821     ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr);
1822   }
1823 
1824   /* Apply interface preconditioner
1825      input/output vecs: pcis->vec1_B and pcis->vec1_D */
1826   ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_TRUE);CHKERRQ(ierr);
1827 
1828   /* Apply transpose of partition of unity operator */
1829   ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr);
1830 
1831   /* Second Dirichlet solve and assembling of output */
1832   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1833   ierr = VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1834   if (n_B) {
1835     if (pcbddc->switch_static) {
1836       Mat_IS *matis = (Mat_IS*)(pc->mat->data);
1837 
1838       ierr = VecScatterBegin(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1839       ierr = VecScatterEnd(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1840       ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1841       ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1842       if (!pcbddc->switch_static_change) {
1843         ierr = MatMultTranspose(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
1844       } else {
1845         ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
1846         ierr = MatMultTranspose(matis->A,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr);
1847         ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
1848       }
1849       ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1850       ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1851     } else {
1852       ierr = MatMultTranspose(pcis->A_BI,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
1853     }
1854   } else if (pcbddc->switch_static) { /* n_B is zero */
1855     Mat_IS *matis = (Mat_IS*)(pc->mat->data);
1856 
1857     if (!pcbddc->switch_static_change) {
1858       ierr = MatMultTranspose(matis->A,pcis->vec1_D,pcis->vec3_D);CHKERRQ(ierr);
1859     } else {
1860       ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_D,pcis->vec1_N);CHKERRQ(ierr);
1861       ierr = MatMultTranspose(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
1862       ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec2_N,pcis->vec3_D);CHKERRQ(ierr);
1863     }
1864   }
1865   ierr = KSPSolveTranspose(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D);CHKERRQ(ierr);
1866   if (!pcbddc->use_exact_dirichlet_trick) {
1867     if (pcbddc->switch_static) {
1868       ierr = VecAXPBYPCZ(pcis->vec2_D,m_one,one,m_one,pcis->vec4_D,pcis->vec1_D);CHKERRQ(ierr);
1869     } else {
1870       ierr = VecAXPBY(pcis->vec2_D,m_one,m_one,pcis->vec4_D);CHKERRQ(ierr);
1871     }
1872     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1873     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1874   } else {
1875     if (pcbddc->switch_static) {
1876       ierr = VecAXPBY(pcis->vec4_D,one,m_one,pcis->vec1_D);CHKERRQ(ierr);
1877     } else {
1878       ierr = VecScale(pcis->vec4_D,m_one);CHKERRQ(ierr);
1879     }
1880     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1881     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1882   }
1883   if (pcbddc->benign_saddle_point) { /* set p0 (computed in PCBDDCApplyInterface) */
1884     ierr = PCBDDCBenignGetOrSetP0(pc,z,PETSC_FALSE);CHKERRQ(ierr);
1885   }
1886   if (pcbddc->ChangeOfBasisMatrix) {
1887     Vec swap;
1888 
1889     swap = r;
1890     r = pcbddc->work_change;
1891     pcbddc->work_change = swap;
1892     ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr);
1893     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr);
1894   }
1895   PetscFunctionReturn(0);
1896 }
1897 /* -------------------------------------------------------------------------- */
1898 
1899 #undef __FUNCT__
1900 #define __FUNCT__ "PCDestroy_BDDC"
1901 PetscErrorCode PCDestroy_BDDC(PC pc)
1902 {
1903   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1904   PetscErrorCode ierr;
1905 
1906   PetscFunctionBegin;
1907   /* free BDDC custom data  */
1908   ierr = PCBDDCResetCustomization(pc);CHKERRQ(ierr);
1909   /* destroy objects related to topography */
1910   ierr = PCBDDCResetTopography(pc);CHKERRQ(ierr);
1911   /* free allocated graph structure */
1912   ierr = PetscFree(pcbddc->mat_graph);CHKERRQ(ierr);
1913   /* free allocated sub schurs structure */
1914   ierr = PetscFree(pcbddc->sub_schurs);CHKERRQ(ierr);
1915   /* destroy objects for scaling operator */
1916   ierr = PCBDDCScalingDestroy(pc);CHKERRQ(ierr);
1917   ierr = PetscFree(pcbddc->deluxe_ctx);CHKERRQ(ierr);
1918   /* free solvers stuff */
1919   ierr = PCBDDCResetSolvers(pc);CHKERRQ(ierr);
1920   /* free global vectors needed in presolve */
1921   ierr = VecDestroy(&pcbddc->temp_solution);CHKERRQ(ierr);
1922   ierr = VecDestroy(&pcbddc->original_rhs);CHKERRQ(ierr);
1923   /* free data created by PCIS */
1924   ierr = PCISDestroy(pc);CHKERRQ(ierr);
1925   /* remove functions */
1926   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",NULL);CHKERRQ(ierr);
1927   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",NULL);CHKERRQ(ierr);
1928   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesIS_C",NULL);CHKERRQ(ierr);
1929   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",NULL);CHKERRQ(ierr);
1930   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",NULL);CHKERRQ(ierr);
1931   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",NULL);CHKERRQ(ierr);
1932   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",NULL);CHKERRQ(ierr);
1933   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNullSpace_C",NULL);CHKERRQ(ierr);
1934   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",NULL);CHKERRQ(ierr);
1935   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",NULL);CHKERRQ(ierr);
1936   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",NULL);CHKERRQ(ierr);
1937   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",NULL);CHKERRQ(ierr);
1938   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",NULL);CHKERRQ(ierr);
1939   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",NULL);CHKERRQ(ierr);
1940   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",NULL);CHKERRQ(ierr);
1941   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",NULL);CHKERRQ(ierr);
1942   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",NULL);CHKERRQ(ierr);
1943   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",NULL);CHKERRQ(ierr);
1944   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",NULL);CHKERRQ(ierr);
1945   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",NULL);CHKERRQ(ierr);
1946   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",NULL);CHKERRQ(ierr);
1947   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",NULL);CHKERRQ(ierr);
1948   /* Free the private data structure */
1949   ierr = PetscFree(pc->data);CHKERRQ(ierr);
1950   PetscFunctionReturn(0);
1951 }
1952 /* -------------------------------------------------------------------------- */
1953 
1954 #undef __FUNCT__
1955 #define __FUNCT__ "PCBDDCMatFETIDPGetRHS_BDDC"
1956 static PetscErrorCode PCBDDCMatFETIDPGetRHS_BDDC(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
1957 {
1958   FETIDPMat_ctx  mat_ctx;
1959   Vec            copy_standard_rhs;
1960   PC_IS*         pcis;
1961   PC_BDDC*       pcbddc;
1962   PetscErrorCode ierr;
1963 
1964   PetscFunctionBegin;
1965   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
1966   pcis = (PC_IS*)mat_ctx->pc->data;
1967   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
1968 
1969   /*
1970      change of basis for physical rhs if needed
1971      It also changes the rhs in case of dirichlet boundaries
1972      TODO: better management when FETIDP will have its own class
1973   */
1974   ierr = VecDuplicate(standard_rhs,&copy_standard_rhs);CHKERRQ(ierr);
1975   ierr = VecCopy(standard_rhs,copy_standard_rhs);CHKERRQ(ierr);
1976   ierr = PCPreSolve_BDDC(mat_ctx->pc,NULL,copy_standard_rhs,NULL);CHKERRQ(ierr);
1977   /* store vectors for computation of fetidp final solution */
1978   ierr = VecScatterBegin(pcis->global_to_D,copy_standard_rhs,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1979   ierr = VecScatterEnd(pcis->global_to_D,copy_standard_rhs,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1980   /* scale rhs since it should be unassembled */
1981   /* TODO use counter scaling? (also below) */
1982   ierr = VecScatterBegin(pcis->global_to_B,copy_standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1983   ierr = VecScatterEnd(pcis->global_to_B,copy_standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1984   /* Apply partition of unity */
1985   ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr);
1986   /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,copy_standard_rhs,mat_ctx->temp_solution_B);CHKERRQ(ierr); */
1987   if (!pcbddc->switch_static) {
1988     /* compute partially subassembled Schur complement right-hand side */
1989     ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
1990     ierr = MatMult(pcis->A_BI,pcis->vec1_D,pcis->vec1_B);CHKERRQ(ierr);
1991     ierr = VecAXPY(mat_ctx->temp_solution_B,-1.0,pcis->vec1_B);CHKERRQ(ierr);
1992     ierr = VecSet(copy_standard_rhs,0.0);CHKERRQ(ierr);
1993     ierr = VecScatterBegin(pcis->global_to_B,mat_ctx->temp_solution_B,copy_standard_rhs,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1994     ierr = VecScatterEnd(pcis->global_to_B,mat_ctx->temp_solution_B,copy_standard_rhs,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1995     /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,copy_standard_rhs,mat_ctx->temp_solution_B);CHKERRQ(ierr); */
1996     ierr = VecScatterBegin(pcis->global_to_B,copy_standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1997     ierr = VecScatterEnd(pcis->global_to_B,copy_standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1998     ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr);
1999   }
2000   ierr = VecDestroy(&copy_standard_rhs);CHKERRQ(ierr);
2001   /* BDDC rhs */
2002   ierr = VecCopy(mat_ctx->temp_solution_B,pcis->vec1_B);CHKERRQ(ierr);
2003   if (pcbddc->switch_static) {
2004     ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
2005   }
2006   /* apply BDDC */
2007   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE);CHKERRQ(ierr);
2008   /* Application of B_delta and assembling of rhs for fetidp fluxes */
2009   ierr = VecSet(fetidp_flux_rhs,0.0);CHKERRQ(ierr);
2010   ierr = MatMult(mat_ctx->B_delta,pcis->vec1_B,mat_ctx->lambda_local);CHKERRQ(ierr);
2011   ierr = VecScatterBegin(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2012   ierr = VecScatterEnd(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2013   PetscFunctionReturn(0);
2014 }
2015 
2016 #undef __FUNCT__
2017 #define __FUNCT__ "PCBDDCMatFETIDPGetRHS"
2018 /*@
2019  PCBDDCMatFETIDPGetRHS - Compute the right-hand side for FETI-DP linear system using the physical right-hand side
2020 
2021    Collective
2022 
2023    Input Parameters:
2024 +  fetidp_mat      - the FETI-DP matrix object obtained by a call to PCBDDCCreateFETIDPOperators
2025 -  standard_rhs    - the right-hand side of the original linear system
2026 
2027    Output Parameters:
2028 .  fetidp_flux_rhs - the right-hand side for the FETI-DP linear system
2029 
2030    Level: developer
2031 
2032    Notes:
2033 
2034 .seealso: PCBDDC, PCBDDCCreateFETIDPOperators, PCBDDCMatFETIDPGetSolution
2035 @*/
2036 PetscErrorCode PCBDDCMatFETIDPGetRHS(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
2037 {
2038   FETIDPMat_ctx  mat_ctx;
2039   PetscErrorCode ierr;
2040 
2041   PetscFunctionBegin;
2042   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
2043   ierr = PetscTryMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetRHS_C",(Mat,Vec,Vec),(fetidp_mat,standard_rhs,fetidp_flux_rhs));CHKERRQ(ierr);
2044   PetscFunctionReturn(0);
2045 }
2046 /* -------------------------------------------------------------------------- */
2047 
2048 #undef __FUNCT__
2049 #define __FUNCT__ "PCBDDCMatFETIDPGetSolution_BDDC"
2050 static PetscErrorCode PCBDDCMatFETIDPGetSolution_BDDC(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
2051 {
2052   FETIDPMat_ctx  mat_ctx;
2053   PC_IS*         pcis;
2054   PC_BDDC*       pcbddc;
2055   PetscErrorCode ierr;
2056 
2057   PetscFunctionBegin;
2058   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
2059   pcis = (PC_IS*)mat_ctx->pc->data;
2060   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
2061 
2062   /* apply B_delta^T */
2063   ierr = VecScatterBegin(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2064   ierr = VecScatterEnd  (mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2065   ierr = MatMultTranspose(mat_ctx->B_delta,mat_ctx->lambda_local,pcis->vec1_B);CHKERRQ(ierr);
2066   /* compute rhs for BDDC application */
2067   ierr = VecAYPX(pcis->vec1_B,-1.0,mat_ctx->temp_solution_B);CHKERRQ(ierr);
2068   if (pcbddc->switch_static) {
2069     ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
2070   }
2071   /* apply BDDC */
2072   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE);CHKERRQ(ierr);
2073   /* put values into standard global vector */
2074   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2075   ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2076   if (!pcbddc->switch_static) {
2077     /* compute values into the interior if solved for the partially subassembled Schur complement */
2078     ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec1_D);CHKERRQ(ierr);
2079     ierr = VecAXPY(mat_ctx->temp_solution_D,-1.0,pcis->vec1_D);CHKERRQ(ierr);
2080     ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
2081   }
2082   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec1_D,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2083   ierr = VecScatterEnd  (pcis->global_to_D,pcis->vec1_D,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2084   /* final change of basis if needed
2085      Is also sums the dirichlet part removed during RHS assembling */
2086   ierr = PCPostSolve_BDDC(mat_ctx->pc,NULL,NULL,standard_sol);CHKERRQ(ierr);
2087   PetscFunctionReturn(0);
2088 }
2089 
2090 #undef __FUNCT__
2091 #define __FUNCT__ "PCBDDCMatFETIDPGetSolution"
2092 /*@
2093  PCBDDCMatFETIDPGetSolution - Compute the physical solution using the solution of the FETI-DP linear system
2094 
2095    Collective
2096 
2097    Input Parameters:
2098 +  fetidp_mat      - the FETI-DP matrix obtained by a call to PCBDDCCreateFETIDPOperators
2099 -  fetidp_flux_sol - the solution of the FETI-DP linear system
2100 
2101    Output Parameters:
2102 .  standard_sol    - the solution defined on the physical domain
2103 
2104    Level: developer
2105 
2106    Notes:
2107 
2108 .seealso: PCBDDC, PCBDDCCreateFETIDPOperators, PCBDDCMatFETIDPGetRHS
2109 @*/
2110 PetscErrorCode PCBDDCMatFETIDPGetSolution(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
2111 {
2112   FETIDPMat_ctx  mat_ctx;
2113   PetscErrorCode ierr;
2114 
2115   PetscFunctionBegin;
2116   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
2117   ierr = PetscTryMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetSolution_C",(Mat,Vec,Vec),(fetidp_mat,fetidp_flux_sol,standard_sol));CHKERRQ(ierr);
2118   PetscFunctionReturn(0);
2119 }
2120 /* -------------------------------------------------------------------------- */
2121 
2122 extern PetscErrorCode FETIDPMatMult(Mat,Vec,Vec);
2123 extern PetscErrorCode FETIDPMatMultTranspose(Mat,Vec,Vec);
2124 extern PetscErrorCode PCBDDCDestroyFETIDPMat(Mat);
2125 extern PetscErrorCode FETIDPPCApply(PC,Vec,Vec);
2126 extern PetscErrorCode FETIDPPCApplyTranspose(PC,Vec,Vec);
2127 extern PetscErrorCode PCBDDCDestroyFETIDPPC(PC);
2128 
2129 #undef __FUNCT__
2130 #define __FUNCT__ "PCBDDCCreateFETIDPOperators_BDDC"
2131 static PetscErrorCode PCBDDCCreateFETIDPOperators_BDDC(PC pc, Mat *fetidp_mat, PC *fetidp_pc)
2132 {
2133 
2134   FETIDPMat_ctx  fetidpmat_ctx;
2135   Mat            newmat;
2136   FETIDPPC_ctx   fetidppc_ctx;
2137   PC             newpc;
2138   MPI_Comm       comm;
2139   PetscErrorCode ierr;
2140 
2141   PetscFunctionBegin;
2142   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
2143   /* FETIDP linear matrix */
2144   ierr = PCBDDCCreateFETIDPMatContext(pc,&fetidpmat_ctx);CHKERRQ(ierr);
2145   ierr = PCBDDCSetupFETIDPMatContext(fetidpmat_ctx);CHKERRQ(ierr);
2146   ierr = MatCreateShell(comm,PETSC_DECIDE,PETSC_DECIDE,fetidpmat_ctx->n_lambda,fetidpmat_ctx->n_lambda,fetidpmat_ctx,&newmat);CHKERRQ(ierr);
2147   ierr = MatShellSetOperation(newmat,MATOP_MULT,(void (*)(void))FETIDPMatMult);CHKERRQ(ierr);
2148   ierr = MatShellSetOperation(newmat,MATOP_MULT_TRANSPOSE,(void (*)(void))FETIDPMatMultTranspose);CHKERRQ(ierr);
2149   ierr = MatShellSetOperation(newmat,MATOP_DESTROY,(void (*)(void))PCBDDCDestroyFETIDPMat);CHKERRQ(ierr);
2150   ierr = MatSetUp(newmat);CHKERRQ(ierr);
2151   /* FETIDP preconditioner */
2152   ierr = PCBDDCCreateFETIDPPCContext(pc,&fetidppc_ctx);CHKERRQ(ierr);
2153   ierr = PCBDDCSetupFETIDPPCContext(newmat,fetidppc_ctx);CHKERRQ(ierr);
2154   ierr = PCCreate(comm,&newpc);CHKERRQ(ierr);
2155   ierr = PCSetType(newpc,PCSHELL);CHKERRQ(ierr);
2156   ierr = PCShellSetContext(newpc,fetidppc_ctx);CHKERRQ(ierr);
2157   ierr = PCShellSetApply(newpc,FETIDPPCApply);CHKERRQ(ierr);
2158   ierr = PCShellSetApplyTranspose(newpc,FETIDPPCApplyTranspose);CHKERRQ(ierr);
2159   ierr = PCShellSetDestroy(newpc,PCBDDCDestroyFETIDPPC);CHKERRQ(ierr);
2160   ierr = PCSetOperators(newpc,newmat,newmat);CHKERRQ(ierr);
2161   ierr = PCSetUp(newpc);CHKERRQ(ierr);
2162   /* return pointers for objects created */
2163   *fetidp_mat=newmat;
2164   *fetidp_pc=newpc;
2165   PetscFunctionReturn(0);
2166 }
2167 
2168 #undef __FUNCT__
2169 #define __FUNCT__ "PCBDDCCreateFETIDPOperators"
2170 /*@
2171  PCBDDCCreateFETIDPOperators - Create FETI-DP operators
2172 
2173    Collective
2174 
2175    Input Parameters:
2176 .  pc - the BDDC preconditioning context (setup should have been called before)
2177 
2178    Output Parameters:
2179 +  fetidp_mat - shell FETI-DP matrix object
2180 -  fetidp_pc  - shell Dirichlet preconditioner for FETI-DP matrix
2181 
2182    Options Database Keys:
2183 .    -fetidp_fullyredundant <false> - use or not a fully redundant set of Lagrange multipliers
2184 
2185    Level: developer
2186 
2187    Notes:
2188      Currently the only operations provided for FETI-DP matrix are MatMult and MatMultTranspose
2189 
2190 .seealso: PCBDDC, PCBDDCMatFETIDPGetRHS, PCBDDCMatFETIDPGetSolution
2191 @*/
2192 PetscErrorCode PCBDDCCreateFETIDPOperators(PC pc, Mat *fetidp_mat, PC *fetidp_pc)
2193 {
2194   PetscErrorCode ierr;
2195 
2196   PetscFunctionBegin;
2197   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2198   if (pc->setupcalled) {
2199     ierr = PetscUseMethod(pc,"PCBDDCCreateFETIDPOperators_C",(PC,Mat*,PC*),(pc,fetidp_mat,fetidp_pc));CHKERRQ(ierr);
2200   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"You must call PCSetup_BDDC() first \n");
2201   PetscFunctionReturn(0);
2202 }
2203 /* -------------------------------------------------------------------------- */
2204 /*MC
2205    PCBDDC - Balancing Domain Decomposition by Constraints.
2206 
2207    An implementation of the BDDC preconditioner based on
2208 
2209 .vb
2210    [1] C. R. Dohrmann. "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149-168, March 2007
2211    [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
2212    [3] J. Mandel, B. Sousedik, C. R. Dohrmann. "Multispace and Multilevel BDDC", http://arxiv.org/abs/0712.3977
2213    [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
2214 .ve
2215 
2216    The matrix to be preconditioned (Pmat) must be of type MATIS.
2217 
2218    Currently works with MATIS matrices with local matrices of type MATSEQAIJ, MATSEQBAIJ or MATSEQSBAIJ, either with real or complex numbers.
2219 
2220    It also works with unsymmetric and indefinite problems.
2221 
2222    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.
2223 
2224    Approximate local solvers are automatically adapted for singular linear problems (see [1]) if the user has provided the nullspace using PCBDDCSetNullSpace()
2225 
2226    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()
2227    Additional information on dofs can be provided by using PCBDDCSetDofsSplitting(), PCBDDCSetDirichletBoundaries(), PCBDDCSetNeumannBoundaries(), and PCBDDCSetPrimalVerticesIS() and their local counterparts.
2228 
2229    Constraints can be customized by attaching a MatNullSpace object to the MATIS matrix via MatSetNearNullSpace(). Non-singular modes are retained via SVD.
2230 
2231    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.
2232    User defined change of basis can be passed to PCBDDC by using PCBDDCSetChangeOfBasisMat()
2233 
2234    The PETSc implementation also supports multilevel BDDC [3]. Coarse grids are partitioned using a MatPartitioning object.
2235 
2236    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.
2237 
2238    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.
2239    Deluxe scaling is not supported yet for FETI-DP.
2240 
2241    Options Database Keys (some of them, run with -h for a complete list):
2242 
2243 .    -pc_bddc_use_vertices <true> - use or not vertices in primal space
2244 .    -pc_bddc_use_edges <true> - use or not edges in primal space
2245 .    -pc_bddc_use_faces <false> - use or not faces in primal space
2246 .    -pc_bddc_symmetric <true> - symmetric computation of primal basis functions. Specify false for unsymmetric problems
2247 .    -pc_bddc_use_change_of_basis <false> - use change of basis approach (on edges only)
2248 .    -pc_bddc_use_change_on_faces <false> - use change of basis approach on faces if change of basis has been requested
2249 .    -pc_bddc_switch_static <false> - switches from M_2 (default) to M_3 operator (see reference article [1])
2250 .    -pc_bddc_levels <0> - maximum number of levels for multilevel
2251 .    -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)
2252 .    -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)
2253 .    -pc_bddc_use_deluxe_scaling <false> - use deluxe scaling
2254 .    -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)
2255 .    -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)
2256 -    -pc_bddc_check_level <0> - set verbosity level of debugging output
2257 
2258    Options for Dirichlet, Neumann or coarse solver can be set with
2259 .vb
2260       -pc_bddc_dirichlet_
2261       -pc_bddc_neumann_
2262       -pc_bddc_coarse_
2263 .ve
2264    e.g -pc_bddc_dirichlet_ksp_type richardson -pc_bddc_dirichlet_pc_type gamg. PCBDDC uses by default KPSPREONLY and PCLU.
2265 
2266    When using a multilevel approach, solvers' options at the N-th level (N > 1) can be specified as
2267 .vb
2268       -pc_bddc_dirichlet_lN_
2269       -pc_bddc_neumann_lN_
2270       -pc_bddc_coarse_lN_
2271 .ve
2272    Note that level number ranges from the finest (0) to the coarsest (N).
2273    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.
2274 .vb
2275      -pc_bddc_coarse_pc_bddc_adaptive_threshold 5 -pc_bddc_coarse_l1_pc_bddc_redistribute 3
2276 .ve
2277    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
2278 
2279    Level: intermediate
2280 
2281    Developer notes:
2282 
2283    Contributed by Stefano Zampini
2284 
2285 .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,  MATIS
2286 M*/
2287 
2288 #undef __FUNCT__
2289 #define __FUNCT__ "PCCreate_BDDC"
2290 PETSC_EXTERN PetscErrorCode PCCreate_BDDC(PC pc)
2291 {
2292   PetscErrorCode      ierr;
2293   PC_BDDC             *pcbddc;
2294 
2295   PetscFunctionBegin;
2296   /* Creates the private data structure for this preconditioner and attach it to the PC object. */
2297   ierr      = PetscNewLog(pc,&pcbddc);CHKERRQ(ierr);
2298   pc->data  = (void*)pcbddc;
2299 
2300   /* create PCIS data structure */
2301   ierr = PCISCreate(pc);CHKERRQ(ierr);
2302 
2303   /* BDDC customization */
2304   pcbddc->use_local_adj       = PETSC_TRUE;
2305   pcbddc->use_vertices        = PETSC_TRUE;
2306   pcbddc->use_edges           = PETSC_TRUE;
2307   pcbddc->use_faces           = PETSC_FALSE;
2308   pcbddc->use_change_of_basis = PETSC_FALSE;
2309   pcbddc->use_change_on_faces = PETSC_FALSE;
2310   pcbddc->switch_static       = PETSC_FALSE;
2311   pcbddc->use_nnsp_true       = PETSC_FALSE;
2312   pcbddc->use_qr_single       = PETSC_FALSE;
2313   pcbddc->symmetric_primal    = PETSC_TRUE;
2314   pcbddc->benign_saddle_point = PETSC_FALSE;
2315   pcbddc->vertex_size         = 1;
2316   pcbddc->dbg_flag            = 0;
2317   /* private */
2318   pcbddc->local_primal_size          = 0;
2319   pcbddc->local_primal_size_cc       = 0;
2320   pcbddc->local_primal_ref_node      = 0;
2321   pcbddc->local_primal_ref_mult      = 0;
2322   pcbddc->n_vertices                 = 0;
2323   pcbddc->primal_indices_local_idxs  = 0;
2324   pcbddc->recompute_topography       = PETSC_FALSE;
2325   pcbddc->coarse_size                = -1;
2326   pcbddc->new_primal_space           = PETSC_FALSE;
2327   pcbddc->new_primal_space_local     = PETSC_FALSE;
2328   pcbddc->global_primal_indices      = 0;
2329   pcbddc->onearnullspace             = 0;
2330   pcbddc->onearnullvecs_state        = 0;
2331   pcbddc->user_primal_vertices       = 0;
2332   pcbddc->user_primal_vertices_local = 0;
2333   pcbddc->NullSpace                  = 0;
2334   pcbddc->temp_solution              = 0;
2335   pcbddc->original_rhs               = 0;
2336   pcbddc->local_mat                  = 0;
2337   pcbddc->ChangeOfBasisMatrix        = 0;
2338   pcbddc->user_ChangeOfBasisMatrix   = 0;
2339   pcbddc->coarse_vec                 = 0;
2340   pcbddc->coarse_ksp                 = 0;
2341   pcbddc->coarse_phi_B               = 0;
2342   pcbddc->coarse_phi_D               = 0;
2343   pcbddc->coarse_psi_B               = 0;
2344   pcbddc->coarse_psi_D               = 0;
2345   pcbddc->vec1_P                     = 0;
2346   pcbddc->vec1_R                     = 0;
2347   pcbddc->vec2_R                     = 0;
2348   pcbddc->local_auxmat1              = 0;
2349   pcbddc->local_auxmat2              = 0;
2350   pcbddc->R_to_B                     = 0;
2351   pcbddc->R_to_D                     = 0;
2352   pcbddc->ksp_D                      = 0;
2353   pcbddc->ksp_R                      = 0;
2354   pcbddc->NeumannBoundaries          = 0;
2355   pcbddc->NeumannBoundariesLocal     = 0;
2356   pcbddc->DirichletBoundaries        = 0;
2357   pcbddc->DirichletBoundariesLocal   = 0;
2358   pcbddc->user_provided_isfordofs    = PETSC_FALSE;
2359   pcbddc->n_ISForDofs                = 0;
2360   pcbddc->n_ISForDofsLocal           = 0;
2361   pcbddc->ISForDofs                  = 0;
2362   pcbddc->ISForDofsLocal             = 0;
2363   pcbddc->ConstraintMatrix           = 0;
2364   pcbddc->use_exact_dirichlet_trick  = PETSC_TRUE;
2365   pcbddc->coarse_loc_to_glob         = 0;
2366   pcbddc->coarsening_ratio           = 8;
2367   pcbddc->coarse_adj_red             = 0;
2368   pcbddc->current_level              = 0;
2369   pcbddc->max_levels                 = 0;
2370   pcbddc->use_coarse_estimates       = PETSC_FALSE;
2371   pcbddc->redistribute_coarse        = 0;
2372   pcbddc->coarse_subassembling       = 0;
2373   pcbddc->coarse_subassembling_init  = 0;
2374   pcbddc->detect_disconnected        = PETSC_FALSE;
2375   pcbddc->n_local_subs               = 0;
2376   pcbddc->local_subs                 = NULL;
2377 
2378   /* benign subspace trick */
2379   pcbddc->benign_change              = 0;
2380   pcbddc->benign_vec                 = 0;
2381   pcbddc->benign_original_mat        = 0;
2382   pcbddc->benign_sf                  = 0;
2383   pcbddc->benign_B0                  = 0;
2384   pcbddc->benign_n                   = 0;
2385   pcbddc->benign_p0                  = NULL;
2386   pcbddc->benign_p0_lidx             = NULL;
2387   pcbddc->benign_p0_gidx             = NULL;
2388   pcbddc->benign_null                = PETSC_FALSE;
2389 
2390   /* create local graph structure */
2391   ierr = PCBDDCGraphCreate(&pcbddc->mat_graph);CHKERRQ(ierr);
2392 
2393   /* scaling */
2394   pcbddc->work_scaling          = 0;
2395   pcbddc->use_deluxe_scaling    = PETSC_FALSE;
2396   pcbddc->faster_deluxe         = PETSC_FALSE;
2397 
2398   /* create sub schurs structure */
2399   ierr = PCBDDCSubSchursCreate(&pcbddc->sub_schurs);CHKERRQ(ierr);
2400   pcbddc->sub_schurs_rebuild     = PETSC_FALSE;
2401   pcbddc->sub_schurs_layers      = -1;
2402   pcbddc->sub_schurs_use_useradj = PETSC_FALSE;
2403 
2404   pcbddc->computed_rowadj = PETSC_FALSE;
2405 
2406   /* adaptivity */
2407   pcbddc->adaptive_threshold      = 0.0;
2408   pcbddc->adaptive_nmax           = 0;
2409   pcbddc->adaptive_nmin           = 0;
2410 
2411   /* function pointers */
2412   pc->ops->apply               = PCApply_BDDC;
2413   pc->ops->applytranspose      = PCApplyTranspose_BDDC;
2414   pc->ops->setup               = PCSetUp_BDDC;
2415   pc->ops->destroy             = PCDestroy_BDDC;
2416   pc->ops->setfromoptions      = PCSetFromOptions_BDDC;
2417   pc->ops->view                = PCView_BDDC;
2418   pc->ops->applyrichardson     = 0;
2419   pc->ops->applysymmetricleft  = 0;
2420   pc->ops->applysymmetricright = 0;
2421   pc->ops->presolve            = PCPreSolve_BDDC;
2422   pc->ops->postsolve           = PCPostSolve_BDDC;
2423 
2424   /* composing function */
2425   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",PCBDDCSetChangeOfBasisMat_BDDC);CHKERRQ(ierr);
2426   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",PCBDDCSetPrimalVerticesLocalIS_BDDC);CHKERRQ(ierr);
2427   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesIS_C",PCBDDCSetPrimalVerticesIS_BDDC);CHKERRQ(ierr);
2428   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",PCBDDCSetCoarseningRatio_BDDC);CHKERRQ(ierr);
2429   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",PCBDDCSetLevel_BDDC);CHKERRQ(ierr);
2430   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",PCBDDCSetUseExactDirichlet_BDDC);CHKERRQ(ierr);
2431   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",PCBDDCSetLevels_BDDC);CHKERRQ(ierr);
2432   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNullSpace_C",PCBDDCSetNullSpace_BDDC);CHKERRQ(ierr);
2433   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",PCBDDCSetDirichletBoundaries_BDDC);CHKERRQ(ierr);
2434   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",PCBDDCSetDirichletBoundariesLocal_BDDC);CHKERRQ(ierr);
2435   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",PCBDDCSetNeumannBoundaries_BDDC);CHKERRQ(ierr);
2436   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",PCBDDCSetNeumannBoundariesLocal_BDDC);CHKERRQ(ierr);
2437   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",PCBDDCGetDirichletBoundaries_BDDC);CHKERRQ(ierr);
2438   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",PCBDDCGetDirichletBoundariesLocal_BDDC);CHKERRQ(ierr);
2439   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",PCBDDCGetNeumannBoundaries_BDDC);CHKERRQ(ierr);
2440   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",PCBDDCGetNeumannBoundariesLocal_BDDC);CHKERRQ(ierr);
2441   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",PCBDDCSetDofsSplitting_BDDC);CHKERRQ(ierr);
2442   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",PCBDDCSetDofsSplittingLocal_BDDC);CHKERRQ(ierr);
2443   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",PCBDDCSetLocalAdjacencyGraph_BDDC);CHKERRQ(ierr);
2444   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",PCBDDCCreateFETIDPOperators_BDDC);CHKERRQ(ierr);
2445   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",PCBDDCMatFETIDPGetRHS_BDDC);CHKERRQ(ierr);
2446   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",PCBDDCMatFETIDPGetSolution_BDDC);CHKERRQ(ierr);
2447   PetscFunctionReturn(0);
2448 }
2449 
2450