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