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