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