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