xref: /petsc/src/ksp/pc/impls/bddc/bddc.c (revision b59f628eff0cd0541d0457de20841eec6c6bc428)
1 /* TODOLIST
2 
3    ConstraintsSetup
4    - tolerances for constraints as an option (take care of single precision!)
5 
6    Solvers
7    - Add support for cholesky for coarse solver (similar to local solvers)
8    - Propagate ksp prefixes for solvers to mat objects?
9    - Propagate nearnullspace info among levels
10 
11    User interface
12    - ** DofSplitting and DM attached to pc?
13 
14    Debugging output
15    - * Better management of verbosity levels of debugging output
16 
17    Build
18    - make runexe59
19 
20    Extra
21    - ** GetRid of PCBDDCApplySchur, use MatSchur instead
22    - *** Is it possible to work with PCBDDCGraph on boundary indices only (less memory consumed)?
23    - add support for computing h,H and related using coordinates?
24    - Change of basis approach does not work with my nonlinear mechanics example. why? (seems not an issue with l2gmap)
25    - Better management in PCIS code
26    - BDDC with MG framework?
27 
28    FETIDP
29    - Move FETIDP code to its own classes
30 
31    MATIS related operations contained in BDDC code
32    - Provide general case for subassembling
33    - *** Preallocation routines in MatISGetMPIAXAIJ
34 
35 */
36 
37 /* ----------------------------------------------------------------------------------------------------------------------------------------------
38    Implementation of BDDC preconditioner based on:
39    C. Dohrmann "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149-168, March 2007
40    ---------------------------------------------------------------------------------------------------------------------------------------------- */
41 
42 #include <../src/ksp/pc/impls/bddc/bddc.h> /*I "petscpc.h" I*/  /* includes for fortran wrappers */
43 #include <../src/ksp/pc/impls/bddc/bddcprivate.h>
44 #include <petscblaslapack.h>
45 
46 /* -------------------------------------------------------------------------- */
47 #undef __FUNCT__
48 #define __FUNCT__ "PCSetFromOptions_BDDC"
49 PetscErrorCode PCSetFromOptions_BDDC(PC pc)
50 {
51   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
52   PetscErrorCode ierr;
53 
54   PetscFunctionBegin;
55   ierr = PetscOptionsHead("BDDC options");CHKERRQ(ierr);
56   /* Verbose debugging */
57   ierr = PetscOptionsInt("-pc_bddc_check_level","Verbose output for PCBDDC (intended for debug)","none",pcbddc->dbg_flag,&pcbddc->dbg_flag,NULL);CHKERRQ(ierr);
58   /* Primal space cumstomization */
59   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);
60   ierr = PetscOptionsBool("-pc_bddc_use_vertices","Use or not corner dofs in coarse space","none",pcbddc->use_vertices,&pcbddc->use_vertices,NULL);CHKERRQ(ierr);
61   ierr = PetscOptionsBool("-pc_bddc_use_edges","Use or not edge constraints in coarse space","none",pcbddc->use_edges,&pcbddc->use_edges,NULL);CHKERRQ(ierr);
62   ierr = PetscOptionsBool("-pc_bddc_use_faces","Use or not face constraints in coarse space","none",pcbddc->use_faces,&pcbddc->use_faces,NULL);CHKERRQ(ierr);
63   /* Change of basis */
64   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);
65   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);
66   if (!pcbddc->use_change_of_basis) {
67     pcbddc->use_change_on_faces = PETSC_FALSE;
68   }
69   /* Switch between M_2 (default) and M_3 preconditioners (as defined by C. Dohrmann in the ref. article) */
70   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);
71   ierr = PetscOptionsInt("-pc_bddc_coarsening_ratio","Set coarsening ratio used in multilevel coarsening","none",pcbddc->coarsening_ratio,&pcbddc->coarsening_ratio,NULL);CHKERRQ(ierr);
72   ierr = PetscOptionsInt("-pc_bddc_levels","Set maximum number of levels for multilevel","none",pcbddc->max_levels,&pcbddc->max_levels,NULL);CHKERRQ(ierr);
73   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);
74   ierr = PetscOptionsBool("-pc_bddc_use_deluxe_scaling","Use deluxe scaling for BDDC","none",pcbddc->use_deluxe_scaling,&pcbddc->use_deluxe_scaling,NULL);CHKERRQ(ierr);
75   ierr = PetscOptionsInt("-pc_bddc_deluxe_threshold","Deluxe subproblems (Schur principal minors) smaller than this value are explicilty computed (-1 computes all)","none",pcbddc->deluxe_threshold,&pcbddc->deluxe_threshold,NULL);CHKERRQ(ierr);
76   ierr = PetscOptionsBool("-pc_bddc_deluxe_rebuild","Whether or not the interface graph for deluxe has to be rebuilt (i.e. use a standard definition of the interface)","none",pcbddc->deluxe_rebuild,&pcbddc->deluxe_rebuild,NULL);CHKERRQ(ierr);
77   ierr = PetscOptionsInt("-pc_bddc_deluxe_layers","Number of dofs' layers for the application of deluxe cheap version (i.e. -1 uses all dofs)","none",pcbddc->deluxe_layers,&pcbddc->deluxe_layers,NULL);CHKERRQ(ierr);
78   ierr = PetscOptionsBool("-pc_bddc_deluxe_use_useradj","Whether or not the CSR graph specified by the user should be used for computing layers (default is to use adj of local mat)","none",pcbddc->deluxe_use_useradj,&pcbddc->deluxe_use_useradj,NULL);CHKERRQ(ierr);
79   ierr = PetscOptionsTail();CHKERRQ(ierr);
80   PetscFunctionReturn(0);
81 }
82 /* -------------------------------------------------------------------------- */
83 #undef __FUNCT__
84 #define __FUNCT__ "PCBDDCSetChangeOfBasisMat_BDDC"
85 static PetscErrorCode PCBDDCSetChangeOfBasisMat_BDDC(PC pc, Mat change)
86 {
87   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
88   PetscErrorCode ierr;
89 
90   PetscFunctionBegin;
91   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
92   ierr = PetscObjectReference((PetscObject)change);CHKERRQ(ierr);
93   pcbddc->user_ChangeOfBasisMatrix = change;
94   PetscFunctionReturn(0);
95 }
96 #undef __FUNCT__
97 #define __FUNCT__ "PCBDDCSetChangeOfBasisMat"
98 /*@
99  PCBDDCSetChangeOfBasisMat - Set user defined change of basis for dofs
100 
101    Collective on PC
102 
103    Input Parameters:
104 +  pc - the preconditioning context
105 -  change - the change of basis matrix
106 
107    Level: intermediate
108 
109    Notes:
110 
111 .seealso: PCBDDC
112 @*/
113 PetscErrorCode PCBDDCSetChangeOfBasisMat(PC pc, Mat change)
114 {
115   PetscErrorCode ierr;
116 
117   PetscFunctionBegin;
118   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
119   PetscValidHeaderSpecific(change,MAT_CLASSID,2);
120   PetscCheckSameComm(pc,1,change,2);
121   if (pc->mat) {
122     PetscInt rows_c,cols_c,rows,cols;
123     ierr = MatGetSize(pc->mat,&rows,&cols);CHKERRQ(ierr);
124     ierr = MatGetSize(change,&rows_c,&cols_c);CHKERRQ(ierr);
125     if (rows_c != rows) {
126       SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of rows for change of basis matrix! %d != %d",rows_c,rows);
127     }
128     if (cols_c != cols) {
129       SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of columns for change of basis matrix! %d != %d",cols_c,cols);
130     }
131     ierr = MatGetLocalSize(pc->mat,&rows,&cols);CHKERRQ(ierr);
132     ierr = MatGetLocalSize(change,&rows_c,&cols_c);CHKERRQ(ierr);
133     if (rows_c != rows) {
134       SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of local rows for change of basis matrix! %d != %d",rows_c,rows);
135     }
136     if (cols_c != cols) {
137       SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of local columns for change of basis matrix! %d != %d",cols_c,cols);
138     }
139   }
140   ierr = PetscTryMethod(pc,"PCBDDCSetChangeOfBasisMat_C",(PC,Mat),(pc,change));CHKERRQ(ierr);
141   PetscFunctionReturn(0);
142 }
143 /* -------------------------------------------------------------------------- */
144 #undef __FUNCT__
145 #define __FUNCT__ "PCBDDCSetPrimalVerticesLocalIS_BDDC"
146 static PetscErrorCode PCBDDCSetPrimalVerticesLocalIS_BDDC(PC pc, IS PrimalVertices)
147 {
148   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
149   PetscErrorCode ierr;
150 
151   PetscFunctionBegin;
152   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
153   ierr = PetscObjectReference((PetscObject)PrimalVertices);CHKERRQ(ierr);
154   pcbddc->user_primal_vertices = PrimalVertices;
155   PetscFunctionReturn(0);
156 }
157 #undef __FUNCT__
158 #define __FUNCT__ "PCBDDCSetPrimalVerticesLocalIS"
159 /*@
160  PCBDDCSetPrimalVerticesLocalIS - Set additional user defined primal vertices in PCBDDC
161 
162    Not collective
163 
164    Input Parameters:
165 +  pc - the preconditioning context
166 -  PrimalVertices - index set of primal vertices in local numbering
167 
168    Level: intermediate
169 
170    Notes:
171 
172 .seealso: PCBDDC
173 @*/
174 PetscErrorCode PCBDDCSetPrimalVerticesLocalIS(PC pc, IS PrimalVertices)
175 {
176   PetscErrorCode ierr;
177 
178   PetscFunctionBegin;
179   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
180   PetscValidHeaderSpecific(PrimalVertices,IS_CLASSID,2);
181   ierr = PetscTryMethod(pc,"PCBDDCSetPrimalVerticesLocalIS_C",(PC,IS),(pc,PrimalVertices));CHKERRQ(ierr);
182   PetscFunctionReturn(0);
183 }
184 /* -------------------------------------------------------------------------- */
185 #undef __FUNCT__
186 #define __FUNCT__ "PCBDDCSetCoarseningRatio_BDDC"
187 static PetscErrorCode PCBDDCSetCoarseningRatio_BDDC(PC pc,PetscInt k)
188 {
189   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
190 
191   PetscFunctionBegin;
192   pcbddc->coarsening_ratio = k;
193   PetscFunctionReturn(0);
194 }
195 
196 #undef __FUNCT__
197 #define __FUNCT__ "PCBDDCSetCoarseningRatio"
198 /*@
199  PCBDDCSetCoarseningRatio - Set coarsening ratio used in multilevel
200 
201    Logically collective on PC
202 
203    Input Parameters:
204 +  pc - the preconditioning context
205 -  k - coarsening ratio (H/h at the coarser level)
206 
207    Approximatively k subdomains at the finer level will be aggregated into a single subdomain at the coarser level
208 
209    Level: intermediate
210 
211    Notes:
212 
213 .seealso: PCBDDC
214 @*/
215 PetscErrorCode PCBDDCSetCoarseningRatio(PC pc,PetscInt k)
216 {
217   PetscErrorCode ierr;
218 
219   PetscFunctionBegin;
220   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
221   PetscValidLogicalCollectiveInt(pc,k,2);
222   ierr = PetscTryMethod(pc,"PCBDDCSetCoarseningRatio_C",(PC,PetscInt),(pc,k));CHKERRQ(ierr);
223   PetscFunctionReturn(0);
224 }
225 
226 /* The following functions (PCBDDCSetUseExactDirichlet PCBDDCSetLevel) are not public */
227 #undef __FUNCT__
228 #define __FUNCT__ "PCBDDCSetUseExactDirichlet_BDDC"
229 static PetscErrorCode PCBDDCSetUseExactDirichlet_BDDC(PC pc,PetscBool flg)
230 {
231   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
232 
233   PetscFunctionBegin;
234   pcbddc->use_exact_dirichlet_trick = flg;
235   PetscFunctionReturn(0);
236 }
237 
238 #undef __FUNCT__
239 #define __FUNCT__ "PCBDDCSetUseExactDirichlet"
240 PetscErrorCode PCBDDCSetUseExactDirichlet(PC pc,PetscBool flg)
241 {
242   PetscErrorCode ierr;
243 
244   PetscFunctionBegin;
245   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
246   PetscValidLogicalCollectiveBool(pc,flg,2);
247   ierr = PetscTryMethod(pc,"PCBDDCSetUseExactDirichlet_C",(PC,PetscBool),(pc,flg));CHKERRQ(ierr);
248   PetscFunctionReturn(0);
249 }
250 
251 #undef __FUNCT__
252 #define __FUNCT__ "PCBDDCSetLevel_BDDC"
253 static PetscErrorCode PCBDDCSetLevel_BDDC(PC pc,PetscInt level)
254 {
255   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
256 
257   PetscFunctionBegin;
258   pcbddc->current_level = level;
259   PetscFunctionReturn(0);
260 }
261 
262 #undef __FUNCT__
263 #define __FUNCT__ "PCBDDCSetLevel"
264 PetscErrorCode PCBDDCSetLevel(PC pc,PetscInt level)
265 {
266   PetscErrorCode ierr;
267 
268   PetscFunctionBegin;
269   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
270   PetscValidLogicalCollectiveInt(pc,level,2);
271   ierr = PetscTryMethod(pc,"PCBDDCSetLevel_C",(PC,PetscInt),(pc,level));CHKERRQ(ierr);
272   PetscFunctionReturn(0);
273 }
274 
275 #undef __FUNCT__
276 #define __FUNCT__ "PCBDDCSetLevels_BDDC"
277 static PetscErrorCode PCBDDCSetLevels_BDDC(PC pc,PetscInt levels)
278 {
279   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
280 
281   PetscFunctionBegin;
282   pcbddc->max_levels = levels;
283   PetscFunctionReturn(0);
284 }
285 
286 #undef __FUNCT__
287 #define __FUNCT__ "PCBDDCSetLevels"
288 /*@
289  PCBDDCSetLevels - Sets the maximum number of levels for multilevel
290 
291    Logically collective on PC
292 
293    Input Parameters:
294 +  pc - the preconditioning context
295 -  levels - the maximum number of levels (max 9)
296 
297    Default value is 0, i.e. traditional one-level BDDC
298 
299    Level: intermediate
300 
301    Notes:
302 
303 .seealso: PCBDDC
304 @*/
305 PetscErrorCode PCBDDCSetLevels(PC pc,PetscInt levels)
306 {
307   PetscErrorCode ierr;
308 
309   PetscFunctionBegin;
310   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
311   PetscValidLogicalCollectiveInt(pc,levels,2);
312   if (levels > 99) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Maximum number of levels for bddc is 99\n");
313   ierr = PetscTryMethod(pc,"PCBDDCSetLevels_C",(PC,PetscInt),(pc,levels));CHKERRQ(ierr);
314   PetscFunctionReturn(0);
315 }
316 /* -------------------------------------------------------------------------- */
317 
318 #undef __FUNCT__
319 #define __FUNCT__ "PCBDDCSetNullSpace_BDDC"
320 static PetscErrorCode PCBDDCSetNullSpace_BDDC(PC pc,MatNullSpace NullSpace)
321 {
322   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
323   PetscErrorCode ierr;
324 
325   PetscFunctionBegin;
326   ierr = PetscObjectReference((PetscObject)NullSpace);CHKERRQ(ierr);
327   ierr = MatNullSpaceDestroy(&pcbddc->NullSpace);CHKERRQ(ierr);
328   pcbddc->NullSpace = NullSpace;
329   PetscFunctionReturn(0);
330 }
331 
332 #undef __FUNCT__
333 #define __FUNCT__ "PCBDDCSetNullSpace"
334 /*@
335  PCBDDCSetNullSpace - Set nullspace for BDDC operator
336 
337    Logically collective on PC and MatNullSpace
338 
339    Input Parameters:
340 +  pc - the preconditioning context
341 -  NullSpace - Null space of the linear operator to be preconditioned (Pmat)
342 
343    Level: intermediate
344 
345    Notes:
346 
347 .seealso: PCBDDC
348 @*/
349 PetscErrorCode PCBDDCSetNullSpace(PC pc,MatNullSpace NullSpace)
350 {
351   PetscErrorCode ierr;
352 
353   PetscFunctionBegin;
354   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
355   PetscValidHeaderSpecific(NullSpace,MAT_NULLSPACE_CLASSID,2);
356   PetscCheckSameComm(pc,1,NullSpace,2);
357   ierr = PetscTryMethod(pc,"PCBDDCSetNullSpace_C",(PC,MatNullSpace),(pc,NullSpace));CHKERRQ(ierr);
358   PetscFunctionReturn(0);
359 }
360 /* -------------------------------------------------------------------------- */
361 
362 #undef __FUNCT__
363 #define __FUNCT__ "PCBDDCSetDirichletBoundaries_BDDC"
364 static PetscErrorCode PCBDDCSetDirichletBoundaries_BDDC(PC pc,IS DirichletBoundaries)
365 {
366   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
367   PetscErrorCode ierr;
368 
369   PetscFunctionBegin;
370   /* last user setting takes precendence -> destroy any other customization */
371   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
372   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
373   ierr = PetscObjectReference((PetscObject)DirichletBoundaries);CHKERRQ(ierr);
374   pcbddc->DirichletBoundaries = DirichletBoundaries;
375   pcbddc->recompute_topography = PETSC_TRUE;
376   PetscFunctionReturn(0);
377 }
378 
379 #undef __FUNCT__
380 #define __FUNCT__ "PCBDDCSetDirichletBoundaries"
381 /*@
382  PCBDDCSetDirichletBoundaries - Set IS defining Dirichlet boundaries for the global problem.
383 
384    Collective
385 
386    Input Parameters:
387 +  pc - the preconditioning context
388 -  DirichletBoundaries - parallel IS defining the Dirichlet boundaries
389 
390    Level: intermediate
391 
392    Notes: Any process can list any global node
393 
394 .seealso: PCBDDC
395 @*/
396 PetscErrorCode PCBDDCSetDirichletBoundaries(PC pc,IS DirichletBoundaries)
397 {
398   PetscErrorCode ierr;
399 
400   PetscFunctionBegin;
401   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
402   PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2);
403   PetscCheckSameComm(pc,1,DirichletBoundaries,2);
404   ierr = PetscTryMethod(pc,"PCBDDCSetDirichletBoundaries_C",(PC,IS),(pc,DirichletBoundaries));CHKERRQ(ierr);
405   PetscFunctionReturn(0);
406 }
407 /* -------------------------------------------------------------------------- */
408 
409 #undef __FUNCT__
410 #define __FUNCT__ "PCBDDCSetDirichletBoundariesLocal_BDDC"
411 static PetscErrorCode PCBDDCSetDirichletBoundariesLocal_BDDC(PC pc,IS DirichletBoundaries)
412 {
413   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
414   PetscErrorCode ierr;
415 
416   PetscFunctionBegin;
417   /* last user setting takes precendence -> destroy any other customization */
418   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
419   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
420   ierr = PetscObjectReference((PetscObject)DirichletBoundaries);CHKERRQ(ierr);
421   pcbddc->DirichletBoundariesLocal = DirichletBoundaries;
422   pcbddc->recompute_topography = PETSC_TRUE;
423   PetscFunctionReturn(0);
424 }
425 
426 #undef __FUNCT__
427 #define __FUNCT__ "PCBDDCSetDirichletBoundariesLocal"
428 /*@
429  PCBDDCSetDirichletBoundariesLocal - Set IS defining Dirichlet boundaries for the global problem in local ordering.
430 
431    Collective
432 
433    Input Parameters:
434 +  pc - the preconditioning context
435 -  DirichletBoundaries - parallel IS defining the Dirichlet boundaries (in local ordering)
436 
437    Level: intermediate
438 
439    Notes:
440 
441 .seealso: PCBDDC
442 @*/
443 PetscErrorCode PCBDDCSetDirichletBoundariesLocal(PC pc,IS DirichletBoundaries)
444 {
445   PetscErrorCode ierr;
446 
447   PetscFunctionBegin;
448   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
449   PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2);
450   PetscCheckSameComm(pc,1,DirichletBoundaries,2);
451   ierr = PetscTryMethod(pc,"PCBDDCSetDirichletBoundariesLocal_C",(PC,IS),(pc,DirichletBoundaries));CHKERRQ(ierr);
452   PetscFunctionReturn(0);
453 }
454 /* -------------------------------------------------------------------------- */
455 
456 #undef __FUNCT__
457 #define __FUNCT__ "PCBDDCSetNeumannBoundaries_BDDC"
458 static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc,IS NeumannBoundaries)
459 {
460   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
461   PetscErrorCode ierr;
462 
463   PetscFunctionBegin;
464   /* last user setting takes precendence -> destroy any other customization */
465   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
466   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
467   ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr);
468   pcbddc->NeumannBoundaries = NeumannBoundaries;
469   pcbddc->recompute_topography = PETSC_TRUE;
470   PetscFunctionReturn(0);
471 }
472 
473 #undef __FUNCT__
474 #define __FUNCT__ "PCBDDCSetNeumannBoundaries"
475 /*@
476  PCBDDCSetNeumannBoundaries - Set IS defining Neumann boundaries for the global problem.
477 
478    Collective
479 
480    Input Parameters:
481 +  pc - the preconditioning context
482 -  NeumannBoundaries - parallel IS defining the Neumann boundaries
483 
484    Level: intermediate
485 
486    Notes: Any process can list any global node
487 
488 .seealso: PCBDDC
489 @*/
490 PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc,IS NeumannBoundaries)
491 {
492   PetscErrorCode ierr;
493 
494   PetscFunctionBegin;
495   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
496   PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2);
497   PetscCheckSameComm(pc,1,NeumannBoundaries,2);
498   ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundaries_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr);
499   PetscFunctionReturn(0);
500 }
501 /* -------------------------------------------------------------------------- */
502 
503 #undef __FUNCT__
504 #define __FUNCT__ "PCBDDCSetNeumannBoundariesLocal_BDDC"
505 static PetscErrorCode PCBDDCSetNeumannBoundariesLocal_BDDC(PC pc,IS NeumannBoundaries)
506 {
507   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
508   PetscErrorCode ierr;
509 
510   PetscFunctionBegin;
511   /* last user setting takes precendence -> destroy any other customization */
512   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
513   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
514   ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr);
515   pcbddc->NeumannBoundariesLocal = NeumannBoundaries;
516   pcbddc->recompute_topography = PETSC_TRUE;
517   PetscFunctionReturn(0);
518 }
519 
520 #undef __FUNCT__
521 #define __FUNCT__ "PCBDDCSetNeumannBoundariesLocal"
522 /*@
523  PCBDDCSetNeumannBoundariesLocal - Set IS defining Neumann boundaries for the global problem in local ordering.
524 
525    Collective
526 
527    Input Parameters:
528 +  pc - the preconditioning context
529 -  NeumannBoundaries - parallel IS defining the subdomain part of Neumann boundaries (in local ordering)
530 
531    Level: intermediate
532 
533    Notes:
534 
535 .seealso: PCBDDC
536 @*/
537 PetscErrorCode PCBDDCSetNeumannBoundariesLocal(PC pc,IS NeumannBoundaries)
538 {
539   PetscErrorCode ierr;
540 
541   PetscFunctionBegin;
542   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
543   PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2);
544   PetscCheckSameComm(pc,1,NeumannBoundaries,2);
545   ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundariesLocal_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr);
546   PetscFunctionReturn(0);
547 }
548 /* -------------------------------------------------------------------------- */
549 
550 #undef __FUNCT__
551 #define __FUNCT__ "PCBDDCGetDirichletBoundaries_BDDC"
552 static PetscErrorCode PCBDDCGetDirichletBoundaries_BDDC(PC pc,IS *DirichletBoundaries)
553 {
554   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
555 
556   PetscFunctionBegin;
557   *DirichletBoundaries = pcbddc->DirichletBoundaries;
558   PetscFunctionReturn(0);
559 }
560 
561 #undef __FUNCT__
562 #define __FUNCT__ "PCBDDCGetDirichletBoundaries"
563 /*@
564  PCBDDCGetDirichletBoundaries - Get parallel IS for Dirichlet boundaries
565 
566    Collective
567 
568    Input Parameters:
569 .  pc - the preconditioning context
570 
571    Output Parameters:
572 .  DirichletBoundaries - index set defining the Dirichlet boundaries
573 
574    Level: intermediate
575 
576    Notes: The IS returned (if any) is the same passed in earlier by the user with PCBDDCSetDirichletBoundaries
577 
578 .seealso: PCBDDC
579 @*/
580 PetscErrorCode PCBDDCGetDirichletBoundaries(PC pc,IS *DirichletBoundaries)
581 {
582   PetscErrorCode ierr;
583 
584   PetscFunctionBegin;
585   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
586   ierr = PetscUseMethod(pc,"PCBDDCGetDirichletBoundaries_C",(PC,IS*),(pc,DirichletBoundaries));CHKERRQ(ierr);
587   PetscFunctionReturn(0);
588 }
589 /* -------------------------------------------------------------------------- */
590 
591 #undef __FUNCT__
592 #define __FUNCT__ "PCBDDCGetDirichletBoundariesLocal_BDDC"
593 static PetscErrorCode PCBDDCGetDirichletBoundariesLocal_BDDC(PC pc,IS *DirichletBoundaries)
594 {
595   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
596 
597   PetscFunctionBegin;
598   *DirichletBoundaries = pcbddc->DirichletBoundariesLocal;
599   PetscFunctionReturn(0);
600 }
601 
602 #undef __FUNCT__
603 #define __FUNCT__ "PCBDDCGetDirichletBoundariesLocal"
604 /*@
605  PCBDDCGetDirichletBoundariesLocal - Get parallel IS for Dirichlet boundaries (in local ordering)
606 
607    Collective
608 
609    Input Parameters:
610 .  pc - the preconditioning context
611 
612    Output Parameters:
613 .  DirichletBoundaries - index set defining the subdomain part of Dirichlet boundaries
614 
615    Level: intermediate
616 
617    Notes:
618 
619 .seealso: PCBDDC
620 @*/
621 PetscErrorCode PCBDDCGetDirichletBoundariesLocal(PC pc,IS *DirichletBoundaries)
622 {
623   PetscErrorCode ierr;
624 
625   PetscFunctionBegin;
626   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
627   ierr = PetscUseMethod(pc,"PCBDDCGetDirichletBoundariesLocal_C",(PC,IS*),(pc,DirichletBoundaries));CHKERRQ(ierr);
628   PetscFunctionReturn(0);
629 }
630 /* -------------------------------------------------------------------------- */
631 
632 #undef __FUNCT__
633 #define __FUNCT__ "PCBDDCGetNeumannBoundaries_BDDC"
634 static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc,IS *NeumannBoundaries)
635 {
636   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
637 
638   PetscFunctionBegin;
639   *NeumannBoundaries = pcbddc->NeumannBoundaries;
640   PetscFunctionReturn(0);
641 }
642 
643 #undef __FUNCT__
644 #define __FUNCT__ "PCBDDCGetNeumannBoundaries"
645 /*@
646  PCBDDCGetNeumannBoundaries - Get parallel IS for Neumann boundaries
647 
648    Collective
649 
650    Input Parameters:
651 .  pc - the preconditioning context
652 
653    Output Parameters:
654 .  NeumannBoundaries - index set defining the Neumann boundaries
655 
656    Level: intermediate
657 
658    Notes: The IS returned (if any) is the same passed in earlier by the user with PCBDDCSetNeumannBoundaries
659 
660 .seealso: PCBDDC
661 @*/
662 PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc,IS *NeumannBoundaries)
663 {
664   PetscErrorCode ierr;
665 
666   PetscFunctionBegin;
667   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
668   ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundaries_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr);
669   PetscFunctionReturn(0);
670 }
671 /* -------------------------------------------------------------------------- */
672 
673 #undef __FUNCT__
674 #define __FUNCT__ "PCBDDCGetNeumannBoundariesLocal_BDDC"
675 static PetscErrorCode PCBDDCGetNeumannBoundariesLocal_BDDC(PC pc,IS *NeumannBoundaries)
676 {
677   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
678 
679   PetscFunctionBegin;
680   *NeumannBoundaries = pcbddc->NeumannBoundariesLocal;
681   PetscFunctionReturn(0);
682 }
683 
684 #undef __FUNCT__
685 #define __FUNCT__ "PCBDDCGetNeumannBoundariesLocal"
686 /*@
687  PCBDDCGetNeumannBoundariesLocal - Get parallel IS for Neumann boundaries (in local ordering)
688 
689    Collective
690 
691    Input Parameters:
692 .  pc - the preconditioning context
693 
694    Output Parameters:
695 .  NeumannBoundaries - index set defining the subdomain part of Neumann boundaries
696 
697    Level: intermediate
698 
699    Notes:
700 
701 .seealso: PCBDDC
702 @*/
703 PetscErrorCode PCBDDCGetNeumannBoundariesLocal(PC pc,IS *NeumannBoundaries)
704 {
705   PetscErrorCode ierr;
706 
707   PetscFunctionBegin;
708   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
709   ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundariesLocal_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr);
710   PetscFunctionReturn(0);
711 }
712 /* -------------------------------------------------------------------------- */
713 
714 #undef __FUNCT__
715 #define __FUNCT__ "PCBDDCSetLocalAdjacencyGraph_BDDC"
716 static PetscErrorCode PCBDDCSetLocalAdjacencyGraph_BDDC(PC pc, PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode)
717 {
718   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
719   PCBDDCGraph    mat_graph = pcbddc->mat_graph;
720   PetscErrorCode ierr;
721 
722   PetscFunctionBegin;
723   /* free old CSR */
724   ierr = PCBDDCGraphResetCSR(mat_graph);CHKERRQ(ierr);
725   /* TODO: PCBDDCGraphSetAdjacency */
726   /* get CSR into graph structure */
727   if (copymode == PETSC_COPY_VALUES) {
728     ierr = PetscMalloc1((nvtxs+1),&mat_graph->xadj);CHKERRQ(ierr);
729     ierr = PetscMalloc1(xadj[nvtxs],&mat_graph->adjncy);CHKERRQ(ierr);
730     ierr = PetscMemcpy(mat_graph->xadj,xadj,(nvtxs+1)*sizeof(PetscInt));CHKERRQ(ierr);
731     ierr = PetscMemcpy(mat_graph->adjncy,adjncy,xadj[nvtxs]*sizeof(PetscInt));CHKERRQ(ierr);
732   } else if (copymode == PETSC_OWN_POINTER) {
733     mat_graph->xadj = (PetscInt*)xadj;
734     mat_graph->adjncy = (PetscInt*)adjncy;
735   }
736   mat_graph->nvtxs_csr = nvtxs;
737   PetscFunctionReturn(0);
738 }
739 
740 #undef __FUNCT__
741 #define __FUNCT__ "PCBDDCSetLocalAdjacencyGraph"
742 /*@
743  PCBDDCSetLocalAdjacencyGraph - Set adjacency structure (CSR graph) of the local Neumann matrix
744 
745    Not collective
746 
747    Input Parameters:
748 +  pc - the preconditioning context
749 .  nvtxs - number of local vertices of the graph (i.e., the local size of your problem)
750 .  xadj, adjncy - the CSR graph
751 -  copymode - either PETSC_COPY_VALUES or PETSC_OWN_POINTER.
752 
753    Level: intermediate
754 
755    Notes:
756 
757 .seealso: PCBDDC,PetscCopyMode
758 @*/
759 PetscErrorCode PCBDDCSetLocalAdjacencyGraph(PC pc,PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode)
760 {
761   void (*f)(void) = 0;
762   PetscErrorCode ierr;
763 
764   PetscFunctionBegin;
765   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
766   PetscValidIntPointer(xadj,3);
767   PetscValidIntPointer(adjncy,4);
768   if (copymode != PETSC_COPY_VALUES && copymode != PETSC_OWN_POINTER) {
769     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported copy mode %d in %s\n",copymode,__FUNCT__);
770   }
771   ierr = PetscTryMethod(pc,"PCBDDCSetLocalAdjacencyGraph_C",(PC,PetscInt,const PetscInt[],const PetscInt[],PetscCopyMode),(pc,nvtxs,xadj,adjncy,copymode));CHKERRQ(ierr);
772   /* free arrays if PCBDDC is not the PC type */
773   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",&f);CHKERRQ(ierr);
774   if (!f && copymode == PETSC_OWN_POINTER) {
775     ierr = PetscFree(xadj);CHKERRQ(ierr);
776     ierr = PetscFree(adjncy);CHKERRQ(ierr);
777   }
778   PetscFunctionReturn(0);
779 }
780 /* -------------------------------------------------------------------------- */
781 
782 #undef __FUNCT__
783 #define __FUNCT__ "PCBDDCSetDofsSplittingLocal_BDDC"
784 static PetscErrorCode PCBDDCSetDofsSplittingLocal_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
785 {
786   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
787   PetscInt i;
788   PetscErrorCode ierr;
789 
790   PetscFunctionBegin;
791   /* Destroy ISes if they were already set */
792   for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
793     ierr = ISDestroy(&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
794   }
795   ierr = PetscFree(pcbddc->ISForDofsLocal);CHKERRQ(ierr);
796   /* last user setting takes precendence -> destroy any other customization */
797   for (i=0;i<pcbddc->n_ISForDofs;i++) {
798     ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
799   }
800   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
801   pcbddc->n_ISForDofs = 0;
802   /* allocate space then set */
803   ierr = PetscMalloc(n_is*sizeof(IS),&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
804   for (i=0;i<n_is;i++) {
805     ierr = PetscObjectReference((PetscObject)ISForDofs[i]);CHKERRQ(ierr);
806     pcbddc->ISForDofsLocal[i]=ISForDofs[i];
807   }
808   pcbddc->n_ISForDofsLocal=n_is;
809   if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE;
810   pcbddc->recompute_topography = PETSC_TRUE;
811   PetscFunctionReturn(0);
812 }
813 
814 #undef __FUNCT__
815 #define __FUNCT__ "PCBDDCSetDofsSplittingLocal"
816 /*@
817  PCBDDCSetDofsSplittingLocal - Set index sets defining fields of the local subdomain matrix
818 
819    Collective
820 
821    Input Parameters:
822 +  pc - the preconditioning context
823 -  n_is - number of index sets defining the fields
824 .  ISForDofs - array of IS describing the fields in local ordering
825 
826    Level: intermediate
827 
828    Notes: n_is should be the same among processes. Not all nodes need to be listed: unlisted nodes will belong to a different field.
829 
830 .seealso: PCBDDC
831 @*/
832 PetscErrorCode PCBDDCSetDofsSplittingLocal(PC pc,PetscInt n_is, IS ISForDofs[])
833 {
834   PetscInt       i;
835   PetscErrorCode ierr;
836 
837   PetscFunctionBegin;
838   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
839   PetscValidLogicalCollectiveInt(pc,n_is,2);
840   for (i=0;i<n_is;i++) {
841     PetscCheckSameComm(pc,1,ISForDofs[i],3);
842     PetscValidHeaderSpecific(ISForDofs[i],IS_CLASSID,3);
843   }
844   ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplitting_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr);
845   PetscFunctionReturn(0);
846 }
847 /* -------------------------------------------------------------------------- */
848 
849 #undef __FUNCT__
850 #define __FUNCT__ "PCBDDCSetDofsSplitting_BDDC"
851 static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
852 {
853   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
854   PetscInt i;
855   PetscErrorCode ierr;
856 
857   PetscFunctionBegin;
858   /* Destroy ISes if they were already set */
859   for (i=0;i<pcbddc->n_ISForDofs;i++) {
860     ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
861   }
862   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
863   /* last user setting takes precendence -> destroy any other customization */
864   for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
865     ierr = ISDestroy(&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
866   }
867   ierr = PetscFree(pcbddc->ISForDofsLocal);CHKERRQ(ierr);
868   pcbddc->n_ISForDofsLocal = 0;
869   /* allocate space then set */
870   ierr = PetscMalloc1(n_is,&pcbddc->ISForDofs);CHKERRQ(ierr);
871   for (i=0;i<n_is;i++) {
872     ierr = PetscObjectReference((PetscObject)ISForDofs[i]);CHKERRQ(ierr);
873     pcbddc->ISForDofs[i]=ISForDofs[i];
874   }
875   pcbddc->n_ISForDofs=n_is;
876   if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE;
877   pcbddc->recompute_topography = PETSC_TRUE;
878   PetscFunctionReturn(0);
879 }
880 
881 #undef __FUNCT__
882 #define __FUNCT__ "PCBDDCSetDofsSplitting"
883 /*@
884  PCBDDCSetDofsSplitting - Set index sets defining fields of the global matrix
885 
886    Collective
887 
888    Input Parameters:
889 +  pc - the preconditioning context
890 -  n_is - number of index sets defining the fields
891 .  ISForDofs - array of IS describing the fields in global ordering
892 
893    Level: intermediate
894 
895    Notes: Any process can list any global node. Not all nodes need to be listed: unlisted nodes will belong to a different field.
896 
897 .seealso: PCBDDC
898 @*/
899 PetscErrorCode PCBDDCSetDofsSplitting(PC pc,PetscInt n_is, IS ISForDofs[])
900 {
901   PetscInt       i;
902   PetscErrorCode ierr;
903 
904   PetscFunctionBegin;
905   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
906   PetscValidLogicalCollectiveInt(pc,n_is,2);
907   for (i=0;i<n_is;i++) {
908     PetscCheckSameComm(pc,1,ISForDofs[i],3);
909     PetscValidHeaderSpecific(ISForDofs[i],IS_CLASSID,3);
910   }
911   ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplitting_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr);
912   PetscFunctionReturn(0);
913 }
914 
915 /* -------------------------------------------------------------------------- */
916 #undef __FUNCT__
917 #define __FUNCT__ "PCPreSolve_BDDC"
918 /* -------------------------------------------------------------------------- */
919 /*
920    PCPreSolve_BDDC - Changes the right hand side and (if necessary) the initial
921                      guess if a transformation of basis approach has been selected.
922 
923    Input Parameter:
924 +  pc - the preconditioner contex
925 
926    Application Interface Routine: PCPreSolve()
927 
928    Notes:
929    The interface routine PCPreSolve() is not usually called directly by
930    the user, but instead is called by KSPSolve().
931 */
932 static PetscErrorCode PCPreSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
933 {
934   PetscErrorCode ierr;
935   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
936   PC_IS          *pcis = (PC_IS*)(pc->data);
937   IS             dirIS;
938   Vec            used_vec;
939 
940   PetscFunctionBegin;
941   /* if we are working with cg, one dirichlet solve can be avoided during Krylov iterations */
942   if (ksp) {
943     PetscBool iscg;
944     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPCG,&iscg);CHKERRQ(ierr);
945     if (!iscg) {
946       ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
947     }
948   }
949   /* Creates parallel work vectors used in presolve */
950   if (!pcbddc->original_rhs) {
951     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs);CHKERRQ(ierr);
952   }
953   if (!pcbddc->temp_solution) {
954     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->temp_solution);CHKERRQ(ierr);
955   }
956   if (x) {
957     ierr = PetscObjectReference((PetscObject)x);CHKERRQ(ierr);
958     used_vec = x;
959   } else {
960     ierr = PetscObjectReference((PetscObject)pcbddc->temp_solution);CHKERRQ(ierr);
961     used_vec = pcbddc->temp_solution;
962     ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
963   }
964   /* hack into ksp data structure PCPreSolve comes earlier in src/ksp/ksp/interface/itfunc.c */
965   if (ksp) {
966     PetscBool guess_nonzero;
967     ierr = KSPGetInitialGuessNonzero(ksp,&guess_nonzero);CHKERRQ(ierr);
968     if (!guess_nonzero) {
969       ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
970     }
971   }
972 
973   /* store the original rhs */
974   ierr = VecCopy(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
975 
976   /* Take into account zeroed rows -> change rhs and store solution removed */
977   /* note that Dirichlet boundaries in global ordering (if any) has already been translated into local ordering in PCBDDCAnalyzeInterface */
978   ierr = PCBDDCGetDirichletBoundariesLocal(pc,&dirIS);CHKERRQ(ierr);
979   if (rhs && dirIS) {
980     Mat_IS      *matis = (Mat_IS*)pc->pmat->data;
981     PetscInt    dirsize,i,*is_indices;
982     PetscScalar *array_x,*array_diagonal;
983 
984     ierr = MatGetDiagonal(pc->pmat,pcis->vec1_global);CHKERRQ(ierr);
985     ierr = VecPointwiseDivide(pcis->vec1_global,rhs,pcis->vec1_global);CHKERRQ(ierr);
986     ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
987     ierr = VecScatterEnd(matis->ctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
988     ierr = VecScatterBegin(matis->ctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
989     ierr = VecScatterEnd(matis->ctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
990     ierr = ISGetLocalSize(dirIS,&dirsize);CHKERRQ(ierr);
991     ierr = VecGetArray(pcis->vec1_N,&array_x);CHKERRQ(ierr);
992     ierr = VecGetArray(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr);
993     ierr = ISGetIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
994     for (i=0; i<dirsize; i++) array_x[is_indices[i]] = array_diagonal[is_indices[i]];
995     ierr = ISRestoreIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
996     ierr = VecRestoreArray(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr);
997     ierr = VecRestoreArray(pcis->vec1_N,&array_x);CHKERRQ(ierr);
998     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
999     ierr = VecScatterEnd(matis->ctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1000 
1001     /* remove the computed solution from the rhs */
1002     ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr);
1003     ierr = MatMultAdd(pc->pmat,used_vec,rhs,rhs);CHKERRQ(ierr);
1004     ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr);
1005   }
1006 
1007   /* store partially computed solution and set initial guess */
1008   if (x) {
1009     ierr = VecCopy(used_vec,pcbddc->temp_solution);CHKERRQ(ierr);
1010     ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
1011     if (pcbddc->use_exact_dirichlet_trick) {
1012       ierr = VecScatterBegin(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1013       ierr = VecScatterEnd(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1014       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
1015       ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1016       ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1017       if (ksp) {
1018         ierr = KSPSetInitialGuessNonzero(ksp,PETSC_TRUE);CHKERRQ(ierr);
1019       }
1020     }
1021   }
1022 
1023   if (pcbddc->ChangeOfBasisMatrix) {
1024     PCBDDCChange_ctx change_ctx;
1025 
1026     /* get change ctx */
1027     ierr = MatShellGetContext(pcbddc->new_global_mat,&change_ctx);CHKERRQ(ierr);
1028 
1029     /* set current iteration matrix inside change context (change of basis has been already set into the ctx during PCSetUp) */
1030     ierr = MatDestroy(&change_ctx->original_mat);CHKERRQ(ierr);
1031     ierr = PetscObjectReference((PetscObject)pc->mat);CHKERRQ(ierr);
1032     change_ctx->original_mat = pc->mat;
1033 
1034     /* change iteration matrix */
1035     ierr = MatDestroy(&pc->mat);CHKERRQ(ierr);
1036     ierr = PetscObjectReference((PetscObject)pcbddc->new_global_mat);CHKERRQ(ierr);
1037     pc->mat = pcbddc->new_global_mat;
1038 
1039     /* change rhs */
1040     ierr = MatMultTranspose(change_ctx->global_change,rhs,pcis->vec1_global);CHKERRQ(ierr);
1041     ierr = VecCopy(pcis->vec1_global,rhs);CHKERRQ(ierr);
1042   }
1043 
1044   /* remove nullspace if present */
1045   if (ksp && pcbddc->NullSpace) {
1046     ierr = MatNullSpaceRemove(pcbddc->NullSpace,used_vec);CHKERRQ(ierr);
1047     ierr = MatNullSpaceRemove(pcbddc->NullSpace,rhs);CHKERRQ(ierr);
1048   }
1049   ierr = VecDestroy(&used_vec);CHKERRQ(ierr);
1050   PetscFunctionReturn(0);
1051 }
1052 
1053 /* -------------------------------------------------------------------------- */
1054 #undef __FUNCT__
1055 #define __FUNCT__ "PCPostSolve_BDDC"
1056 /* -------------------------------------------------------------------------- */
1057 /*
1058    PCPostSolve_BDDC - Changes the computed solution if a transformation of basis
1059                      approach has been selected. Also, restores rhs to its original state.
1060 
1061    Input Parameter:
1062 +  pc - the preconditioner contex
1063 
1064    Application Interface Routine: PCPostSolve()
1065 
1066    Notes:
1067    The interface routine PCPostSolve() is not usually called directly by
1068    the user, but instead is called by KSPSolve().
1069 */
1070 static PetscErrorCode PCPostSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
1071 {
1072   PetscErrorCode ierr;
1073   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1074 
1075   PetscFunctionBegin;
1076   if (pcbddc->ChangeOfBasisMatrix) {
1077     PCBDDCChange_ctx change_ctx;
1078 
1079     /* get change ctx */
1080     ierr = MatShellGetContext(pcbddc->new_global_mat,&change_ctx);CHKERRQ(ierr);
1081 
1082     /* restore iteration matrix */
1083     ierr = MatDestroy(&pc->mat);CHKERRQ(ierr);
1084     ierr = PetscObjectReference((PetscObject)change_ctx->original_mat);CHKERRQ(ierr);
1085     pc->mat = change_ctx->original_mat;
1086 
1087     /* get solution in original basis */
1088     if (x) {
1089       PC_IS *pcis = (PC_IS*)(pc->data);
1090       ierr = MatMult(change_ctx->global_change,x,pcis->vec1_global);CHKERRQ(ierr);
1091       ierr = VecCopy(pcis->vec1_global,x);CHKERRQ(ierr);
1092     }
1093   }
1094 
1095   /* add solution removed in presolve */
1096   if (x) {
1097     ierr = VecAXPY(x,1.0,pcbddc->temp_solution);CHKERRQ(ierr);
1098   }
1099 
1100   /* restore rhs to its original state */
1101   if (rhs) {
1102     ierr = VecCopy(pcbddc->original_rhs,rhs);CHKERRQ(ierr);
1103   }
1104   PetscFunctionReturn(0);
1105 }
1106 /* -------------------------------------------------------------------------- */
1107 #undef __FUNCT__
1108 #define __FUNCT__ "PCSetUp_BDDC"
1109 /* -------------------------------------------------------------------------- */
1110 /*
1111    PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner
1112                   by setting data structures and options.
1113 
1114    Input Parameter:
1115 +  pc - the preconditioner context
1116 
1117    Application Interface Routine: PCSetUp()
1118 
1119    Notes:
1120    The interface routine PCSetUp() is not usually called directly by
1121    the user, but instead is called by PCApply() if necessary.
1122 */
1123 PetscErrorCode PCSetUp_BDDC(PC pc)
1124 {
1125   PetscErrorCode   ierr;
1126   PC_BDDC*         pcbddc = (PC_BDDC*)pc->data;
1127   MatNullSpace     nearnullspace;
1128   PetscBool        computeis,computetopography,computesolvers;
1129   PetscBool        new_nearnullspace_provided;
1130 
1131   PetscFunctionBegin;
1132   /* the following lines of code should be replaced by a better logic between PCIS, PCNN, PCBDDC and other future nonoverlapping preconditioners */
1133   /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup
1134      Also, BDDC directly build the Dirichlet problem */
1135   /* split work */
1136   if (pc->setupcalled) {
1137     computeis = PETSC_FALSE;
1138     if (pc->flag == SAME_NONZERO_PATTERN) {
1139       computetopography = PETSC_FALSE;
1140       computesolvers = PETSC_TRUE;
1141     } else { /* DIFFERENT_NONZERO_PATTERN */
1142       computetopography = PETSC_TRUE;
1143       computesolvers = PETSC_TRUE;
1144     }
1145   } else {
1146     computeis = PETSC_TRUE;
1147     computetopography = PETSC_TRUE;
1148     computesolvers = PETSC_TRUE;
1149   }
1150   if (pcbddc->recompute_topography) {
1151     computetopography = PETSC_TRUE;
1152   }
1153 
1154   /* Get stdout for dbg */
1155   if (pcbddc->dbg_flag) {
1156     if (!pcbddc->dbg_viewer) {
1157       pcbddc->dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pc));
1158       ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
1159     }
1160     ierr = PetscViewerASCIIAddTab(pcbddc->dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
1161   }
1162 
1163   /* Set up all the "iterative substructuring" common block without computing solvers */
1164   if (computeis) {
1165     /* HACK INTO PCIS */
1166     PC_IS* pcis = (PC_IS*)pc->data;
1167     pcis->computesolvers = PETSC_FALSE;
1168     ierr = PCISSetUp(pc);CHKERRQ(ierr);
1169     ierr = ISLocalToGlobalMappingCreateIS(pcis->is_B_local,&pcbddc->BtoNmap);CHKERRQ(ierr);
1170   }
1171 
1172   /* use_change_of_basis flag is used to automatically compute a change of basis from constraints */
1173   if (pcbddc->user_ChangeOfBasisMatrix) {
1174     pcbddc->use_change_of_basis = PETSC_FALSE;
1175   }
1176 
1177   /* Analyze interface */
1178   if (computetopography) {
1179     ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
1180     /* Schurs on subsets should be reset */
1181     if (pcbddc->deluxe_ctx) {
1182       ierr = PCBDDCSubSchursReset(pcbddc->deluxe_ctx->sub_schurs);CHKERRQ(ierr);
1183     }
1184   }
1185 
1186   /* infer if NullSpace object attached to Mat via MatSetNearNullSpace has changed */
1187   new_nearnullspace_provided = PETSC_FALSE;
1188   ierr = MatGetNearNullSpace(pc->pmat,&nearnullspace);CHKERRQ(ierr);
1189   if (pcbddc->onearnullspace) { /* already used nearnullspace */
1190     if (!nearnullspace) { /* near null space attached to mat has been destroyed */
1191       new_nearnullspace_provided = PETSC_TRUE;
1192     } else {
1193       /* determine if the two nullspaces are different (should be lightweight) */
1194       if (nearnullspace != pcbddc->onearnullspace) {
1195         new_nearnullspace_provided = PETSC_TRUE;
1196       } else { /* maybe the user has changed the content of the nearnullspace so check vectors ObjectStateId */
1197         PetscInt         i;
1198         const Vec        *nearnullvecs;
1199         PetscObjectState state;
1200         PetscInt         nnsp_size;
1201         ierr = MatNullSpaceGetVecs(nearnullspace,NULL,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
1202         for (i=0;i<nnsp_size;i++) {
1203           ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&state);CHKERRQ(ierr);
1204           if (pcbddc->onearnullvecs_state[i] != state) {
1205             new_nearnullspace_provided = PETSC_TRUE;
1206             break;
1207           }
1208         }
1209       }
1210     }
1211   } else {
1212     if (!nearnullspace) { /* both nearnullspaces are null */
1213       new_nearnullspace_provided = PETSC_FALSE;
1214     } else { /* nearnullspace attached later */
1215       new_nearnullspace_provided = PETSC_TRUE;
1216     }
1217   }
1218 
1219   /* Setup constraints and related work vectors */
1220   /* reset primal space flags */
1221   pcbddc->new_primal_space = PETSC_FALSE;
1222   pcbddc->new_primal_space_local = PETSC_FALSE;
1223   if (computetopography || new_nearnullspace_provided) {
1224     /* It also sets the primal space flags */
1225     ierr = PCBDDCConstraintsSetUp(pc);CHKERRQ(ierr);
1226     /* Allocate needed local vectors (which depends on quantities defined during ConstraintsSetUp) */
1227     ierr = PCBDDCSetUpLocalWorkVectors(pc);CHKERRQ(ierr);
1228     /* Schurs on subsets should be reset */
1229     if (pcbddc->deluxe_ctx) {
1230       ierr = PCBDDCSubSchursReset(pcbddc->deluxe_ctx->sub_schurs);CHKERRQ(ierr);
1231     }
1232   }
1233 
1234   if (computesolvers || pcbddc->new_primal_space) {
1235     /* Create coarse and local stuffs */
1236     ierr = PCBDDCSetUpSolvers(pc);CHKERRQ(ierr);
1237     /* Create scaling operators */
1238     ierr = PCBDDCScalingSetUp(pc);CHKERRQ(ierr);
1239   }
1240 
1241   if (pcbddc->dbg_flag) {
1242     ierr = PetscViewerASCIISubtractTab(pcbddc->dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
1243   }
1244   PetscFunctionReturn(0);
1245 }
1246 
1247 /* -------------------------------------------------------------------------- */
1248 /*
1249    PCApply_BDDC - Applies the BDDC operator to a vector.
1250 
1251    Input Parameters:
1252 .  pc - the preconditioner context
1253 .  r - input vector (global)
1254 
1255    Output Parameter:
1256 .  z - output vector (global)
1257 
1258    Application Interface Routine: PCApply()
1259  */
1260 #undef __FUNCT__
1261 #define __FUNCT__ "PCApply_BDDC"
1262 PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z)
1263 {
1264   PC_IS             *pcis = (PC_IS*)(pc->data);
1265   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
1266   PetscErrorCode    ierr;
1267   const PetscScalar one = 1.0;
1268   const PetscScalar m_one = -1.0;
1269   const PetscScalar zero = 0.0;
1270 
1271 /* This code is similar to that provided in nn.c for PCNN
1272    NN interface preconditioner changed to BDDC
1273    Added support for M_3 preconditioner in the reference article (code is active if pcbddc->switch_static = PETSC_TRUE) */
1274 
1275   PetscFunctionBegin;
1276   if (!pcbddc->use_exact_dirichlet_trick) {
1277     /* First Dirichlet solve */
1278     ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1279     ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1280     ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
1281     /*
1282       Assembling right hand side for BDDC operator
1283       - pcis->vec1_D for the Dirichlet part (if needed, i.e. prec_flag=PETSC_TRUE)
1284       - pcis->vec1_B the interface part of the global vector z
1285     */
1286     ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
1287     ierr = MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
1288     if (pcbddc->switch_static) { ierr = MatMultAdd(pcis->A_II,pcis->vec2_D,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
1289     ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
1290     ierr = VecCopy(r,z);CHKERRQ(ierr);
1291     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1292     ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1293     ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr);
1294   } else {
1295     ierr = VecSet(pcis->vec1_D,zero);CHKERRQ(ierr);
1296     ierr = VecSet(pcis->vec2_D,zero);CHKERRQ(ierr);
1297     ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr);
1298   }
1299 
1300   /* Apply interface preconditioner
1301      input/output vecs: pcis->vec1_B and pcis->vec1_D */
1302   ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
1303 
1304   /* Apply transpose of partition of unity operator */
1305   ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr);
1306 
1307   /* Second Dirichlet solve and assembling of output */
1308   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1309   ierr = VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1310   ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
1311   if (pcbddc->switch_static) { ierr = MatMultAdd(pcis->A_II,pcis->vec1_D,pcis->vec3_D,pcis->vec3_D);CHKERRQ(ierr); }
1312   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D);CHKERRQ(ierr);
1313   ierr = VecScale(pcis->vec4_D,m_one);CHKERRQ(ierr);
1314   if (pcbddc->switch_static) { ierr = VecAXPY(pcis->vec4_D,one,pcis->vec1_D);CHKERRQ(ierr); }
1315   ierr = VecAXPY(pcis->vec2_D,one,pcis->vec4_D);CHKERRQ(ierr);
1316   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1317   ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1318   PetscFunctionReturn(0);
1319 }
1320 
1321 /* -------------------------------------------------------------------------- */
1322 /*
1323    PCApplyTranspose_BDDC - Applies the transpose of the BDDC operator to a vector.
1324 
1325    Input Parameters:
1326 .  pc - the preconditioner context
1327 .  r - input vector (global)
1328 
1329    Output Parameter:
1330 .  z - output vector (global)
1331 
1332    Application Interface Routine: PCApplyTranspose()
1333  */
1334 #undef __FUNCT__
1335 #define __FUNCT__ "PCApplyTranspose_BDDC"
1336 PetscErrorCode PCApplyTranspose_BDDC(PC pc,Vec r,Vec z)
1337 {
1338   PC_IS             *pcis = (PC_IS*)(pc->data);
1339   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
1340   PetscErrorCode    ierr;
1341   const PetscScalar one = 1.0;
1342   const PetscScalar m_one = -1.0;
1343   const PetscScalar zero = 0.0;
1344 
1345   PetscFunctionBegin;
1346   if (!pcbddc->use_exact_dirichlet_trick) {
1347     /* First Dirichlet solve */
1348     ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1349     ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1350     ierr = KSPSolveTranspose(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
1351     /*
1352       Assembling right hand side for BDDC operator
1353       - pcis->vec1_D for the Dirichlet part (if needed, i.e. prec_flag=PETSC_TRUE)
1354       - pcis->vec1_B the interface part of the global vector z
1355     */
1356     ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
1357     ierr = MatMultTranspose(pcis->A_IB,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
1358     if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcis->A_II,pcis->vec2_D,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
1359     ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
1360     ierr = VecCopy(r,z);CHKERRQ(ierr);
1361     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1362     ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1363     ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr);
1364   } else {
1365     ierr = VecSet(pcis->vec1_D,zero);CHKERRQ(ierr);
1366     ierr = VecSet(pcis->vec2_D,zero);CHKERRQ(ierr);
1367     ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr);
1368   }
1369 
1370   /* Apply interface preconditioner
1371      input/output vecs: pcis->vec1_B and pcis->vec1_D */
1372   ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_TRUE);CHKERRQ(ierr);
1373 
1374   /* Apply transpose of partition of unity operator */
1375   ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr);
1376 
1377   /* Second Dirichlet solve and assembling of output */
1378   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1379   ierr = VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1380   ierr = MatMultTranspose(pcis->A_BI,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
1381   if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcis->A_II,pcis->vec1_D,pcis->vec3_D,pcis->vec3_D);CHKERRQ(ierr); }
1382   ierr = KSPSolveTranspose(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D);CHKERRQ(ierr);
1383   ierr = VecScale(pcis->vec4_D,m_one);CHKERRQ(ierr);
1384   if (pcbddc->switch_static) { ierr = VecAXPY(pcis->vec4_D,one,pcis->vec1_D);CHKERRQ(ierr); }
1385   ierr = VecAXPY(pcis->vec2_D,one,pcis->vec4_D);CHKERRQ(ierr);
1386   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1387   ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1388   PetscFunctionReturn(0);
1389 }
1390 /* -------------------------------------------------------------------------- */
1391 
1392 #undef __FUNCT__
1393 #define __FUNCT__ "PCDestroy_BDDC"
1394 PetscErrorCode PCDestroy_BDDC(PC pc)
1395 {
1396   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1397   PetscErrorCode ierr;
1398 
1399   PetscFunctionBegin;
1400   /* free data created by PCIS */
1401   ierr = PCISDestroy(pc);CHKERRQ(ierr);
1402   /* free BDDC custom data  */
1403   ierr = PCBDDCResetCustomization(pc);CHKERRQ(ierr);
1404   /* destroy objects related to topography */
1405   ierr = PCBDDCResetTopography(pc);CHKERRQ(ierr);
1406   /* free allocated graph structure */
1407   ierr = PetscFree(pcbddc->mat_graph);CHKERRQ(ierr);
1408   /* destroy objects for scaling operator */
1409   ierr = PCBDDCScalingDestroy(pc);CHKERRQ(ierr);
1410   ierr = PetscFree(pcbddc->deluxe_ctx);CHKERRQ(ierr);
1411   /* free solvers stuff */
1412   ierr = PCBDDCResetSolvers(pc);CHKERRQ(ierr);
1413   /* free global vectors needed in presolve */
1414   ierr = VecDestroy(&pcbddc->temp_solution);CHKERRQ(ierr);
1415   ierr = VecDestroy(&pcbddc->original_rhs);CHKERRQ(ierr);
1416   /* free stuff for change of basis hooks */
1417   if (pcbddc->new_global_mat) {
1418     PCBDDCChange_ctx change_ctx;
1419     ierr = MatShellGetContext(pcbddc->new_global_mat,&change_ctx);CHKERRQ(ierr);
1420     ierr = MatDestroy(&change_ctx->original_mat);CHKERRQ(ierr);
1421     ierr = MatDestroy(&change_ctx->global_change);CHKERRQ(ierr);
1422     ierr = VecDestroyVecs(2,&change_ctx->work);CHKERRQ(ierr);
1423     ierr = PetscFree(change_ctx);CHKERRQ(ierr);
1424   }
1425   ierr = MatDestroy(&pcbddc->new_global_mat);CHKERRQ(ierr);
1426   /* remove map from local boundary to local numbering */
1427   ierr = ISLocalToGlobalMappingDestroy(&pcbddc->BtoNmap);CHKERRQ(ierr);
1428   /* remove functions */
1429   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",NULL);CHKERRQ(ierr);
1430   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",NULL);CHKERRQ(ierr);
1431   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",NULL);CHKERRQ(ierr);
1432   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",NULL);CHKERRQ(ierr);
1433   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",NULL);CHKERRQ(ierr);
1434   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",NULL);CHKERRQ(ierr);
1435   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNullSpace_C",NULL);CHKERRQ(ierr);
1436   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",NULL);CHKERRQ(ierr);
1437   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",NULL);CHKERRQ(ierr);
1438   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",NULL);CHKERRQ(ierr);
1439   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",NULL);CHKERRQ(ierr);
1440   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",NULL);CHKERRQ(ierr);
1441   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",NULL);CHKERRQ(ierr);
1442   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",NULL);CHKERRQ(ierr);
1443   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",NULL);CHKERRQ(ierr);
1444   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",NULL);CHKERRQ(ierr);
1445   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",NULL);CHKERRQ(ierr);
1446   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",NULL);CHKERRQ(ierr);
1447   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",NULL);CHKERRQ(ierr);
1448   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",NULL);CHKERRQ(ierr);
1449   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",NULL);CHKERRQ(ierr);
1450   /* Free the private data structure */
1451   ierr = PetscFree(pc->data);CHKERRQ(ierr);
1452   PetscFunctionReturn(0);
1453 }
1454 /* -------------------------------------------------------------------------- */
1455 
1456 #undef __FUNCT__
1457 #define __FUNCT__ "PCBDDCMatFETIDPGetRHS_BDDC"
1458 static PetscErrorCode PCBDDCMatFETIDPGetRHS_BDDC(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
1459 {
1460   FETIDPMat_ctx  mat_ctx;
1461   PC_IS*         pcis;
1462   PC_BDDC*       pcbddc;
1463   PetscErrorCode ierr;
1464 
1465   PetscFunctionBegin;
1466   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
1467   pcis = (PC_IS*)mat_ctx->pc->data;
1468   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
1469 
1470   /* change of basis for physical rhs if needed
1471      It also changes the rhs in case of dirichlet boundaries */
1472   ierr = PCPreSolve_BDDC(mat_ctx->pc,NULL,standard_rhs,NULL);CHKERRQ(ierr);
1473   /* store vectors for computation of fetidp final solution */
1474   ierr = VecScatterBegin(pcis->global_to_D,standard_rhs,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1475   ierr = VecScatterEnd(pcis->global_to_D,standard_rhs,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1476   /* scale rhs since it should be unassembled */
1477   /* TODO use counter scaling? (also below) */
1478   ierr = VecScatterBegin(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1479   ierr = VecScatterEnd(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1480   /* Apply partition of unity */
1481   ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr);
1482   /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,standard_rhs,mat_ctx->temp_solution_B);CHKERRQ(ierr); */
1483   if (!pcbddc->switch_static) {
1484     /* compute partially subassembled Schur complement right-hand side */
1485     ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
1486     ierr = MatMult(pcis->A_BI,pcis->vec1_D,pcis->vec1_B);CHKERRQ(ierr);
1487     ierr = VecAXPY(mat_ctx->temp_solution_B,-1.0,pcis->vec1_B);CHKERRQ(ierr);
1488     ierr = VecSet(standard_rhs,0.0);CHKERRQ(ierr);
1489     ierr = VecScatterBegin(pcis->global_to_B,mat_ctx->temp_solution_B,standard_rhs,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1490     ierr = VecScatterEnd(pcis->global_to_B,mat_ctx->temp_solution_B,standard_rhs,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1491     /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,standard_rhs,mat_ctx->temp_solution_B);CHKERRQ(ierr); */
1492     ierr = VecScatterBegin(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1493     ierr = VecScatterEnd(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1494     ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr);
1495   }
1496   /* BDDC rhs */
1497   ierr = VecCopy(mat_ctx->temp_solution_B,pcis->vec1_B);CHKERRQ(ierr);
1498   if (pcbddc->switch_static) {
1499     ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
1500   }
1501   /* apply BDDC */
1502   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE);CHKERRQ(ierr);
1503   /* Application of B_delta and assembling of rhs for fetidp fluxes */
1504   ierr = VecSet(fetidp_flux_rhs,0.0);CHKERRQ(ierr);
1505   ierr = MatMult(mat_ctx->B_delta,pcis->vec1_B,mat_ctx->lambda_local);CHKERRQ(ierr);
1506   ierr = VecScatterBegin(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1507   ierr = VecScatterEnd  (mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1508   /* restore original rhs */
1509   ierr = VecCopy(pcbddc->original_rhs,standard_rhs);CHKERRQ(ierr);
1510   PetscFunctionReturn(0);
1511 }
1512 
1513 #undef __FUNCT__
1514 #define __FUNCT__ "PCBDDCMatFETIDPGetRHS"
1515 /*@
1516  PCBDDCMatFETIDPGetRHS - Compute the right-hand side for FETIDP linear system
1517 
1518    Collective
1519 
1520    Input Parameters:
1521 +  fetidp_mat   - the FETIDP matrix object obtained by calling PCBDDCCreateFETIDPOperators
1522 .  standard_rhs - the right-hand side for your linear system
1523 
1524    Output Parameters:
1525 -  fetidp_flux_rhs   - the right-hand side for the FETIDP linear system
1526 
1527    Level: developer
1528 
1529    Notes:
1530 
1531 .seealso: PCBDDC,PCBDDCCreateFETIDPOperators
1532 @*/
1533 PetscErrorCode PCBDDCMatFETIDPGetRHS(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
1534 {
1535   FETIDPMat_ctx  mat_ctx;
1536   PetscErrorCode ierr;
1537 
1538   PetscFunctionBegin;
1539   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
1540   ierr = PetscTryMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetRHS_C",(Mat,Vec,Vec),(fetidp_mat,standard_rhs,fetidp_flux_rhs));CHKERRQ(ierr);
1541   PetscFunctionReturn(0);
1542 }
1543 /* -------------------------------------------------------------------------- */
1544 
1545 #undef __FUNCT__
1546 #define __FUNCT__ "PCBDDCMatFETIDPGetSolution_BDDC"
1547 static PetscErrorCode PCBDDCMatFETIDPGetSolution_BDDC(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
1548 {
1549   FETIDPMat_ctx  mat_ctx;
1550   PC_IS*         pcis;
1551   PC_BDDC*       pcbddc;
1552   PetscErrorCode ierr;
1553 
1554   PetscFunctionBegin;
1555   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
1556   pcis = (PC_IS*)mat_ctx->pc->data;
1557   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
1558 
1559   /* apply B_delta^T */
1560   ierr = VecScatterBegin(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1561   ierr = VecScatterEnd  (mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1562   ierr = MatMultTranspose(mat_ctx->B_delta,mat_ctx->lambda_local,pcis->vec1_B);CHKERRQ(ierr);
1563   /* compute rhs for BDDC application */
1564   ierr = VecAYPX(pcis->vec1_B,-1.0,mat_ctx->temp_solution_B);CHKERRQ(ierr);
1565   if (pcbddc->switch_static) {
1566     ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
1567   }
1568   /* apply BDDC */
1569   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE);CHKERRQ(ierr);
1570   /* put values into standard global vector */
1571   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1572   ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1573   if (!pcbddc->switch_static) {
1574     /* compute values into the interior if solved for the partially subassembled Schur complement */
1575     ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec1_D);CHKERRQ(ierr);
1576     ierr = VecAXPY(mat_ctx->temp_solution_D,-1.0,pcis->vec1_D);CHKERRQ(ierr);
1577     ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
1578   }
1579   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec1_D,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1580   ierr = VecScatterEnd  (pcis->global_to_D,pcis->vec1_D,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1581   /* final change of basis if needed
1582      Is also sums the dirichlet part removed during RHS assembling */
1583   ierr = PCPostSolve_BDDC(mat_ctx->pc,NULL,NULL,standard_sol);CHKERRQ(ierr);
1584   PetscFunctionReturn(0);
1585 }
1586 
1587 #undef __FUNCT__
1588 #define __FUNCT__ "PCBDDCMatFETIDPGetSolution"
1589 /*@
1590  PCBDDCMatFETIDPGetSolution - Compute the physical solution from the solution of the FETIDP linear system
1591 
1592    Collective
1593 
1594    Input Parameters:
1595 +  fetidp_mat        - the FETIDP matrix obtained by calling PCBDDCCreateFETIDPOperators
1596 .  fetidp_flux_sol - the solution of the FETIDP linear system
1597 
1598    Output Parameters:
1599 -  standard_sol      - the solution defined on the physical domain
1600 
1601    Level: developer
1602 
1603    Notes:
1604 
1605 .seealso: PCBDDC,PCBDDCCreateFETIDPOperators
1606 @*/
1607 PetscErrorCode PCBDDCMatFETIDPGetSolution(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
1608 {
1609   FETIDPMat_ctx  mat_ctx;
1610   PetscErrorCode ierr;
1611 
1612   PetscFunctionBegin;
1613   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
1614   ierr = PetscTryMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetSolution_C",(Mat,Vec,Vec),(fetidp_mat,fetidp_flux_sol,standard_sol));CHKERRQ(ierr);
1615   PetscFunctionReturn(0);
1616 }
1617 /* -------------------------------------------------------------------------- */
1618 
1619 extern PetscErrorCode FETIDPMatMult(Mat,Vec,Vec);
1620 extern PetscErrorCode FETIDPMatMultTranspose(Mat,Vec,Vec);
1621 extern PetscErrorCode PCBDDCDestroyFETIDPMat(Mat);
1622 extern PetscErrorCode FETIDPPCApply(PC,Vec,Vec);
1623 extern PetscErrorCode FETIDPPCApplyTranspose(PC,Vec,Vec);
1624 extern PetscErrorCode PCBDDCDestroyFETIDPPC(PC);
1625 
1626 #undef __FUNCT__
1627 #define __FUNCT__ "PCBDDCCreateFETIDPOperators_BDDC"
1628 static PetscErrorCode PCBDDCCreateFETIDPOperators_BDDC(PC pc, Mat *fetidp_mat, PC *fetidp_pc)
1629 {
1630 
1631   FETIDPMat_ctx  fetidpmat_ctx;
1632   Mat            newmat;
1633   FETIDPPC_ctx   fetidppc_ctx;
1634   PC             newpc;
1635   MPI_Comm       comm;
1636   PetscErrorCode ierr;
1637 
1638   PetscFunctionBegin;
1639   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
1640   /* FETIDP linear matrix */
1641   ierr = PCBDDCCreateFETIDPMatContext(pc,&fetidpmat_ctx);CHKERRQ(ierr);
1642   ierr = PCBDDCSetupFETIDPMatContext(fetidpmat_ctx);CHKERRQ(ierr);
1643   ierr = MatCreateShell(comm,PETSC_DECIDE,PETSC_DECIDE,fetidpmat_ctx->n_lambda,fetidpmat_ctx->n_lambda,fetidpmat_ctx,&newmat);CHKERRQ(ierr);
1644   ierr = MatShellSetOperation(newmat,MATOP_MULT,(void (*)(void))FETIDPMatMult);CHKERRQ(ierr);
1645   ierr = MatShellSetOperation(newmat,MATOP_MULT_TRANSPOSE,(void (*)(void))FETIDPMatMultTranspose);CHKERRQ(ierr);
1646   ierr = MatShellSetOperation(newmat,MATOP_DESTROY,(void (*)(void))PCBDDCDestroyFETIDPMat);CHKERRQ(ierr);
1647   ierr = MatSetUp(newmat);CHKERRQ(ierr);
1648   /* FETIDP preconditioner */
1649   ierr = PCBDDCCreateFETIDPPCContext(pc,&fetidppc_ctx);CHKERRQ(ierr);
1650   ierr = PCBDDCSetupFETIDPPCContext(newmat,fetidppc_ctx);CHKERRQ(ierr);
1651   ierr = PCCreate(comm,&newpc);CHKERRQ(ierr);
1652   ierr = PCSetType(newpc,PCSHELL);CHKERRQ(ierr);
1653   ierr = PCShellSetContext(newpc,fetidppc_ctx);CHKERRQ(ierr);
1654   ierr = PCShellSetApply(newpc,FETIDPPCApply);CHKERRQ(ierr);
1655   ierr = PCShellSetApplyTranspose(newpc,FETIDPPCApplyTranspose);CHKERRQ(ierr);
1656   ierr = PCShellSetDestroy(newpc,PCBDDCDestroyFETIDPPC);CHKERRQ(ierr);
1657   ierr = PCSetOperators(newpc,newmat,newmat);CHKERRQ(ierr);
1658   ierr = PCSetUp(newpc);CHKERRQ(ierr);
1659   /* return pointers for objects created */
1660   *fetidp_mat=newmat;
1661   *fetidp_pc=newpc;
1662   PetscFunctionReturn(0);
1663 }
1664 
1665 #undef __FUNCT__
1666 #define __FUNCT__ "PCBDDCCreateFETIDPOperators"
1667 /*@
1668  PCBDDCCreateFETIDPOperators - Create operators for FETIDP
1669 
1670    Collective
1671 
1672    Input Parameters:
1673 +  pc - the BDDC preconditioning context already setup
1674 
1675    Output Parameters:
1676 .  fetidp_mat - shell FETIDP matrix object
1677 .  fetidp_pc  - shell Dirichlet preconditioner for FETIDP matrix
1678 
1679    Options Database Keys:
1680 -    -fetidp_fullyredundant: use or not a fully redundant set of Lagrange multipliers
1681 
1682    Level: developer
1683 
1684    Notes:
1685      Currently the only operation provided for FETIDP matrix is MatMult
1686 
1687 .seealso: PCBDDC
1688 @*/
1689 PetscErrorCode PCBDDCCreateFETIDPOperators(PC pc, Mat *fetidp_mat, PC *fetidp_pc)
1690 {
1691   PetscErrorCode ierr;
1692 
1693   PetscFunctionBegin;
1694   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1695   if (pc->setupcalled) {
1696     ierr = PetscUseMethod(pc,"PCBDDCCreateFETIDPOperators_C",(PC,Mat*,PC*),(pc,fetidp_mat,fetidp_pc));CHKERRQ(ierr);
1697   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"You must call PCSetup_BDDC() first \n");
1698   PetscFunctionReturn(0);
1699 }
1700 /* -------------------------------------------------------------------------- */
1701 /*MC
1702    PCBDDC - Balancing Domain Decomposition by Constraints.
1703 
1704    An implementation of the BDDC preconditioner based on
1705 
1706 .vb
1707    [1] C. R. Dohrmann. "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149-168, March 2007
1708    [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
1709    [3] J. Mandel, B. Sousedik, C. R. Dohrmann. "Multispace and Multilevel BDDC", http://arxiv.org/abs/0712.3977
1710 .ve
1711 
1712    The matrix to be preconditioned (Pmat) must be of type MATIS.
1713 
1714    Currently works with MATIS matrices with local Neumann matrices of type MATSEQAIJ, MATSEQBAIJ or MATSEQSBAIJ, either with real or complex numbers.
1715 
1716    It also works with unsymmetric and indefinite problems.
1717 
1718    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.
1719 
1720    Approximate local solvers are automatically adapted for singular linear problems (see [1]) if the user has provided the nullspace using PCBDDCSetNullSpace
1721 
1722    Boundary nodes are split in vertices, edges and faces 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()
1723 
1724    Constraints can be customized by attaching a MatNullSpace object to the MATIS matrix via MatSetNearNullSpace().
1725 
1726    Change of basis is performed similarly to [2] when requested. When more the 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.
1727 
1728    The PETSc implementation also supports multilevel BDDC [3]. Coarse grids are partitioned using MatPartitioning object.
1729 
1730    Options Database Keys:
1731 
1732 .    -pc_bddc_use_vertices <1> - use or not vertices in primal space
1733 .    -pc_bddc_use_edges <1> - use or not edges in primal space
1734 .    -pc_bddc_use_faces <0> - use or not faces in primal space
1735 .    -pc_bddc_use_change_of_basis <0> - use change of basis approach (on edges only)
1736 .    -pc_bddc_use_change_on_faces <0> - use change of basis approach on faces if change of basis has been requested
1737 .    -pc_bddc_switch_static <0> - switches from M_2 to M_3 operator (see reference article [1])
1738 .    -pc_bddc_levels <0> - maximum number of levels for multilevel
1739 .    -pc_bddc_coarsening_ratio - H/h ratio at the coarser level
1740 -    -pc_bddc_check_level <0> - set verbosity level of debugging output
1741 
1742    Options for Dirichlet, Neumann or coarse solver can be set with
1743 .vb
1744       -pc_bddc_dirichlet_
1745       -pc_bddc_neumann_
1746       -pc_bddc_coarse_
1747 .ve
1748    e.g -pc_bddc_dirichlet_ksp_type richardson -pc_bddc_dirichlet_pc_type gamg
1749 
1750    When using a multilevel approach, solvers' options at the N-th level can be specified as
1751 .vb
1752       -pc_bddc_dirichlet_lN_
1753       -pc_bddc_neumann_lN_
1754       -pc_bddc_coarse_lN_
1755 .ve
1756    Note that level number ranges from the finest 0 to the coarsest N.
1757 
1758    Level: intermediate
1759 
1760    Developer notes:
1761 
1762    New deluxe scaling operator will be available soon.
1763 
1764    Contributed by Stefano Zampini
1765 
1766 .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,  MATIS
1767 M*/
1768 
1769 #undef __FUNCT__
1770 #define __FUNCT__ "PCCreate_BDDC"
1771 PETSC_EXTERN PetscErrorCode PCCreate_BDDC(PC pc)
1772 {
1773   PetscErrorCode      ierr;
1774   PC_BDDC             *pcbddc;
1775 
1776   PetscFunctionBegin;
1777   /* Creates the private data structure for this preconditioner and attach it to the PC object. */
1778   ierr      = PetscNewLog(pc,&pcbddc);CHKERRQ(ierr);
1779   pc->data  = (void*)pcbddc;
1780 
1781   /* create PCIS data structure */
1782   ierr = PCISCreate(pc);CHKERRQ(ierr);
1783 
1784   /* BDDC customization */
1785   pcbddc->use_local_adj       = PETSC_TRUE;
1786   pcbddc->use_vertices        = PETSC_TRUE;
1787   pcbddc->use_edges           = PETSC_TRUE;
1788   pcbddc->use_faces           = PETSC_FALSE;
1789   pcbddc->use_change_of_basis = PETSC_FALSE;
1790   pcbddc->use_change_on_faces = PETSC_FALSE;
1791   pcbddc->switch_static       = PETSC_FALSE;
1792   pcbddc->use_nnsp_true       = PETSC_FALSE; /* not yet exposed */
1793   pcbddc->dbg_flag            = 0;
1794   /* private */
1795   pcbddc->issym                      = PETSC_FALSE;
1796   pcbddc->BtoNmap                    = 0;
1797   pcbddc->local_primal_size          = 0;
1798   pcbddc->n_vertices                 = 0;
1799   pcbddc->n_actual_vertices          = 0;
1800   pcbddc->n_constraints              = 0;
1801   pcbddc->primal_indices_local_idxs  = 0;
1802   pcbddc->recompute_topography       = PETSC_FALSE;
1803   pcbddc->coarse_size                = -1;
1804   pcbddc->new_primal_space           = PETSC_FALSE;
1805   pcbddc->new_primal_space_local     = PETSC_FALSE;
1806   pcbddc->global_primal_indices      = 0;
1807   pcbddc->onearnullspace             = 0;
1808   pcbddc->onearnullvecs_state        = 0;
1809   pcbddc->user_primal_vertices       = 0;
1810   pcbddc->NullSpace                  = 0;
1811   pcbddc->temp_solution              = 0;
1812   pcbddc->original_rhs               = 0;
1813   pcbddc->local_mat                  = 0;
1814   pcbddc->ChangeOfBasisMatrix        = 0;
1815   pcbddc->user_ChangeOfBasisMatrix   = 0;
1816   pcbddc->new_global_mat             = 0;
1817   pcbddc->coarse_vec                 = 0;
1818   pcbddc->coarse_rhs                 = 0;
1819   pcbddc->coarse_ksp                 = 0;
1820   pcbddc->coarse_phi_B               = 0;
1821   pcbddc->coarse_phi_D               = 0;
1822   pcbddc->coarse_psi_B               = 0;
1823   pcbddc->coarse_psi_D               = 0;
1824   pcbddc->vec1_P                     = 0;
1825   pcbddc->vec1_R                     = 0;
1826   pcbddc->vec2_R                     = 0;
1827   pcbddc->local_auxmat1              = 0;
1828   pcbddc->local_auxmat2              = 0;
1829   pcbddc->R_to_B                     = 0;
1830   pcbddc->R_to_D                     = 0;
1831   pcbddc->ksp_D                      = 0;
1832   pcbddc->ksp_R                      = 0;
1833   pcbddc->NeumannBoundaries          = 0;
1834   pcbddc->NeumannBoundariesLocal     = 0;
1835   pcbddc->DirichletBoundaries        = 0;
1836   pcbddc->DirichletBoundariesLocal   = 0;
1837   pcbddc->user_provided_isfordofs    = PETSC_FALSE;
1838   pcbddc->n_ISForDofs                = 0;
1839   pcbddc->n_ISForDofsLocal           = 0;
1840   pcbddc->ISForDofs                  = 0;
1841   pcbddc->ISForDofsLocal             = 0;
1842   pcbddc->ConstraintMatrix           = 0;
1843   pcbddc->use_exact_dirichlet_trick  = PETSC_TRUE;
1844   pcbddc->coarse_loc_to_glob         = 0;
1845   pcbddc->coarsening_ratio           = 8;
1846   pcbddc->current_level              = 0;
1847   pcbddc->max_levels                 = 0;
1848   pcbddc->use_coarse_estimates       = PETSC_FALSE;
1849   pcbddc->coarse_subassembling       = 0;
1850   pcbddc->coarse_subassembling_init  = 0;
1851 
1852   /* create local graph structure */
1853   ierr = PCBDDCGraphCreate(&pcbddc->mat_graph);CHKERRQ(ierr);
1854 
1855   /* scaling */
1856   pcbddc->work_scaling          = 0;
1857   pcbddc->use_deluxe_scaling    = PETSC_FALSE;
1858   pcbddc->deluxe_threshold      = 1;
1859   pcbddc->deluxe_rebuild        = PETSC_FALSE;
1860   pcbddc->deluxe_layers         = -1;
1861   pcbddc->deluxe_use_useradj    = PETSC_FALSE;
1862   pcbddc->deluxe_compute_rowadj = PETSC_TRUE;
1863 
1864   /* function pointers */
1865   pc->ops->apply               = PCApply_BDDC;
1866   pc->ops->applytranspose      = PCApplyTranspose_BDDC;
1867   pc->ops->setup               = PCSetUp_BDDC;
1868   pc->ops->destroy             = PCDestroy_BDDC;
1869   pc->ops->setfromoptions      = PCSetFromOptions_BDDC;
1870   pc->ops->view                = 0;
1871   pc->ops->applyrichardson     = 0;
1872   pc->ops->applysymmetricleft  = 0;
1873   pc->ops->applysymmetricright = 0;
1874   pc->ops->presolve            = PCPreSolve_BDDC;
1875   pc->ops->postsolve           = PCPostSolve_BDDC;
1876 
1877   /* composing function */
1878   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",PCBDDCSetChangeOfBasisMat_BDDC);CHKERRQ(ierr);
1879   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",PCBDDCSetPrimalVerticesLocalIS_BDDC);CHKERRQ(ierr);
1880   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",PCBDDCSetCoarseningRatio_BDDC);CHKERRQ(ierr);
1881   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",PCBDDCSetLevel_BDDC);CHKERRQ(ierr);
1882   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",PCBDDCSetUseExactDirichlet_BDDC);CHKERRQ(ierr);
1883   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",PCBDDCSetLevels_BDDC);CHKERRQ(ierr);
1884   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNullSpace_C",PCBDDCSetNullSpace_BDDC);CHKERRQ(ierr);
1885   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",PCBDDCSetDirichletBoundaries_BDDC);CHKERRQ(ierr);
1886   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",PCBDDCSetDirichletBoundariesLocal_BDDC);CHKERRQ(ierr);
1887   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",PCBDDCSetNeumannBoundaries_BDDC);CHKERRQ(ierr);
1888   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",PCBDDCSetNeumannBoundariesLocal_BDDC);CHKERRQ(ierr);
1889   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",PCBDDCGetDirichletBoundaries_BDDC);CHKERRQ(ierr);
1890   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",PCBDDCGetDirichletBoundariesLocal_BDDC);CHKERRQ(ierr);
1891   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",PCBDDCGetNeumannBoundaries_BDDC);CHKERRQ(ierr);
1892   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",PCBDDCGetNeumannBoundariesLocal_BDDC);CHKERRQ(ierr);
1893   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",PCBDDCSetDofsSplitting_BDDC);CHKERRQ(ierr);
1894   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",PCBDDCSetDofsSplittingLocal_BDDC);CHKERRQ(ierr);
1895   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",PCBDDCSetLocalAdjacencyGraph_BDDC);CHKERRQ(ierr);
1896   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",PCBDDCCreateFETIDPOperators_BDDC);CHKERRQ(ierr);
1897   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",PCBDDCMatFETIDPGetRHS_BDDC);CHKERRQ(ierr);
1898   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",PCBDDCMatFETIDPGetSolution_BDDC);CHKERRQ(ierr);
1899   PetscFunctionReturn(0);
1900 }
1901 
1902