xref: /petsc/src/ksp/pc/impls/bddc/bddc.c (revision f4ddd8eecafc09061839cfbaf2bc8c47641ebc86)
1 /* TODOLIST
2 
3    ConstraintsSetup
4    - assure same constraints between neighbours by sorting vals by global index before SVD!
5    - tolerances for constraints as an option (take care of single precision!)
6    - Allow different constraints customizations among different linear solves (requires also reset/destroy of ksp_R and coarse_ksp)
7    - MAT_IGNORE_ZERO_ENTRIES for Constraints Matrix
8 
9    Solvers
10    - Try to reduce the work when reusing the solvers
11    - Add support for reuse fill and cholecky factor for coarse solver (similar to local solvers)
12    - reuse already allocated coarse matrix if possible
13    - Propagate ksp prefixes for solvers to mat objects?
14    - Propagate nearnullspace info among levels
15 
16    User interface
17    - Change SetNeumannBoundaries to SetNeumannBoundariesLocal and provide new SetNeumannBoundaries (same Dirichlet)
18    - Negative indices in dirichlet and Neumann is should be skipped (now they cause out-of-bounds access)
19    - Provide PCApplyTranpose_BDDC
20    - DofSplitting and DM attached to pc?
21 
22    Debugging output
23    - Better management of verbosity levels of debugging output
24    - Crashes on some architecture -> call SynchronizedAllow before every SynchronizedPrintf
25 
26    Build
27    - make runexe59
28 
29    Extra
30    - Is it possible to work with PCBDDCGraph on boundary indices only (less memory consumed)?
31    - Why options for "pc_bddc_coarse" solver gets propagated to "pc_bddc_coarse_1" solver?
32    - add support for computing h,H and related using coordinates?
33    - Change of basis approach does not work with my nonlinear mechanics example. why? (seems not an issue with l2gmap)
34    - Better management in PCIS code
35    - BDDC with MG framework?
36 
37    FETIDP
38    - Move FETIDP code to its own classes
39 
40    MATIS related operations contained in BDDC code
41    - Provide general case for subassembling
42    - Preallocation routines in MatConvert_IS_AIJ
43 
44 */
45 
46 /* ----------------------------------------------------------------------------------------------------------------------------------------------
47    Implementation of BDDC preconditioner based on:
48    C. Dohrmann "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149-168, March 2007
49    ---------------------------------------------------------------------------------------------------------------------------------------------- */
50 
51 #include "bddc.h" /*I "petscpc.h" I*/  /* includes for fortran wrappers */
52 #include "bddcprivate.h"
53 #include <petscblaslapack.h>
54 
55 /* -------------------------------------------------------------------------- */
56 #undef __FUNCT__
57 #define __FUNCT__ "PCSetFromOptions_BDDC"
58 PetscErrorCode PCSetFromOptions_BDDC(PC pc)
59 {
60   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
61   PetscErrorCode ierr;
62 
63   PetscFunctionBegin;
64   ierr = PetscOptionsHead("BDDC options");CHKERRQ(ierr);
65   /* Verbose debugging */
66   ierr = PetscOptionsInt("-pc_bddc_check_level","Verbose output for PCBDDC (intended for debug)","none",pcbddc->dbg_flag,&pcbddc->dbg_flag,NULL);CHKERRQ(ierr);
67   /* Primal space cumstomization */
68   ierr = PetscOptionsBool("-pc_bddc_use_vertices","Use or not corner dofs in coarse space","none",pcbddc->use_vertices,&pcbddc->use_vertices,NULL);CHKERRQ(ierr);
69   ierr = PetscOptionsBool("-pc_bddc_use_edges","Use or not edge constraints in coarse space","none",pcbddc->use_edges,&pcbddc->use_edges,NULL);CHKERRQ(ierr);
70   ierr = PetscOptionsBool("-pc_bddc_use_faces","Use or not face constraints in coarse space","none",pcbddc->use_faces,&pcbddc->use_faces,NULL);CHKERRQ(ierr);
71   /* Change of basis */
72   ierr = PetscOptionsBool("-pc_bddc_use_change_of_basis","Use or not change of basis on local edge nodes","none",pcbddc->use_change_of_basis,&pcbddc->use_change_of_basis,NULL);CHKERRQ(ierr);
73   ierr = PetscOptionsBool("-pc_bddc_use_change_on_faces","Use or not change of basis on local face nodes","none",pcbddc->use_change_on_faces,&pcbddc->use_change_on_faces,NULL);CHKERRQ(ierr);
74   if (!pcbddc->use_change_of_basis) {
75     pcbddc->use_change_on_faces = PETSC_FALSE;
76   }
77   /* Switch between M_2 (default) and M_3 preconditioners (as defined by C. Dohrmann in the ref. article) */
78   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);
79   ierr = PetscOptionsInt("-pc_bddc_coarsening_ratio","Set coarsening ratio used in multilevel coarsening","none",pcbddc->coarsening_ratio,&pcbddc->coarsening_ratio,NULL);CHKERRQ(ierr);
80   ierr = PetscOptionsInt("-pc_bddc_levels","Set maximum number of levels for multilevel","none",pcbddc->max_levels,&pcbddc->max_levels,NULL);CHKERRQ(ierr);
81   ierr = PetscOptionsBool("-pc_bddc_use_deluxe_scaling","Use deluxe scaling for BDDC","none",pcbddc->use_deluxe_scaling,&pcbddc->use_deluxe_scaling,NULL);CHKERRQ(ierr);
82   ierr = PetscOptionsTail();CHKERRQ(ierr);
83   PetscFunctionReturn(0);
84 }
85 /* -------------------------------------------------------------------------- */
86 #undef __FUNCT__
87 #define __FUNCT__ "PCBDDCSetPrimalVerticesLocalIS_BDDC"
88 static PetscErrorCode PCBDDCSetPrimalVerticesLocalIS_BDDC(PC pc, IS PrimalVertices)
89 {
90   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
91   PetscErrorCode ierr;
92 
93   PetscFunctionBegin;
94   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
95   ierr = PetscObjectReference((PetscObject)PrimalVertices);CHKERRQ(ierr);
96   pcbddc->user_primal_vertices = PrimalVertices;
97   PetscFunctionReturn(0);
98 }
99 #undef __FUNCT__
100 #define __FUNCT__ "PCBDDCSetPrimalVerticesLocalIS"
101 /*@
102  PCBDDCSetPrimalVerticesLocalIS - Set additional user defined primal vertices in PCBDDC
103 
104    Not collective
105 
106    Input Parameters:
107 +  pc - the preconditioning context
108 -  PrimalVertices - index set of primal vertices in local numbering
109 
110    Level: intermediate
111 
112    Notes:
113 
114 .seealso: PCBDDC
115 @*/
116 PetscErrorCode PCBDDCSetPrimalVerticesLocalIS(PC pc, IS PrimalVertices)
117 {
118   PetscErrorCode ierr;
119 
120   PetscFunctionBegin;
121   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
122   PetscValidHeaderSpecific(PrimalVertices,IS_CLASSID,2);
123   ierr = PetscTryMethod(pc,"PCBDDCSetPrimalVerticesLocalIS_C",(PC,IS),(pc,PrimalVertices));CHKERRQ(ierr);
124   PetscFunctionReturn(0);
125 }
126 /* -------------------------------------------------------------------------- */
127 #undef __FUNCT__
128 #define __FUNCT__ "PCBDDCSetCoarseningRatio_BDDC"
129 static PetscErrorCode PCBDDCSetCoarseningRatio_BDDC(PC pc,PetscInt k)
130 {
131   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
132 
133   PetscFunctionBegin;
134   pcbddc->coarsening_ratio = k;
135   PetscFunctionReturn(0);
136 }
137 
138 #undef __FUNCT__
139 #define __FUNCT__ "PCBDDCSetCoarseningRatio"
140 /*@
141  PCBDDCSetCoarseningRatio - Set coarsening ratio used in multilevel
142 
143    Logically collective on PC
144 
145    Input Parameters:
146 +  pc - the preconditioning context
147 -  k - coarsening ratio (H/h at the coarser level)
148 
149    Approximatively k subdomains at the finer level will be aggregated into a single subdomain at the coarser level
150 
151    Level: intermediate
152 
153    Notes:
154 
155 .seealso: PCBDDC
156 @*/
157 PetscErrorCode PCBDDCSetCoarseningRatio(PC pc,PetscInt k)
158 {
159   PetscErrorCode ierr;
160 
161   PetscFunctionBegin;
162   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
163   PetscValidLogicalCollectiveInt(pc,k,2);
164   ierr = PetscTryMethod(pc,"PCBDDCSetCoarseningRatio_C",(PC,PetscInt),(pc,k));CHKERRQ(ierr);
165   PetscFunctionReturn(0);
166 }
167 
168 /* The following functions (PCBDDCSetUseExactDirichlet PCBDDCSetLevel) are not public */
169 #undef __FUNCT__
170 #define __FUNCT__ "PCBDDCSetUseExactDirichlet_BDDC"
171 static PetscErrorCode PCBDDCSetUseExactDirichlet_BDDC(PC pc,PetscBool flg)
172 {
173   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
174 
175   PetscFunctionBegin;
176   pcbddc->use_exact_dirichlet_trick = flg;
177   PetscFunctionReturn(0);
178 }
179 
180 #undef __FUNCT__
181 #define __FUNCT__ "PCBDDCSetUseExactDirichlet"
182 PetscErrorCode PCBDDCSetUseExactDirichlet(PC pc,PetscBool flg)
183 {
184   PetscErrorCode ierr;
185 
186   PetscFunctionBegin;
187   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
188   PetscValidLogicalCollectiveBool(pc,flg,2);
189   ierr = PetscTryMethod(pc,"PCBDDCSetUseExactDirichlet_C",(PC,PetscBool),(pc,flg));CHKERRQ(ierr);
190   PetscFunctionReturn(0);
191 }
192 
193 #undef __FUNCT__
194 #define __FUNCT__ "PCBDDCSetLevel_BDDC"
195 static PetscErrorCode PCBDDCSetLevel_BDDC(PC pc,PetscInt level)
196 {
197   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
198 
199   PetscFunctionBegin;
200   pcbddc->current_level = level;
201   PetscFunctionReturn(0);
202 }
203 
204 #undef __FUNCT__
205 #define __FUNCT__ "PCBDDCSetLevel"
206 PetscErrorCode PCBDDCSetLevel(PC pc,PetscInt level)
207 {
208   PetscErrorCode ierr;
209 
210   PetscFunctionBegin;
211   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
212   PetscValidLogicalCollectiveInt(pc,level,2);
213   ierr = PetscTryMethod(pc,"PCBDDCSetLevel_C",(PC,PetscInt),(pc,level));CHKERRQ(ierr);
214   PetscFunctionReturn(0);
215 }
216 
217 #undef __FUNCT__
218 #define __FUNCT__ "PCBDDCSetLevels_BDDC"
219 static PetscErrorCode PCBDDCSetLevels_BDDC(PC pc,PetscInt levels)
220 {
221   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
222 
223   PetscFunctionBegin;
224   pcbddc->max_levels = levels;
225   PetscFunctionReturn(0);
226 }
227 
228 #undef __FUNCT__
229 #define __FUNCT__ "PCBDDCSetLevels"
230 /*@
231  PCBDDCSetLevels - Sets the maximum number of levels for multilevel
232 
233    Logically collective on PC
234 
235    Input Parameters:
236 +  pc - the preconditioning context
237 -  levels - the maximum number of levels (max 9)
238 
239    Default value is 0, i.e. traditional one-level BDDC
240 
241    Level: intermediate
242 
243    Notes:
244 
245 .seealso: PCBDDC
246 @*/
247 PetscErrorCode PCBDDCSetLevels(PC pc,PetscInt levels)
248 {
249   PetscErrorCode ierr;
250 
251   PetscFunctionBegin;
252   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
253   PetscValidLogicalCollectiveInt(pc,levels,2);
254   ierr = PetscTryMethod(pc,"PCBDDCSetLevels_C",(PC,PetscInt),(pc,levels));CHKERRQ(ierr);
255   PetscFunctionReturn(0);
256 }
257 /* -------------------------------------------------------------------------- */
258 
259 #undef __FUNCT__
260 #define __FUNCT__ "PCBDDCSetNullSpace_BDDC"
261 static PetscErrorCode PCBDDCSetNullSpace_BDDC(PC pc,MatNullSpace NullSpace)
262 {
263   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
264   PetscErrorCode ierr;
265 
266   PetscFunctionBegin;
267   ierr = PetscObjectReference((PetscObject)NullSpace);CHKERRQ(ierr);
268   ierr = MatNullSpaceDestroy(&pcbddc->NullSpace);CHKERRQ(ierr);
269   pcbddc->NullSpace = NullSpace;
270   PetscFunctionReturn(0);
271 }
272 
273 #undef __FUNCT__
274 #define __FUNCT__ "PCBDDCSetNullSpace"
275 /*@
276  PCBDDCSetNullSpace - Set nullspace for BDDC operator
277 
278    Logically collective on PC and MatNullSpace
279 
280    Input Parameters:
281 +  pc - the preconditioning context
282 -  NullSpace - Null space of the linear operator to be preconditioned (Pmat)
283 
284    Level: intermediate
285 
286    Notes:
287 
288 .seealso: PCBDDC
289 @*/
290 PetscErrorCode PCBDDCSetNullSpace(PC pc,MatNullSpace NullSpace)
291 {
292   PetscErrorCode ierr;
293 
294   PetscFunctionBegin;
295   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
296   PetscValidHeaderSpecific(NullSpace,MAT_NULLSPACE_CLASSID,2);
297   PetscCheckSameComm(pc,1,NullSpace,2);
298   ierr = PetscTryMethod(pc,"PCBDDCSetNullSpace_C",(PC,MatNullSpace),(pc,NullSpace));CHKERRQ(ierr);
299   PetscFunctionReturn(0);
300 }
301 /* -------------------------------------------------------------------------- */
302 
303 #undef __FUNCT__
304 #define __FUNCT__ "PCBDDCSetDirichletBoundaries_BDDC"
305 static PetscErrorCode PCBDDCSetDirichletBoundaries_BDDC(PC pc,IS DirichletBoundaries)
306 {
307   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
308   PetscErrorCode ierr;
309 
310   PetscFunctionBegin;
311   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
312   ierr = PetscObjectReference((PetscObject)DirichletBoundaries);CHKERRQ(ierr);
313   pcbddc->DirichletBoundaries=DirichletBoundaries;
314   PetscFunctionReturn(0);
315 }
316 
317 #undef __FUNCT__
318 #define __FUNCT__ "PCBDDCSetDirichletBoundaries"
319 /*@
320  PCBDDCSetDirichletBoundaries - Set IS defining Dirichlet boundaries for the global problem.
321 
322    Not collective
323 
324    Input Parameters:
325 +  pc - the preconditioning context
326 -  DirichletBoundaries - sequential IS defining the subdomain part of Dirichlet boundaries (in local ordering)
327 
328    Level: intermediate
329 
330    Notes:
331 
332 .seealso: PCBDDC
333 @*/
334 PetscErrorCode PCBDDCSetDirichletBoundaries(PC pc,IS DirichletBoundaries)
335 {
336   PetscErrorCode ierr;
337 
338   PetscFunctionBegin;
339   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
340   PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2);
341   ierr = PetscTryMethod(pc,"PCBDDCSetDirichletBoundaries_C",(PC,IS),(pc,DirichletBoundaries));CHKERRQ(ierr);
342   PetscFunctionReturn(0);
343 }
344 /* -------------------------------------------------------------------------- */
345 
346 #undef __FUNCT__
347 #define __FUNCT__ "PCBDDCSetNeumannBoundaries_BDDC"
348 static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc,IS NeumannBoundaries)
349 {
350   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
351   PetscErrorCode ierr;
352 
353   PetscFunctionBegin;
354   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
355   ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr);
356   pcbddc->NeumannBoundaries=NeumannBoundaries;
357   PetscFunctionReturn(0);
358 }
359 
360 #undef __FUNCT__
361 #define __FUNCT__ "PCBDDCSetNeumannBoundaries"
362 /*@
363  PCBDDCSetNeumannBoundaries - Set IS defining Neumann boundaries for the global problem.
364 
365    Not collective
366 
367    Input Parameters:
368 +  pc - the preconditioning context
369 -  NeumannBoundaries - sequential IS defining the subdomain part of Neumann boundaries (in local ordering)
370 
371    Level: intermediate
372 
373    Notes:
374 
375 .seealso: PCBDDC
376 @*/
377 PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc,IS NeumannBoundaries)
378 {
379   PetscErrorCode ierr;
380 
381   PetscFunctionBegin;
382   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
383   PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2);
384   ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundaries_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr);
385   PetscFunctionReturn(0);
386 }
387 /* -------------------------------------------------------------------------- */
388 
389 #undef __FUNCT__
390 #define __FUNCT__ "PCBDDCGetDirichletBoundaries_BDDC"
391 static PetscErrorCode PCBDDCGetDirichletBoundaries_BDDC(PC pc,IS *DirichletBoundaries)
392 {
393   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
394 
395   PetscFunctionBegin;
396   *DirichletBoundaries = pcbddc->DirichletBoundaries;
397   PetscFunctionReturn(0);
398 }
399 
400 #undef __FUNCT__
401 #define __FUNCT__ "PCBDDCGetDirichletBoundaries"
402 /*@
403  PCBDDCGetDirichletBoundaries - Get IS for local Dirichlet boundaries
404 
405    Not collective
406 
407    Input Parameters:
408 .  pc - the preconditioning context
409 
410    Output Parameters:
411 .  DirichletBoundaries - index set defining the subdomain part of Dirichlet boundaries
412 
413    Level: intermediate
414 
415    Notes:
416 
417 .seealso: PCBDDC
418 @*/
419 PetscErrorCode PCBDDCGetDirichletBoundaries(PC pc,IS *DirichletBoundaries)
420 {
421   PetscErrorCode ierr;
422 
423   PetscFunctionBegin;
424   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
425   ierr = PetscUseMethod(pc,"PCBDDCGetDirichletBoundaries_C",(PC,IS*),(pc,DirichletBoundaries));CHKERRQ(ierr);
426   PetscFunctionReturn(0);
427 }
428 /* -------------------------------------------------------------------------- */
429 
430 #undef __FUNCT__
431 #define __FUNCT__ "PCBDDCGetNeumannBoundaries_BDDC"
432 static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc,IS *NeumannBoundaries)
433 {
434   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
435 
436   PetscFunctionBegin;
437   *NeumannBoundaries = pcbddc->NeumannBoundaries;
438   PetscFunctionReturn(0);
439 }
440 
441 #undef __FUNCT__
442 #define __FUNCT__ "PCBDDCGetNeumannBoundaries"
443 /*@
444  PCBDDCGetNeumannBoundaries - Get IS for local Neumann boundaries
445 
446    Not collective
447 
448    Input Parameters:
449 .  pc - the preconditioning context
450 
451    Output Parameters:
452 .  NeumannBoundaries - index set defining the subdomain part of Neumann boundaries
453 
454    Level: intermediate
455 
456    Notes:
457 
458 .seealso: PCBDDC
459 @*/
460 PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc,IS *NeumannBoundaries)
461 {
462   PetscErrorCode ierr;
463 
464   PetscFunctionBegin;
465   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
466   ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundaries_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr);
467   PetscFunctionReturn(0);
468 }
469 /* -------------------------------------------------------------------------- */
470 
471 #undef __FUNCT__
472 #define __FUNCT__ "PCBDDCSetLocalAdjacencyGraph_BDDC"
473 static PetscErrorCode PCBDDCSetLocalAdjacencyGraph_BDDC(PC pc, PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode)
474 {
475   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
476   PCBDDCGraph    mat_graph = pcbddc->mat_graph;
477   PetscErrorCode ierr;
478 
479   PetscFunctionBegin;
480   /* free old CSR */
481   ierr = PCBDDCGraphResetCSR(mat_graph);CHKERRQ(ierr);
482   /* TODO: PCBDDCGraphSetAdjacency */
483   /* get CSR into graph structure */
484   if (copymode == PETSC_COPY_VALUES) {
485     ierr = PetscMalloc((nvtxs+1)*sizeof(PetscInt),&mat_graph->xadj);CHKERRQ(ierr);
486     ierr = PetscMalloc(xadj[nvtxs]*sizeof(PetscInt),&mat_graph->adjncy);CHKERRQ(ierr);
487     ierr = PetscMemcpy(mat_graph->xadj,xadj,(nvtxs+1)*sizeof(PetscInt));CHKERRQ(ierr);
488     ierr = PetscMemcpy(mat_graph->adjncy,adjncy,xadj[nvtxs]*sizeof(PetscInt));CHKERRQ(ierr);
489   } else if (copymode == PETSC_OWN_POINTER) {
490     mat_graph->xadj = (PetscInt*)xadj;
491     mat_graph->adjncy = (PetscInt*)adjncy;
492   }
493   mat_graph->nvtxs_csr = nvtxs;
494   PetscFunctionReturn(0);
495 }
496 
497 #undef __FUNCT__
498 #define __FUNCT__ "PCBDDCSetLocalAdjacencyGraph"
499 /*@
500  PCBDDCSetLocalAdjacencyGraph - Set adjacency structure (CSR graph) of the local Neumann matrix
501 
502    Not collective
503 
504    Input Parameters:
505 +  pc - the preconditioning context
506 .  nvtxs - number of local vertices of the graph (i.e., the local size of your problem)
507 .  xadj, adjncy - the CSR graph
508 -  copymode - either PETSC_COPY_VALUES or PETSC_OWN_POINTER.
509 
510    Level: intermediate
511 
512    Notes:
513 
514 .seealso: PCBDDC,PetscCopyMode
515 @*/
516 PetscErrorCode PCBDDCSetLocalAdjacencyGraph(PC pc,PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode)
517 {
518   void (*f)(void) = 0;
519   PetscErrorCode ierr;
520 
521   PetscFunctionBegin;
522   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
523   PetscValidIntPointer(xadj,3);
524   PetscValidIntPointer(xadj,4);
525   if (copymode != PETSC_COPY_VALUES && copymode != PETSC_OWN_POINTER) {
526     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported copy mode %d in %s\n",copymode,__FUNCT__);
527   }
528   ierr = PetscTryMethod(pc,"PCBDDCSetLocalAdjacencyGraph_C",(PC,PetscInt,const PetscInt[],const PetscInt[],PetscCopyMode),(pc,nvtxs,xadj,adjncy,copymode));CHKERRQ(ierr);
529   /* free arrays if PCBDDC is not the PC type */
530   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",&f);CHKERRQ(ierr);
531   if (!f && copymode == PETSC_OWN_POINTER) {
532     ierr = PetscFree(xadj);CHKERRQ(ierr);
533     ierr = PetscFree(adjncy);CHKERRQ(ierr);
534   }
535   PetscFunctionReturn(0);
536 }
537 /* -------------------------------------------------------------------------- */
538 
539 #undef __FUNCT__
540 #define __FUNCT__ "PCBDDCSetDofsSplitting_BDDC"
541 static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
542 {
543   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
544   PetscInt i;
545   PetscErrorCode ierr;
546 
547   PetscFunctionBegin;
548   /* Destroy ISes if they were already set */
549   for (i=0;i<pcbddc->n_ISForDofs;i++) {
550     ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
551   }
552   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
553   /* allocate space then set */
554   ierr = PetscMalloc(n_is*sizeof(IS),&pcbddc->ISForDofs);CHKERRQ(ierr);
555   for (i=0;i<n_is;i++) {
556     ierr = PetscObjectReference((PetscObject)ISForDofs[i]);CHKERRQ(ierr);
557     pcbddc->ISForDofs[i]=ISForDofs[i];
558   }
559   pcbddc->n_ISForDofs=n_is;
560   pcbddc->user_provided_isfordofs = PETSC_TRUE;
561   PetscFunctionReturn(0);
562 }
563 
564 #undef __FUNCT__
565 #define __FUNCT__ "PCBDDCSetDofsSplitting"
566 /*@
567  PCBDDCSetDofsSplitting - Set index sets defining fields of the local Neumann matrix
568 
569    Not collective
570 
571    Input Parameters:
572 +  pc - the preconditioning context
573 -  n_is - number of index sets defining the fields
574 .  ISForDofs - array of IS describing the fields
575 
576    Level: intermediate
577 
578    Notes:
579 
580 .seealso: PCBDDC
581 @*/
582 PetscErrorCode PCBDDCSetDofsSplitting(PC pc,PetscInt n_is, IS ISForDofs[])
583 {
584   PetscInt       i;
585   PetscErrorCode ierr;
586 
587   PetscFunctionBegin;
588   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
589   for (i=0;i<n_is;i++) {
590     PetscValidHeaderSpecific(ISForDofs[i],IS_CLASSID,2);
591   }
592   ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplitting_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr);
593   PetscFunctionReturn(0);
594 }
595 /* -------------------------------------------------------------------------- */
596 #undef __FUNCT__
597 #define __FUNCT__ "PCPreSolve_BDDC"
598 /* -------------------------------------------------------------------------- */
599 /*
600    PCPreSolve_BDDC - Changes the right hand side and (if necessary) the initial
601                      guess if a transformation of basis approach has been selected.
602 
603    Input Parameter:
604 +  pc - the preconditioner contex
605 
606    Application Interface Routine: PCPreSolve()
607 
608    Notes:
609    The interface routine PCPreSolve() is not usually called directly by
610    the user, but instead is called by KSPSolve().
611 */
612 static PetscErrorCode PCPreSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
613 {
614   PetscErrorCode ierr;
615   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
616   PC_IS          *pcis = (PC_IS*)(pc->data);
617   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
618   Mat            temp_mat;
619   IS             dirIS;
620   PetscInt       dirsize,i,*is_indices;
621   PetscScalar    *array_x,*array_diagonal;
622   Vec            used_vec;
623   PetscBool      guess_nonzero,flg,bddc_has_dirichlet_boundaries;
624 
625   PetscFunctionBegin;
626   /* if we are working with cg, one dirichlet solve can be avoided during Krylov iterations */
627   if (ksp) {
628     PetscBool iscg;
629     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPCG,&iscg);CHKERRQ(ierr);
630     if (!iscg) {
631       ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
632     }
633   }
634   /* Creates parallel work vectors used in presolve */
635   if (!pcbddc->original_rhs) {
636     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs);CHKERRQ(ierr);
637   }
638   if (!pcbddc->temp_solution) {
639     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->temp_solution);CHKERRQ(ierr);
640   }
641   if (x) {
642     ierr = PetscObjectReference((PetscObject)x);CHKERRQ(ierr);
643     used_vec = x;
644   } else {
645     ierr = PetscObjectReference((PetscObject)pcbddc->temp_solution);CHKERRQ(ierr);
646     used_vec = pcbddc->temp_solution;
647     ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
648   }
649   /* hack into ksp data structure PCPreSolve comes earlier in src/ksp/ksp/interface/itfunc.c */
650   if (ksp) {
651     ierr = KSPGetInitialGuessNonzero(ksp,&guess_nonzero);CHKERRQ(ierr);
652     if (!guess_nonzero) {
653       ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
654     }
655   }
656 
657   /* TODO: remove when Dirichlet boundaries will be shared */
658   ierr = PCBDDCGetDirichletBoundaries(pc,&dirIS);CHKERRQ(ierr);
659   flg = PETSC_FALSE;
660   if (dirIS) flg = PETSC_TRUE;
661   ierr = MPI_Allreduce(&flg,&bddc_has_dirichlet_boundaries,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
662 
663   /* store the original rhs */
664   ierr = VecCopy(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
665 
666   /* Take into account zeroed rows -> change rhs and store solution removed */
667   if (rhs && bddc_has_dirichlet_boundaries) {
668     ierr = MatGetDiagonal(pc->pmat,pcis->vec1_global);CHKERRQ(ierr);
669     ierr = VecPointwiseDivide(pcis->vec1_global,rhs,pcis->vec1_global);CHKERRQ(ierr);
670     ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
671     ierr = VecScatterEnd(matis->ctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
672     ierr = VecScatterBegin(matis->ctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
673     ierr = VecScatterEnd(matis->ctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
674     if (dirIS) {
675       ierr = ISGetSize(dirIS,&dirsize);CHKERRQ(ierr);
676       ierr = VecGetArray(pcis->vec1_N,&array_x);CHKERRQ(ierr);
677       ierr = VecGetArray(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr);
678       ierr = ISGetIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
679       for (i=0; i<dirsize; i++) array_x[is_indices[i]] = array_diagonal[is_indices[i]];
680       ierr = ISRestoreIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
681       ierr = VecRestoreArray(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr);
682       ierr = VecRestoreArray(pcis->vec1_N,&array_x);CHKERRQ(ierr);
683     }
684     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
685     ierr = VecScatterEnd(matis->ctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
686 
687     /* remove the computed solution from the rhs */
688     ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr);
689     ierr = MatMultAdd(pc->pmat,used_vec,rhs,rhs);CHKERRQ(ierr);
690     ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr);
691   }
692 
693   /* store partially computed solution and set initial guess */
694   if (x) {
695     ierr = VecCopy(used_vec,pcbddc->temp_solution);CHKERRQ(ierr);
696     ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
697     if (pcbddc->use_exact_dirichlet_trick) {
698       ierr = VecScatterBegin(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
699       ierr = VecScatterEnd  (pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
700       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
701       ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
702       ierr = VecScatterEnd  (pcis->global_to_D,pcis->vec2_D,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
703       if (ksp) {
704         ierr = KSPSetInitialGuessNonzero(ksp,PETSC_TRUE);CHKERRQ(ierr);
705       }
706     }
707   }
708 
709   /* prepare MatMult and rhs for solver */
710   if (pcbddc->use_change_of_basis) {
711     /* swap pointers for local matrices */
712     temp_mat = matis->A;
713     matis->A = pcbddc->local_mat;
714     pcbddc->local_mat = temp_mat;
715     if (rhs) {
716       /* Get local rhs and apply transformation of basis */
717       ierr = VecScatterBegin(pcis->global_to_B,rhs,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
718       ierr = VecScatterEnd  (pcis->global_to_B,rhs,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
719       /* from original basis to modified basis */
720       ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
721       /* put back modified values into the global vec using INSERT_VALUES copy mode */
722       ierr = VecScatterBegin(pcis->global_to_B,pcis->vec2_B,rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
723       ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec2_B,rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
724     }
725   }
726 
727   /* remove nullspace if present */
728   if (ksp && pcbddc->NullSpace) {
729     ierr = MatNullSpaceRemove(pcbddc->NullSpace,used_vec);CHKERRQ(ierr);
730     ierr = MatNullSpaceRemove(pcbddc->NullSpace,rhs);CHKERRQ(ierr);
731   }
732   ierr = VecDestroy(&used_vec);CHKERRQ(ierr);
733   PetscFunctionReturn(0);
734 }
735 /* -------------------------------------------------------------------------- */
736 #undef __FUNCT__
737 #define __FUNCT__ "PCPostSolve_BDDC"
738 /* -------------------------------------------------------------------------- */
739 /*
740    PCPostSolve_BDDC - Changes the computed solution if a transformation of basis
741                      approach has been selected. Also, restores rhs to its original state.
742 
743    Input Parameter:
744 +  pc - the preconditioner contex
745 
746    Application Interface Routine: PCPostSolve()
747 
748    Notes:
749    The interface routine PCPostSolve() is not usually called directly by
750    the user, but instead is called by KSPSolve().
751 */
752 static PetscErrorCode PCPostSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
753 {
754   PetscErrorCode ierr;
755   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
756   PC_IS          *pcis   = (PC_IS*)(pc->data);
757   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
758   Mat            temp_mat;
759 
760   PetscFunctionBegin;
761   if (pcbddc->use_change_of_basis) {
762     /* swap pointers for local matrices */
763     temp_mat = matis->A;
764     matis->A = pcbddc->local_mat;
765     pcbddc->local_mat = temp_mat;
766   }
767   if (pcbddc->use_change_of_basis && x) {
768     /* Get Local boundary and apply transformation of basis to solution vector */
769     ierr = VecScatterBegin(pcis->global_to_B,x,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
770     ierr = VecScatterEnd  (pcis->global_to_B,x,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
771     /* from modified basis to original basis */
772     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
773     /* put back modified values into the global vec using INSERT_VALUES copy mode */
774     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec2_B,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
775     ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec2_B,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
776   }
777   /* add solution removed in presolve */
778   if (x) {
779     ierr = VecAXPY(x,1.0,pcbddc->temp_solution);CHKERRQ(ierr);
780   }
781   /* restore rhs to its original state */
782   if (rhs) {
783     ierr = VecCopy(pcbddc->original_rhs,rhs);CHKERRQ(ierr);
784   }
785   PetscFunctionReturn(0);
786 }
787 /* -------------------------------------------------------------------------- */
788 #undef __FUNCT__
789 #define __FUNCT__ "PCSetUp_BDDC"
790 /* -------------------------------------------------------------------------- */
791 /*
792    PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner
793                   by setting data structures and options.
794 
795    Input Parameter:
796 +  pc - the preconditioner context
797 
798    Application Interface Routine: PCSetUp()
799 
800    Notes:
801    The interface routine PCSetUp() is not usually called directly by
802    the user, but instead is called by PCApply() if necessary.
803 */
804 PetscErrorCode PCSetUp_BDDC(PC pc)
805 {
806   PetscErrorCode   ierr;
807   PC_BDDC*         pcbddc = (PC_BDDC*)pc->data;
808   MatNullSpace     nearnullspace;
809   const Vec        *nearnullvecs,*onearnullvecs;
810   MatStructure     flag;
811   PetscObjectState state;
812   PetscInt         nnsp_size,onnsp_size;
813   PetscBool        computeis,computetopography,computesolvers;
814   PetscBool        new_nearnullspace_provided,nnsp_has_cnst,onnsp_has_cnst;
815 
816   PetscFunctionBegin;
817   /* the following lines of code should be replaced by a better logic between PCIS, PCNN, PCBDDC and other future nonoverlapping preconditioners */
818   /* PCIS does not support MatStructure flags different from SAME_PRECONDITIONER */
819   /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup
820      Also, BDDC directly build the Dirichlet problem */
821 
822   /* split work */
823   if (pc->setupcalled) {
824     computeis = PETSC_FALSE;
825     ierr = PCGetOperators(pc,NULL,NULL,&flag);CHKERRQ(ierr);
826     if (flag == SAME_PRECONDITIONER) {
827       PetscFunctionReturn(0);
828     } else if (flag == SAME_NONZERO_PATTERN) {
829       computetopography = PETSC_FALSE;
830       computesolvers = PETSC_TRUE;
831     } else { /* DIFFERENT_NONZERO_PATTERN */
832       computetopography = PETSC_TRUE;
833       computesolvers = PETSC_TRUE;
834     }
835   } else {
836     computeis = PETSC_TRUE;
837     computetopography = PETSC_TRUE;
838     computesolvers = PETSC_TRUE;
839   }
840 
841   /* Get stdout for dbg */
842   if (pcbddc->dbg_flag && !pcbddc->dbg_viewer) {
843     ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)pc),&pcbddc->dbg_viewer);CHKERRQ(ierr);
844     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
845     if (pcbddc->current_level) {
846       ierr = PetscViewerASCIIAddTab(pcbddc->dbg_viewer,2);CHKERRQ(ierr);
847     }
848   }
849 
850   /* Set up all the "iterative substructuring" common block without computing solvers */
851   if (computeis) {
852     /* HACK INTO PCIS */
853     PC_IS* pcis = (PC_IS*)pc->data;
854     pcis->computesolvers = PETSC_FALSE;
855     ierr = PCISSetUp(pc);CHKERRQ(ierr);
856   }
857 
858   /* Analyze interface */
859   if (computetopography) {
860     ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
861   }
862 
863   /* infer if NullSpace object attached to Mat via MatSetNearNullSpace has changed */
864   new_nearnullspace_provided = PETSC_FALSE;
865   ierr = MatGetNearNullSpace(pc->pmat,&nearnullspace);CHKERRQ(ierr);
866   if (pcbddc->onearnullspace) { /* already used nearnullspace */
867     if (!nearnullspace) { /* near null space attached to mat has been destroyed */
868       new_nearnullspace_provided = PETSC_TRUE;
869     } else {
870       /* determine if the two nullspaces are different (should be lightweight) */
871       if (nearnullspace != pcbddc->onearnullspace) {
872         new_nearnullspace_provided = PETSC_TRUE;
873       } else { /* maybe the user has changed the content of the nearnullspace */
874         ierr = MatNullSpaceGetVecs(nearnullspace,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
875         ierr = MatNullSpaceGetVecs(pcbddc->onearnullspace,&onnsp_has_cnst,&onnsp_size,&onearnullvecs);CHKERRQ(ierr);
876         if ( (nnsp_has_cnst != onnsp_has_cnst) || (nnsp_size != onnsp_size) ) {
877           new_nearnullspace_provided = PETSC_TRUE;
878         } else { /* nullspaces have the same size, so check vectors or their ObjectStateId */
879           PetscInt i;
880           for (i=0;i<nnsp_size;i++) {
881             ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&state);CHKERRQ(ierr);
882             if (nearnullvecs[i] != onearnullvecs[i] || pcbddc->onearnullvecs_state[i] != state) {
883               new_nearnullspace_provided = PETSC_TRUE;
884               break;
885             }
886           }
887         }
888       }
889     }
890   } else {
891     if (!nearnullspace) { /* both nearnullspaces are null */
892       new_nearnullspace_provided = PETSC_FALSE;
893     } else { /* nearnullspace attached later */
894       new_nearnullspace_provided = PETSC_TRUE;
895     }
896   }
897 
898   /* Setup constraints and related work vectors */
899   pcbddc->new_primal_space = PETSC_FALSE;
900   if (computetopography || new_nearnullspace_provided) {
901     ierr = PCBDDCConstraintsSetUp(pc);CHKERRQ(ierr);
902     /* Allocate needed local vectors (which depends on quantities defined during ConstraintsSetUp) */
903     ierr = PCBDDCSetUpLocalWorkVectors(pc);CHKERRQ(ierr);
904     /* set flag for primal space */
905     pcbddc->new_primal_space = PETSC_TRUE;
906   }
907 
908   if (computesolvers || pcbddc->new_primal_space) {
909     /* reset data */
910     ierr = PCBDDCScalingDestroy(pc);CHKERRQ(ierr);
911     /* Create coarse and local stuffs */
912     ierr = PCBDDCSetUpSolvers(pc);CHKERRQ(ierr);
913     ierr = PCBDDCScalingSetUp(pc);CHKERRQ(ierr);
914   }
915   if (pcbddc->dbg_flag && pcbddc->current_level) {
916     ierr = PetscViewerASCIISubtractTab(pcbddc->dbg_viewer,2);CHKERRQ(ierr);
917   }
918   PetscFunctionReturn(0);
919 }
920 
921 /* -------------------------------------------------------------------------- */
922 /*
923    PCApply_BDDC - Applies the BDDC preconditioner to a vector.
924 
925    Input Parameters:
926 .  pc - the preconditioner context
927 .  r - input vector (global)
928 
929    Output Parameter:
930 .  z - output vector (global)
931 
932    Application Interface Routine: PCApply()
933  */
934 #undef __FUNCT__
935 #define __FUNCT__ "PCApply_BDDC"
936 PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z)
937 {
938   PC_IS             *pcis = (PC_IS*)(pc->data);
939   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
940   PetscErrorCode    ierr;
941   const PetscScalar one = 1.0;
942   const PetscScalar m_one = -1.0;
943   const PetscScalar zero = 0.0;
944 
945 /* This code is similar to that provided in nn.c for PCNN
946    NN interface preconditioner changed to BDDC
947    Added support for M_3 preconditioner in the reference article (code is active if pcbddc->switch_static = PETSC_TRUE) */
948 
949   PetscFunctionBegin;
950   if (!pcbddc->use_exact_dirichlet_trick) {
951     /* First Dirichlet solve */
952     ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
953     ierr = VecScatterEnd  (pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
954     ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
955     /*
956       Assembling right hand side for BDDC operator
957       - pcis->vec1_D for the Dirichlet part (if needed, i.e. prec_flag=PETSC_TRUE)
958       - pcis->vec1_B the interface part of the global vector z
959     */
960     ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
961     ierr = MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
962     if (pcbddc->switch_static) { ierr = MatMultAdd(pcis->A_II,pcis->vec2_D,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
963     ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
964     ierr = VecCopy(r,z);CHKERRQ(ierr);
965     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
966     ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
967     ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr);
968   } else {
969     ierr = VecSet(pcis->vec1_D,zero);CHKERRQ(ierr);
970     ierr = VecSet(pcis->vec2_D,zero);CHKERRQ(ierr);
971     ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr);
972   }
973 
974   /* Apply interface preconditioner
975      input/output vecs: pcis->vec1_B and pcis->vec1_D */
976   ierr = PCBDDCApplyInterfacePreconditioner(pc);CHKERRQ(ierr);
977 
978   /* Apply transpose of partition of unity operator */
979   ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr);
980 
981   /* Second Dirichlet solve and assembling of output */
982   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
983   ierr = VecScatterEnd  (pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
984   ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
985   if (pcbddc->switch_static) { ierr = MatMultAdd(pcis->A_II,pcis->vec1_D,pcis->vec3_D,pcis->vec3_D);CHKERRQ(ierr); }
986   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D);CHKERRQ(ierr);
987   ierr = VecScale(pcis->vec4_D,m_one);CHKERRQ(ierr);
988   if (pcbddc->switch_static) { ierr = VecAXPY (pcis->vec4_D,one,pcis->vec1_D);CHKERRQ(ierr); }
989   ierr = VecAXPY (pcis->vec2_D,one,pcis->vec4_D);CHKERRQ(ierr);
990   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
991   ierr = VecScatterEnd  (pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
992   PetscFunctionReturn(0);
993 }
994 /* -------------------------------------------------------------------------- */
995 
996 #undef __FUNCT__
997 #define __FUNCT__ "PCDestroy_BDDC"
998 PetscErrorCode PCDestroy_BDDC(PC pc)
999 {
1000   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1001   PetscErrorCode ierr;
1002 
1003   PetscFunctionBegin;
1004   /* free data created by PCIS */
1005   ierr = PCISDestroy(pc);CHKERRQ(ierr);
1006   /* free BDDC custom data  */
1007   ierr = PCBDDCResetCustomization(pc);CHKERRQ(ierr);
1008   /* destroy objects related to topography */
1009   ierr = PCBDDCResetTopography(pc);CHKERRQ(ierr);
1010   /* free allocated graph structure */
1011   ierr = PetscFree(pcbddc->mat_graph);CHKERRQ(ierr);
1012   /* free data for scaling operator */
1013   ierr = PCBDDCScalingDestroy(pc);CHKERRQ(ierr);
1014   /* free solvers stuff */
1015   ierr = PCBDDCResetSolvers(pc);CHKERRQ(ierr);
1016   /* free global vectors needed in presolve */
1017   ierr = VecDestroy(&pcbddc->temp_solution);CHKERRQ(ierr);
1018   ierr = VecDestroy(&pcbddc->original_rhs);CHKERRQ(ierr);
1019   /* remove functions */
1020   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",NULL);CHKERRQ(ierr);
1021   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",NULL);CHKERRQ(ierr);
1022   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",NULL);CHKERRQ(ierr);
1023   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",NULL);CHKERRQ(ierr);
1024   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",NULL);CHKERRQ(ierr);
1025   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNullSpace_C",NULL);CHKERRQ(ierr);
1026   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",NULL);CHKERRQ(ierr);
1027   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",NULL);CHKERRQ(ierr);
1028   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",NULL);CHKERRQ(ierr);
1029   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",NULL);CHKERRQ(ierr);
1030   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",NULL);CHKERRQ(ierr);
1031   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",NULL);CHKERRQ(ierr);
1032   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",NULL);CHKERRQ(ierr);
1033   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",NULL);CHKERRQ(ierr);
1034   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",NULL);CHKERRQ(ierr);
1035   /* Free the private data structure */
1036   ierr = PetscFree(pc->data);CHKERRQ(ierr);
1037   PetscFunctionReturn(0);
1038 }
1039 /* -------------------------------------------------------------------------- */
1040 
1041 #undef __FUNCT__
1042 #define __FUNCT__ "PCBDDCMatFETIDPGetRHS_BDDC"
1043 static PetscErrorCode PCBDDCMatFETIDPGetRHS_BDDC(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
1044 {
1045   FETIDPMat_ctx  mat_ctx;
1046   PC_IS*         pcis;
1047   PC_BDDC*       pcbddc;
1048   PetscErrorCode ierr;
1049 
1050   PetscFunctionBegin;
1051   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
1052   pcis = (PC_IS*)mat_ctx->pc->data;
1053   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
1054 
1055   /* change of basis for physical rhs if needed
1056      It also changes the rhs in case of dirichlet boundaries */
1057   ierr = PCPreSolve_BDDC(mat_ctx->pc,NULL,standard_rhs,NULL);CHKERRQ(ierr);
1058   /* store vectors for computation of fetidp final solution */
1059   ierr = VecScatterBegin(pcis->global_to_D,standard_rhs,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1060   ierr = VecScatterEnd(pcis->global_to_D,standard_rhs,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1061   /* scale rhs since it should be unassembled */
1062   /* TODO use counter scaling? (also below) */
1063   ierr = VecScatterBegin(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1064   ierr = VecScatterEnd(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1065   /* Apply partition of unity */
1066   ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr);
1067   /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,standard_rhs,mat_ctx->temp_solution_B);CHKERRQ(ierr); */
1068   if (!pcbddc->switch_static) {
1069     /* compute partially subassembled Schur complement right-hand side */
1070     ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
1071     ierr = MatMult(pcis->A_BI,pcis->vec1_D,pcis->vec1_B);CHKERRQ(ierr);
1072     ierr = VecAXPY(mat_ctx->temp_solution_B,-1.0,pcis->vec1_B);CHKERRQ(ierr);
1073     ierr = VecSet(standard_rhs,0.0);CHKERRQ(ierr);
1074     ierr = VecScatterBegin(pcis->global_to_B,mat_ctx->temp_solution_B,standard_rhs,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1075     ierr = VecScatterEnd(pcis->global_to_B,mat_ctx->temp_solution_B,standard_rhs,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1076     /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,standard_rhs,mat_ctx->temp_solution_B);CHKERRQ(ierr); */
1077     ierr = VecScatterBegin(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1078     ierr = VecScatterEnd(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1079     ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr);
1080   }
1081   /* BDDC rhs */
1082   ierr = VecCopy(mat_ctx->temp_solution_B,pcis->vec1_B);CHKERRQ(ierr);
1083   if (pcbddc->switch_static) {
1084     ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
1085   }
1086   /* apply BDDC */
1087   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc);CHKERRQ(ierr);
1088   /* Application of B_delta and assembling of rhs for fetidp fluxes */
1089   ierr = VecSet(fetidp_flux_rhs,0.0);CHKERRQ(ierr);
1090   ierr = MatMult(mat_ctx->B_delta,pcis->vec1_B,mat_ctx->lambda_local);CHKERRQ(ierr);
1091   ierr = VecScatterBegin(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1092   ierr = VecScatterEnd  (mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1093   /* restore original rhs */
1094   ierr = VecCopy(pcbddc->original_rhs,standard_rhs);CHKERRQ(ierr);
1095   PetscFunctionReturn(0);
1096 }
1097 
1098 #undef __FUNCT__
1099 #define __FUNCT__ "PCBDDCMatFETIDPGetRHS"
1100 /*@
1101  PCBDDCMatFETIDPGetRHS - Compute the right-hand side for FETIDP linear system
1102 
1103    Collective
1104 
1105    Input Parameters:
1106 +  fetidp_mat   - the FETIDP matrix object obtained by calling PCBDDCCreateFETIDPOperators
1107 .  standard_rhs - the right-hand side for your linear system
1108 
1109    Output Parameters:
1110 -  fetidp_flux_rhs   - the right-hand side for the FETIDP linear system
1111 
1112    Level: developer
1113 
1114    Notes:
1115 
1116 .seealso: PCBDDC,PCBDDCCreateFETIDPOperators
1117 @*/
1118 PetscErrorCode PCBDDCMatFETIDPGetRHS(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
1119 {
1120   FETIDPMat_ctx  mat_ctx;
1121   PetscErrorCode ierr;
1122 
1123   PetscFunctionBegin;
1124   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
1125   ierr = PetscTryMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetRHS_C",(Mat,Vec,Vec),(fetidp_mat,standard_rhs,fetidp_flux_rhs));CHKERRQ(ierr);
1126   PetscFunctionReturn(0);
1127 }
1128 /* -------------------------------------------------------------------------- */
1129 
1130 #undef __FUNCT__
1131 #define __FUNCT__ "PCBDDCMatFETIDPGetSolution_BDDC"
1132 static PetscErrorCode PCBDDCMatFETIDPGetSolution_BDDC(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
1133 {
1134   FETIDPMat_ctx  mat_ctx;
1135   PC_IS*         pcis;
1136   PC_BDDC*       pcbddc;
1137   PetscErrorCode ierr;
1138 
1139   PetscFunctionBegin;
1140   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
1141   pcis = (PC_IS*)mat_ctx->pc->data;
1142   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
1143 
1144   /* apply B_delta^T */
1145   ierr = VecScatterBegin(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1146   ierr = VecScatterEnd  (mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1147   ierr = MatMultTranspose(mat_ctx->B_delta,mat_ctx->lambda_local,pcis->vec1_B);CHKERRQ(ierr);
1148   /* compute rhs for BDDC application */
1149   ierr = VecAYPX(pcis->vec1_B,-1.0,mat_ctx->temp_solution_B);CHKERRQ(ierr);
1150   if (pcbddc->switch_static) {
1151     ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
1152   }
1153   /* apply BDDC */
1154   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc);CHKERRQ(ierr);
1155   /* put values into standard global vector */
1156   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1157   ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1158   if (!pcbddc->switch_static) {
1159     /* compute values into the interior if solved for the partially subassembled Schur complement */
1160     ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec1_D);CHKERRQ(ierr);
1161     ierr = VecAXPY(mat_ctx->temp_solution_D,-1.0,pcis->vec1_D);CHKERRQ(ierr);
1162     ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
1163   }
1164   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec1_D,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1165   ierr = VecScatterEnd  (pcis->global_to_D,pcis->vec1_D,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1166   /* final change of basis if needed
1167      Is also sums the dirichlet part removed during RHS assembling */
1168   ierr = PCPostSolve_BDDC(mat_ctx->pc,NULL,NULL,standard_sol);CHKERRQ(ierr);
1169   PetscFunctionReturn(0);
1170 }
1171 
1172 #undef __FUNCT__
1173 #define __FUNCT__ "PCBDDCMatFETIDPGetSolution"
1174 /*@
1175  PCBDDCMatFETIDPGetSolution - Compute the physical solution from the solution of the FETIDP linear system
1176 
1177    Collective
1178 
1179    Input Parameters:
1180 +  fetidp_mat        - the FETIDP matrix obtained by calling PCBDDCCreateFETIDPOperators
1181 .  fetidp_flux_sol - the solution of the FETIDP linear system
1182 
1183    Output Parameters:
1184 -  standard_sol      - the solution defined on the physical domain
1185 
1186    Level: developer
1187 
1188    Notes:
1189 
1190 .seealso: PCBDDC,PCBDDCCreateFETIDPOperators
1191 @*/
1192 PetscErrorCode PCBDDCMatFETIDPGetSolution(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
1193 {
1194   FETIDPMat_ctx  mat_ctx;
1195   PetscErrorCode ierr;
1196 
1197   PetscFunctionBegin;
1198   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
1199   ierr = PetscTryMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetSolution_C",(Mat,Vec,Vec),(fetidp_mat,fetidp_flux_sol,standard_sol));CHKERRQ(ierr);
1200   PetscFunctionReturn(0);
1201 }
1202 /* -------------------------------------------------------------------------- */
1203 
1204 extern PetscErrorCode FETIDPMatMult(Mat,Vec,Vec);
1205 extern PetscErrorCode PCBDDCDestroyFETIDPMat(Mat);
1206 extern PetscErrorCode FETIDPPCApply(PC,Vec,Vec);
1207 extern PetscErrorCode PCBDDCDestroyFETIDPPC(PC);
1208 
1209 #undef __FUNCT__
1210 #define __FUNCT__ "PCBDDCCreateFETIDPOperators_BDDC"
1211 static PetscErrorCode PCBDDCCreateFETIDPOperators_BDDC(PC pc, Mat *fetidp_mat, PC *fetidp_pc)
1212 {
1213 
1214   FETIDPMat_ctx  fetidpmat_ctx;
1215   Mat            newmat;
1216   FETIDPPC_ctx   fetidppc_ctx;
1217   PC             newpc;
1218   MPI_Comm       comm;
1219   PetscErrorCode ierr;
1220 
1221   PetscFunctionBegin;
1222   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
1223   /* FETIDP linear matrix */
1224   ierr = PCBDDCCreateFETIDPMatContext(pc,&fetidpmat_ctx);CHKERRQ(ierr);
1225   ierr = PCBDDCSetupFETIDPMatContext(fetidpmat_ctx);CHKERRQ(ierr);
1226   ierr = MatCreateShell(comm,PETSC_DECIDE,PETSC_DECIDE,fetidpmat_ctx->n_lambda,fetidpmat_ctx->n_lambda,fetidpmat_ctx,&newmat);CHKERRQ(ierr);
1227   ierr = MatShellSetOperation(newmat,MATOP_MULT,(void (*)(void))FETIDPMatMult);CHKERRQ(ierr);
1228   ierr = MatShellSetOperation(newmat,MATOP_DESTROY,(void (*)(void))PCBDDCDestroyFETIDPMat);CHKERRQ(ierr);
1229   ierr = MatSetUp(newmat);CHKERRQ(ierr);
1230   /* FETIDP preconditioner */
1231   ierr = PCBDDCCreateFETIDPPCContext(pc,&fetidppc_ctx);CHKERRQ(ierr);
1232   ierr = PCBDDCSetupFETIDPPCContext(newmat,fetidppc_ctx);CHKERRQ(ierr);
1233   ierr = PCCreate(comm,&newpc);CHKERRQ(ierr);
1234   ierr = PCSetType(newpc,PCSHELL);CHKERRQ(ierr);
1235   ierr = PCShellSetContext(newpc,fetidppc_ctx);CHKERRQ(ierr);
1236   ierr = PCShellSetApply(newpc,FETIDPPCApply);CHKERRQ(ierr);
1237   ierr = PCShellSetDestroy(newpc,PCBDDCDestroyFETIDPPC);CHKERRQ(ierr);
1238   ierr = PCSetOperators(newpc,newmat,newmat,SAME_PRECONDITIONER);CHKERRQ(ierr);
1239   ierr = PCSetUp(newpc);CHKERRQ(ierr);
1240   /* return pointers for objects created */
1241   *fetidp_mat=newmat;
1242   *fetidp_pc=newpc;
1243   PetscFunctionReturn(0);
1244 }
1245 
1246 #undef __FUNCT__
1247 #define __FUNCT__ "PCBDDCCreateFETIDPOperators"
1248 /*@
1249  PCBDDCCreateFETIDPOperators - Create operators for FETIDP
1250 
1251    Collective
1252 
1253    Input Parameters:
1254 +  pc - the BDDC preconditioning context already setup
1255 
1256    Output Parameters:
1257 .  fetidp_mat - shell FETIDP matrix object
1258 .  fetidp_pc  - shell Dirichlet preconditioner for FETIDP matrix
1259 
1260    Options Database Keys:
1261 -    -fetidp_fullyredundant: use or not a fully redundant set of Lagrange multipliers
1262 
1263    Level: developer
1264 
1265    Notes:
1266      Currently the only operation provided for FETIDP matrix is MatMult
1267 
1268 .seealso: PCBDDC
1269 @*/
1270 PetscErrorCode PCBDDCCreateFETIDPOperators(PC pc, Mat *fetidp_mat, PC *fetidp_pc)
1271 {
1272   PetscErrorCode ierr;
1273 
1274   PetscFunctionBegin;
1275   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1276   if (pc->setupcalled) {
1277     ierr = PetscUseMethod(pc,"PCBDDCCreateFETIDPOperators_C",(PC,Mat*,PC*),(pc,fetidp_mat,fetidp_pc));CHKERRQ(ierr);
1278   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"You must call PCSetup_BDDC() first \n");
1279   PetscFunctionReturn(0);
1280 }
1281 /* -------------------------------------------------------------------------- */
1282 /*MC
1283    PCBDDC - Balancing Domain Decomposition by Constraints.
1284 
1285    An implementation of the BDDC preconditioner based on
1286 
1287 .vb
1288    [1] C. R. Dohrmann. "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149-168, March 2007
1289    [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
1290    [3] J. Mandel, B. Sousedik, C. R. Dohrmann. "Multispace and Multilevel BDDC", http://arxiv.org/abs/0712.3977
1291 .ve
1292 
1293    The matrix to be preconditioned (Pmat) must be of type MATIS.
1294 
1295    Currently works with MATIS matrices with local Neumann matrices of type MATSEQAIJ, MATSEQBAIJ or MATSEQSBAIJ, either with real or complex numbers.
1296 
1297    It also works with unsymmetric and indefinite problems.
1298 
1299    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.
1300 
1301    Approximate local solvers are automatically adapted for singular linear problems (see [1]) if the user has provided the nullspace using PCBDDCSetNullSpace
1302 
1303    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
1304 
1305    Constraints can be customized by attaching a MatNullSpace object to the MATIS matrix via MatSetNearNullSpace.
1306 
1307    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.
1308 
1309    The PETSc implementation also supports multilevel BDDC [3]. Coarse grids are partitioned using MatPartitioning object.
1310 
1311    Options Database Keys:
1312 
1313 .    -pc_bddc_use_vertices <1> - use or not vertices in primal space
1314 .    -pc_bddc_use_edges <1> - use or not edges in primal space
1315 .    -pc_bddc_use_faces <0> - use or not faces in primal space
1316 .    -pc_bddc_use_change_of_basis <0> - use change of basis approach (on edges only)
1317 .    -pc_bddc_use_change_on_faces <0> - use change of basis approach on faces if change of basis has been requested
1318 .    -pc_bddc_switch_static <0> - switches from M_2 to M_3 operator (see reference article [1])
1319 .    -pc_bddc_levels <0> - maximum number of levels for multilevel
1320 .    -pc_bddc_coarsening_ratio - H/h ratio at the coarser level
1321 -    -pc_bddc_check_level <0> - set verbosity level of debugging output
1322 
1323    Options for Dirichlet, Neumann or coarse solver can be set with
1324 .vb
1325       -pc_bddc_dirichlet_
1326       -pc_bddc_neumann_
1327       -pc_bddc_coarse_
1328 .ve
1329    e.g -pc_bddc_dirichlet_ksp_type richardson -pc_bddc_dirichlet_pc_type gamg
1330 
1331    When using a multilevel approach, solvers' options at the N-th level can be specified as
1332 .vb
1333       -pc_bddc_dirichlet_N_
1334       -pc_bddc_neumann_N_
1335       -pc_bddc_coarse_N_
1336 .ve
1337    Note that level number ranges from the finest 0 to the coarsest N
1338 
1339    Level: intermediate
1340 
1341    Developer notes:
1342      Currently does not work with KSPBCGS and other KSPs requiring the specialization of PCApplyTranspose
1343 
1344      New deluxe scaling operator will be available soon.
1345 
1346    Contributed by Stefano Zampini
1347 
1348 .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,  MATIS
1349 M*/
1350 
1351 #undef __FUNCT__
1352 #define __FUNCT__ "PCCreate_BDDC"
1353 PETSC_EXTERN PetscErrorCode PCCreate_BDDC(PC pc)
1354 {
1355   PetscErrorCode      ierr;
1356   PC_BDDC             *pcbddc;
1357 
1358   PetscFunctionBegin;
1359   /* Creates the private data structure for this preconditioner and attach it to the PC object. */
1360   ierr      = PetscNewLog(pc,PC_BDDC,&pcbddc);CHKERRQ(ierr);
1361   pc->data  = (void*)pcbddc;
1362 
1363   /* create PCIS data structure */
1364   ierr = PCISCreate(pc);CHKERRQ(ierr);
1365 
1366   /* BDDC customization */
1367   pcbddc->use_vertices        = PETSC_TRUE;
1368   pcbddc->use_edges           = PETSC_TRUE;
1369   pcbddc->use_faces           = PETSC_FALSE;
1370   pcbddc->use_change_of_basis = PETSC_FALSE;
1371   pcbddc->use_change_on_faces = PETSC_FALSE;
1372   pcbddc->switch_static       = PETSC_FALSE;
1373   pcbddc->use_nnsp_true       = PETSC_FALSE; /* not yet exposed */
1374   pcbddc->dbg_flag            = 0;
1375 
1376   pcbddc->coarse_size                = 0;
1377   pcbddc->new_primal_space           = PETSC_FALSE;
1378   pcbddc->global_primal_indices      = 0;
1379   pcbddc->onearnullspace             = 0;
1380   pcbddc->onearnullvecs_state        = 0;
1381   pcbddc->user_primal_vertices       = 0;
1382   pcbddc->NullSpace                  = 0;
1383   pcbddc->temp_solution              = 0;
1384   pcbddc->original_rhs               = 0;
1385   pcbddc->local_mat                  = 0;
1386   pcbddc->ChangeOfBasisMatrix        = 0;
1387   pcbddc->coarse_vec                 = 0;
1388   pcbddc->coarse_rhs                 = 0;
1389   pcbddc->coarse_ksp                 = 0;
1390   pcbddc->coarse_phi_B               = 0;
1391   pcbddc->coarse_phi_D               = 0;
1392   pcbddc->coarse_psi_B               = 0;
1393   pcbddc->coarse_psi_D               = 0;
1394   pcbddc->vec1_P                     = 0;
1395   pcbddc->vec1_R                     = 0;
1396   pcbddc->vec2_R                     = 0;
1397   pcbddc->local_auxmat1              = 0;
1398   pcbddc->local_auxmat2              = 0;
1399   pcbddc->R_to_B                     = 0;
1400   pcbddc->R_to_D                     = 0;
1401   pcbddc->ksp_D                      = 0;
1402   pcbddc->ksp_R                      = 0;
1403   pcbddc->NeumannBoundaries          = 0;
1404   pcbddc->user_provided_isfordofs    = PETSC_FALSE;
1405   pcbddc->n_ISForDofs                = 0;
1406   pcbddc->ISForDofs                  = 0;
1407   pcbddc->ConstraintMatrix           = 0;
1408   pcbddc->use_exact_dirichlet_trick  = PETSC_TRUE;
1409   pcbddc->coarse_loc_to_glob         = 0;
1410   pcbddc->coarsening_ratio           = 8;
1411   pcbddc->current_level              = 0;
1412   pcbddc->max_levels                 = 0;
1413 
1414   /* create local graph structure */
1415   ierr = PCBDDCGraphCreate(&pcbddc->mat_graph);CHKERRQ(ierr);
1416 
1417   /* scaling */
1418   pcbddc->use_deluxe_scaling         = PETSC_FALSE;
1419   pcbddc->work_scaling               = 0;
1420 
1421   /* function pointers */
1422   pc->ops->apply               = PCApply_BDDC;
1423   pc->ops->applytranspose      = 0;
1424   pc->ops->setup               = PCSetUp_BDDC;
1425   pc->ops->destroy             = PCDestroy_BDDC;
1426   pc->ops->setfromoptions      = PCSetFromOptions_BDDC;
1427   pc->ops->view                = 0;
1428   pc->ops->applyrichardson     = 0;
1429   pc->ops->applysymmetricleft  = 0;
1430   pc->ops->applysymmetricright = 0;
1431   pc->ops->presolve            = PCPreSolve_BDDC;
1432   pc->ops->postsolve           = PCPostSolve_BDDC;
1433 
1434   /* composing function */
1435   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",PCBDDCSetPrimalVerticesLocalIS_BDDC);CHKERRQ(ierr);
1436   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",PCBDDCSetCoarseningRatio_BDDC);CHKERRQ(ierr);
1437   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",PCBDDCSetLevel_BDDC);CHKERRQ(ierr);
1438   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",PCBDDCSetUseExactDirichlet_BDDC);CHKERRQ(ierr);
1439   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",PCBDDCSetLevels_BDDC);CHKERRQ(ierr);
1440   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNullSpace_C",PCBDDCSetNullSpace_BDDC);CHKERRQ(ierr);
1441   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",PCBDDCSetDirichletBoundaries_BDDC);CHKERRQ(ierr);
1442   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",PCBDDCSetNeumannBoundaries_BDDC);CHKERRQ(ierr);
1443   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",PCBDDCGetDirichletBoundaries_BDDC);CHKERRQ(ierr);
1444   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",PCBDDCGetNeumannBoundaries_BDDC);CHKERRQ(ierr);
1445   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",PCBDDCSetDofsSplitting_BDDC);CHKERRQ(ierr);
1446   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",PCBDDCSetLocalAdjacencyGraph_BDDC);CHKERRQ(ierr);
1447   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",PCBDDCCreateFETIDPOperators_BDDC);CHKERRQ(ierr);
1448   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",PCBDDCMatFETIDPGetRHS_BDDC);CHKERRQ(ierr);
1449   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",PCBDDCMatFETIDPGetSolution_BDDC);CHKERRQ(ierr);
1450   PetscFunctionReturn(0);
1451 }
1452 
1453