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