xref: /petsc/src/ksp/pc/impls/bddc/bddc.c (revision bc960bbfb30a081b8d72a268e9288db11c216b54)
153cdbc3dSStefano Zampini /* TODOLIST
2eb97c9d2SStefano Zampini 
3eb97c9d2SStefano Zampini    Solvers
4a0d3c3abSStefano Zampini    - Add support for cholesky for coarse solver (similar to local solvers)
5eb97c9d2SStefano Zampini    - Propagate ksp prefixes for solvers to mat objects?
6eb97c9d2SStefano Zampini 
7eb97c9d2SStefano Zampini    User interface
80f202f7eSStefano Zampini    - ** DM attached to pc?
9eb97c9d2SStefano Zampini 
10eb97c9d2SStefano Zampini    Debugging output
11b9b85e73SStefano Zampini    - * Better management of verbosity levels of debugging output
12eb97c9d2SStefano Zampini 
13eb97c9d2SStefano Zampini    Extra
14b9b85e73SStefano Zampini    - *** Is it possible to work with PCBDDCGraph on boundary indices only (less memory consumed)?
15eb97c9d2SStefano Zampini    - BDDC with MG framework?
16eb97c9d2SStefano Zampini 
17eb97c9d2SStefano Zampini    MATIS related operations contained in BDDC code
18eb97c9d2SStefano Zampini    - Provide general case for subassembling
19eb97c9d2SStefano Zampini 
2053cdbc3dSStefano Zampini */
210c7d97c5SJed Brown 
22ab5c6b0cSJed Brown #include <../src/ksp/pc/impls/bddc/bddc.h> /*I "petscpc.h" I*/  /* includes for fortran wrappers */
23ab5c6b0cSJed Brown #include <../src/ksp/pc/impls/bddc/bddcprivate.h>
243b03a366Sstefano_zampini #include <petscblaslapack.h>
25674ae819SStefano Zampini 
2643371fb9SStefano Zampini static PetscBool PCBDDCPackageInitialized = PETSC_FALSE;
2743371fb9SStefano Zampini 
28f3d41395Sstefano_zampini static PetscBool  cited = PETSC_FALSE;
29f3d41395Sstefano_zampini static const char citation[] =
30f3d41395Sstefano_zampini "@article{ZampiniPCBDDC,\n"
31f3d41395Sstefano_zampini "author = {Stefano Zampini},\n"
32f3d41395Sstefano_zampini "title = {{PCBDDC}: A Class of Robust Dual-Primal Methods in {PETS}c},\n"
33f3d41395Sstefano_zampini "journal = {SIAM Journal on Scientific Computing},\n"
34f3d41395Sstefano_zampini "volume = {38},\n"
35f3d41395Sstefano_zampini "number = {5},\n"
36f3d41395Sstefano_zampini "pages = {S282-S306},\n"
37f3d41395Sstefano_zampini "year = {2016},\n"
38f3d41395Sstefano_zampini "doi = {10.1137/15M1025785},\n"
39f3d41395Sstefano_zampini "URL = {http://dx.doi.org/10.1137/15M1025785},\n"
40f3d41395Sstefano_zampini "eprint = {http://dx.doi.org/10.1137/15M1025785}\n"
41f3d41395Sstefano_zampini "}\n";
42f3d41395Sstefano_zampini 
4343371fb9SStefano Zampini PetscLogEvent PC_BDDC_Topology[PETSC_PCBDDC_MAXLEVELS];
4443371fb9SStefano Zampini PetscLogEvent PC_BDDC_LocalSolvers[PETSC_PCBDDC_MAXLEVELS];
4543371fb9SStefano Zampini PetscLogEvent PC_BDDC_LocalWork[PETSC_PCBDDC_MAXLEVELS];
4643371fb9SStefano Zampini PetscLogEvent PC_BDDC_CorrectionSetUp[PETSC_PCBDDC_MAXLEVELS];
478ead10e4SStefano Zampini PetscLogEvent PC_BDDC_ApproxSetUp[PETSC_PCBDDC_MAXLEVELS];
488ead10e4SStefano Zampini PetscLogEvent PC_BDDC_ApproxApply[PETSC_PCBDDC_MAXLEVELS];
4943371fb9SStefano Zampini PetscLogEvent PC_BDDC_CoarseSetUp[PETSC_PCBDDC_MAXLEVELS];
5043371fb9SStefano Zampini PetscLogEvent PC_BDDC_CoarseSolver[PETSC_PCBDDC_MAXLEVELS];
5143371fb9SStefano Zampini PetscLogEvent PC_BDDC_AdaptiveSetUp[PETSC_PCBDDC_MAXLEVELS];
5243371fb9SStefano Zampini PetscLogEvent PC_BDDC_Scaling[PETSC_PCBDDC_MAXLEVELS];
5343371fb9SStefano Zampini PetscLogEvent PC_BDDC_Schurs[PETSC_PCBDDC_MAXLEVELS];
5443371fb9SStefano Zampini 
55*bc960bbfSJed Brown const char *const PCBDDCInterfaceExtTypes[] = {"DIRICHLET","LUMP","PCBDDCInterfaceExtType","PC_BDDC_INTERFACE_EXT_",NULL};
56*bc960bbfSJed Brown 
570369aaf7SStefano Zampini PetscErrorCode PCApply_BDDC(PC,Vec,Vec);
580369aaf7SStefano Zampini 
594416b707SBarry Smith PetscErrorCode PCSetFromOptions_BDDC(PetscOptionItems *PetscOptionsObject,PC pc)
600c7d97c5SJed Brown {
610c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
62e569e4e1SStefano Zampini   PetscInt       nt,i;
630c7d97c5SJed Brown   PetscErrorCode ierr;
640c7d97c5SJed Brown 
650c7d97c5SJed Brown   PetscFunctionBegin;
66e55864a3SBarry Smith   ierr = PetscOptionsHead(PetscOptionsObject,"BDDC options");CHKERRQ(ierr);
678eeda7d8SStefano Zampini   /* Verbose debugging */
68a13144ffSStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_check_level","Verbose output for PCBDDC (intended for debug)","none",pcbddc->dbg_flag,&pcbddc->dbg_flag,NULL);CHKERRQ(ierr);
69a13144ffSStefano Zampini   /* Approximate solvers */
70*bc960bbfSJed Brown   ierr = PetscOptionsEnum("-pc_bddc_interface_ext_type","Use DIRICHLET or LUMP to extend interface corrections to interior","PCBDDCSetInterfaceExtType",PCBDDCInterfaceExtTypes,(PetscEnum)pcbddc->interface_extension,(PetscEnum*)&pcbddc->interface_extension,NULL);CHKERRQ(ierr);
71*bc960bbfSJed Brown   if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_DIRICHLET) {
72c7017625SStefano Zampini     ierr = PetscOptionsBool("-pc_bddc_dirichlet_approximate","Inform PCBDDC that we are using approximate Dirichlet solvers","none",pcbddc->NullSpace_corr[0],&pcbddc->NullSpace_corr[0],NULL);CHKERRQ(ierr);
73c7017625SStefano Zampini     ierr = PetscOptionsBool("-pc_bddc_dirichlet_approximate_scale","Inform PCBDDC that we need to scale the Dirichlet solve","none",pcbddc->NullSpace_corr[1],&pcbddc->NullSpace_corr[1],NULL);CHKERRQ(ierr);
74*bc960bbfSJed Brown   } else {
75*bc960bbfSJed Brown     /* This flag is needed/implied by lumping */
76*bc960bbfSJed Brown     pcbddc->switch_static = PETSC_TRUE;
77*bc960bbfSJed Brown   }
78c7017625SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_neumann_approximate","Inform PCBDDC that we are using approximate Neumann solvers","none",pcbddc->NullSpace_corr[2],&pcbddc->NullSpace_corr[2],NULL);CHKERRQ(ierr);
79c7017625SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_neumann_approximate_scale","Inform PCBDDC that we need to scale the Neumann solve","none",pcbddc->NullSpace_corr[3],&pcbddc->NullSpace_corr[3],NULL);CHKERRQ(ierr);
806b78500eSPatrick Sanan   /* Primal space customization */
8108a5cf49SStefano Zampini   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);
82be12c134Sstefano_zampini   ierr = PetscOptionsInt("-pc_bddc_graph_maxcount","Maximum number of shared subdomains for a connected component","none",pcbddc->graphmaxcount,&pcbddc->graphmaxcount,NULL);CHKERRQ(ierr);
831c7a958bSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_corner_selection","Activates face-based corner selection","none",pcbddc->corner_selection,&pcbddc->corner_selection,NULL);CHKERRQ(ierr);
848eeda7d8SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_use_vertices","Use or not corner dofs in coarse space","none",pcbddc->use_vertices,&pcbddc->use_vertices,NULL);CHKERRQ(ierr);
858eeda7d8SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_use_edges","Use or not edge constraints in coarse space","none",pcbddc->use_edges,&pcbddc->use_edges,NULL);CHKERRQ(ierr);
868eeda7d8SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_use_faces","Use or not face constraints in coarse space","none",pcbddc->use_faces,&pcbddc->use_faces,NULL);CHKERRQ(ierr);
8714f95afaSStefano Zampini   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);
886d9e27e4SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_use_nnsp","Use near null space attached to the matrix to compute constraints","none",pcbddc->use_nnsp,&pcbddc->use_nnsp,NULL);CHKERRQ(ierr);
896d9e27e4SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_use_nnsp_true","Use near null space attached to the matrix to compute constraints as is","none",pcbddc->use_nnsp_true,&pcbddc->use_nnsp_true,NULL);CHKERRQ(ierr);
9014f95afaSStefano Zampini   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);
918eeda7d8SStefano Zampini   /* Change of basis */
92b9b85e73SStefano Zampini   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);
93b9b85e73SStefano Zampini   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);
94674ae819SStefano Zampini   if (!pcbddc->use_change_of_basis) {
95674ae819SStefano Zampini     pcbddc->use_change_on_faces = PETSC_FALSE;
96674ae819SStefano Zampini   }
978eeda7d8SStefano Zampini   /* Switch between M_2 (default) and M_3 preconditioners (as defined by C. Dohrmann in the ref. article) */
988eeda7d8SStefano Zampini   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);
99e569e4e1SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_coarse_eqs_per_proc","Target 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);
100e569e4e1SStefano Zampini   i    = pcbddc->coarsening_ratio;
101e569e4e1SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_coarsening_ratio","Set coarsening ratio used in multilevel coarsening","PCBDDCSetCoarseningRatio",i,&i,NULL);CHKERRQ(ierr);
102e569e4e1SStefano Zampini   ierr = PCBDDCSetCoarseningRatio(pc,i);CHKERRQ(ierr);
103e569e4e1SStefano Zampini   i    = pcbddc->max_levels;
104e569e4e1SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_levels","Set maximum number of levels for multilevel","PCBDDCSetLevels",i,&i,NULL);CHKERRQ(ierr);
105e569e4e1SStefano Zampini   ierr = PCBDDCSetLevels(pc,i);CHKERRQ(ierr);
106e569e4e1SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_coarse_eqs_limit","Set maximum number of equations on coarsest grid to aim for","none",pcbddc->coarse_eqs_limit,&pcbddc->coarse_eqs_limit,NULL);CHKERRQ(ierr);
107323d395dSStefano Zampini   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);
108674ae819SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_use_deluxe_scaling","Use deluxe scaling for BDDC","none",pcbddc->use_deluxe_scaling,&pcbddc->use_deluxe_scaling,NULL);CHKERRQ(ierr);
109b96c3477SStefano Zampini   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);
110b96c3477SStefano Zampini   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);
111b96c3477SStefano Zampini   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);
112683d3df6SStefano Zampini   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);
113bf3a8328SStefano Zampini   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);
114839e9adbSstefano_zampini   ierr = PetscOptionsBool("-pc_bddc_deluxe_singlemat","Collapse deluxe operators","none",pcbddc->deluxe_singlemat,&pcbddc->deluxe_singlemat,NULL);CHKERRQ(ierr);
115bf3a8328SStefano Zampini   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);
116bd2a564bSStefano Zampini   nt   = 2;
117bd2a564bSStefano Zampini   ierr = PetscOptionsRealArray("-pc_bddc_adaptive_threshold","Thresholds to be used for adaptive selection of constraints","none",pcbddc->adaptive_threshold,&nt,NULL);CHKERRQ(ierr);
118bd2a564bSStefano Zampini   if (nt == 1) pcbddc->adaptive_threshold[1] = pcbddc->adaptive_threshold[0];
11908122e43SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_adaptive_nmin","Minimum number of constraints per connected components","none",pcbddc->adaptive_nmin,&pcbddc->adaptive_nmin,NULL);CHKERRQ(ierr);
12008122e43SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_adaptive_nmax","Maximum number of constraints per connected components","none",pcbddc->adaptive_nmax,&pcbddc->adaptive_nmax,NULL);CHKERRQ(ierr);
1213301b35fSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_symmetric","Symmetric computation of primal basis functions","none",pcbddc->symmetric_primal,&pcbddc->symmetric_primal,NULL);CHKERRQ(ierr);
122b0c7d250SStefano Zampini   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);
123b3afcdbeSStefano Zampini   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);
124e9627c49SStefano Zampini   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);
12527b6a85dSStefano Zampini   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);
126a198735bSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_nonetflux","Automatic computation of no-net-flux quadrature weights","none",pcbddc->compute_nonetflux,&pcbddc->compute_nonetflux,NULL);CHKERRQ(ierr);
1274f1b2e48SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_detect_disconnected","Detects disconnected subdomains","none",pcbddc->detect_disconnected,&pcbddc->detect_disconnected,NULL);CHKERRQ(ierr);
1288361f951SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_detect_disconnected_filter","Filters out small entries in the local matrix when detecting disconnected subdomains","none",pcbddc->detect_disconnected_filter,&pcbddc->detect_disconnected_filter,NULL);CHKERRQ(ierr);
12970c64980SStefano Zampini   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);
1300c7d97c5SJed Brown   ierr = PetscOptionsTail();CHKERRQ(ierr);
1310c7d97c5SJed Brown   PetscFunctionReturn(0);
1320c7d97c5SJed Brown }
1336b78500eSPatrick Sanan 
1346b78500eSPatrick Sanan static PetscErrorCode PCView_BDDC(PC pc,PetscViewer viewer)
1356b78500eSPatrick Sanan {
1366b78500eSPatrick Sanan   PC_BDDC              *pcbddc = (PC_BDDC*)pc->data;
137e9627c49SStefano Zampini   PC_IS                *pcis = (PC_IS*)pc->data;
1386b78500eSPatrick Sanan   PetscErrorCode       ierr;
13971783a16SStefano Zampini   PetscBool            isascii;
140e9627c49SStefano Zampini   PetscSubcomm         subcomm;
141e9627c49SStefano Zampini   PetscViewer          subviewer;
1426b78500eSPatrick Sanan 
1436b78500eSPatrick Sanan   PetscFunctionBegin;
1446b78500eSPatrick Sanan   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
1456b78500eSPatrick Sanan   /* ASCII viewer */
1466b78500eSPatrick Sanan   if (isascii) {
1474b2aedd3SStefano Zampini     PetscMPIInt   color,rank,size;
148fbad9177SStefano Zampini     PetscInt64    loc[7],gsum[6],gmax[6],gmin[6],totbenign;
149e9627c49SStefano Zampini     PetscScalar   interface_size;
150e9627c49SStefano Zampini     PetscReal     ratio1=0.,ratio2=0.;
151e9627c49SStefano Zampini     Vec           counter;
1526b78500eSPatrick Sanan 
153b74ba07aSstefano_zampini     if (!pc->setupcalled) {
154b74ba07aSstefano_zampini       ierr = PetscViewerASCIIPrintf(viewer,"  Partial information available: preconditioner has not been setup yet\n");CHKERRQ(ierr);
155b74ba07aSstefano_zampini     }
156efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use verbose output: %D\n",pcbddc->dbg_flag);CHKERRQ(ierr);
1576f0c0a6aSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Use user-defined CSR: %d\n",!!pcbddc->mat_graph->nvtxs_csr);CHKERRQ(ierr);
1586f0c0a6aSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Use local mat graph: %d\n",pcbddc->use_local_adj && !pcbddc->mat_graph->nvtxs_csr);CHKERRQ(ierr);
159e9627c49SStefano Zampini     if (pcbddc->mat_graph->twodim) {
160efd4aadfSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  Connectivity graph topological dimension: 2\n");CHKERRQ(ierr);
161e9627c49SStefano Zampini     } else {
162efd4aadfSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  Connectivity graph topological dimension: 3\n");CHKERRQ(ierr);
163e9627c49SStefano Zampini     }
164aefa1729SStefano Zampini     if (pcbddc->graphmaxcount != PETSC_MAX_INT) {
165efd4aadfSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  Graph max count: %D\n",pcbddc->graphmaxcount);CHKERRQ(ierr);
166aefa1729SStefano Zampini     }
16750e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Use vertices: %d (vertex size %D)\n",pcbddc->use_vertices,pcbddc->vertex_size);CHKERRQ(ierr);
168efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use edges: %d\n",pcbddc->use_edges);CHKERRQ(ierr);
169efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use faces: %d\n",pcbddc->use_faces);CHKERRQ(ierr);
170efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use true near null space: %d\n",pcbddc->use_nnsp_true);CHKERRQ(ierr);
171efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use QR for single constraints on cc: %d\n",pcbddc->use_qr_single);CHKERRQ(ierr);
172efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use change of basis on local edge nodes: %d\n",pcbddc->use_change_of_basis);CHKERRQ(ierr);
173efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use change of basis on local face nodes: %d\n",pcbddc->use_change_on_faces);CHKERRQ(ierr);
174efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  User defined change of basis matrix: %d\n",!!pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
175efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Has change of basis matrix: %d\n",!!pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
176efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Eliminate dirichlet boundary dofs: %d\n",pcbddc->eliminate_dirdofs);CHKERRQ(ierr);
177efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Switch on static condensation ops around the interface preconditioner: %d\n",pcbddc->switch_static);CHKERRQ(ierr);
178efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use exact dirichlet trick: %d\n",pcbddc->use_exact_dirichlet_trick);CHKERRQ(ierr);
179*bc960bbfSJed Brown     ierr = PetscViewerASCIIPrintf(viewer,"  Interface extension: %s\n",PCBDDCInterfaceExtTypes[pcbddc->interface_extension]);CHKERRQ(ierr);
18050e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Multilevel max levels: %D\n",pcbddc->max_levels);CHKERRQ(ierr);
18150e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Multilevel coarsening ratio: %D\n",pcbddc->coarsening_ratio);CHKERRQ(ierr);
182efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use estimated eigs for coarse problem: %d\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
183efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use deluxe scaling: %d\n",pcbddc->use_deluxe_scaling);CHKERRQ(ierr);
184efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use deluxe zerorows: %d\n",pcbddc->deluxe_zerorows);CHKERRQ(ierr);
185efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use deluxe singlemat: %d\n",pcbddc->deluxe_singlemat);CHKERRQ(ierr);
186efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Rebuild interface graph for Schur principal minors: %d\n",pcbddc->sub_schurs_rebuild);CHKERRQ(ierr);
18750e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Number of dofs' layers for the computation of principal minors: %D\n",pcbddc->sub_schurs_layers);CHKERRQ(ierr);
188efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use user CSR graph to compute successive layers: %d\n",pcbddc->sub_schurs_use_useradj);CHKERRQ(ierr);
189bd2a564bSStefano Zampini     if (pcbddc->adaptive_threshold[1] != pcbddc->adaptive_threshold[0]) {
190bd2a564bSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"  Adaptive constraint selection thresholds (active %d, userdefined %d): %g,%g\n",pcbddc->adaptive_selection,pcbddc->adaptive_userdefined,pcbddc->adaptive_threshold[0],pcbddc->adaptive_threshold[1]);CHKERRQ(ierr);
191bd2a564bSStefano Zampini     } else {
192bd2a564bSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"  Adaptive constraint selection threshold (active %d, userdefined %d): %g\n",pcbddc->adaptive_selection,pcbddc->adaptive_userdefined,pcbddc->adaptive_threshold[0]);CHKERRQ(ierr);
193bd2a564bSStefano Zampini     }
19450e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Min constraints / connected component: %D\n",pcbddc->adaptive_nmin);CHKERRQ(ierr);
19550e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Max constraints / connected component: %D\n",pcbddc->adaptive_nmax);CHKERRQ(ierr);
196efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Invert exact Schur complement for adaptive selection: %d\n",pcbddc->sub_schurs_exact_schur);CHKERRQ(ierr);
197efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Symmetric computation of primal basis functions: %d\n",pcbddc->symmetric_primal);CHKERRQ(ierr);
19850e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Num. Procs. to map coarse adjacency list: %D\n",pcbddc->coarse_adj_red);CHKERRQ(ierr);
19950e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Coarse eqs per proc (significant at the coarsest level): %D\n",pcbddc->coarse_eqs_per_proc);CHKERRQ(ierr);
2008361f951SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Detect disconnected: %d (filter %d)\n",pcbddc->detect_disconnected,pcbddc->detect_disconnected_filter);CHKERRQ(ierr);
201efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Benign subspace trick: %d (change explicit %d)\n",pcbddc->benign_saddle_point,pcbddc->benign_change_explicit);CHKERRQ(ierr);
202efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Benign subspace trick is active: %d\n",pcbddc->benign_have_null);CHKERRQ(ierr);
20315579a77SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Algebraic computation of no-net-flux: %d\n",pcbddc->compute_nonetflux);CHKERRQ(ierr);
204b74ba07aSstefano_zampini     if (!pc->setupcalled) PetscFunctionReturn(0);
2056b78500eSPatrick Sanan 
206fbad9177SStefano Zampini     /* compute interface size */
207e9627c49SStefano Zampini     ierr = VecSet(pcis->vec1_B,1.0);CHKERRQ(ierr);
208e9627c49SStefano Zampini     ierr = MatCreateVecs(pc->pmat,&counter,0);CHKERRQ(ierr);
209e9627c49SStefano Zampini     ierr = VecSet(counter,0.0);CHKERRQ(ierr);
210e9627c49SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,counter,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
211e9627c49SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,counter,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
212e9627c49SStefano Zampini     ierr = VecSum(counter,&interface_size);CHKERRQ(ierr);
213e9627c49SStefano Zampini     ierr = VecDestroy(&counter);CHKERRQ(ierr);
214fbad9177SStefano Zampini 
215fbad9177SStefano Zampini     /* compute some statistics on the domain decomposition */
216e9627c49SStefano Zampini     gsum[0] = 1;
217fbad9177SStefano Zampini     gsum[1] = gsum[2] = gsum[3] = gsum[4] = gsum[5] = 0;
218e9627c49SStefano Zampini     loc[0]  = !!pcis->n;
219e9627c49SStefano Zampini     loc[1]  = pcis->n - pcis->n_B;
220e9627c49SStefano Zampini     loc[2]  = pcis->n_B;
221e9627c49SStefano Zampini     loc[3]  = pcbddc->local_primal_size;
222345ecf6cSStefano Zampini     loc[4]  = pcis->n;
223fbad9177SStefano Zampini     loc[5]  = pcbddc->n_local_subs > 0 ? pcbddc->n_local_subs : (pcis->n ? 1 : 0);
224fbad9177SStefano Zampini     loc[6]  = pcbddc->benign_n;
225fbad9177SStefano Zampini     ierr = MPI_Reduce(loc,gsum,6,MPIU_INT64,MPI_SUM,0,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
226fbad9177SStefano Zampini     if (!loc[0]) loc[1] = loc[2] = loc[3] = loc[4] = loc[5] = -1;
227fbad9177SStefano Zampini     ierr = MPI_Reduce(loc,gmax,6,MPIU_INT64,MPI_MAX,0,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
228fbad9177SStefano Zampini     if (!loc[0]) loc[1] = loc[2] = loc[3] = loc[4] = loc[5] = PETSC_MAX_INT;
229fbad9177SStefano Zampini     ierr = MPI_Reduce(loc,gmin,6,MPIU_INT64,MPI_MIN,0,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
230fbad9177SStefano Zampini     ierr = MPI_Reduce(&loc[6],&totbenign,1,MPIU_INT64,MPI_SUM,0,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
231e9627c49SStefano Zampini     if (pcbddc->coarse_size) {
232e9627c49SStefano Zampini       ratio1 = pc->pmat->rmap->N/(1.*pcbddc->coarse_size);
233e9627c49SStefano Zampini       ratio2 = PetscRealPart(interface_size)/pcbddc->coarse_size;
234e9627c49SStefano Zampini     }
235efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"********************************** STATISTICS AT LEVEL %d **********************************\n",pcbddc->current_level);CHKERRQ(ierr);
23650e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Global dofs sizes: all %D interface %D coarse %D\n",pc->pmat->rmap->N,(PetscInt)PetscRealPart(interface_size),pcbddc->coarse_size);CHKERRQ(ierr);
23750e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Coarsening ratios: all/coarse %D interface/coarse %D\n",(PetscInt)ratio1,(PetscInt)ratio2);CHKERRQ(ierr);
23850e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Active processes : %D\n",(PetscInt)gsum[0]);CHKERRQ(ierr);
23950e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Total subdomains : %D\n",(PetscInt)gsum[5]);CHKERRQ(ierr);
240345ecf6cSStefano Zampini     if (pcbddc->benign_have_null) {
24150e0721cSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"  Benign subs      : %D\n",(PetscInt)totbenign);CHKERRQ(ierr);
242345ecf6cSStefano Zampini     }
24350e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Dofs type        :\tMIN\tMAX\tMEAN\n");CHKERRQ(ierr);
24450e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Interior  dofs   :\t%D\t%D\t%D\n",(PetscInt)gmin[1],(PetscInt)gmax[1],(PetscInt)(gsum[1]/gsum[0]));CHKERRQ(ierr);
24550e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Interface dofs   :\t%D\t%D\t%D\n",(PetscInt)gmin[2],(PetscInt)gmax[2],(PetscInt)(gsum[2]/gsum[0]));CHKERRQ(ierr);
24650e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Primal    dofs   :\t%D\t%D\t%D\n",(PetscInt)gmin[3],(PetscInt)gmax[3],(PetscInt)(gsum[3]/gsum[0]));CHKERRQ(ierr);
24750e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Local     dofs   :\t%D\t%D\t%D\n",(PetscInt)gmin[4],(PetscInt)gmax[4],(PetscInt)(gsum[4]/gsum[0]));CHKERRQ(ierr);
24850e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Local     subs   :\t%D\t%D\n"    ,(PetscInt)gmin[5],(PetscInt)gmax[5]);CHKERRQ(ierr);
24915579a77SStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
25015579a77SStefano Zampini 
25115579a77SStefano Zampini     ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
25215579a77SStefano Zampini 
25315579a77SStefano Zampini     /* local solvers */
25415579a77SStefano Zampini     ierr = PetscViewerGetSubViewer(viewer,PetscObjectComm((PetscObject)pcbddc->ksp_D),&subviewer);CHKERRQ(ierr);
25515579a77SStefano Zampini     if (!rank) {
25615579a77SStefano Zampini       ierr = PetscViewerASCIIPrintf(subviewer,"--- Interior solver (rank 0)\n");CHKERRQ(ierr);
25715579a77SStefano Zampini       ierr = PetscViewerASCIIPushTab(subviewer);CHKERRQ(ierr);
25815579a77SStefano Zampini       ierr = KSPView(pcbddc->ksp_D,subviewer);CHKERRQ(ierr);
25915579a77SStefano Zampini       ierr = PetscViewerASCIIPopTab(subviewer);CHKERRQ(ierr);
26015579a77SStefano Zampini       ierr = PetscViewerASCIIPrintf(subviewer,"--- Correction solver (rank 0)\n");CHKERRQ(ierr);
26115579a77SStefano Zampini       ierr = PetscViewerASCIIPushTab(subviewer);CHKERRQ(ierr);
26215579a77SStefano Zampini       ierr = KSPView(pcbddc->ksp_R,subviewer);CHKERRQ(ierr);
26315579a77SStefano Zampini       ierr = PetscViewerASCIIPopTab(subviewer);CHKERRQ(ierr);
26415579a77SStefano Zampini       ierr = PetscViewerFlush(subviewer);CHKERRQ(ierr);
26515579a77SStefano Zampini     }
26615579a77SStefano Zampini     ierr = PetscViewerRestoreSubViewer(viewer,PetscObjectComm((PetscObject)pcbddc->ksp_D),&subviewer);CHKERRQ(ierr);
26727b6a85dSStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
268e9627c49SStefano Zampini 
269fbad9177SStefano Zampini     /* the coarse problem can be handled by a different communicator */
270e9627c49SStefano Zampini     if (pcbddc->coarse_ksp) color = 1;
271e9627c49SStefano Zampini     else color = 0;
2724b2aedd3SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
273e9627c49SStefano Zampini     ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)pc),&subcomm);CHKERRQ(ierr);
2744b2aedd3SStefano Zampini     ierr = PetscSubcommSetNumber(subcomm,PetscMin(size,2));CHKERRQ(ierr);
275e9627c49SStefano Zampini     ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
276e9627c49SStefano Zampini     ierr = PetscViewerGetSubViewer(viewer,PetscSubcommChild(subcomm),&subviewer);CHKERRQ(ierr);
277e9627c49SStefano Zampini     if (color == 1) {
27815579a77SStefano Zampini       ierr = PetscViewerASCIIPrintf(subviewer,"--- Coarse solver\n");CHKERRQ(ierr);
27915579a77SStefano Zampini       ierr = PetscViewerASCIIPushTab(subviewer);CHKERRQ(ierr);
280e9627c49SStefano Zampini       ierr = KSPView(pcbddc->coarse_ksp,subviewer);CHKERRQ(ierr);
28115579a77SStefano Zampini       ierr = PetscViewerASCIIPopTab(subviewer);CHKERRQ(ierr);
282e9627c49SStefano Zampini       ierr = PetscViewerFlush(subviewer);CHKERRQ(ierr);
283e9627c49SStefano Zampini     }
284e9627c49SStefano Zampini     ierr = PetscViewerRestoreSubViewer(viewer,PetscSubcommChild(subcomm),&subviewer);CHKERRQ(ierr);
285e9627c49SStefano Zampini     ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
286e9627c49SStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
287e9627c49SStefano Zampini   }
2886b78500eSPatrick Sanan   PetscFunctionReturn(0);
2896b78500eSPatrick Sanan }
290a13144ffSStefano Zampini 
2911e0482f5SStefano Zampini static PetscErrorCode PCBDDCSetDiscreteGradient_BDDC(PC pc, Mat G, PetscInt order, PetscInt field, PetscBool global, PetscBool conforming)
292a13144ffSStefano Zampini {
293a13144ffSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
294a13144ffSStefano Zampini   PetscErrorCode ierr;
295a13144ffSStefano Zampini 
296a13144ffSStefano Zampini   PetscFunctionBegin;
297a13144ffSStefano Zampini   ierr = PetscObjectReference((PetscObject)G);CHKERRQ(ierr);
298a13144ffSStefano Zampini   ierr = MatDestroy(&pcbddc->discretegradient);CHKERRQ(ierr);
299a13144ffSStefano Zampini   pcbddc->discretegradient = G;
300a13144ffSStefano Zampini   pcbddc->nedorder         = order > 0 ? order : -order;
301495a2a07SStefano Zampini   pcbddc->nedfield         = field;
3021e0482f5SStefano Zampini   pcbddc->nedglobal        = global;
3031e0482f5SStefano Zampini   pcbddc->conforming       = conforming;
304a13144ffSStefano Zampini   PetscFunctionReturn(0);
305a13144ffSStefano Zampini }
306a13144ffSStefano Zampini 
307a13144ffSStefano Zampini /*@
308a13144ffSStefano Zampini  PCBDDCSetDiscreteGradient - Sets the discrete gradient
309a13144ffSStefano Zampini 
310a13144ffSStefano Zampini    Collective on PC
311a13144ffSStefano Zampini 
312a13144ffSStefano Zampini    Input Parameters:
313a13144ffSStefano Zampini +  pc         - the preconditioning context
314a13144ffSStefano Zampini .  G          - the discrete gradient matrix (should be in AIJ format)
315a13144ffSStefano Zampini .  order      - the order of the Nedelec space (1 for the lowest order)
316495a2a07SStefano Zampini .  field      - the field id of the Nedelec dofs (not used if the fields have not been specified)
3171e0482f5SStefano Zampini .  global     - the type of global ordering for the rows of G
318a13144ffSStefano Zampini -  conforming - whether the mesh is conforming or not
319a13144ffSStefano Zampini 
320a13144ffSStefano Zampini    Level: advanced
321a13144ffSStefano Zampini 
32295452b02SPatrick Sanan    Notes:
32395452b02SPatrick Sanan     The discrete gradient matrix G is used to analyze the subdomain edges, and it should not contain any zero entry.
324495a2a07SStefano Zampini           For variable order spaces, the order should be set to zero.
3251e0482f5SStefano Zampini           If global is true, the rows of G should be given in global ordering for the whole dofs;
3261e0482f5SStefano Zampini           if false, the ordering should be global for the Nedelec field.
3271e0482f5SStefano Zampini           In the latter case, it should hold gid[i] < gid[j] iff geid[i] < geid[j], with gid the global orderding for all the dofs
3281e0482f5SStefano Zampini           and geid the one for the Nedelec field.
329a13144ffSStefano Zampini 
330495a2a07SStefano Zampini .seealso: PCBDDC,PCBDDCSetDofsSplitting(),PCBDDCSetDofsSplittingLocal()
331a13144ffSStefano Zampini @*/
3321e0482f5SStefano Zampini PetscErrorCode PCBDDCSetDiscreteGradient(PC pc, Mat G, PetscInt order, PetscInt field, PetscBool global, PetscBool conforming)
333a13144ffSStefano Zampini {
334a13144ffSStefano Zampini   PetscErrorCode ierr;
335a13144ffSStefano Zampini 
336a13144ffSStefano Zampini   PetscFunctionBegin;
337a13144ffSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
338a13144ffSStefano Zampini   PetscValidHeaderSpecific(G,MAT_CLASSID,2);
339a13144ffSStefano Zampini   PetscValidLogicalCollectiveInt(pc,order,3);
3401e0482f5SStefano Zampini   PetscValidLogicalCollectiveInt(pc,field,4);
3411e0482f5SStefano Zampini   PetscValidLogicalCollectiveBool(pc,global,5);
3421e0482f5SStefano Zampini   PetscValidLogicalCollectiveBool(pc,conforming,6);
3431e0482f5SStefano Zampini   PetscCheckSameComm(pc,1,G,2);
3441e0482f5SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDiscreteGradient_C",(PC,Mat,PetscInt,PetscInt,PetscBool,PetscBool),(pc,G,order,field,global,conforming));CHKERRQ(ierr);
345a13144ffSStefano Zampini   PetscFunctionReturn(0);
346a13144ffSStefano Zampini }
347a13144ffSStefano Zampini 
3488ae0ca82SStefano Zampini static PetscErrorCode PCBDDCSetDivergenceMat_BDDC(PC pc, Mat divudotp, PetscBool trans, IS vl2l)
349a198735bSStefano Zampini {
350a198735bSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
351a198735bSStefano Zampini   PetscErrorCode ierr;
3526b78500eSPatrick Sanan 
353a198735bSStefano Zampini   PetscFunctionBegin;
354a198735bSStefano Zampini   ierr = PetscObjectReference((PetscObject)divudotp);CHKERRQ(ierr);
355a198735bSStefano Zampini   ierr = MatDestroy(&pcbddc->divudotp);CHKERRQ(ierr);
356a198735bSStefano Zampini   pcbddc->divudotp = divudotp;
3578ae0ca82SStefano Zampini   pcbddc->divudotp_trans = trans;
358a198735bSStefano Zampini   pcbddc->compute_nonetflux = PETSC_TRUE;
359a198735bSStefano Zampini   if (vl2l) {
360a198735bSStefano Zampini     ierr = PetscObjectReference((PetscObject)vl2l);CHKERRQ(ierr);
361fa23a32eSStefano Zampini     ierr = ISDestroy(&pcbddc->divudotp_vl2l);CHKERRQ(ierr);
362a198735bSStefano Zampini     pcbddc->divudotp_vl2l = vl2l;
363a198735bSStefano Zampini   }
364a198735bSStefano Zampini   PetscFunctionReturn(0);
365a198735bSStefano Zampini }
3663d996552SStefano Zampini 
367a198735bSStefano Zampini /*@
368a198735bSStefano Zampini  PCBDDCSetDivergenceMat - Sets the linear operator representing \int_\Omega \div {\bf u} \cdot p dx
369a198735bSStefano Zampini 
370a198735bSStefano Zampini    Collective on PC
371a198735bSStefano Zampini 
372a198735bSStefano Zampini    Input Parameters:
373a198735bSStefano Zampini +  pc - the preconditioning context
374a198735bSStefano Zampini .  divudotp - the matrix (must be of type MATIS)
3758ae0ca82SStefano Zampini .  trans - if trans if false (resp. true), then pressures are in the test (trial) space and velocities are in the trial (test) space.
37605a3bf82SStefano Zampini -  vl2l - optional index set describing the local (wrt the local matrix in divudotp) to local (wrt the local matrix in the preconditioning matrix) map for the velocities
377a198735bSStefano Zampini 
378a198735bSStefano Zampini    Level: advanced
379a198735bSStefano Zampini 
38095452b02SPatrick Sanan    Notes:
38195452b02SPatrick Sanan     This auxiliary matrix is used to compute quadrature weights representing the net-flux across subdomain boundaries
38205a3bf82SStefano Zampini           If vl2l is NULL, the local ordering for velocities in divudotp should match that of the preconditioning matrix
383a198735bSStefano Zampini 
384a198735bSStefano Zampini .seealso: PCBDDC
385a198735bSStefano Zampini @*/
3868ae0ca82SStefano Zampini PetscErrorCode PCBDDCSetDivergenceMat(PC pc, Mat divudotp, PetscBool trans, IS vl2l)
387a198735bSStefano Zampini {
388a198735bSStefano Zampini   PetscBool      ismatis;
389a198735bSStefano Zampini   PetscErrorCode ierr;
390a198735bSStefano Zampini 
391a198735bSStefano Zampini   PetscFunctionBegin;
392a198735bSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
393a198735bSStefano Zampini   PetscValidHeaderSpecific(divudotp,MAT_CLASSID,2);
394a198735bSStefano Zampini   PetscCheckSameComm(pc,1,divudotp,2);
3958ae0ca82SStefano Zampini   PetscValidLogicalCollectiveBool(pc,trans,3);
3961b24a7afSStefano Zampini   if (vl2l) PetscValidHeaderSpecific(vl2l,IS_CLASSID,4);
397a198735bSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)divudotp,MATIS,&ismatis);CHKERRQ(ierr);
398a198735bSStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"Divergence matrix needs to be of type MATIS");
3998ae0ca82SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDivergenceMat_C",(PC,Mat,PetscBool,IS),(pc,divudotp,trans,vl2l));CHKERRQ(ierr);
400a198735bSStefano Zampini   PetscFunctionReturn(0);
401a198735bSStefano Zampini }
4022d505d7fSStefano Zampini 
4031dd7afcfSStefano Zampini static PetscErrorCode PCBDDCSetChangeOfBasisMat_BDDC(PC pc, Mat change, PetscBool interior)
404b9b85e73SStefano Zampini {
405b9b85e73SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
406b9b85e73SStefano Zampini   PetscErrorCode ierr;
407b9b85e73SStefano Zampini 
408b9b85e73SStefano Zampini   PetscFunctionBegin;
409b9b85e73SStefano Zampini   ierr = PetscObjectReference((PetscObject)change);CHKERRQ(ierr);
41056282151SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
411b9b85e73SStefano Zampini   pcbddc->user_ChangeOfBasisMatrix = change;
4121dd7afcfSStefano Zampini   pcbddc->change_interior = interior;
413b9b85e73SStefano Zampini   PetscFunctionReturn(0);
414b9b85e73SStefano Zampini }
415b9b85e73SStefano Zampini /*@
416906d46d4SStefano Zampini  PCBDDCSetChangeOfBasisMat - Set user defined change of basis for dofs
417b9b85e73SStefano Zampini 
418b9b85e73SStefano Zampini    Collective on PC
419b9b85e73SStefano Zampini 
420b9b85e73SStefano Zampini    Input Parameters:
421b9b85e73SStefano Zampini +  pc - the preconditioning context
4221dd7afcfSStefano Zampini .  change - the change of basis matrix
4231dd7afcfSStefano Zampini -  interior - whether or not the change of basis modifies interior dofs
424b9b85e73SStefano Zampini 
425b9b85e73SStefano Zampini    Level: intermediate
426b9b85e73SStefano Zampini 
427b9b85e73SStefano Zampini    Notes:
428b9b85e73SStefano Zampini 
429b9b85e73SStefano Zampini .seealso: PCBDDC
430b9b85e73SStefano Zampini @*/
4311dd7afcfSStefano Zampini PetscErrorCode PCBDDCSetChangeOfBasisMat(PC pc, Mat change, PetscBool interior)
432b9b85e73SStefano Zampini {
433b9b85e73SStefano Zampini   PetscErrorCode ierr;
434b9b85e73SStefano Zampini 
435b9b85e73SStefano Zampini   PetscFunctionBegin;
436b9b85e73SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
437b9b85e73SStefano Zampini   PetscValidHeaderSpecific(change,MAT_CLASSID,2);
438906d46d4SStefano Zampini   PetscCheckSameComm(pc,1,change,2);
439906d46d4SStefano Zampini   if (pc->mat) {
440906d46d4SStefano Zampini     PetscInt rows_c,cols_c,rows,cols;
441906d46d4SStefano Zampini     ierr = MatGetSize(pc->mat,&rows,&cols);CHKERRQ(ierr);
442906d46d4SStefano Zampini     ierr = MatGetSize(change,&rows_c,&cols_c);CHKERRQ(ierr);
443e0fe2d75SToby Isaac     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);
444e0fe2d75SToby Isaac     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);
445906d46d4SStefano Zampini     ierr = MatGetLocalSize(pc->mat,&rows,&cols);CHKERRQ(ierr);
446906d46d4SStefano Zampini     ierr = MatGetLocalSize(change,&rows_c,&cols_c);CHKERRQ(ierr);
447e0fe2d75SToby Isaac     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);
448e0fe2d75SToby Isaac     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);
449906d46d4SStefano Zampini   }
4501dd7afcfSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetChangeOfBasisMat_C",(PC,Mat,PetscBool),(pc,change,interior));CHKERRQ(ierr);
451b9b85e73SStefano Zampini   PetscFunctionReturn(0);
452b9b85e73SStefano Zampini }
4532d505d7fSStefano Zampini 
45430368db7SStefano Zampini static PetscErrorCode PCBDDCSetPrimalVerticesIS_BDDC(PC pc, IS PrimalVertices)
45530368db7SStefano Zampini {
45630368db7SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
45756282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
45830368db7SStefano Zampini   PetscErrorCode ierr;
45930368db7SStefano Zampini 
46030368db7SStefano Zampini   PetscFunctionBegin;
46156282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)PrimalVertices);CHKERRQ(ierr);
46256282151SStefano Zampini   if (pcbddc->user_primal_vertices) {
46356282151SStefano Zampini     ierr = ISEqual(PrimalVertices,pcbddc->user_primal_vertices,&isequal);CHKERRQ(ierr);
46456282151SStefano Zampini   }
46530368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
46630368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
46730368db7SStefano Zampini   pcbddc->user_primal_vertices = PrimalVertices;
46856282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
46930368db7SStefano Zampini   PetscFunctionReturn(0);
47030368db7SStefano Zampini }
471ab8c8b98SStefano Zampini 
47230368db7SStefano Zampini /*@
47330368db7SStefano Zampini  PCBDDCSetPrimalVerticesIS - Set additional user defined primal vertices in PCBDDC
47430368db7SStefano Zampini 
47530368db7SStefano Zampini    Collective
47630368db7SStefano Zampini 
47730368db7SStefano Zampini    Input Parameters:
47830368db7SStefano Zampini +  pc - the preconditioning context
47930368db7SStefano Zampini -  PrimalVertices - index set of primal vertices in global numbering (can be empty)
48030368db7SStefano Zampini 
48130368db7SStefano Zampini    Level: intermediate
48230368db7SStefano Zampini 
48330368db7SStefano Zampini    Notes:
48430368db7SStefano Zampini      Any process can list any global node
48530368db7SStefano Zampini 
4863100ebe3SStefano Zampini .seealso: PCBDDC, PCBDDCGetPrimalVerticesIS(), PCBDDCSetPrimalVerticesLocalIS(), PCBDDCGetPrimalVerticesLocalIS()
48730368db7SStefano Zampini @*/
48830368db7SStefano Zampini PetscErrorCode PCBDDCSetPrimalVerticesIS(PC pc, IS PrimalVertices)
48930368db7SStefano Zampini {
49030368db7SStefano Zampini   PetscErrorCode ierr;
49130368db7SStefano Zampini 
49230368db7SStefano Zampini   PetscFunctionBegin;
49330368db7SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
49430368db7SStefano Zampini   PetscValidHeaderSpecific(PrimalVertices,IS_CLASSID,2);
49530368db7SStefano Zampini   PetscCheckSameComm(pc,1,PrimalVertices,2);
49630368db7SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetPrimalVerticesIS_C",(PC,IS),(pc,PrimalVertices));CHKERRQ(ierr);
49730368db7SStefano Zampini   PetscFunctionReturn(0);
49830368db7SStefano Zampini }
4992d505d7fSStefano Zampini 
5003100ebe3SStefano Zampini static PetscErrorCode PCBDDCGetPrimalVerticesIS_BDDC(PC pc, IS *is)
5013100ebe3SStefano Zampini {
5023100ebe3SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC*)pc->data;
5033100ebe3SStefano Zampini 
5043100ebe3SStefano Zampini   PetscFunctionBegin;
5053100ebe3SStefano Zampini   *is = pcbddc->user_primal_vertices;
5063100ebe3SStefano Zampini   PetscFunctionReturn(0);
5073100ebe3SStefano Zampini }
5083100ebe3SStefano Zampini 
5093100ebe3SStefano Zampini /*@
5103100ebe3SStefano Zampini  PCBDDCGetPrimalVerticesIS - Get user defined primal vertices set with PCBDDCSetPrimalVerticesIS()
5113100ebe3SStefano Zampini 
5123100ebe3SStefano Zampini    Collective
5133100ebe3SStefano Zampini 
5143100ebe3SStefano Zampini    Input Parameters:
5153100ebe3SStefano Zampini .  pc - the preconditioning context
5163100ebe3SStefano Zampini 
5173100ebe3SStefano Zampini    Output Parameters:
5183100ebe3SStefano Zampini .  is - index set of primal vertices in global numbering (NULL if not set)
5193100ebe3SStefano Zampini 
5203100ebe3SStefano Zampini    Level: intermediate
5213100ebe3SStefano Zampini 
5223100ebe3SStefano Zampini    Notes:
5233100ebe3SStefano Zampini 
5243100ebe3SStefano Zampini .seealso: PCBDDC, PCBDDCSetPrimalVerticesIS(), PCBDDCSetPrimalVerticesLocalIS(), PCBDDCGetPrimalVerticesLocalIS()
5253100ebe3SStefano Zampini @*/
5263100ebe3SStefano Zampini PetscErrorCode PCBDDCGetPrimalVerticesIS(PC pc, IS *is)
5273100ebe3SStefano Zampini {
5283100ebe3SStefano Zampini   PetscErrorCode ierr;
5293100ebe3SStefano Zampini 
5303100ebe3SStefano Zampini   PetscFunctionBegin;
5313100ebe3SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
5323100ebe3SStefano Zampini   PetscValidPointer(is,2);
5333100ebe3SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetPrimalVerticesIS_C",(PC,IS*),(pc,is));CHKERRQ(ierr);
5343100ebe3SStefano Zampini   PetscFunctionReturn(0);
5353100ebe3SStefano Zampini }
5363100ebe3SStefano Zampini 
537674ae819SStefano Zampini static PetscErrorCode PCBDDCSetPrimalVerticesLocalIS_BDDC(PC pc, IS PrimalVertices)
538674ae819SStefano Zampini {
539674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
54056282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
541674ae819SStefano Zampini   PetscErrorCode ierr;
5421e6b0712SBarry Smith 
543674ae819SStefano Zampini   PetscFunctionBegin;
54456282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)PrimalVertices);CHKERRQ(ierr);
54556282151SStefano Zampini   if (pcbddc->user_primal_vertices_local) {
54656282151SStefano Zampini     ierr = ISEqual(PrimalVertices,pcbddc->user_primal_vertices_local,&isequal);CHKERRQ(ierr);
54756282151SStefano Zampini   }
548674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
54930368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
55030368db7SStefano Zampini   pcbddc->user_primal_vertices_local = PrimalVertices;
55156282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
552674ae819SStefano Zampini   PetscFunctionReturn(0);
553674ae819SStefano Zampini }
5543100ebe3SStefano Zampini 
555674ae819SStefano Zampini /*@
55628509bceSStefano Zampini  PCBDDCSetPrimalVerticesLocalIS - Set additional user defined primal vertices in PCBDDC
557674ae819SStefano Zampini 
55817eb1463SStefano Zampini    Collective
559674ae819SStefano Zampini 
560674ae819SStefano Zampini    Input Parameters:
561674ae819SStefano Zampini +  pc - the preconditioning context
56217eb1463SStefano Zampini -  PrimalVertices - index set of primal vertices in local numbering (can be empty)
563674ae819SStefano Zampini 
564674ae819SStefano Zampini    Level: intermediate
565674ae819SStefano Zampini 
566674ae819SStefano Zampini    Notes:
567674ae819SStefano Zampini 
5683100ebe3SStefano Zampini .seealso: PCBDDC, PCBDDCSetPrimalVerticesIS(), PCBDDCGetPrimalVerticesIS(), PCBDDCGetPrimalVerticesLocalIS()
569674ae819SStefano Zampini @*/
570674ae819SStefano Zampini PetscErrorCode PCBDDCSetPrimalVerticesLocalIS(PC pc, IS PrimalVertices)
571674ae819SStefano Zampini {
572674ae819SStefano Zampini   PetscErrorCode ierr;
573674ae819SStefano Zampini 
574674ae819SStefano Zampini   PetscFunctionBegin;
575674ae819SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
576674ae819SStefano Zampini   PetscValidHeaderSpecific(PrimalVertices,IS_CLASSID,2);
57717eb1463SStefano Zampini   PetscCheckSameComm(pc,1,PrimalVertices,2);
578674ae819SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetPrimalVerticesLocalIS_C",(PC,IS),(pc,PrimalVertices));CHKERRQ(ierr);
579674ae819SStefano Zampini   PetscFunctionReturn(0);
580674ae819SStefano Zampini }
5812d505d7fSStefano Zampini 
5823100ebe3SStefano Zampini static PetscErrorCode PCBDDCGetPrimalVerticesLocalIS_BDDC(PC pc, IS *is)
5833100ebe3SStefano Zampini {
5843100ebe3SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC*)pc->data;
5853100ebe3SStefano Zampini 
5863100ebe3SStefano Zampini   PetscFunctionBegin;
5873100ebe3SStefano Zampini   *is = pcbddc->user_primal_vertices_local;
5883100ebe3SStefano Zampini   PetscFunctionReturn(0);
5893100ebe3SStefano Zampini }
5903100ebe3SStefano Zampini 
5913100ebe3SStefano Zampini /*@
5923100ebe3SStefano Zampini  PCBDDCGetPrimalVerticesLocalIS - Get user defined primal vertices set with PCBDDCSetPrimalVerticesLocalIS()
5933100ebe3SStefano Zampini 
5943100ebe3SStefano Zampini    Collective
5953100ebe3SStefano Zampini 
5963100ebe3SStefano Zampini    Input Parameters:
5973100ebe3SStefano Zampini .  pc - the preconditioning context
5983100ebe3SStefano Zampini 
5993100ebe3SStefano Zampini    Output Parameters:
6003100ebe3SStefano Zampini .  is - index set of primal vertices in local numbering (NULL if not set)
6013100ebe3SStefano Zampini 
6023100ebe3SStefano Zampini    Level: intermediate
6033100ebe3SStefano Zampini 
6043100ebe3SStefano Zampini    Notes:
6053100ebe3SStefano Zampini 
6063100ebe3SStefano Zampini .seealso: PCBDDC, PCBDDCSetPrimalVerticesIS(), PCBDDCGetPrimalVerticesIS(), PCBDDCSetPrimalVerticesLocalIS()
6073100ebe3SStefano Zampini @*/
6083100ebe3SStefano Zampini PetscErrorCode PCBDDCGetPrimalVerticesLocalIS(PC pc, IS *is)
6093100ebe3SStefano Zampini {
6103100ebe3SStefano Zampini   PetscErrorCode ierr;
6113100ebe3SStefano Zampini 
6123100ebe3SStefano Zampini   PetscFunctionBegin;
6133100ebe3SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
6143100ebe3SStefano Zampini   PetscValidPointer(is,2);
6153100ebe3SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetPrimalVerticesLocalIS_C",(PC,IS*),(pc,is));CHKERRQ(ierr);
6163100ebe3SStefano Zampini   PetscFunctionReturn(0);
6173100ebe3SStefano Zampini }
6183100ebe3SStefano Zampini 
6194fad6a16SStefano Zampini static PetscErrorCode PCBDDCSetCoarseningRatio_BDDC(PC pc,PetscInt k)
6204fad6a16SStefano Zampini {
6214fad6a16SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
6224fad6a16SStefano Zampini 
6234fad6a16SStefano Zampini   PetscFunctionBegin;
6244fad6a16SStefano Zampini   pcbddc->coarsening_ratio = k;
6254fad6a16SStefano Zampini   PetscFunctionReturn(0);
6264fad6a16SStefano Zampini }
6271e6b0712SBarry Smith 
6284fad6a16SStefano Zampini /*@
62928509bceSStefano Zampini  PCBDDCSetCoarseningRatio - Set coarsening ratio used in multilevel
6304fad6a16SStefano Zampini 
6314fad6a16SStefano Zampini    Logically collective on PC
6324fad6a16SStefano Zampini 
6334fad6a16SStefano Zampini    Input Parameters:
6344fad6a16SStefano Zampini +  pc - the preconditioning context
63528509bceSStefano Zampini -  k - coarsening ratio (H/h at the coarser level)
6364fad6a16SStefano Zampini 
6370f202f7eSStefano Zampini    Options Database Keys:
6380f202f7eSStefano Zampini .    -pc_bddc_coarsening_ratio
6394fad6a16SStefano Zampini 
6404fad6a16SStefano Zampini    Level: intermediate
6414fad6a16SStefano Zampini 
6424fad6a16SStefano Zampini    Notes:
6430f202f7eSStefano Zampini      Approximatively k subdomains at the finer level will be aggregated into a single subdomain at the coarser level
6444fad6a16SStefano Zampini 
6450f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetLevels()
6464fad6a16SStefano Zampini @*/
6474fad6a16SStefano Zampini PetscErrorCode PCBDDCSetCoarseningRatio(PC pc,PetscInt k)
6484fad6a16SStefano Zampini {
6494fad6a16SStefano Zampini   PetscErrorCode ierr;
6504fad6a16SStefano Zampini 
6514fad6a16SStefano Zampini   PetscFunctionBegin;
6524fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
6532b510759SStefano Zampini   PetscValidLogicalCollectiveInt(pc,k,2);
6544fad6a16SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetCoarseningRatio_C",(PC,PetscInt),(pc,k));CHKERRQ(ierr);
6554fad6a16SStefano Zampini   PetscFunctionReturn(0);
6564fad6a16SStefano Zampini }
6572b510759SStefano Zampini 
658b8ffe317SStefano Zampini /* The following functions (PCBDDCSetUseExactDirichlet PCBDDCSetLevel) are not public */
659b8ffe317SStefano Zampini static PetscErrorCode PCBDDCSetUseExactDirichlet_BDDC(PC pc,PetscBool flg)
660b8ffe317SStefano Zampini {
661b8ffe317SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
662b8ffe317SStefano Zampini 
663b8ffe317SStefano Zampini   PetscFunctionBegin;
66485c4d303SStefano Zampini   pcbddc->use_exact_dirichlet_trick = flg;
665b8ffe317SStefano Zampini   PetscFunctionReturn(0);
666b8ffe317SStefano Zampini }
667b8ffe317SStefano Zampini 
668b8ffe317SStefano Zampini PetscErrorCode PCBDDCSetUseExactDirichlet(PC pc,PetscBool flg)
6692b510759SStefano Zampini {
6702b510759SStefano Zampini   PetscErrorCode ierr;
6712b510759SStefano Zampini 
6722b510759SStefano Zampini   PetscFunctionBegin;
6732b510759SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
674b8ffe317SStefano Zampini   PetscValidLogicalCollectiveBool(pc,flg,2);
675b8ffe317SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetUseExactDirichlet_C",(PC,PetscBool),(pc,flg));CHKERRQ(ierr);
6762b510759SStefano Zampini   PetscFunctionReturn(0);
6772b510759SStefano Zampini }
6781e6b0712SBarry Smith 
6792b510759SStefano Zampini static PetscErrorCode PCBDDCSetLevel_BDDC(PC pc,PetscInt level)
6804fad6a16SStefano Zampini {
6814fad6a16SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
6824fad6a16SStefano Zampini 
6834fad6a16SStefano Zampini   PetscFunctionBegin;
6842b510759SStefano Zampini   pcbddc->current_level = level;
6854fad6a16SStefano Zampini   PetscFunctionReturn(0);
6864fad6a16SStefano Zampini }
6871e6b0712SBarry Smith 
688b8ffe317SStefano Zampini PetscErrorCode PCBDDCSetLevel(PC pc,PetscInt level)
689b8ffe317SStefano Zampini {
690b8ffe317SStefano Zampini   PetscErrorCode ierr;
691b8ffe317SStefano Zampini 
692b8ffe317SStefano Zampini   PetscFunctionBegin;
693b8ffe317SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
694b8ffe317SStefano Zampini   PetscValidLogicalCollectiveInt(pc,level,2);
695b8ffe317SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetLevel_C",(PC,PetscInt),(pc,level));CHKERRQ(ierr);
696b8ffe317SStefano Zampini   PetscFunctionReturn(0);
697b8ffe317SStefano Zampini }
698b8ffe317SStefano Zampini 
6992b510759SStefano Zampini static PetscErrorCode PCBDDCSetLevels_BDDC(PC pc,PetscInt levels)
7002b510759SStefano Zampini {
7012b510759SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
7022b510759SStefano Zampini 
7032b510759SStefano Zampini   PetscFunctionBegin;
7046080607fSStefano Zampini   if (levels > PETSC_PCBDDC_MAXLEVELS-1) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Maximum number of additional levels for BDDC is %d",PETSC_PCBDDC_MAXLEVELS-1);
7052b510759SStefano Zampini   pcbddc->max_levels = levels;
7062b510759SStefano Zampini   PetscFunctionReturn(0);
7072b510759SStefano Zampini }
7082b510759SStefano Zampini 
7094fad6a16SStefano Zampini /*@
71037ebbdf7SStefano Zampini  PCBDDCSetLevels - Sets the maximum number of additional levels allowed for multilevel BDDC
7114fad6a16SStefano Zampini 
7124fad6a16SStefano Zampini    Logically collective on PC
7134fad6a16SStefano Zampini 
7144fad6a16SStefano Zampini    Input Parameters:
7154fad6a16SStefano Zampini +  pc - the preconditioning context
71637ebbdf7SStefano Zampini -  levels - the maximum number of levels
7174fad6a16SStefano Zampini 
7180f202f7eSStefano Zampini    Options Database Keys:
7190f202f7eSStefano Zampini .    -pc_bddc_levels
7204fad6a16SStefano Zampini 
7214fad6a16SStefano Zampini    Level: intermediate
7224fad6a16SStefano Zampini 
7234fad6a16SStefano Zampini    Notes:
72437ebbdf7SStefano Zampini      The default value is 0, that gives the classical two-levels BDDC
7254fad6a16SStefano Zampini 
7260f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetCoarseningRatio()
7274fad6a16SStefano Zampini @*/
7282b510759SStefano Zampini PetscErrorCode PCBDDCSetLevels(PC pc,PetscInt levels)
7294fad6a16SStefano Zampini {
7304fad6a16SStefano Zampini   PetscErrorCode ierr;
7314fad6a16SStefano Zampini 
7324fad6a16SStefano Zampini   PetscFunctionBegin;
7334fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
7342b510759SStefano Zampini   PetscValidLogicalCollectiveInt(pc,levels,2);
7352b510759SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetLevels_C",(PC,PetscInt),(pc,levels));CHKERRQ(ierr);
7364fad6a16SStefano Zampini   PetscFunctionReturn(0);
7374fad6a16SStefano Zampini }
7381e6b0712SBarry Smith 
7393b03a366Sstefano_zampini static PetscErrorCode PCBDDCSetDirichletBoundaries_BDDC(PC pc,IS DirichletBoundaries)
7403b03a366Sstefano_zampini {
7413b03a366Sstefano_zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
74256282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
7433b03a366Sstefano_zampini   PetscErrorCode ierr;
7443b03a366Sstefano_zampini 
7453b03a366Sstefano_zampini   PetscFunctionBegin;
74656282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)DirichletBoundaries);CHKERRQ(ierr);
74756282151SStefano Zampini   if (pcbddc->DirichletBoundaries) {
74856282151SStefano Zampini     ierr = ISEqual(DirichletBoundaries,pcbddc->DirichletBoundaries,&isequal);CHKERRQ(ierr);
74956282151SStefano Zampini   }
750785d1243SStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
751785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
7523b03a366Sstefano_zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
75336e030ebSStefano Zampini   pcbddc->DirichletBoundaries = DirichletBoundaries;
75456282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
7553b03a366Sstefano_zampini   PetscFunctionReturn(0);
7563b03a366Sstefano_zampini }
7571e6b0712SBarry Smith 
7583b03a366Sstefano_zampini /*@
75928509bceSStefano Zampini  PCBDDCSetDirichletBoundaries - Set IS defining Dirichlet boundaries for the global problem.
7603b03a366Sstefano_zampini 
761785d1243SStefano Zampini    Collective
7623b03a366Sstefano_zampini 
7633b03a366Sstefano_zampini    Input Parameters:
7643b03a366Sstefano_zampini +  pc - the preconditioning context
765785d1243SStefano Zampini -  DirichletBoundaries - parallel IS defining the Dirichlet boundaries
7663b03a366Sstefano_zampini 
7673b03a366Sstefano_zampini    Level: intermediate
7683b03a366Sstefano_zampini 
7690f202f7eSStefano Zampini    Notes:
7700f202f7eSStefano Zampini      Provide the information if you used MatZeroRows/Columns routines. Any process can list any global node
7713b03a366Sstefano_zampini 
7720f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetDirichletBoundariesLocal(), MatZeroRows(), MatZeroRowsColumns()
7733b03a366Sstefano_zampini @*/
7743b03a366Sstefano_zampini PetscErrorCode PCBDDCSetDirichletBoundaries(PC pc,IS DirichletBoundaries)
7753b03a366Sstefano_zampini {
7763b03a366Sstefano_zampini   PetscErrorCode ierr;
7773b03a366Sstefano_zampini 
7783b03a366Sstefano_zampini   PetscFunctionBegin;
7793b03a366Sstefano_zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
780674ae819SStefano Zampini   PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2);
781785d1243SStefano Zampini   PetscCheckSameComm(pc,1,DirichletBoundaries,2);
7823b03a366Sstefano_zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDirichletBoundaries_C",(PC,IS),(pc,DirichletBoundaries));CHKERRQ(ierr);
7833b03a366Sstefano_zampini   PetscFunctionReturn(0);
7843b03a366Sstefano_zampini }
7851e6b0712SBarry Smith 
78682ba6b80SStefano Zampini static PetscErrorCode PCBDDCSetDirichletBoundariesLocal_BDDC(PC pc,IS DirichletBoundaries)
7873b03a366Sstefano_zampini {
7883b03a366Sstefano_zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
78956282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
7903b03a366Sstefano_zampini   PetscErrorCode ierr;
7913b03a366Sstefano_zampini 
7923b03a366Sstefano_zampini   PetscFunctionBegin;
79356282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)DirichletBoundaries);CHKERRQ(ierr);
79456282151SStefano Zampini   if (pcbddc->DirichletBoundariesLocal) {
79556282151SStefano Zampini     ierr = ISEqual(DirichletBoundaries,pcbddc->DirichletBoundariesLocal,&isequal);CHKERRQ(ierr);
79656282151SStefano Zampini   }
797785d1243SStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
798785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
7993b03a366Sstefano_zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
800785d1243SStefano Zampini   pcbddc->DirichletBoundariesLocal = DirichletBoundaries;
80156282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
8023b03a366Sstefano_zampini   PetscFunctionReturn(0);
8033b03a366Sstefano_zampini }
8043b03a366Sstefano_zampini 
8053b03a366Sstefano_zampini /*@
80682ba6b80SStefano Zampini  PCBDDCSetDirichletBoundariesLocal - Set IS defining Dirichlet boundaries for the global problem in local ordering.
8073b03a366Sstefano_zampini 
808785d1243SStefano Zampini    Collective
8093b03a366Sstefano_zampini 
8103b03a366Sstefano_zampini    Input Parameters:
8113b03a366Sstefano_zampini +  pc - the preconditioning context
81282ba6b80SStefano Zampini -  DirichletBoundaries - parallel IS defining the Dirichlet boundaries (in local ordering)
8133b03a366Sstefano_zampini 
8143b03a366Sstefano_zampini    Level: intermediate
8153b03a366Sstefano_zampini 
8163b03a366Sstefano_zampini    Notes:
8173b03a366Sstefano_zampini 
8180f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetDirichletBoundaries(), MatZeroRows(), MatZeroRowsColumns()
8193b03a366Sstefano_zampini @*/
82082ba6b80SStefano Zampini PetscErrorCode PCBDDCSetDirichletBoundariesLocal(PC pc,IS DirichletBoundaries)
8213b03a366Sstefano_zampini {
8223b03a366Sstefano_zampini   PetscErrorCode ierr;
8233b03a366Sstefano_zampini 
8243b03a366Sstefano_zampini   PetscFunctionBegin;
8253b03a366Sstefano_zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
8263b03a366Sstefano_zampini   PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2);
82782ba6b80SStefano Zampini   PetscCheckSameComm(pc,1,DirichletBoundaries,2);
82882ba6b80SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDirichletBoundariesLocal_C",(PC,IS),(pc,DirichletBoundaries));CHKERRQ(ierr);
8293b03a366Sstefano_zampini   PetscFunctionReturn(0);
8303b03a366Sstefano_zampini }
8313b03a366Sstefano_zampini 
83253cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc,IS NeumannBoundaries)
8330c7d97c5SJed Brown {
8340c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
83556282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
83653cdbc3dSStefano Zampini   PetscErrorCode ierr;
8370c7d97c5SJed Brown 
8380c7d97c5SJed Brown   PetscFunctionBegin;
83956282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr);
84056282151SStefano Zampini   if (pcbddc->NeumannBoundaries) {
84156282151SStefano Zampini     ierr = ISEqual(NeumannBoundaries,pcbddc->NeumannBoundaries,&isequal);CHKERRQ(ierr);
84256282151SStefano Zampini   }
843785d1243SStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
844785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
84553cdbc3dSStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
84636e030ebSStefano Zampini   pcbddc->NeumannBoundaries = NeumannBoundaries;
84756282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
8480c7d97c5SJed Brown   PetscFunctionReturn(0);
8490c7d97c5SJed Brown }
8501e6b0712SBarry Smith 
85157527edcSJed Brown /*@
85228509bceSStefano Zampini  PCBDDCSetNeumannBoundaries - Set IS defining Neumann boundaries for the global problem.
85357527edcSJed Brown 
854785d1243SStefano Zampini    Collective
85557527edcSJed Brown 
85657527edcSJed Brown    Input Parameters:
85757527edcSJed Brown +  pc - the preconditioning context
858785d1243SStefano Zampini -  NeumannBoundaries - parallel IS defining the Neumann boundaries
85957527edcSJed Brown 
86057527edcSJed Brown    Level: intermediate
86157527edcSJed Brown 
8620f202f7eSStefano Zampini    Notes:
8630f202f7eSStefano Zampini      Any process can list any global node
86457527edcSJed Brown 
8650f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetNeumannBoundariesLocal()
86657527edcSJed Brown @*/
86753cdbc3dSStefano Zampini PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc,IS NeumannBoundaries)
8680c7d97c5SJed Brown {
8690c7d97c5SJed Brown   PetscErrorCode ierr;
8700c7d97c5SJed Brown 
8710c7d97c5SJed Brown   PetscFunctionBegin;
8720c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
873674ae819SStefano Zampini   PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2);
874785d1243SStefano Zampini   PetscCheckSameComm(pc,1,NeumannBoundaries,2);
87553cdbc3dSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundaries_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr);
87653cdbc3dSStefano Zampini   PetscFunctionReturn(0);
87753cdbc3dSStefano Zampini }
8781e6b0712SBarry Smith 
87982ba6b80SStefano Zampini static PetscErrorCode PCBDDCSetNeumannBoundariesLocal_BDDC(PC pc,IS NeumannBoundaries)
8800c7d97c5SJed Brown {
8810c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
88256282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
8830c7d97c5SJed Brown   PetscErrorCode ierr;
8840c7d97c5SJed Brown 
8850c7d97c5SJed Brown   PetscFunctionBegin;
88656282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr);
88756282151SStefano Zampini   if (pcbddc->NeumannBoundariesLocal) {
88856282151SStefano Zampini     ierr = ISEqual(NeumannBoundaries,pcbddc->NeumannBoundariesLocal,&isequal);CHKERRQ(ierr);
88956282151SStefano Zampini   }
890785d1243SStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
891785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
8920c7d97c5SJed Brown   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
893785d1243SStefano Zampini   pcbddc->NeumannBoundariesLocal = NeumannBoundaries;
89456282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
8950c7d97c5SJed Brown   PetscFunctionReturn(0);
8960c7d97c5SJed Brown }
8970c7d97c5SJed Brown 
8980c7d97c5SJed Brown /*@
89982ba6b80SStefano Zampini  PCBDDCSetNeumannBoundariesLocal - Set IS defining Neumann boundaries for the global problem in local ordering.
9000c7d97c5SJed Brown 
901785d1243SStefano Zampini    Collective
9020c7d97c5SJed Brown 
9030c7d97c5SJed Brown    Input Parameters:
9040c7d97c5SJed Brown +  pc - the preconditioning context
90582ba6b80SStefano Zampini -  NeumannBoundaries - parallel IS defining the subdomain part of Neumann boundaries (in local ordering)
9060c7d97c5SJed Brown 
9070c7d97c5SJed Brown    Level: intermediate
9080c7d97c5SJed Brown 
9090c7d97c5SJed Brown    Notes:
9100c7d97c5SJed Brown 
9110f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetNeumannBoundaries()
9120c7d97c5SJed Brown @*/
91382ba6b80SStefano Zampini PetscErrorCode PCBDDCSetNeumannBoundariesLocal(PC pc,IS NeumannBoundaries)
9140c7d97c5SJed Brown {
9150c7d97c5SJed Brown   PetscErrorCode ierr;
9160c7d97c5SJed Brown 
9170c7d97c5SJed Brown   PetscFunctionBegin;
9180c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
9190c7d97c5SJed Brown   PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2);
92082ba6b80SStefano Zampini   PetscCheckSameComm(pc,1,NeumannBoundaries,2);
92182ba6b80SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundariesLocal_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr);
92253cdbc3dSStefano Zampini   PetscFunctionReturn(0);
92353cdbc3dSStefano Zampini }
92453cdbc3dSStefano Zampini 
925da1bb401SStefano Zampini static PetscErrorCode PCBDDCGetDirichletBoundaries_BDDC(PC pc,IS *DirichletBoundaries)
926da1bb401SStefano Zampini {
927da1bb401SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
928da1bb401SStefano Zampini 
929da1bb401SStefano Zampini   PetscFunctionBegin;
930da1bb401SStefano Zampini   *DirichletBoundaries = pcbddc->DirichletBoundaries;
931da1bb401SStefano Zampini   PetscFunctionReturn(0);
932da1bb401SStefano Zampini }
9331e6b0712SBarry Smith 
934da1bb401SStefano Zampini /*@
935785d1243SStefano Zampini  PCBDDCGetDirichletBoundaries - Get parallel IS for Dirichlet boundaries
936da1bb401SStefano Zampini 
937785d1243SStefano Zampini    Collective
938785d1243SStefano Zampini 
939785d1243SStefano Zampini    Input Parameters:
940785d1243SStefano Zampini .  pc - the preconditioning context
941785d1243SStefano Zampini 
942785d1243SStefano Zampini    Output Parameters:
943785d1243SStefano Zampini .  DirichletBoundaries - index set defining the Dirichlet boundaries
944785d1243SStefano Zampini 
945785d1243SStefano Zampini    Level: intermediate
946785d1243SStefano Zampini 
9470f202f7eSStefano Zampini    Notes:
9480f202f7eSStefano Zampini      The IS returned (if any) is the same passed in earlier by the user with PCBDDCSetDirichletBoundaries
949785d1243SStefano Zampini 
950785d1243SStefano Zampini .seealso: PCBDDC
951785d1243SStefano Zampini @*/
952785d1243SStefano Zampini PetscErrorCode PCBDDCGetDirichletBoundaries(PC pc,IS *DirichletBoundaries)
953785d1243SStefano Zampini {
954785d1243SStefano Zampini   PetscErrorCode ierr;
955785d1243SStefano Zampini 
956785d1243SStefano Zampini   PetscFunctionBegin;
957785d1243SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
958785d1243SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetDirichletBoundaries_C",(PC,IS*),(pc,DirichletBoundaries));CHKERRQ(ierr);
959785d1243SStefano Zampini   PetscFunctionReturn(0);
960785d1243SStefano Zampini }
961785d1243SStefano Zampini 
962785d1243SStefano Zampini static PetscErrorCode PCBDDCGetDirichletBoundariesLocal_BDDC(PC pc,IS *DirichletBoundaries)
963785d1243SStefano Zampini {
964785d1243SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
965785d1243SStefano Zampini 
966785d1243SStefano Zampini   PetscFunctionBegin;
967785d1243SStefano Zampini   *DirichletBoundaries = pcbddc->DirichletBoundariesLocal;
968785d1243SStefano Zampini   PetscFunctionReturn(0);
969785d1243SStefano Zampini }
970785d1243SStefano Zampini 
971da1bb401SStefano Zampini /*@
97282ba6b80SStefano Zampini  PCBDDCGetDirichletBoundariesLocal - Get parallel IS for Dirichlet boundaries (in local ordering)
973da1bb401SStefano Zampini 
974785d1243SStefano Zampini    Collective
975da1bb401SStefano Zampini 
976da1bb401SStefano Zampini    Input Parameters:
97728509bceSStefano Zampini .  pc - the preconditioning context
978da1bb401SStefano Zampini 
979da1bb401SStefano Zampini    Output Parameters:
98028509bceSStefano Zampini .  DirichletBoundaries - index set defining the subdomain part of Dirichlet boundaries
981da1bb401SStefano Zampini 
982da1bb401SStefano Zampini    Level: intermediate
983da1bb401SStefano Zampini 
984da1bb401SStefano Zampini    Notes:
9850f202f7eSStefano Zampini      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).
9860f202f7eSStefano Zampini           In the latter case, the IS will be available after PCSetUp.
987da1bb401SStefano Zampini 
988da1bb401SStefano Zampini .seealso: PCBDDC
989da1bb401SStefano Zampini @*/
99082ba6b80SStefano Zampini PetscErrorCode PCBDDCGetDirichletBoundariesLocal(PC pc,IS *DirichletBoundaries)
991da1bb401SStefano Zampini {
992da1bb401SStefano Zampini   PetscErrorCode ierr;
993da1bb401SStefano Zampini 
994da1bb401SStefano Zampini   PetscFunctionBegin;
995da1bb401SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
99682ba6b80SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetDirichletBoundariesLocal_C",(PC,IS*),(pc,DirichletBoundaries));CHKERRQ(ierr);
997da1bb401SStefano Zampini   PetscFunctionReturn(0);
998da1bb401SStefano Zampini }
9991e6b0712SBarry Smith 
100053cdbc3dSStefano Zampini static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc,IS *NeumannBoundaries)
100153cdbc3dSStefano Zampini {
100253cdbc3dSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
100353cdbc3dSStefano Zampini 
100453cdbc3dSStefano Zampini   PetscFunctionBegin;
100553cdbc3dSStefano Zampini   *NeumannBoundaries = pcbddc->NeumannBoundaries;
100653cdbc3dSStefano Zampini   PetscFunctionReturn(0);
100753cdbc3dSStefano Zampini }
10081e6b0712SBarry Smith 
100953cdbc3dSStefano Zampini /*@
1010785d1243SStefano Zampini  PCBDDCGetNeumannBoundaries - Get parallel IS for Neumann boundaries
101153cdbc3dSStefano Zampini 
1012785d1243SStefano Zampini    Collective
1013785d1243SStefano Zampini 
1014785d1243SStefano Zampini    Input Parameters:
1015785d1243SStefano Zampini .  pc - the preconditioning context
1016785d1243SStefano Zampini 
1017785d1243SStefano Zampini    Output Parameters:
1018785d1243SStefano Zampini .  NeumannBoundaries - index set defining the Neumann boundaries
1019785d1243SStefano Zampini 
1020785d1243SStefano Zampini    Level: intermediate
1021785d1243SStefano Zampini 
10220f202f7eSStefano Zampini    Notes:
10230f202f7eSStefano Zampini      The IS returned (if any) is the same passed in earlier by the user with PCBDDCSetNeumannBoundaries
1024785d1243SStefano Zampini 
1025785d1243SStefano Zampini .seealso: PCBDDC
1026785d1243SStefano Zampini @*/
1027785d1243SStefano Zampini PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc,IS *NeumannBoundaries)
1028785d1243SStefano Zampini {
1029785d1243SStefano Zampini   PetscErrorCode ierr;
1030785d1243SStefano Zampini 
1031785d1243SStefano Zampini   PetscFunctionBegin;
1032785d1243SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1033785d1243SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundaries_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr);
1034785d1243SStefano Zampini   PetscFunctionReturn(0);
1035785d1243SStefano Zampini }
1036785d1243SStefano Zampini 
1037785d1243SStefano Zampini static PetscErrorCode PCBDDCGetNeumannBoundariesLocal_BDDC(PC pc,IS *NeumannBoundaries)
1038785d1243SStefano Zampini {
1039785d1243SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
1040785d1243SStefano Zampini 
1041785d1243SStefano Zampini   PetscFunctionBegin;
1042785d1243SStefano Zampini   *NeumannBoundaries = pcbddc->NeumannBoundariesLocal;
1043785d1243SStefano Zampini   PetscFunctionReturn(0);
1044785d1243SStefano Zampini }
1045785d1243SStefano Zampini 
104653cdbc3dSStefano Zampini /*@
104782ba6b80SStefano Zampini  PCBDDCGetNeumannBoundariesLocal - Get parallel IS for Neumann boundaries (in local ordering)
104853cdbc3dSStefano Zampini 
1049785d1243SStefano Zampini    Collective
105053cdbc3dSStefano Zampini 
105153cdbc3dSStefano Zampini    Input Parameters:
105228509bceSStefano Zampini .  pc - the preconditioning context
105353cdbc3dSStefano Zampini 
105453cdbc3dSStefano Zampini    Output Parameters:
105528509bceSStefano Zampini .  NeumannBoundaries - index set defining the subdomain part of Neumann boundaries
105653cdbc3dSStefano Zampini 
105753cdbc3dSStefano Zampini    Level: intermediate
105853cdbc3dSStefano Zampini 
105953cdbc3dSStefano Zampini    Notes:
10600f202f7eSStefano Zampini      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).
10610f202f7eSStefano Zampini           In the latter case, the IS will be available after PCSetUp.
106253cdbc3dSStefano Zampini 
106353cdbc3dSStefano Zampini .seealso: PCBDDC
106453cdbc3dSStefano Zampini @*/
106582ba6b80SStefano Zampini PetscErrorCode PCBDDCGetNeumannBoundariesLocal(PC pc,IS *NeumannBoundaries)
106653cdbc3dSStefano Zampini {
106753cdbc3dSStefano Zampini   PetscErrorCode ierr;
106853cdbc3dSStefano Zampini 
106953cdbc3dSStefano Zampini   PetscFunctionBegin;
107053cdbc3dSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
107182ba6b80SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundariesLocal_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr);
10720c7d97c5SJed Brown   PetscFunctionReturn(0);
10730c7d97c5SJed Brown }
10741e6b0712SBarry Smith 
10751a83f524SJed Brown static PetscErrorCode PCBDDCSetLocalAdjacencyGraph_BDDC(PC pc, PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode)
107636e030ebSStefano Zampini {
107736e030ebSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1078da1bb401SStefano Zampini   PCBDDCGraph    mat_graph = pcbddc->mat_graph;
107956282151SStefano Zampini   PetscBool      same_data = PETSC_FALSE;
1080da1bb401SStefano Zampini   PetscErrorCode ierr;
108136e030ebSStefano Zampini 
108236e030ebSStefano Zampini   PetscFunctionBegin;
10838687889aSStefano Zampini   if (!nvtxs) {
108404194a47SStefano Zampini     if (copymode == PETSC_OWN_POINTER) {
108504194a47SStefano Zampini       ierr = PetscFree(xadj);CHKERRQ(ierr);
108604194a47SStefano Zampini       ierr = PetscFree(adjncy);CHKERRQ(ierr);
108704194a47SStefano Zampini     }
10888687889aSStefano Zampini     ierr = PCBDDCGraphResetCSR(mat_graph);CHKERRQ(ierr);
10898687889aSStefano Zampini     PetscFunctionReturn(0);
10908687889aSStefano Zampini   }
109166da6bd7Sstefano_zampini   if (mat_graph->nvtxs == nvtxs && mat_graph->freecsr) { /* we own the data */
109256282151SStefano Zampini     if (mat_graph->xadj == xadj && mat_graph->adjncy == adjncy) same_data = PETSC_TRUE;
109356282151SStefano Zampini     if (!same_data && mat_graph->xadj[nvtxs] == xadj[nvtxs]) {
1094580bdb30SBarry Smith       ierr = PetscArraycmp(xadj,mat_graph->xadj,nvtxs+1,&same_data);CHKERRQ(ierr);
10952d505d7fSStefano Zampini       if (same_data) {
1096580bdb30SBarry Smith         ierr = PetscArraycmp(adjncy,mat_graph->adjncy,xadj[nvtxs],&same_data);CHKERRQ(ierr);
10972d505d7fSStefano Zampini       }
109856282151SStefano Zampini     }
109956282151SStefano Zampini   }
110056282151SStefano Zampini   if (!same_data) {
1101674ae819SStefano Zampini     /* free old CSR */
1102674ae819SStefano Zampini     ierr = PCBDDCGraphResetCSR(mat_graph);CHKERRQ(ierr);
1103674ae819SStefano Zampini     /* get CSR into graph structure */
1104da1bb401SStefano Zampini     if (copymode == PETSC_COPY_VALUES) {
1105854ce69bSBarry Smith       ierr = PetscMalloc1(nvtxs+1,&mat_graph->xadj);CHKERRQ(ierr);
1106785e854fSJed Brown       ierr = PetscMalloc1(xadj[nvtxs],&mat_graph->adjncy);CHKERRQ(ierr);
1107580bdb30SBarry Smith       ierr = PetscArraycpy(mat_graph->xadj,xadj,nvtxs+1);CHKERRQ(ierr);
1108580bdb30SBarry Smith       ierr = PetscArraycpy(mat_graph->adjncy,adjncy,xadj[nvtxs]);CHKERRQ(ierr);
1109a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_TRUE;
1110da1bb401SStefano Zampini     } else if (copymode == PETSC_OWN_POINTER) {
11111a83f524SJed Brown       mat_graph->xadj    = (PetscInt*)xadj;
11121a83f524SJed Brown       mat_graph->adjncy  = (PetscInt*)adjncy;
1113a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_TRUE;
1114a1dbd327SStefano Zampini     } else if (copymode == PETSC_USE_POINTER) {
1115a1dbd327SStefano Zampini       mat_graph->xadj    = (PetscInt*)xadj;
1116a1dbd327SStefano Zampini       mat_graph->adjncy  = (PetscInt*)adjncy;
1117a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_FALSE;
1118e0fe2d75SToby Isaac     } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported copy mode %D",copymode);
1119575ad6abSStefano Zampini     mat_graph->nvtxs_csr = nvtxs;
112056282151SStefano Zampini     pcbddc->recompute_topography = PETSC_TRUE;
112156282151SStefano Zampini   }
112236e030ebSStefano Zampini   PetscFunctionReturn(0);
112336e030ebSStefano Zampini }
11241e6b0712SBarry Smith 
112536e030ebSStefano Zampini /*@
112654fffbccSStefano Zampini  PCBDDCSetLocalAdjacencyGraph - Set adjacency structure (CSR graph) of the local degrees of freedom.
112736e030ebSStefano Zampini 
112836e030ebSStefano Zampini    Not collective
112936e030ebSStefano Zampini 
113036e030ebSStefano Zampini    Input Parameters:
113154fffbccSStefano Zampini +  pc - the preconditioning context.
113254fffbccSStefano Zampini .  nvtxs - number of local vertices of the graph (i.e., the number of local dofs).
113354fffbccSStefano Zampini .  xadj, adjncy - the connectivity of the dofs in CSR format.
113454fffbccSStefano Zampini -  copymode - supported modes are PETSC_COPY_VALUES, PETSC_USE_POINTER or PETSC_OWN_POINTER.
113536e030ebSStefano Zampini 
113636e030ebSStefano Zampini    Level: intermediate
113736e030ebSStefano Zampini 
113895452b02SPatrick Sanan    Notes:
113995452b02SPatrick Sanan     A dof is considered connected with all local dofs if xadj[dof+1]-xadj[dof] == 1 and adjncy[xadj[dof]] is negative.
114036e030ebSStefano Zampini 
114128509bceSStefano Zampini .seealso: PCBDDC,PetscCopyMode
114236e030ebSStefano Zampini @*/
11431a83f524SJed Brown PetscErrorCode PCBDDCSetLocalAdjacencyGraph(PC pc,PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode)
114436e030ebSStefano Zampini {
1145575ad6abSStefano Zampini   void (*f)(void) = 0;
114636e030ebSStefano Zampini   PetscErrorCode ierr;
114736e030ebSStefano Zampini 
114836e030ebSStefano Zampini   PetscFunctionBegin;
114936e030ebSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
11508687889aSStefano Zampini   if (nvtxs) {
1151674ae819SStefano Zampini     PetscValidIntPointer(xadj,3);
11521633d1f0SStefano Zampini     if (xadj[nvtxs]) PetscValidIntPointer(adjncy,4);
11538687889aSStefano Zampini   }
11541a83f524SJed Brown   ierr = PetscTryMethod(pc,"PCBDDCSetLocalAdjacencyGraph_C",(PC,PetscInt,const PetscInt[],const PetscInt[],PetscCopyMode),(pc,nvtxs,xadj,adjncy,copymode));CHKERRQ(ierr);
1155575ad6abSStefano Zampini   /* free arrays if PCBDDC is not the PC type */
1156575ad6abSStefano Zampini   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",&f);CHKERRQ(ierr);
1157575ad6abSStefano Zampini   if (!f && copymode == PETSC_OWN_POINTER) {
1158575ad6abSStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
1159575ad6abSStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
1160da1bb401SStefano Zampini   }
116136e030ebSStefano Zampini   PetscFunctionReturn(0);
116236e030ebSStefano Zampini }
11631e6b0712SBarry Smith 
116463602bcaSStefano Zampini static PetscErrorCode PCBDDCSetDofsSplittingLocal_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
116563602bcaSStefano Zampini {
116663602bcaSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
116763602bcaSStefano Zampini   PetscInt       i;
116856282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
116963602bcaSStefano Zampini   PetscErrorCode ierr;
117063602bcaSStefano Zampini 
117163602bcaSStefano Zampini   PetscFunctionBegin;
117256282151SStefano Zampini   if (pcbddc->n_ISForDofsLocal == n_is) {
117356282151SStefano Zampini     for (i=0;i<n_is;i++) {
117456282151SStefano Zampini       PetscBool isequalt;
117556282151SStefano Zampini       ierr = ISEqual(ISForDofs[i],pcbddc->ISForDofsLocal[i],&isequalt);CHKERRQ(ierr);
117656282151SStefano Zampini       if (!isequalt) break;
117756282151SStefano Zampini     }
117856282151SStefano Zampini     if (i == n_is) isequal = PETSC_TRUE;
117956282151SStefano Zampini   }
118056282151SStefano Zampini   for (i=0;i<n_is;i++) {
118156282151SStefano Zampini     ierr = PetscObjectReference((PetscObject)ISForDofs[i]);CHKERRQ(ierr);
118256282151SStefano Zampini   }
118363602bcaSStefano Zampini   /* Destroy ISes if they were already set */
118463602bcaSStefano Zampini   for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
118563602bcaSStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
118663602bcaSStefano Zampini   }
118763602bcaSStefano Zampini   ierr = PetscFree(pcbddc->ISForDofsLocal);CHKERRQ(ierr);
118863602bcaSStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
118963602bcaSStefano Zampini   for (i=0;i<pcbddc->n_ISForDofs;i++) {
119063602bcaSStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
119163602bcaSStefano Zampini   }
119263602bcaSStefano Zampini   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
119363602bcaSStefano Zampini   pcbddc->n_ISForDofs = 0;
119463602bcaSStefano Zampini   /* allocate space then set */
1195d02579f5SStefano Zampini   if (n_is) {
1196d02579f5SStefano Zampini     ierr = PetscMalloc1(n_is,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
1197d02579f5SStefano Zampini   }
119863602bcaSStefano Zampini   for (i=0;i<n_is;i++) {
119963602bcaSStefano Zampini     pcbddc->ISForDofsLocal[i] = ISForDofs[i];
120063602bcaSStefano Zampini   }
120163602bcaSStefano Zampini   pcbddc->n_ISForDofsLocal = n_is;
120263602bcaSStefano Zampini   if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE;
120356282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
120463602bcaSStefano Zampini   PetscFunctionReturn(0);
120563602bcaSStefano Zampini }
120663602bcaSStefano Zampini 
120763602bcaSStefano Zampini /*@
120863602bcaSStefano Zampini  PCBDDCSetDofsSplittingLocal - Set index sets defining fields of the local subdomain matrix
120963602bcaSStefano Zampini 
121063602bcaSStefano Zampini    Collective
121163602bcaSStefano Zampini 
121263602bcaSStefano Zampini    Input Parameters:
121363602bcaSStefano Zampini +  pc - the preconditioning context
12140f202f7eSStefano Zampini .  n_is - number of index sets defining the fields
12150f202f7eSStefano Zampini -  ISForDofs - array of IS describing the fields in local ordering
121663602bcaSStefano Zampini 
121763602bcaSStefano Zampini    Level: intermediate
121863602bcaSStefano Zampini 
12190f202f7eSStefano Zampini    Notes:
12200f202f7eSStefano Zampini      n_is should be the same among processes. Not all nodes need to be listed: unlisted nodes will belong to the complement field.
122163602bcaSStefano Zampini 
122263602bcaSStefano Zampini .seealso: PCBDDC
122363602bcaSStefano Zampini @*/
122463602bcaSStefano Zampini PetscErrorCode PCBDDCSetDofsSplittingLocal(PC pc,PetscInt n_is, IS ISForDofs[])
122563602bcaSStefano Zampini {
122663602bcaSStefano Zampini   PetscInt       i;
122763602bcaSStefano Zampini   PetscErrorCode ierr;
122863602bcaSStefano Zampini 
122963602bcaSStefano Zampini   PetscFunctionBegin;
123063602bcaSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
123163602bcaSStefano Zampini   PetscValidLogicalCollectiveInt(pc,n_is,2);
123263602bcaSStefano Zampini   for (i=0;i<n_is;i++) {
123363602bcaSStefano Zampini     PetscCheckSameComm(pc,1,ISForDofs[i],3);
123463602bcaSStefano Zampini     PetscValidHeaderSpecific(ISForDofs[i],IS_CLASSID,3);
123563602bcaSStefano Zampini   }
1236e71e7a71SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplittingLocal_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr);
123763602bcaSStefano Zampini   PetscFunctionReturn(0);
123863602bcaSStefano Zampini }
123963602bcaSStefano Zampini 
12409c0446d6SStefano Zampini static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
12419c0446d6SStefano Zampini {
12429c0446d6SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
12439c0446d6SStefano Zampini   PetscInt       i;
124456282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
12459c0446d6SStefano Zampini   PetscErrorCode ierr;
12469c0446d6SStefano Zampini 
12479c0446d6SStefano Zampini   PetscFunctionBegin;
124856282151SStefano Zampini   if (pcbddc->n_ISForDofs == n_is) {
124956282151SStefano Zampini     for (i=0;i<n_is;i++) {
125056282151SStefano Zampini       PetscBool isequalt;
125156282151SStefano Zampini       ierr = ISEqual(ISForDofs[i],pcbddc->ISForDofs[i],&isequalt);CHKERRQ(ierr);
125256282151SStefano Zampini       if (!isequalt) break;
125356282151SStefano Zampini     }
125456282151SStefano Zampini     if (i == n_is) isequal = PETSC_TRUE;
125556282151SStefano Zampini   }
125656282151SStefano Zampini   for (i=0;i<n_is;i++) {
125756282151SStefano Zampini     ierr = PetscObjectReference((PetscObject)ISForDofs[i]);CHKERRQ(ierr);
125856282151SStefano Zampini   }
1259da1bb401SStefano Zampini   /* Destroy ISes if they were already set */
12609c0446d6SStefano Zampini   for (i=0;i<pcbddc->n_ISForDofs;i++) {
12619c0446d6SStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
12629c0446d6SStefano Zampini   }
1263d11ae9bbSstefano_zampini   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
126463602bcaSStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
126563602bcaSStefano Zampini   for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
126663602bcaSStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
126763602bcaSStefano Zampini   }
126863602bcaSStefano Zampini   ierr = PetscFree(pcbddc->ISForDofsLocal);CHKERRQ(ierr);
126963602bcaSStefano Zampini   pcbddc->n_ISForDofsLocal = 0;
1270da1bb401SStefano Zampini   /* allocate space then set */
1271d02579f5SStefano Zampini   if (n_is) {
1272785e854fSJed Brown     ierr = PetscMalloc1(n_is,&pcbddc->ISForDofs);CHKERRQ(ierr);
1273d02579f5SStefano Zampini   }
12749c0446d6SStefano Zampini   for (i=0;i<n_is;i++) {
1275da1bb401SStefano Zampini     pcbddc->ISForDofs[i] = ISForDofs[i];
12769c0446d6SStefano Zampini   }
12779c0446d6SStefano Zampini   pcbddc->n_ISForDofs = n_is;
127863602bcaSStefano Zampini   if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE;
127956282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
12809c0446d6SStefano Zampini   PetscFunctionReturn(0);
12819c0446d6SStefano Zampini }
12821e6b0712SBarry Smith 
12839c0446d6SStefano Zampini /*@
128463602bcaSStefano Zampini  PCBDDCSetDofsSplitting - Set index sets defining fields of the global matrix
12859c0446d6SStefano Zampini 
128663602bcaSStefano Zampini    Collective
12879c0446d6SStefano Zampini 
12889c0446d6SStefano Zampini    Input Parameters:
12899c0446d6SStefano Zampini +  pc - the preconditioning context
12900f202f7eSStefano Zampini .  n_is - number of index sets defining the fields
12910f202f7eSStefano Zampini -  ISForDofs - array of IS describing the fields in global ordering
12929c0446d6SStefano Zampini 
12939c0446d6SStefano Zampini    Level: intermediate
12949c0446d6SStefano Zampini 
12950f202f7eSStefano Zampini    Notes:
12960f202f7eSStefano Zampini      Any process can list any global node. Not all nodes need to be listed: unlisted nodes will belong to the complement field.
12979c0446d6SStefano Zampini 
12989c0446d6SStefano Zampini .seealso: PCBDDC
12999c0446d6SStefano Zampini @*/
13009c0446d6SStefano Zampini PetscErrorCode PCBDDCSetDofsSplitting(PC pc,PetscInt n_is, IS ISForDofs[])
13019c0446d6SStefano Zampini {
13022b510759SStefano Zampini   PetscInt       i;
13039c0446d6SStefano Zampini   PetscErrorCode ierr;
13049c0446d6SStefano Zampini 
13059c0446d6SStefano Zampini   PetscFunctionBegin;
13069c0446d6SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
130763602bcaSStefano Zampini   PetscValidLogicalCollectiveInt(pc,n_is,2);
13082b510759SStefano Zampini   for (i=0;i<n_is;i++) {
130963602bcaSStefano Zampini     PetscValidHeaderSpecific(ISForDofs[i],IS_CLASSID,3);
1310a011d5a7Sstefano_zampini     PetscCheckSameComm(pc,1,ISForDofs[i],3);
13112b510759SStefano Zampini   }
13129c0446d6SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplitting_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr);
13139c0446d6SStefano Zampini   PetscFunctionReturn(0);
13149c0446d6SStefano Zampini }
1315906d46d4SStefano Zampini 
1316534831adSStefano Zampini /*
1317534831adSStefano Zampini    PCPreSolve_BDDC - Changes the right hand side and (if necessary) the initial
1318534831adSStefano Zampini                      guess if a transformation of basis approach has been selected.
13199c0446d6SStefano Zampini 
1320534831adSStefano Zampini    Input Parameter:
1321534831adSStefano Zampini +  pc - the preconditioner contex
1322534831adSStefano Zampini 
1323534831adSStefano Zampini    Application Interface Routine: PCPreSolve()
1324534831adSStefano Zampini 
1325534831adSStefano Zampini    Notes:
1326534831adSStefano Zampini      The interface routine PCPreSolve() is not usually called directly by
1327534831adSStefano Zampini    the user, but instead is called by KSPSolve().
1328534831adSStefano Zampini */
1329534831adSStefano Zampini static PetscErrorCode PCPreSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
1330534831adSStefano Zampini {
1331534831adSStefano Zampini   PetscErrorCode ierr;
1332534831adSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1333534831adSStefano Zampini   PC_IS          *pcis = (PC_IS*)(pc->data);
13343972b0daSStefano Zampini   Vec            used_vec;
13354df7a6bfSStefano Zampini   PetscBool      iscg = PETSC_FALSE, save_rhs = PETSC_TRUE, benign_correction_computed;
1336534831adSStefano Zampini 
1337534831adSStefano Zampini   PetscFunctionBegin;
13381f4df5f7SStefano Zampini   /* if we are working with CG, one dirichlet solve can be avoided during Krylov iterations */
133985c4d303SStefano Zampini   if (ksp) {
13404df7a6bfSStefano Zampini     PetscBool isgroppcg, ispipecg, ispipelcg, ispipecgrr;
13414df7a6bfSStefano Zampini 
134285c4d303SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPCG,&iscg);CHKERRQ(ierr);
134327b6a85dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPGROPPCG,&isgroppcg);CHKERRQ(ierr);
134427b6a85dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPPIPECG,&ispipecg);CHKERRQ(ierr);
13454df7a6bfSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPPIPECG,&ispipelcg);CHKERRQ(ierr);
1346f94e96cbSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPPIPECGRR,&ispipecgrr);CHKERRQ(ierr);
13474df7a6bfSStefano Zampini     iscg = (PetscBool)(iscg || isgroppcg || ispipecg || ispipelcg || ispipecgrr);
13483bf6e316SStefano Zampini     if (pcbddc->benign_apply_coarse_only || pcbddc->switch_static || !iscg || pc->mat != pc->pmat) {
134985c4d303SStefano Zampini       ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
135085c4d303SStefano Zampini     }
135185c4d303SStefano Zampini   }
13523bf6e316SStefano Zampini   if (pcbddc->benign_apply_coarse_only || pcbddc->switch_static || pc->mat != pc->pmat) {
1353fc17d649SStefano Zampini     ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
1354fc17d649SStefano Zampini   }
13551f4df5f7SStefano Zampini 
135685c4d303SStefano Zampini   /* Creates parallel work vectors used in presolve */
135762a6ff1dSStefano Zampini   if (!pcbddc->original_rhs) {
135862a6ff1dSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs);CHKERRQ(ierr);
135962a6ff1dSStefano Zampini   }
136062a6ff1dSStefano Zampini   if (!pcbddc->temp_solution) {
136162a6ff1dSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->temp_solution);CHKERRQ(ierr);
136262a6ff1dSStefano Zampini   }
13638d00608fSStefano Zampini 
136427b6a85dSStefano Zampini   pcbddc->temp_solution_used = PETSC_FALSE;
13653972b0daSStefano Zampini   if (x) {
13663972b0daSStefano Zampini     ierr = PetscObjectReference((PetscObject)x);CHKERRQ(ierr);
13673972b0daSStefano Zampini     used_vec = x;
13688d00608fSStefano Zampini   } else { /* it can only happen when calling PCBDDCMatFETIDPGetRHS */
13693972b0daSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->temp_solution);CHKERRQ(ierr);
13703972b0daSStefano Zampini     used_vec = pcbddc->temp_solution;
13713972b0daSStefano Zampini     ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
137227b6a85dSStefano Zampini     pcbddc->temp_solution_used = PETSC_TRUE;
1373266e20e9SStefano Zampini     ierr = VecCopy(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
1374266e20e9SStefano Zampini     save_rhs = PETSC_FALSE;
1375266e20e9SStefano Zampini     pcbddc->eliminate_dirdofs = PETSC_TRUE;
13763972b0daSStefano Zampini   }
13778efcfb23SStefano Zampini 
13788efcfb23SStefano Zampini   /* hack into ksp data structure since PCPreSolve comes earlier than setting to zero the guess in src/ksp/ksp/interface/itfunc.c */
13793972b0daSStefano Zampini   if (ksp) {
1380a0cb1b98SStefano Zampini     /* store the flag for the initial guess since it will be restored back during PCPostSolve_BDDC */
13818efcfb23SStefano Zampini     ierr = KSPGetInitialGuessNonzero(ksp,&pcbddc->ksp_guess_nonzero);CHKERRQ(ierr);
13828efcfb23SStefano Zampini     if (!pcbddc->ksp_guess_nonzero) {
13833972b0daSStefano Zampini       ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
13843972b0daSStefano Zampini     }
13853972b0daSStefano Zampini   }
13863308cffdSStefano Zampini 
13878d00608fSStefano Zampini   pcbddc->rhs_change = PETSC_FALSE;
13883972b0daSStefano Zampini   /* Take into account zeroed rows -> change rhs and store solution removed */
138970c64980SStefano Zampini   if (rhs && pcbddc->eliminate_dirdofs) {
13903975b054SStefano Zampini     IS dirIS = NULL;
13913975b054SStefano Zampini 
1392a07ea27aSStefano Zampini     /* DirichletBoundariesLocal may not be consistent among neighbours; gets a dirichlet dofs IS from graph (may be cached) */
13933975b054SStefano Zampini     ierr = PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS);CHKERRQ(ierr);
13943975b054SStefano Zampini     if (dirIS) {
1395906d46d4SStefano Zampini       Mat_IS            *matis = (Mat_IS*)pc->pmat->data;
1396785d1243SStefano Zampini       PetscInt          dirsize,i,*is_indices;
13972b095fd8SStefano Zampini       PetscScalar       *array_x;
13982b095fd8SStefano Zampini       const PetscScalar *array_diagonal;
1399785d1243SStefano Zampini 
14003972b0daSStefano Zampini       ierr = MatGetDiagonal(pc->pmat,pcis->vec1_global);CHKERRQ(ierr);
14013972b0daSStefano Zampini       ierr = VecPointwiseDivide(pcis->vec1_global,rhs,pcis->vec1_global);CHKERRQ(ierr);
1402e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1403e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1404e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1405e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
140682ba6b80SStefano Zampini       ierr = ISGetLocalSize(dirIS,&dirsize);CHKERRQ(ierr);
14073972b0daSStefano Zampini       ierr = VecGetArray(pcis->vec1_N,&array_x);CHKERRQ(ierr);
14082b095fd8SStefano Zampini       ierr = VecGetArrayRead(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr);
14093972b0daSStefano Zampini       ierr = ISGetIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
14102fa5cd67SKarl Rupp       for (i=0; i<dirsize; i++) array_x[is_indices[i]] = array_diagonal[is_indices[i]];
14113972b0daSStefano Zampini       ierr = ISRestoreIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
14122b095fd8SStefano Zampini       ierr = VecRestoreArrayRead(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr);
14133972b0daSStefano Zampini       ierr = VecRestoreArray(pcis->vec1_N,&array_x);CHKERRQ(ierr);
1414e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1415e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
14168d00608fSStefano Zampini       pcbddc->rhs_change = PETSC_TRUE;
14171b968477SStefano Zampini       ierr = ISDestroy(&dirIS);CHKERRQ(ierr);
14188efcfb23SStefano Zampini     }
1419a07ea27aSStefano Zampini   }
1420b76ba322SStefano Zampini 
14218efcfb23SStefano Zampini   /* remove the computed solution or the initial guess from the rhs */
14228d00608fSStefano Zampini   if (pcbddc->rhs_change || (ksp && pcbddc->ksp_guess_nonzero) ) {
142327b6a85dSStefano Zampini     /* save the original rhs */
142427b6a85dSStefano Zampini     if (save_rhs) {
142527b6a85dSStefano Zampini       ierr = VecSwap(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
142627b6a85dSStefano Zampini       save_rhs = PETSC_FALSE;
14278d00608fSStefano Zampini     }
14288d00608fSStefano Zampini     pcbddc->rhs_change = PETSC_TRUE;
14293972b0daSStefano Zampini     ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr);
143027b6a85dSStefano Zampini     ierr = MatMultAdd(pc->mat,used_vec,pcbddc->original_rhs,rhs);CHKERRQ(ierr);
14313972b0daSStefano Zampini     ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr);
14328efcfb23SStefano Zampini     ierr = VecCopy(used_vec,pcbddc->temp_solution);CHKERRQ(ierr);
143327b6a85dSStefano Zampini     pcbddc->temp_solution_used = PETSC_TRUE;
14347acc28cbSStefano Zampini     if (ksp) {
14357acc28cbSStefano Zampini       ierr = KSPSetInitialGuessNonzero(ksp,PETSC_FALSE);CHKERRQ(ierr);
14367acc28cbSStefano Zampini     }
14373308cffdSStefano Zampini   }
14388efcfb23SStefano Zampini   ierr = VecDestroy(&used_vec);CHKERRQ(ierr);
1439b76ba322SStefano Zampini 
1440fc17d649SStefano Zampini   /* compute initial vector in benign space if needed
144127b6a85dSStefano Zampini      and remove non-benign solution from the rhs */
144227b6a85dSStefano Zampini   benign_correction_computed = PETSC_FALSE;
144308af2428SStefano Zampini   if (rhs && pcbddc->benign_compute_correction && (pcbddc->benign_have_null || pcbddc->benign_apply_coarse_only)) {
14441f4df5f7SStefano Zampini     /* compute u^*_h using ideas similar to those in Xuemin Tu's PhD thesis (see Section 4.8.1)
14451f4df5f7SStefano Zampini        Recursively apply BDDC in the multilevel case */
14460369aaf7SStefano Zampini     if (!pcbddc->benign_vec) {
14470369aaf7SStefano Zampini       ierr = VecDuplicate(rhs,&pcbddc->benign_vec);CHKERRQ(ierr);
14480369aaf7SStefano Zampini     }
1449c69e9cc1SStefano Zampini     /* keep applying coarse solver unless we no longer have benign subdomains */
1450c69e9cc1SStefano Zampini     pcbddc->benign_apply_coarse_only = pcbddc->benign_have_null ? PETSC_TRUE : PETSC_FALSE;
145127b6a85dSStefano Zampini     if (!pcbddc->benign_skip_correction) {
14521dd7afcfSStefano Zampini       ierr = PCApply_BDDC(pc,rhs,pcbddc->benign_vec);CHKERRQ(ierr);
14533bca92a6SStefano Zampini       benign_correction_computed = PETSC_TRUE;
14541f4df5f7SStefano Zampini       if (pcbddc->temp_solution_used) {
14551f4df5f7SStefano Zampini         ierr = VecAXPY(pcbddc->temp_solution,1.0,pcbddc->benign_vec);CHKERRQ(ierr);
14561f4df5f7SStefano Zampini       }
14571f4df5f7SStefano Zampini       ierr = VecScale(pcbddc->benign_vec,-1.0);CHKERRQ(ierr);
145827b6a85dSStefano Zampini       /* store the original rhs if not done earlier */
145927b6a85dSStefano Zampini       if (save_rhs) {
146027b6a85dSStefano Zampini         ierr = VecSwap(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
146192e3dcfbSStefano Zampini       }
146227b6a85dSStefano Zampini       if (pcbddc->rhs_change) {
14630369aaf7SStefano Zampini         ierr = MatMultAdd(pc->mat,pcbddc->benign_vec,rhs,rhs);CHKERRQ(ierr);
146427b6a85dSStefano Zampini       } else {
146527b6a85dSStefano Zampini         ierr = MatMultAdd(pc->mat,pcbddc->benign_vec,pcbddc->original_rhs,rhs);CHKERRQ(ierr);
146627b6a85dSStefano Zampini       }
14670369aaf7SStefano Zampini       pcbddc->rhs_change = PETSC_TRUE;
146827b6a85dSStefano Zampini     }
146927b6a85dSStefano Zampini     pcbddc->benign_apply_coarse_only = PETSC_FALSE;
14704df7a6bfSStefano Zampini   } else {
14714df7a6bfSStefano Zampini     ierr = VecDestroy(&pcbddc->benign_vec);CHKERRQ(ierr);
14720369aaf7SStefano Zampini   }
14732d4c4fecSStefano Zampini 
14742d4c4fecSStefano Zampini   /* dbg output */
1475a198735bSStefano Zampini   if (pcbddc->dbg_flag && benign_correction_computed) {
14761f4df5f7SStefano Zampini     Vec v;
1477c69e9cc1SStefano Zampini 
14781f4df5f7SStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&v);CHKERRQ(ierr);
1479c69e9cc1SStefano Zampini     if (pcbddc->ChangeOfBasisMatrix) {
14801f4df5f7SStefano Zampini       ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,rhs,v);CHKERRQ(ierr);
1481c69e9cc1SStefano Zampini     } else {
1482c69e9cc1SStefano Zampini       ierr = VecCopy(rhs,v);CHKERRQ(ierr);
1483c69e9cc1SStefano Zampini     }
14841f4df5f7SStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,v,PETSC_TRUE);CHKERRQ(ierr);
1485e0fe2d75SToby Isaac     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"LEVEL %D: is the correction benign?\n",pcbddc->current_level);CHKERRQ(ierr);
1486c69e9cc1SStefano Zampini     ierr = PetscScalarView(pcbddc->benign_n,pcbddc->benign_p0,pcbddc->dbg_viewer);CHKERRQ(ierr);
1487c69e9cc1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
14881f4df5f7SStefano Zampini     ierr = VecDestroy(&v);CHKERRQ(ierr);
14891f4df5f7SStefano Zampini   }
14900369aaf7SStefano Zampini 
14910369aaf7SStefano Zampini   /* set initial guess if using PCG */
14928ae0ca82SStefano Zampini   pcbddc->exact_dirichlet_trick_app = PETSC_FALSE;
14930369aaf7SStefano Zampini   if (x && pcbddc->use_exact_dirichlet_trick) {
14940369aaf7SStefano Zampini     ierr = VecSet(x,0.0);CHKERRQ(ierr);
14951dd7afcfSStefano Zampini     if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) {
149627b6a85dSStefano Zampini       if (benign_correction_computed) { /* we have already saved the changed rhs */
14978860a134SJunchao Zhang         ierr = VecLockReadPop(pcis->vec1_global);CHKERRQ(ierr);
14981dd7afcfSStefano Zampini       } else {
14991dd7afcfSStefano Zampini         ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,rhs,pcis->vec1_global);CHKERRQ(ierr);
15001dd7afcfSStefano Zampini       }
15011dd7afcfSStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,pcis->vec1_global,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15021dd7afcfSStefano Zampini       ierr = VecScatterEnd(pcis->global_to_D,pcis->vec1_global,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15031dd7afcfSStefano Zampini     } else {
15040369aaf7SStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15050369aaf7SStefano Zampini       ierr = VecScatterEnd(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15061dd7afcfSStefano Zampini     }
15070369aaf7SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
1508c0decd05SBarry Smith     ierr = KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec2_D);CHKERRQ(ierr);
15091dd7afcfSStefano Zampini     if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) {
15101dd7afcfSStefano Zampini       ierr = VecSet(pcis->vec1_global,0.);CHKERRQ(ierr);
15111dd7afcfSStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,pcis->vec1_global,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
15121dd7afcfSStefano Zampini       ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,pcis->vec1_global,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
15131dd7afcfSStefano Zampini       ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x);CHKERRQ(ierr);
15141dd7afcfSStefano Zampini     } else {
15150369aaf7SStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
15160369aaf7SStefano Zampini       ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
15171dd7afcfSStefano Zampini     }
15180369aaf7SStefano Zampini     if (ksp) {
15190369aaf7SStefano Zampini       ierr = KSPSetInitialGuessNonzero(ksp,PETSC_TRUE);CHKERRQ(ierr);
15200369aaf7SStefano Zampini     }
15218ae0ca82SStefano Zampini     pcbddc->exact_dirichlet_trick_app = PETSC_TRUE;
1522266e20e9SStefano Zampini   } else if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior && benign_correction_computed && pcbddc->use_exact_dirichlet_trick) {
15238860a134SJunchao Zhang     ierr = VecLockReadPop(pcis->vec1_global);CHKERRQ(ierr);
15240369aaf7SStefano Zampini   }
1525534831adSStefano Zampini   PetscFunctionReturn(0);
1526534831adSStefano Zampini }
1527906d46d4SStefano Zampini 
1528534831adSStefano Zampini /*
1529534831adSStefano Zampini    PCPostSolve_BDDC - Changes the computed solution if a transformation of basis
1530534831adSStefano Zampini                      approach has been selected. Also, restores rhs to its original state.
1531534831adSStefano Zampini 
1532534831adSStefano Zampini    Input Parameter:
1533534831adSStefano Zampini +  pc - the preconditioner contex
1534534831adSStefano Zampini 
1535534831adSStefano Zampini    Application Interface Routine: PCPostSolve()
1536534831adSStefano Zampini 
1537534831adSStefano Zampini    Notes:
1538534831adSStefano Zampini      The interface routine PCPostSolve() is not usually called directly by
1539534831adSStefano Zampini      the user, but instead is called by KSPSolve().
1540534831adSStefano Zampini */
1541534831adSStefano Zampini static PetscErrorCode PCPostSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
1542534831adSStefano Zampini {
1543534831adSStefano Zampini   PetscErrorCode ierr;
1544534831adSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1545534831adSStefano Zampini 
1546534831adSStefano Zampini   PetscFunctionBegin;
15473972b0daSStefano Zampini   /* add solution removed in presolve */
15486bcfc461SStefano Zampini   if (x && pcbddc->rhs_change) {
154927b6a85dSStefano Zampini     if (pcbddc->temp_solution_used) {
15503425bc38SStefano Zampini       ierr = VecAXPY(x,1.0,pcbddc->temp_solution);CHKERRQ(ierr);
1551af140850Sstefano_zampini     } else if (pcbddc->benign_compute_correction && pcbddc->benign_vec) {
155227b6a85dSStefano Zampini       ierr = VecAXPY(x,-1.0,pcbddc->benign_vec);CHKERRQ(ierr);
15533425bc38SStefano Zampini     }
1554af140850Sstefano_zampini     /* restore to original state (not for FETI-DP) */
1555af140850Sstefano_zampini     if (ksp) pcbddc->temp_solution_used = PETSC_FALSE;
155627b6a85dSStefano Zampini   }
155727b6a85dSStefano Zampini 
1558266e20e9SStefano Zampini   /* restore rhs to its original state (not needed for FETI-DP) */
15598d00608fSStefano Zampini   if (rhs && pcbddc->rhs_change) {
156027b6a85dSStefano Zampini     ierr = VecSwap(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
15618d00608fSStefano Zampini     pcbddc->rhs_change = PETSC_FALSE;
1562af140850Sstefano_zampini   }
15638efcfb23SStefano Zampini   /* restore ksp guess state */
15648efcfb23SStefano Zampini   if (ksp) {
15658efcfb23SStefano Zampini     ierr = KSPSetInitialGuessNonzero(ksp,pcbddc->ksp_guess_nonzero);CHKERRQ(ierr);
15668ae0ca82SStefano Zampini     /* reset flag for exact dirichlet trick */
15678ae0ca82SStefano Zampini     pcbddc->exact_dirichlet_trick_app = PETSC_FALSE;
1568af140850Sstefano_zampini   }
1569534831adSStefano Zampini   PetscFunctionReturn(0);
1570534831adSStefano Zampini }
1571af140850Sstefano_zampini 
15720c7d97c5SJed Brown /*
15730c7d97c5SJed Brown    PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner
15740c7d97c5SJed Brown                   by setting data structures and options.
15750c7d97c5SJed Brown 
15760c7d97c5SJed Brown    Input Parameter:
157753cdbc3dSStefano Zampini +  pc - the preconditioner context
15780c7d97c5SJed Brown 
15790c7d97c5SJed Brown    Application Interface Routine: PCSetUp()
15800c7d97c5SJed Brown 
15810c7d97c5SJed Brown    Notes:
15820c7d97c5SJed Brown      The interface routine PCSetUp() is not usually called directly by
15830c7d97c5SJed Brown      the user, but instead is called by PCApply() if necessary.
15840c7d97c5SJed Brown */
158553cdbc3dSStefano Zampini PetscErrorCode PCSetUp_BDDC(PC pc)
15860c7d97c5SJed Brown {
15870c7d97c5SJed Brown   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
1588c703fcc7SStefano Zampini   PCBDDCSubSchurs sub_schurs;
15895e8657edSStefano Zampini   Mat_IS*         matis;
159008122e43SStefano Zampini   MatNullSpace    nearnullspace;
159135509ce9Sstefano_zampini   Mat             lA;
159235509ce9Sstefano_zampini   IS              lP,zerodiag = NULL;
159391e8d312SStefano Zampini   PetscInt        nrows,ncols;
159486bfa4cfSStefano Zampini   PetscMPIInt     size;
1595c703fcc7SStefano Zampini   PetscBool       computesubschurs;
15968de1fae6SStefano Zampini   PetscBool       computeconstraintsmatrix;
15973b03f7bbSStefano Zampini   PetscBool       new_nearnullspace_provided,ismatis,rl;
1598c703fcc7SStefano Zampini   PetscErrorCode  ierr;
15990c7d97c5SJed Brown 
16000c7d97c5SJed Brown   PetscFunctionBegin;
16015e8657edSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc->pmat,MATIS,&ismatis);CHKERRQ(ierr);
16026c4ed002SBarry Smith   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"PCBDDC preconditioner requires matrix of type MATIS");
160391e8d312SStefano Zampini   ierr = MatGetSize(pc->pmat,&nrows,&ncols);CHKERRQ(ierr);
16046c4ed002SBarry Smith   if (nrows != ncols) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PCBDDC preconditioner requires a square preconditioning matrix");
160586bfa4cfSStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
160686bfa4cfSStefano Zampini 
16075e8657edSStefano Zampini   matis = (Mat_IS*)pc->pmat->data;
1608f4ddd8eeSStefano Zampini   /* the following lines of code should be replaced by a better logic between PCIS, PCNN, PCBDDC and other future nonoverlapping preconditioners */
16093b03a366Sstefano_zampini   /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup
161071582508SStefano Zampini      Also, BDDC builds its own KSP for the Dirichlet problem */
16113b03f7bbSStefano Zampini   rl = pcbddc->recompute_topography;
16123b03f7bbSStefano Zampini   if (!pc->setupcalled || pc->flag == DIFFERENT_NONZERO_PATTERN) rl = PETSC_TRUE;
16133b03f7bbSStefano Zampini   ierr = MPIU_Allreduce(&rl,&pcbddc->recompute_topography,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
1614c83e1ba7SStefano Zampini   if (pcbddc->recompute_topography) {
1615c83e1ba7SStefano Zampini     pcbddc->graphanalyzed    = PETSC_FALSE;
1616c83e1ba7SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1617c83e1ba7SStefano Zampini   } else {
16188de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_FALSE;
1619c83e1ba7SStefano Zampini   }
1620b087196eSStefano Zampini 
1621b087196eSStefano Zampini   /* check parameters' compatibility */
1622b7ab4a40SStefano Zampini   if (!pcbddc->use_deluxe_scaling) pcbddc->deluxe_zerorows = PETSC_FALSE;
1623bd2a564bSStefano Zampini   pcbddc->adaptive_selection   = (PetscBool)(pcbddc->adaptive_threshold[0] != 0.0 || pcbddc->adaptive_threshold[1] != 0.0);
162486bfa4cfSStefano Zampini   pcbddc->use_deluxe_scaling   = (PetscBool)(pcbddc->use_deluxe_scaling && size > 1);
162586bfa4cfSStefano Zampini   pcbddc->adaptive_selection   = (PetscBool)(pcbddc->adaptive_selection && size > 1);
1626bf3a8328SStefano Zampini   pcbddc->adaptive_userdefined = (PetscBool)(pcbddc->adaptive_selection && pcbddc->adaptive_userdefined);
1627862806e4SStefano Zampini   if (pcbddc->adaptive_selection) pcbddc->use_faces = PETSC_TRUE;
1628862806e4SStefano Zampini 
16295a95e1ceSStefano Zampini   computesubschurs = (PetscBool)(pcbddc->adaptive_selection || pcbddc->use_deluxe_scaling);
163016909a7fSStefano Zampini 
163171582508SStefano Zampini   /* activate all connected components if the netflux has been requested */
1632bb05f991SStefano Zampini   if (pcbddc->compute_nonetflux) {
1633bb05f991SStefano Zampini     pcbddc->use_vertices = PETSC_TRUE;
1634bb05f991SStefano Zampini     pcbddc->use_edges    = PETSC_TRUE;
1635bb05f991SStefano Zampini     pcbddc->use_faces    = PETSC_TRUE;
1636bb05f991SStefano Zampini   }
1637bb05f991SStefano Zampini 
1638f4ddd8eeSStefano Zampini   /* Get stdout for dbg */
163970cf5478SStefano Zampini   if (pcbddc->dbg_flag) {
164070cf5478SStefano Zampini     if (!pcbddc->dbg_viewer) {
164158a03d70SStefano Zampini       pcbddc->dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pc));
1642f4ddd8eeSStefano Zampini     }
1643d9869140SStefano Zampini     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
164458a03d70SStefano Zampini     ierr = PetscViewerASCIIAddTab(pcbddc->dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
1645f4ddd8eeSStefano Zampini   }
1646f4ddd8eeSStefano Zampini 
1647c703fcc7SStefano Zampini   /* process topology information */
164843371fb9SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_Topology[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
164971582508SStefano Zampini   if (pcbddc->recompute_topography) {
165071582508SStefano Zampini     ierr = PCBDDCComputeLocalTopologyInfo(pc);CHKERRQ(ierr);
1651c703fcc7SStefano Zampini     if (pcbddc->discretegradient) {
1652a13144ffSStefano Zampini       ierr = PCBDDCNedelecSupport(pc);CHKERRQ(ierr);
1653a13144ffSStefano Zampini     }
1654c703fcc7SStefano Zampini   }
16554f819b78SStefano Zampini   if (pcbddc->corner_selected) pcbddc->use_vertices = PETSC_TRUE;
1656a13144ffSStefano Zampini 
1657c703fcc7SStefano Zampini   /* change basis if requested by the user */
16585e8657edSStefano Zampini   if (pcbddc->user_ChangeOfBasisMatrix) {
16595e8657edSStefano Zampini     /* use_change_of_basis flag is used to automatically compute a change of basis from constraints */
16605e8657edSStefano Zampini     pcbddc->use_change_of_basis = PETSC_FALSE;
16615e8657edSStefano Zampini     ierr = PCBDDCComputeLocalMatrix(pc,pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
16625e8657edSStefano Zampini   } else {
1663b96c3477SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
16645e8657edSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
16655e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
1666d16cbb6bSStefano Zampini   }
1667d16cbb6bSStefano Zampini 
16684f1b2e48SStefano Zampini   /*
1669c703fcc7SStefano Zampini      Compute change of basis on local pressures (aka zerodiag dofs) with the benign trick
16704f1b2e48SStefano Zampini      This should come earlier then PCISSetUp for extracting the correct subdomain matrices
16714f1b2e48SStefano Zampini   */
16721dd7afcfSStefano Zampini   ierr = PCBDDCBenignShellMat(pc,PETSC_TRUE);CHKERRQ(ierr);
1673d16cbb6bSStefano Zampini   if (pcbddc->benign_saddle_point) {
16749f47a83aSStefano Zampini     PC_IS* pcis = (PC_IS*)pc->data;
16759f47a83aSStefano Zampini 
167605b28244SStefano Zampini     if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->use_change_of_basis || !computesubschurs) pcbddc->benign_change_explicit = PETSC_TRUE;
16773b03f7bbSStefano Zampini     /* detect local saddle point and change the basis in pcbddc->local_mat */
16783b03f7bbSStefano Zampini     ierr = PCBDDCBenignDetectSaddlePoint(pc,(PetscBool)(!pcbddc->recompute_topography),&zerodiag);CHKERRQ(ierr);
1679a3df083aSStefano Zampini     /* pop B0 mat from local mat */
1680c263805aSStefano Zampini     ierr = PCBDDCBenignPopOrPushB0(pc,PETSC_TRUE);CHKERRQ(ierr);
16811dd7afcfSStefano Zampini     /* give pcis a hint to not reuse submatrices during PCISCreate */
16821dd7afcfSStefano Zampini     if (pc->flag == SAME_NONZERO_PATTERN && pcis->reusesubmatrices == PETSC_TRUE) {
16831dd7afcfSStefano Zampini       if (pcbddc->benign_n && (pcbddc->benign_change_explicit || pcbddc->dbg_flag)) {
16841dd7afcfSStefano Zampini         pcis->reusesubmatrices = PETSC_FALSE;
16851dd7afcfSStefano Zampini       } else {
1686a3df083aSStefano Zampini         pcis->reusesubmatrices = PETSC_TRUE;
16871dd7afcfSStefano Zampini       }
1688a3df083aSStefano Zampini     } else {
16899f47a83aSStefano Zampini       pcis->reusesubmatrices = PETSC_FALSE;
1690674ae819SStefano Zampini     }
1691a3df083aSStefano Zampini   }
169227b6a85dSStefano Zampini 
16938037d520SStefano Zampini   /* propagate relevant information */
169406a4e24aSStefano Zampini   if (matis->A->symmetric_set) {
169506a4e24aSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
169606a4e24aSStefano Zampini   }
169706a4e24aSStefano Zampini   if (matis->A->spd_set) {
169806a4e24aSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SPD,matis->A->spd);CHKERRQ(ierr);
169906a4e24aSStefano Zampini   }
1700e496cd5dSStefano Zampini 
17015e8657edSStefano Zampini   /* Set up all the "iterative substructuring" common block without computing solvers */
17025e8657edSStefano Zampini   {
17035e8657edSStefano Zampini     Mat temp_mat;
17045e8657edSStefano Zampini 
17055e8657edSStefano Zampini     temp_mat = matis->A;
17065e8657edSStefano Zampini     matis->A = pcbddc->local_mat;
1707d9869140SStefano Zampini     ierr = PCISSetUp(pc,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr);
17085e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
17095e8657edSStefano Zampini     matis->A = temp_mat;
17105e8657edSStefano Zampini   }
1711684f6988SStefano Zampini 
171281d14e9dSStefano Zampini   /* Analyze interface */
171364ac59b8SStefano Zampini   if (!pcbddc->graphanalyzed) {
1714674ae819SStefano Zampini     ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
17158de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1716345ecf6cSStefano Zampini     if (pcbddc->adaptive_selection && !pcbddc->use_deluxe_scaling && !pcbddc->mat_graph->twodim) {
17174247aa23Sstefano_zampini       SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot compute the adaptive primal space for a problem with 3D edges without deluxe scaling");
1718345ecf6cSStefano Zampini     }
1719a198735bSStefano Zampini     if (pcbddc->compute_nonetflux) {
1720669cc0f4SStefano Zampini       MatNullSpace nnfnnsp;
1721669cc0f4SStefano Zampini 
172221ef3d20SStefano Zampini       if (!pcbddc->divudotp) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Missing divudotp operator");
17238ae0ca82SStefano Zampini       ierr = PCBDDCComputeNoNetFlux(pc->pmat,pcbddc->divudotp,pcbddc->divudotp_trans,pcbddc->divudotp_vl2l,pcbddc->mat_graph,&nnfnnsp);CHKERRQ(ierr);
172471582508SStefano Zampini       /* TODO what if a nearnullspace is already attached? */
17258037d520SStefano Zampini       if (nnfnnsp) {
1726669cc0f4SStefano Zampini         ierr = MatSetNearNullSpace(pc->pmat,nnfnnsp);CHKERRQ(ierr);
1727669cc0f4SStefano Zampini         ierr = MatNullSpaceDestroy(&nnfnnsp);CHKERRQ(ierr);
1728669cc0f4SStefano Zampini       }
1729674ae819SStefano Zampini     }
17308037d520SStefano Zampini   }
173143371fb9SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_Topology[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
1732fb8d54d4SStefano Zampini 
17335408967cSStefano Zampini   /* check existence of a divergence free extension, i.e.
17345408967cSStefano Zampini      b(v_I,p_0) = 0 for all v_I (raise error if not).
17355408967cSStefano Zampini      Also, check that PCBDDCBenignGetOrSetP0 works */
1736ff1f7e73Sstefano_zampini   if (pcbddc->benign_saddle_point && pcbddc->dbg_flag > 1) {
17375408967cSStefano Zampini     ierr = PCBDDCBenignCheck(pc,zerodiag);CHKERRQ(ierr);
173809f581a4SStefano Zampini   }
17394f1b2e48SStefano Zampini   ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
174006f24817SStefano Zampini 
1741b96c3477SStefano Zampini   /* Setup local dirichlet solver ksp_D and sub_schurs solvers */
1742c703fcc7SStefano Zampini   if (computesubschurs && pcbddc->recompute_topography) {
174308122e43SStefano Zampini     ierr = PCBDDCInitSubSchurs(pc);CHKERRQ(ierr);
1744b1b3d7a2SStefano Zampini   }
17459d54b7f4SStefano Zampini   /* SetUp Scaling operator (scaling matrices could be needed in SubSchursSetUp)*/
17469d54b7f4SStefano Zampini   if (!pcbddc->use_deluxe_scaling) {
17479d54b7f4SStefano Zampini     ierr = PCBDDCScalingSetUp(pc);CHKERRQ(ierr);
17489d54b7f4SStefano Zampini   }
1749c703fcc7SStefano Zampini 
1750c703fcc7SStefano Zampini   /* finish setup solvers and do adaptive selection of constraints */
1751b334f244SStefano Zampini   sub_schurs = pcbddc->sub_schurs;
1752b334f244SStefano Zampini   if (sub_schurs && sub_schurs->schur_explicit) {
17532070dbb6SStefano Zampini     if (computesubschurs) {
175408122e43SStefano Zampini       ierr = PCBDDCSetUpSubSchurs(pc);CHKERRQ(ierr);
17552070dbb6SStefano Zampini     }
1756d5574798SStefano Zampini     ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr);
1757d5574798SStefano Zampini   } else {
1758d5574798SStefano Zampini     ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr);
17592070dbb6SStefano Zampini     if (computesubschurs) {
1760d5574798SStefano Zampini       ierr = PCBDDCSetUpSubSchurs(pc);CHKERRQ(ierr);
1761d5574798SStefano Zampini     }
17622070dbb6SStefano Zampini   }
176308122e43SStefano Zampini   if (pcbddc->adaptive_selection) {
176408122e43SStefano Zampini     ierr = PCBDDCAdaptiveSelection(pc);CHKERRQ(ierr);
17658de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1766b7eb3628SStefano Zampini   }
1767684f6988SStefano Zampini 
1768f4ddd8eeSStefano Zampini   /* infer if NullSpace object attached to Mat via MatSetNearNullSpace has changed */
1769fb8d54d4SStefano Zampini   new_nearnullspace_provided = PETSC_FALSE;
1770f4ddd8eeSStefano Zampini   ierr = MatGetNearNullSpace(pc->pmat,&nearnullspace);CHKERRQ(ierr);
1771f4ddd8eeSStefano Zampini   if (pcbddc->onearnullspace) { /* already used nearnullspace */
1772f4ddd8eeSStefano Zampini     if (!nearnullspace) { /* near null space attached to mat has been destroyed */
1773f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_TRUE;
1774f4ddd8eeSStefano Zampini     } else {
1775f4ddd8eeSStefano Zampini       /* determine if the two nullspaces are different (should be lightweight) */
1776f4ddd8eeSStefano Zampini       if (nearnullspace != pcbddc->onearnullspace) {
1777f4ddd8eeSStefano Zampini         new_nearnullspace_provided = PETSC_TRUE;
1778165b64e2SStefano Zampini       } else { /* maybe the user has changed the content of the nearnullspace so check vectors ObjectStateId */
1779f4ddd8eeSStefano Zampini         PetscInt         i;
1780165b64e2SStefano Zampini         const Vec        *nearnullvecs;
1781165b64e2SStefano Zampini         PetscObjectState state;
1782165b64e2SStefano Zampini         PetscInt         nnsp_size;
1783165b64e2SStefano Zampini         ierr = MatNullSpaceGetVecs(nearnullspace,NULL,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
1784f4ddd8eeSStefano Zampini         for (i=0;i<nnsp_size;i++) {
1785f4ddd8eeSStefano Zampini           ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&state);CHKERRQ(ierr);
1786165b64e2SStefano Zampini           if (pcbddc->onearnullvecs_state[i] != state) {
1787f4ddd8eeSStefano Zampini             new_nearnullspace_provided = PETSC_TRUE;
1788f4ddd8eeSStefano Zampini             break;
1789f4ddd8eeSStefano Zampini           }
1790f4ddd8eeSStefano Zampini         }
1791f4ddd8eeSStefano Zampini       }
1792f4ddd8eeSStefano Zampini     }
1793f4ddd8eeSStefano Zampini   } else {
1794f4ddd8eeSStefano Zampini     if (!nearnullspace) { /* both nearnullspaces are null */
1795f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_FALSE;
1796f4ddd8eeSStefano Zampini     } else { /* nearnullspace attached later */
1797f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_TRUE;
1798f4ddd8eeSStefano Zampini     }
1799f4ddd8eeSStefano Zampini   }
1800f4ddd8eeSStefano Zampini 
1801f4ddd8eeSStefano Zampini   /* Setup constraints and related work vectors */
1802727cdba6SStefano Zampini   /* reset primal space flags */
180343371fb9SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_LocalWork[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
1804f4ddd8eeSStefano Zampini   pcbddc->new_primal_space = PETSC_FALSE;
1805727cdba6SStefano Zampini   pcbddc->new_primal_space_local = PETSC_FALSE;
18068de1fae6SStefano Zampini   if (computeconstraintsmatrix || new_nearnullspace_provided) {
1807727cdba6SStefano Zampini     /* It also sets the primal space flags */
1808674ae819SStefano Zampini     ierr = PCBDDCConstraintsSetUp(pc);CHKERRQ(ierr);
18099543d0ffSStefano Zampini   }
1810e7b262bdSStefano Zampini   /* Allocate needed local vectors (which depends on quantities defined during ConstraintsSetUp) */
1811f4ddd8eeSStefano Zampini   ierr = PCBDDCSetUpLocalWorkVectors(pc);CHKERRQ(ierr);
18125e8657edSStefano Zampini 
18135e8657edSStefano Zampini   if (pcbddc->use_change_of_basis) {
18145e8657edSStefano Zampini     PC_IS *pcis = (PC_IS*)(pc->data);
18155e8657edSStefano Zampini 
18165e8657edSStefano Zampini     ierr = PCBDDCComputeLocalMatrix(pc,pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
18174f1b2e48SStefano Zampini     if (pcbddc->benign_change) {
18181dd7afcfSStefano Zampini       ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
1819c263805aSStefano Zampini       /* pop B0 from pcbddc->local_mat */
1820c263805aSStefano Zampini       ierr = PCBDDCBenignPopOrPushB0(pc,PETSC_TRUE);CHKERRQ(ierr);
1821c263805aSStefano Zampini     }
18225e8657edSStefano Zampini     /* get submatrices */
18235e8657edSStefano Zampini     ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr);
18245e8657edSStefano Zampini     ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr);
18255e8657edSStefano Zampini     ierr = MatDestroy(&pcis->A_BB);CHKERRQ(ierr);
18267dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_BB);CHKERRQ(ierr);
18277dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_IB);CHKERRQ(ierr);
18287dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&pcis->A_BI);CHKERRQ(ierr);
18293975b054SStefano Zampini     /* set flag in pcis to not reuse submatrices during PCISCreate */
18303975b054SStefano Zampini     pcis->reusesubmatrices = PETSC_FALSE;
18319c6a02ceSStefano Zampini   } else if (!pcbddc->user_ChangeOfBasisMatrix && !pcbddc->benign_change) {
1832b96c3477SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
18335e8657edSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
18345e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
18355e8657edSStefano Zampini   }
183635509ce9Sstefano_zampini 
183735509ce9Sstefano_zampini   /* interface pressure block row for B_C */
183835509ce9Sstefano_zampini   ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lP" ,(PetscObject*)&lP);CHKERRQ(ierr);
183935509ce9Sstefano_zampini   ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject*)&lA);CHKERRQ(ierr);
184035509ce9Sstefano_zampini   if (lA && lP) {
184135509ce9Sstefano_zampini     PC_IS*    pcis = (PC_IS*)pc->data;
184235509ce9Sstefano_zampini     Mat       B_BI,B_BB,Bt_BI,Bt_BB;
184335509ce9Sstefano_zampini     PetscBool issym;
184435509ce9Sstefano_zampini     ierr = MatIsSymmetric(lA,PETSC_SMALL,&issym);CHKERRQ(ierr);
18456cc1294bSstefano_zampini     if (issym) {
18467dae84e0SHong Zhang       ierr = MatCreateSubMatrix(lA,lP,pcis->is_I_local,MAT_INITIAL_MATRIX,&B_BI);CHKERRQ(ierr);
18477dae84e0SHong Zhang       ierr = MatCreateSubMatrix(lA,lP,pcis->is_B_local,MAT_INITIAL_MATRIX,&B_BB);CHKERRQ(ierr);
184835509ce9Sstefano_zampini       ierr = MatCreateTranspose(B_BI,&Bt_BI);CHKERRQ(ierr);
184935509ce9Sstefano_zampini       ierr = MatCreateTranspose(B_BB,&Bt_BB);CHKERRQ(ierr);
185035509ce9Sstefano_zampini     } else {
18517dae84e0SHong Zhang       ierr = MatCreateSubMatrix(lA,lP,pcis->is_I_local,MAT_INITIAL_MATRIX,&B_BI);CHKERRQ(ierr);
18527dae84e0SHong Zhang       ierr = MatCreateSubMatrix(lA,lP,pcis->is_B_local,MAT_INITIAL_MATRIX,&B_BB);CHKERRQ(ierr);
18537dae84e0SHong Zhang       ierr = MatCreateSubMatrix(lA,pcis->is_I_local,lP,MAT_INITIAL_MATRIX,&Bt_BI);CHKERRQ(ierr);
18547dae84e0SHong Zhang       ierr = MatCreateSubMatrix(lA,pcis->is_B_local,lP,MAT_INITIAL_MATRIX,&Bt_BB);CHKERRQ(ierr);
185535509ce9Sstefano_zampini     }
185635509ce9Sstefano_zampini     ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_B_BI",(PetscObject)B_BI);CHKERRQ(ierr);
185735509ce9Sstefano_zampini     ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_B_BB",(PetscObject)B_BB);CHKERRQ(ierr);
185835509ce9Sstefano_zampini     ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_Bt_BI",(PetscObject)Bt_BI);CHKERRQ(ierr);
185935509ce9Sstefano_zampini     ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_Bt_BB",(PetscObject)Bt_BB);CHKERRQ(ierr);
186035509ce9Sstefano_zampini     ierr = MatDestroy(&B_BI);CHKERRQ(ierr);
186135509ce9Sstefano_zampini     ierr = MatDestroy(&B_BB);CHKERRQ(ierr);
186235509ce9Sstefano_zampini     ierr = MatDestroy(&Bt_BI);CHKERRQ(ierr);
186335509ce9Sstefano_zampini     ierr = MatDestroy(&Bt_BB);CHKERRQ(ierr);
186435509ce9Sstefano_zampini   }
186543371fb9SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_LocalWork[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
186635509ce9Sstefano_zampini 
1867b96c3477SStefano Zampini   /* SetUp coarse and local Neumann solvers */
186899cc7994SStefano Zampini   ierr = PCBDDCSetUpSolvers(pc);CHKERRQ(ierr);
1869b96c3477SStefano Zampini   /* SetUp Scaling operator */
18709d54b7f4SStefano Zampini   if (pcbddc->use_deluxe_scaling) {
1871674ae819SStefano Zampini     ierr = PCBDDCScalingSetUp(pc);CHKERRQ(ierr);
18720c7d97c5SJed Brown   }
1873c703fcc7SStefano Zampini 
18741dd7afcfSStefano Zampini   /* mark topography as done */
187556282151SStefano Zampini   pcbddc->recompute_topography = PETSC_FALSE;
18760369aaf7SStefano Zampini 
18771dd7afcfSStefano Zampini   /* wrap pcis->A_IB and pcis->A_BI if we did not change explicitly the variables on the pressures */
18781dd7afcfSStefano Zampini   ierr = PCBDDCBenignShellMat(pc,PETSC_FALSE);CHKERRQ(ierr);
18791dd7afcfSStefano Zampini 
188058a03d70SStefano Zampini   if (pcbddc->dbg_flag) {
188158a03d70SStefano Zampini     ierr = PetscViewerASCIISubtractTab(pcbddc->dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
1882d9869140SStefano Zampini     ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
18832b510759SStefano Zampini   }
18840c7d97c5SJed Brown   PetscFunctionReturn(0);
18850c7d97c5SJed Brown }
18860c7d97c5SJed Brown 
18870c7d97c5SJed Brown /*
188850efa1b5SStefano Zampini    PCApply_BDDC - Applies the BDDC operator to a vector.
18890c7d97c5SJed Brown 
18900c7d97c5SJed Brown    Input Parameters:
18910f202f7eSStefano Zampini +  pc - the preconditioner context
18920f202f7eSStefano Zampini -  r - input vector (global)
18930c7d97c5SJed Brown 
18940c7d97c5SJed Brown    Output Parameter:
18950c7d97c5SJed Brown .  z - output vector (global)
18960c7d97c5SJed Brown 
18970c7d97c5SJed Brown    Application Interface Routine: PCApply()
18980c7d97c5SJed Brown  */
189953cdbc3dSStefano Zampini PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z)
19000c7d97c5SJed Brown {
19010c7d97c5SJed Brown   PC_IS             *pcis = (PC_IS*)(pc->data);
19020c7d97c5SJed Brown   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
1903b3338236SStefano Zampini   Mat               lA = NULL;
1904b097fa66SStefano Zampini   PetscInt          n_B = pcis->n_B, n_D = pcis->n - n_B;
19050c7d97c5SJed Brown   PetscErrorCode    ierr;
19063b03a366Sstefano_zampini   const PetscScalar one = 1.0;
19073b03a366Sstefano_zampini   const PetscScalar m_one = -1.0;
19082617d88aSStefano Zampini   const PetscScalar zero = 0.0;
19090c7d97c5SJed Brown /* This code is similar to that provided in nn.c for PCNN
19100c7d97c5SJed Brown    NN interface preconditioner changed to BDDC
1911b097fa66SStefano Zampini    Added support for M_3 preconditioner in the reference article (code is active if pcbddc->switch_static == PETSC_TRUE) */
19120c7d97c5SJed Brown 
19130c7d97c5SJed Brown   PetscFunctionBegin;
1914f3d41395Sstefano_zampini   ierr = PetscCitationsRegister(citation,&cited);CHKERRQ(ierr);
1915b3338236SStefano Zampini   if (pcbddc->switch_static) {
1916b3338236SStefano Zampini     ierr = MatISGetLocalMat(pc->useAmat ? pc->mat : pc->pmat,&lA);CHKERRQ(ierr);
1917b3338236SStefano Zampini   }
1918b3338236SStefano Zampini 
19191dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
19201dd7afcfSStefano Zampini     Vec swap;
192127b6a85dSStefano Zampini 
192227b6a85dSStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change);CHKERRQ(ierr);
19231dd7afcfSStefano Zampini     swap = pcbddc->work_change;
19241dd7afcfSStefano Zampini     pcbddc->work_change = r;
19251dd7afcfSStefano Zampini     r = swap;
19261dd7afcfSStefano Zampini     /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */
19279cc2a9b1Sstefano_zampini     if (pcbddc->benign_apply_coarse_only && pcbddc->use_exact_dirichlet_trick && pcbddc->change_interior) {
19281dd7afcfSStefano Zampini       ierr = VecCopy(r,pcis->vec1_global);CHKERRQ(ierr);
19298860a134SJunchao Zhang       ierr = VecLockReadPush(pcis->vec1_global);CHKERRQ(ierr);
19301dd7afcfSStefano Zampini     }
19311dd7afcfSStefano Zampini   }
193227b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* get p0 from r */
1933015636ebSStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,r,PETSC_TRUE);CHKERRQ(ierr);
1934efc2fbd9SStefano Zampini   }
1935*bc960bbfSJed Brown   if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_DIRICHLET && !pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
1936b097fa66SStefano Zampini     ierr = VecCopy(r,z);CHKERRQ(ierr);
19370c7d97c5SJed Brown     /* First Dirichlet solve */
19380c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
19390c7d97c5SJed Brown     ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
19400c7d97c5SJed Brown     /*
19410c7d97c5SJed Brown       Assembling right hand side for BDDC operator
1942b097fa66SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE)
1943674ae819SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
19440c7d97c5SJed Brown     */
1945b097fa66SStefano Zampini     if (n_D) {
1946b097fa66SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
1947c0decd05SBarry Smith       ierr = KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec2_D);CHKERRQ(ierr);
19480c7d97c5SJed Brown       ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
194916909a7fSStefano Zampini       if (pcbddc->switch_static) {
195016909a7fSStefano Zampini         ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
195116909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
195216909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
195316909a7fSStefano Zampini         if (!pcbddc->switch_static_change) {
1954b3338236SStefano Zampini           ierr = MatMult(lA,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
195516909a7fSStefano Zampini         } else {
195616909a7fSStefano Zampini           ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
1957b3338236SStefano Zampini           ierr = MatMult(lA,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr);
195816909a7fSStefano Zampini           ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
195916909a7fSStefano Zampini         }
196016909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
196116909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
196216909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
196316909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
196416909a7fSStefano Zampini       } else {
1965b097fa66SStefano Zampini         ierr = MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
196616909a7fSStefano Zampini       }
1967b097fa66SStefano Zampini     } else {
1968b097fa66SStefano Zampini       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
1969b097fa66SStefano Zampini     }
19700c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
19710c7d97c5SJed Brown     ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1972674ae819SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr);
1973b76ba322SStefano Zampini   } else {
19744fee134fSStefano Zampini     if (!pcbddc->benign_apply_coarse_only) {
1975674ae819SStefano Zampini       ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr);
1976b76ba322SStefano Zampini     }
19774fee134fSStefano Zampini   }
1978*bc960bbfSJed Brown   if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_LUMP) {
1979*bc960bbfSJed Brown     if (!pcbddc->switch_static) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"You forgot to pass -pc_bddc_switch_static");
1980*bc960bbfSJed Brown     ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1981*bc960bbfSJed Brown     ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1982*bc960bbfSJed Brown   }
1983b76ba322SStefano Zampini 
19842617d88aSStefano Zampini   /* Apply interface preconditioner
19852617d88aSStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
1986dc359a40SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
19872617d88aSStefano Zampini 
1988674ae819SStefano Zampini   /* Apply transpose of partition of unity operator */
1989674ae819SStefano Zampini   ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr);
1990*bc960bbfSJed Brown   if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_LUMP) {
1991*bc960bbfSJed Brown     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec1_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1992*bc960bbfSJed Brown     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec1_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1993*bc960bbfSJed Brown     PetscFunctionReturn(0);
1994*bc960bbfSJed Brown   }
19953b03a366Sstefano_zampini   /* Second Dirichlet solve and assembling of output */
19960c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
19970c7d97c5SJed Brown   ierr = VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1998b097fa66SStefano Zampini   if (n_B) {
199916909a7fSStefano Zampini     if (pcbddc->switch_static) {
200016909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
200116909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
200216909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
200316909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
200416909a7fSStefano Zampini       if (!pcbddc->switch_static_change) {
2005b3338236SStefano Zampini         ierr = MatMult(lA,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
200616909a7fSStefano Zampini       } else {
200716909a7fSStefano Zampini         ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
2008b3338236SStefano Zampini         ierr = MatMult(lA,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr);
200916909a7fSStefano Zampini         ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
201016909a7fSStefano Zampini       }
201116909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
201216909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
201316909a7fSStefano Zampini     } else {
20140c7d97c5SJed Brown       ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
201516909a7fSStefano Zampini     }
201616909a7fSStefano Zampini   } else if (pcbddc->switch_static) { /* n_B is zero */
201716909a7fSStefano Zampini     if (!pcbddc->switch_static_change) {
2018b3338236SStefano Zampini       ierr = MatMult(lA,pcis->vec1_D,pcis->vec3_D);CHKERRQ(ierr);
201916909a7fSStefano Zampini     } else {
202016909a7fSStefano Zampini       ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_D,pcis->vec1_N);CHKERRQ(ierr);
2021b3338236SStefano Zampini       ierr = MatMult(lA,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
202216909a7fSStefano Zampini       ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec2_N,pcis->vec3_D);CHKERRQ(ierr);
202316909a7fSStefano Zampini     }
2024b097fa66SStefano Zampini   }
2025df187020SStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D);CHKERRQ(ierr);
2026c0decd05SBarry Smith   ierr = KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec4_D);CHKERRQ(ierr);
2027efc2fbd9SStefano Zampini 
20288ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
2029b097fa66SStefano Zampini     if (pcbddc->switch_static) {
2030b097fa66SStefano Zampini       ierr = VecAXPBYPCZ(pcis->vec2_D,m_one,one,m_one,pcis->vec4_D,pcis->vec1_D);CHKERRQ(ierr);
2031b097fa66SStefano Zampini     } else {
2032b097fa66SStefano Zampini       ierr = VecAXPBY(pcis->vec2_D,m_one,m_one,pcis->vec4_D);CHKERRQ(ierr);
2033b097fa66SStefano Zampini     }
20340c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
20350c7d97c5SJed Brown     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2036b097fa66SStefano Zampini   } else {
2037b097fa66SStefano Zampini     if (pcbddc->switch_static) {
2038b097fa66SStefano Zampini       ierr = VecAXPBY(pcis->vec4_D,one,m_one,pcis->vec1_D);CHKERRQ(ierr);
2039b097fa66SStefano Zampini     } else {
2040b097fa66SStefano Zampini       ierr = VecScale(pcis->vec4_D,m_one);CHKERRQ(ierr);
2041b097fa66SStefano Zampini     }
2042b097fa66SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2043b097fa66SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2044b097fa66SStefano Zampini   }
204527b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */
20461dd7afcfSStefano Zampini     if (pcbddc->benign_apply_coarse_only) {
2047580bdb30SBarry Smith       ierr = PetscArrayzero(pcbddc->benign_p0,pcbddc->benign_n);CHKERRQ(ierr);
20481dd7afcfSStefano Zampini     }
2049015636ebSStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,z,PETSC_FALSE);CHKERRQ(ierr);
2050efc2fbd9SStefano Zampini   }
20511f4df5f7SStefano Zampini 
20521dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
2053f913dca9SStefano Zampini     pcbddc->work_change = r;
20541dd7afcfSStefano Zampini     ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr);
20551dd7afcfSStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr);
20561dd7afcfSStefano Zampini   }
20570c7d97c5SJed Brown   PetscFunctionReturn(0);
20580c7d97c5SJed Brown }
205950efa1b5SStefano Zampini 
206050efa1b5SStefano Zampini /*
206150efa1b5SStefano Zampini    PCApplyTranspose_BDDC - Applies the transpose of the BDDC operator to a vector.
206250efa1b5SStefano Zampini 
206350efa1b5SStefano Zampini    Input Parameters:
20640f202f7eSStefano Zampini +  pc - the preconditioner context
20650f202f7eSStefano Zampini -  r - input vector (global)
206650efa1b5SStefano Zampini 
206750efa1b5SStefano Zampini    Output Parameter:
206850efa1b5SStefano Zampini .  z - output vector (global)
206950efa1b5SStefano Zampini 
207050efa1b5SStefano Zampini    Application Interface Routine: PCApplyTranspose()
207150efa1b5SStefano Zampini  */
207250efa1b5SStefano Zampini PetscErrorCode PCApplyTranspose_BDDC(PC pc,Vec r,Vec z)
207350efa1b5SStefano Zampini {
207450efa1b5SStefano Zampini   PC_IS             *pcis = (PC_IS*)(pc->data);
207550efa1b5SStefano Zampini   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
2076b3338236SStefano Zampini   Mat               lA = NULL;
2077b097fa66SStefano Zampini   PetscInt          n_B = pcis->n_B, n_D = pcis->n - n_B;
207850efa1b5SStefano Zampini   PetscErrorCode    ierr;
207950efa1b5SStefano Zampini   const PetscScalar one = 1.0;
208050efa1b5SStefano Zampini   const PetscScalar m_one = -1.0;
208150efa1b5SStefano Zampini   const PetscScalar zero = 0.0;
208250efa1b5SStefano Zampini 
208350efa1b5SStefano Zampini   PetscFunctionBegin;
2084f3d41395Sstefano_zampini   ierr = PetscCitationsRegister(citation,&cited);CHKERRQ(ierr);
2085b3338236SStefano Zampini   if (pcbddc->switch_static) {
2086b3338236SStefano Zampini     ierr = MatISGetLocalMat(pc->useAmat ? pc->mat : pc->pmat,&lA);CHKERRQ(ierr);
2087b3338236SStefano Zampini   }
20881dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
20891dd7afcfSStefano Zampini     Vec swap;
209027b6a85dSStefano Zampini 
209127b6a85dSStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change);CHKERRQ(ierr);
20921dd7afcfSStefano Zampini     swap = pcbddc->work_change;
20931dd7afcfSStefano Zampini     pcbddc->work_change = r;
20941dd7afcfSStefano Zampini     r = swap;
209527b6a85dSStefano Zampini     /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */
20968ae0ca82SStefano Zampini     if (pcbddc->benign_apply_coarse_only && pcbddc->exact_dirichlet_trick_app && pcbddc->change_interior) {
209727b6a85dSStefano Zampini       ierr = VecCopy(r,pcis->vec1_global);CHKERRQ(ierr);
20988860a134SJunchao Zhang       ierr = VecLockReadPush(pcis->vec1_global);CHKERRQ(ierr);
20991dd7afcfSStefano Zampini     }
210027b6a85dSStefano Zampini   }
210127b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* get p0 from r */
2102537c1cdfSStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,r,PETSC_TRUE);CHKERRQ(ierr);
2103537c1cdfSStefano Zampini   }
21048ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
2105b097fa66SStefano Zampini     ierr = VecCopy(r,z);CHKERRQ(ierr);
210650efa1b5SStefano Zampini     /* First Dirichlet solve */
210750efa1b5SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
210850efa1b5SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
210950efa1b5SStefano Zampini     /*
211050efa1b5SStefano Zampini       Assembling right hand side for BDDC operator
2111b097fa66SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE)
211250efa1b5SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
211350efa1b5SStefano Zampini     */
2114b097fa66SStefano Zampini     if (n_D) {
2115b097fa66SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
2116c0decd05SBarry Smith       ierr = KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec2_D);CHKERRQ(ierr);
211750efa1b5SStefano Zampini       ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
211816909a7fSStefano Zampini       if (pcbddc->switch_static) {
211916909a7fSStefano Zampini         ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
212016909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
212116909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
212216909a7fSStefano Zampini         if (!pcbddc->switch_static_change) {
2123b3338236SStefano Zampini           ierr = MatMultTranspose(lA,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
212416909a7fSStefano Zampini         } else {
212516909a7fSStefano Zampini           ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
2126b3338236SStefano Zampini           ierr = MatMultTranspose(lA,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr);
212716909a7fSStefano Zampini           ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
212816909a7fSStefano Zampini         }
212916909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
213016909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
213116909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
213216909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
213316909a7fSStefano Zampini       } else {
2134b097fa66SStefano Zampini         ierr = MatMultTranspose(pcis->A_IB,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
213516909a7fSStefano Zampini       }
2136b097fa66SStefano Zampini     } else {
2137b097fa66SStefano Zampini       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
2138b097fa66SStefano Zampini     }
213950efa1b5SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
214050efa1b5SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
214150efa1b5SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr);
214250efa1b5SStefano Zampini   } else {
214350efa1b5SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr);
214450efa1b5SStefano Zampini   }
214550efa1b5SStefano Zampini 
214650efa1b5SStefano Zampini   /* Apply interface preconditioner
214750efa1b5SStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
2148dc359a40SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_TRUE);CHKERRQ(ierr);
214950efa1b5SStefano Zampini 
215050efa1b5SStefano Zampini   /* Apply transpose of partition of unity operator */
215150efa1b5SStefano Zampini   ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr);
215250efa1b5SStefano Zampini 
215350efa1b5SStefano Zampini   /* Second Dirichlet solve and assembling of output */
215450efa1b5SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
215550efa1b5SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2156b097fa66SStefano Zampini   if (n_B) {
215716909a7fSStefano Zampini     if (pcbddc->switch_static) {
215816909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
215916909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
216016909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
216116909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
216216909a7fSStefano Zampini       if (!pcbddc->switch_static_change) {
2163b3338236SStefano Zampini         ierr = MatMultTranspose(lA,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
216416909a7fSStefano Zampini       } else {
216516909a7fSStefano Zampini         ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
2166b3338236SStefano Zampini         ierr = MatMultTranspose(lA,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr);
216716909a7fSStefano Zampini         ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
216816909a7fSStefano Zampini       }
216916909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
217016909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
217116909a7fSStefano Zampini     } else {
217250efa1b5SStefano Zampini       ierr = MatMultTranspose(pcis->A_BI,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
217316909a7fSStefano Zampini     }
217416909a7fSStefano Zampini   } else if (pcbddc->switch_static) { /* n_B is zero */
217516909a7fSStefano Zampini     if (!pcbddc->switch_static_change) {
2176b3338236SStefano Zampini       ierr = MatMultTranspose(lA,pcis->vec1_D,pcis->vec3_D);CHKERRQ(ierr);
217716909a7fSStefano Zampini     } else {
217816909a7fSStefano Zampini       ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_D,pcis->vec1_N);CHKERRQ(ierr);
2179b3338236SStefano Zampini       ierr = MatMultTranspose(lA,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
218016909a7fSStefano Zampini       ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec2_N,pcis->vec3_D);CHKERRQ(ierr);
218116909a7fSStefano Zampini     }
2182b097fa66SStefano Zampini   }
2183b0147a47SStefano Zampini   ierr = KSPSolveTranspose(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D);CHKERRQ(ierr);
2184c0decd05SBarry Smith   ierr = KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec4_D);CHKERRQ(ierr);
21858ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
2186b097fa66SStefano Zampini     if (pcbddc->switch_static) {
2187b097fa66SStefano Zampini       ierr = VecAXPBYPCZ(pcis->vec2_D,m_one,one,m_one,pcis->vec4_D,pcis->vec1_D);CHKERRQ(ierr);
2188b097fa66SStefano Zampini     } else {
2189b097fa66SStefano Zampini       ierr = VecAXPBY(pcis->vec2_D,m_one,m_one,pcis->vec4_D);CHKERRQ(ierr);
2190b097fa66SStefano Zampini     }
219150efa1b5SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
219250efa1b5SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2193b097fa66SStefano Zampini   } else {
2194b097fa66SStefano Zampini     if (pcbddc->switch_static) {
2195b097fa66SStefano Zampini       ierr = VecAXPBY(pcis->vec4_D,one,m_one,pcis->vec1_D);CHKERRQ(ierr);
2196b097fa66SStefano Zampini     } else {
2197b097fa66SStefano Zampini       ierr = VecScale(pcis->vec4_D,m_one);CHKERRQ(ierr);
2198b097fa66SStefano Zampini     }
2199b097fa66SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2200b097fa66SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2201b097fa66SStefano Zampini   }
220227b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */
2203537c1cdfSStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,z,PETSC_FALSE);CHKERRQ(ierr);
2204537c1cdfSStefano Zampini   }
22051dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
2206f913dca9SStefano Zampini     pcbddc->work_change = r;
22071dd7afcfSStefano Zampini     ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr);
22081dd7afcfSStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr);
22091dd7afcfSStefano Zampini   }
221050efa1b5SStefano Zampini   PetscFunctionReturn(0);
221150efa1b5SStefano Zampini }
2212674ae819SStefano Zampini 
22139326c5c6Sstefano_zampini PetscErrorCode PCReset_BDDC(PC pc)
2214da1bb401SStefano Zampini {
2215da1bb401SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
22169326c5c6Sstefano_zampini   PC_IS          *pcis = (PC_IS*)pc->data;
22179326c5c6Sstefano_zampini   KSP            kspD,kspR,kspC;
2218da1bb401SStefano Zampini   PetscErrorCode ierr;
2219da1bb401SStefano Zampini 
2220da1bb401SStefano Zampini   PetscFunctionBegin;
2221674ae819SStefano Zampini   /* free BDDC custom data  */
2222674ae819SStefano Zampini   ierr = PCBDDCResetCustomization(pc);CHKERRQ(ierr);
2223674ae819SStefano Zampini   /* destroy objects related to topography */
2224674ae819SStefano Zampini   ierr = PCBDDCResetTopography(pc);CHKERRQ(ierr);
222534a97f8cSStefano Zampini   /* destroy objects for scaling operator */
2226674ae819SStefano Zampini   ierr = PCBDDCScalingDestroy(pc);CHKERRQ(ierr);
2227674ae819SStefano Zampini   /* free solvers stuff */
2228674ae819SStefano Zampini   ierr = PCBDDCResetSolvers(pc);CHKERRQ(ierr);
222962a6ff1dSStefano Zampini   /* free global vectors needed in presolve */
223062a6ff1dSStefano Zampini   ierr = VecDestroy(&pcbddc->temp_solution);CHKERRQ(ierr);
223162a6ff1dSStefano Zampini   ierr = VecDestroy(&pcbddc->original_rhs);CHKERRQ(ierr);
22321dd7afcfSStefano Zampini   /* free data created by PCIS */
22331dd7afcfSStefano Zampini   ierr = PCISDestroy(pc);CHKERRQ(ierr);
22349326c5c6Sstefano_zampini 
22359326c5c6Sstefano_zampini   /* restore defaults */
22369326c5c6Sstefano_zampini   kspD = pcbddc->ksp_D;
22379326c5c6Sstefano_zampini   kspR = pcbddc->ksp_R;
22389326c5c6Sstefano_zampini   kspC = pcbddc->coarse_ksp;
22399326c5c6Sstefano_zampini   ierr = PetscMemzero(pc->data,sizeof(*pcbddc));CHKERRQ(ierr);
22409326c5c6Sstefano_zampini   pcis->n_neigh                     = -1;
22419326c5c6Sstefano_zampini   pcis->scaling_factor              = 1.0;
22429326c5c6Sstefano_zampini   pcis->reusesubmatrices            = PETSC_TRUE;
22439326c5c6Sstefano_zampini   pcbddc->use_local_adj             = PETSC_TRUE;
22449326c5c6Sstefano_zampini   pcbddc->use_vertices              = PETSC_TRUE;
22459326c5c6Sstefano_zampini   pcbddc->use_edges                 = PETSC_TRUE;
22469326c5c6Sstefano_zampini   pcbddc->symmetric_primal          = PETSC_TRUE;
22479326c5c6Sstefano_zampini   pcbddc->vertex_size               = 1;
22489326c5c6Sstefano_zampini   pcbddc->recompute_topography      = PETSC_TRUE;
22499326c5c6Sstefano_zampini   pcbddc->coarse_size               = -1;
22509326c5c6Sstefano_zampini   pcbddc->use_exact_dirichlet_trick = PETSC_TRUE;
22519326c5c6Sstefano_zampini   pcbddc->coarsening_ratio          = 8;
22529326c5c6Sstefano_zampini   pcbddc->coarse_eqs_per_proc       = 1;
22539326c5c6Sstefano_zampini   pcbddc->benign_compute_correction = PETSC_TRUE;
22549326c5c6Sstefano_zampini   pcbddc->nedfield                  = -1;
22559326c5c6Sstefano_zampini   pcbddc->nedglobal                 = PETSC_TRUE;
22569326c5c6Sstefano_zampini   pcbddc->graphmaxcount             = PETSC_MAX_INT;
22579326c5c6Sstefano_zampini   pcbddc->sub_schurs_layers         = -1;
22589326c5c6Sstefano_zampini   pcbddc->ksp_D                     = kspD;
22599326c5c6Sstefano_zampini   pcbddc->ksp_R                     = kspR;
22609326c5c6Sstefano_zampini   pcbddc->coarse_ksp                = kspC;
22619326c5c6Sstefano_zampini   PetscFunctionReturn(0);
22629326c5c6Sstefano_zampini }
22639326c5c6Sstefano_zampini 
22649326c5c6Sstefano_zampini PetscErrorCode PCDestroy_BDDC(PC pc)
22659326c5c6Sstefano_zampini {
22669326c5c6Sstefano_zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
22679326c5c6Sstefano_zampini   PetscErrorCode ierr;
22689326c5c6Sstefano_zampini 
22699326c5c6Sstefano_zampini   PetscFunctionBegin;
22709326c5c6Sstefano_zampini   ierr = PCReset_BDDC(pc);CHKERRQ(ierr);
22719326c5c6Sstefano_zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
22729326c5c6Sstefano_zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
22739326c5c6Sstefano_zampini   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
2274a13144ffSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDiscreteGradient_C",NULL);CHKERRQ(ierr);
2275a198735bSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDivergenceMat_C",NULL);CHKERRQ(ierr);
2276906d46d4SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",NULL);CHKERRQ(ierr);
2277674ae819SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",NULL);CHKERRQ(ierr);
227830368db7SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesIS_C",NULL);CHKERRQ(ierr);
2279bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",NULL);CHKERRQ(ierr);
22802b510759SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",NULL);CHKERRQ(ierr);
2281b8ffe317SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",NULL);CHKERRQ(ierr);
22822b510759SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",NULL);CHKERRQ(ierr);
2283bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",NULL);CHKERRQ(ierr);
228482ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",NULL);CHKERRQ(ierr);
2285bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",NULL);CHKERRQ(ierr);
228682ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",NULL);CHKERRQ(ierr);
2287bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",NULL);CHKERRQ(ierr);
228882ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",NULL);CHKERRQ(ierr);
2289bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",NULL);CHKERRQ(ierr);
2290785d1243SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",NULL);CHKERRQ(ierr);
2291bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",NULL);CHKERRQ(ierr);
229263602bcaSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",NULL);CHKERRQ(ierr);
2293bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",NULL);CHKERRQ(ierr);
2294bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",NULL);CHKERRQ(ierr);
2295bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",NULL);CHKERRQ(ierr);
2296bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",NULL);CHKERRQ(ierr);
2297a06fd7f2SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCPreSolveChangeRHS_C",NULL);CHKERRQ(ierr);
2298ab8c8b98SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCSetCoordinates_C",NULL);CHKERRQ(ierr);
2299674ae819SStefano Zampini   ierr = PetscFree(pc->data);CHKERRQ(ierr);
2300da1bb401SStefano Zampini   PetscFunctionReturn(0);
2301da1bb401SStefano Zampini }
23021e6b0712SBarry Smith 
2303ab8c8b98SStefano Zampini static PetscErrorCode PCSetCoordinates_BDDC(PC pc, PetscInt dim, PetscInt nloc, PetscReal *coords)
2304ab8c8b98SStefano Zampini {
2305ab8c8b98SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2306ab8c8b98SStefano Zampini   PCBDDCGraph    mat_graph = pcbddc->mat_graph;
2307ab8c8b98SStefano Zampini   PetscErrorCode ierr;
2308ab8c8b98SStefano Zampini 
2309ab8c8b98SStefano Zampini   PetscFunctionBegin;
2310ab8c8b98SStefano Zampini   ierr = PetscFree(mat_graph->coords);CHKERRQ(ierr);
2311ab8c8b98SStefano Zampini   ierr = PetscMalloc1(nloc*dim,&mat_graph->coords);CHKERRQ(ierr);
2312580bdb30SBarry Smith   ierr = PetscArraycpy(mat_graph->coords,coords,nloc*dim);CHKERRQ(ierr);
2313ab8c8b98SStefano Zampini   mat_graph->cnloc = nloc;
2314ab8c8b98SStefano Zampini   mat_graph->cdim  = dim;
2315ab8c8b98SStefano Zampini   mat_graph->cloc  = PETSC_FALSE;
23164f819b78SStefano Zampini   /* flg setup */
23174f819b78SStefano Zampini   pcbddc->recompute_topography = PETSC_TRUE;
23184f819b78SStefano Zampini   pcbddc->corner_selected = PETSC_FALSE;
2319ab8c8b98SStefano Zampini   PetscFunctionReturn(0);
2320ab8c8b98SStefano Zampini }
2321ab8c8b98SStefano Zampini 
2322a06fd7f2SStefano Zampini static PetscErrorCode PCPreSolveChangeRHS_BDDC(PC pc, PetscBool* change)
2323a06fd7f2SStefano Zampini {
2324a06fd7f2SStefano Zampini   PetscFunctionBegin;
2325a06fd7f2SStefano Zampini   *change = PETSC_TRUE;
2326a06fd7f2SStefano Zampini   PetscFunctionReturn(0);
2327a06fd7f2SStefano Zampini }
2328a06fd7f2SStefano Zampini 
23293425bc38SStefano Zampini static PetscErrorCode PCBDDCMatFETIDPGetRHS_BDDC(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
23303425bc38SStefano Zampini {
2331674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
2332266e20e9SStefano Zampini   Vec            work;
23333425bc38SStefano Zampini   PC_IS*         pcis;
23343425bc38SStefano Zampini   PC_BDDC*       pcbddc;
23353425bc38SStefano Zampini   PetscErrorCode ierr;
23360c7d97c5SJed Brown 
23373425bc38SStefano Zampini   PetscFunctionBegin;
23383425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
23393425bc38SStefano Zampini   pcis = (PC_IS*)mat_ctx->pc->data;
23403425bc38SStefano Zampini   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
23413425bc38SStefano Zampini 
2342229984c5Sstefano_zampini   ierr = VecSet(fetidp_flux_rhs,0.0);CHKERRQ(ierr);
2343229984c5Sstefano_zampini   /* copy rhs since we may change it during PCPreSolve_BDDC */
2344229984c5Sstefano_zampini   if (!pcbddc->original_rhs) {
2345229984c5Sstefano_zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs);CHKERRQ(ierr);
2346229984c5Sstefano_zampini   }
23476cc1294bSstefano_zampini   if (mat_ctx->rhs_flip) {
23486cc1294bSstefano_zampini     ierr = VecPointwiseMult(pcbddc->original_rhs,standard_rhs,mat_ctx->rhs_flip);CHKERRQ(ierr);
23496cc1294bSstefano_zampini   } else {
2350229984c5Sstefano_zampini     ierr = VecCopy(standard_rhs,pcbddc->original_rhs);CHKERRQ(ierr);
23516cc1294bSstefano_zampini   }
2352af140850Sstefano_zampini   if (mat_ctx->g2g_p) {
2353229984c5Sstefano_zampini     /* interface pressure rhs */
2354022d8d2bSstefano_zampini     ierr = VecScatterBegin(mat_ctx->g2g_p,fetidp_flux_rhs,pcbddc->original_rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2355022d8d2bSstefano_zampini     ierr = VecScatterEnd(mat_ctx->g2g_p,fetidp_flux_rhs,pcbddc->original_rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2356229984c5Sstefano_zampini     ierr = VecScatterBegin(mat_ctx->g2g_p,standard_rhs,fetidp_flux_rhs,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2357229984c5Sstefano_zampini     ierr = VecScatterEnd(mat_ctx->g2g_p,standard_rhs,fetidp_flux_rhs,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
23586cc1294bSstefano_zampini     if (!mat_ctx->rhs_flip) {
2359229984c5Sstefano_zampini       ierr = VecScale(fetidp_flux_rhs,-1.);CHKERRQ(ierr);
2360229984c5Sstefano_zampini     }
23616cc1294bSstefano_zampini   }
2362c08af4c6SStefano Zampini   /*
2363c08af4c6SStefano Zampini      change of basis for physical rhs if needed
2364c08af4c6SStefano Zampini      It also changes the rhs in case of dirichlet boundaries
2365c08af4c6SStefano Zampini   */
23663738a8e6SStefano Zampini   ierr = PCPreSolve_BDDC(mat_ctx->pc,NULL,pcbddc->original_rhs,NULL);CHKERRQ(ierr);
2367fc17d649SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
23683738a8e6SStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,pcbddc->original_rhs,pcbddc->work_change);CHKERRQ(ierr);
23693738a8e6SStefano Zampini     work = pcbddc->work_change;
2370fc17d649SStefano Zampini    } else {
23713738a8e6SStefano Zampini     work = pcbddc->original_rhs;
2372fc17d649SStefano Zampini   }
23733425bc38SStefano Zampini   /* store vectors for computation of fetidp final solution */
2374266e20e9SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,work,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2375266e20e9SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,work,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2376fb223d50SStefano Zampini   /* scale rhs since it should be unassembled */
2377fb223d50SStefano Zampini   /* TODO use counter scaling? (also below) */
2378266e20e9SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2379266e20e9SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2380674ae819SStefano Zampini   /* Apply partition of unity */
23813425bc38SStefano Zampini   ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr);
2382266e20e9SStefano Zampini   /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,work,mat_ctx->temp_solution_B);CHKERRQ(ierr); */
23838eeda7d8SStefano Zampini   if (!pcbddc->switch_static) {
23843425bc38SStefano Zampini     /* compute partially subassembled Schur complement right-hand side */
23853425bc38SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
2386c0decd05SBarry Smith     /* Cannot propagate up error in KSPSolve() because there is no access to the PC */
23873425bc38SStefano Zampini     ierr = MatMult(pcis->A_BI,pcis->vec1_D,pcis->vec1_B);CHKERRQ(ierr);
23883425bc38SStefano Zampini     ierr = VecAXPY(mat_ctx->temp_solution_B,-1.0,pcis->vec1_B);CHKERRQ(ierr);
2389266e20e9SStefano Zampini     ierr = VecSet(work,0.0);CHKERRQ(ierr);
2390266e20e9SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,mat_ctx->temp_solution_B,work,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2391266e20e9SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,mat_ctx->temp_solution_B,work,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2392266e20e9SStefano Zampini     /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,work,mat_ctx->temp_solution_B);CHKERRQ(ierr); */
2393266e20e9SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2394266e20e9SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
23953425bc38SStefano Zampini     ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr);
23963425bc38SStefano Zampini   }
23973425bc38SStefano Zampini   /* BDDC rhs */
23983425bc38SStefano Zampini   ierr = VecCopy(mat_ctx->temp_solution_B,pcis->vec1_B);CHKERRQ(ierr);
23998eeda7d8SStefano Zampini   if (pcbddc->switch_static) {
24003425bc38SStefano Zampini     ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
24013425bc38SStefano Zampini   }
24023425bc38SStefano Zampini   /* apply BDDC */
2403580bdb30SBarry Smith   ierr = PetscArrayzero(pcbddc->benign_p0,pcbddc->benign_n);CHKERRQ(ierr);
2404dc359a40SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE);CHKERRQ(ierr);
2405580bdb30SBarry Smith   ierr = PetscArrayzero(pcbddc->benign_p0,pcbddc->benign_n);CHKERRQ(ierr);
2406229984c5Sstefano_zampini 
24073425bc38SStefano Zampini   /* Application of B_delta and assembling of rhs for fetidp fluxes */
24083425bc38SStefano Zampini   ierr = MatMult(mat_ctx->B_delta,pcis->vec1_B,mat_ctx->lambda_local);CHKERRQ(ierr);
24093425bc38SStefano Zampini   ierr = VecScatterBegin(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
24103425bc38SStefano Zampini   ierr = VecScatterEnd(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2411229984c5Sstefano_zampini   /* Add contribution to interface pressures */
2412229984c5Sstefano_zampini   if (mat_ctx->l2g_p) {
2413229984c5Sstefano_zampini     ierr = MatMult(mat_ctx->B_BB,pcis->vec1_B,mat_ctx->vP);CHKERRQ(ierr);
2414229984c5Sstefano_zampini     if (pcbddc->switch_static) {
2415229984c5Sstefano_zampini       ierr = MatMultAdd(mat_ctx->B_BI,pcis->vec1_D,mat_ctx->vP,mat_ctx->vP);CHKERRQ(ierr);
2416229984c5Sstefano_zampini     }
2417229984c5Sstefano_zampini     ierr = VecScatterBegin(mat_ctx->l2g_p,mat_ctx->vP,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2418229984c5Sstefano_zampini     ierr = VecScatterEnd(mat_ctx->l2g_p,mat_ctx->vP,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2419229984c5Sstefano_zampini   }
24203425bc38SStefano Zampini   PetscFunctionReturn(0);
24213425bc38SStefano Zampini }
24221e6b0712SBarry Smith 
24233425bc38SStefano Zampini /*@
24240f202f7eSStefano Zampini  PCBDDCMatFETIDPGetRHS - Compute the right-hand side for FETI-DP linear system using the physical right-hand side
24253425bc38SStefano Zampini 
24263425bc38SStefano Zampini    Collective
24273425bc38SStefano Zampini 
24283425bc38SStefano Zampini    Input Parameters:
24290f202f7eSStefano Zampini +  fetidp_mat      - the FETI-DP matrix object obtained by a call to PCBDDCCreateFETIDPOperators
24300f202f7eSStefano Zampini -  standard_rhs    - the right-hand side of the original linear system
24313425bc38SStefano Zampini 
24323425bc38SStefano Zampini    Output Parameters:
24330f202f7eSStefano Zampini .  fetidp_flux_rhs - the right-hand side for the FETI-DP linear system
24343425bc38SStefano Zampini 
24353425bc38SStefano Zampini    Level: developer
24363425bc38SStefano Zampini 
24373425bc38SStefano Zampini    Notes:
24383425bc38SStefano Zampini 
24390f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCCreateFETIDPOperators, PCBDDCMatFETIDPGetSolution
24403425bc38SStefano Zampini @*/
24413425bc38SStefano Zampini PetscErrorCode PCBDDCMatFETIDPGetRHS(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
24423425bc38SStefano Zampini {
2443674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
24443425bc38SStefano Zampini   PetscErrorCode ierr;
24453425bc38SStefano Zampini 
24463425bc38SStefano Zampini   PetscFunctionBegin;
2447266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_mat,MAT_CLASSID,1);
2448266e20e9SStefano Zampini   PetscValidHeaderSpecific(standard_rhs,VEC_CLASSID,2);
2449266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_flux_rhs,VEC_CLASSID,3);
24503425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
2451163d334eSBarry Smith   ierr = PetscUseMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetRHS_C",(Mat,Vec,Vec),(fetidp_mat,standard_rhs,fetidp_flux_rhs));CHKERRQ(ierr);
24523425bc38SStefano Zampini   PetscFunctionReturn(0);
24533425bc38SStefano Zampini }
24541e6b0712SBarry Smith 
24553425bc38SStefano Zampini static PetscErrorCode PCBDDCMatFETIDPGetSolution_BDDC(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
24563425bc38SStefano Zampini {
2457674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
24583425bc38SStefano Zampini   PC_IS*         pcis;
24593425bc38SStefano Zampini   PC_BDDC*       pcbddc;
24603425bc38SStefano Zampini   PetscErrorCode ierr;
2461229984c5Sstefano_zampini   Vec            work;
24623425bc38SStefano Zampini 
24633425bc38SStefano Zampini   PetscFunctionBegin;
24643425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
24653425bc38SStefano Zampini   pcis = (PC_IS*)mat_ctx->pc->data;
24663425bc38SStefano Zampini   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
24673425bc38SStefano Zampini 
24683425bc38SStefano Zampini   /* apply B_delta^T */
2469af140850Sstefano_zampini   ierr = VecSet(pcis->vec1_B,0.);CHKERRQ(ierr);
24703425bc38SStefano Zampini   ierr = VecScatterBegin(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
24713425bc38SStefano Zampini   ierr = VecScatterEnd(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
24723425bc38SStefano Zampini   ierr = MatMultTranspose(mat_ctx->B_delta,mat_ctx->lambda_local,pcis->vec1_B);CHKERRQ(ierr);
2473229984c5Sstefano_zampini   if (mat_ctx->l2g_p) {
2474229984c5Sstefano_zampini     ierr = VecScatterBegin(mat_ctx->l2g_p,fetidp_flux_sol,mat_ctx->vP,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2475229984c5Sstefano_zampini     ierr = VecScatterEnd(mat_ctx->l2g_p,fetidp_flux_sol,mat_ctx->vP,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2476229984c5Sstefano_zampini     ierr = MatMultAdd(mat_ctx->Bt_BB,mat_ctx->vP,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
2477229984c5Sstefano_zampini   }
2478229984c5Sstefano_zampini 
24793425bc38SStefano Zampini   /* compute rhs for BDDC application */
24803425bc38SStefano Zampini   ierr = VecAYPX(pcis->vec1_B,-1.0,mat_ctx->temp_solution_B);CHKERRQ(ierr);
24818eeda7d8SStefano Zampini   if (pcbddc->switch_static) {
24823425bc38SStefano Zampini     ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
2483229984c5Sstefano_zampini     if (mat_ctx->l2g_p) {
2484229984c5Sstefano_zampini       ierr = VecScale(mat_ctx->vP,-1.);CHKERRQ(ierr);
2485229984c5Sstefano_zampini       ierr = MatMultAdd(mat_ctx->Bt_BI,mat_ctx->vP,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr);
24863425bc38SStefano Zampini     }
2487229984c5Sstefano_zampini   }
2488229984c5Sstefano_zampini 
24893425bc38SStefano Zampini   /* apply BDDC */
2490580bdb30SBarry Smith   ierr = PetscArrayzero(pcbddc->benign_p0,pcbddc->benign_n);CHKERRQ(ierr);
2491dc359a40SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE);CHKERRQ(ierr);
2492229984c5Sstefano_zampini 
2493229984c5Sstefano_zampini   /* put values into global vector */
2494af140850Sstefano_zampini   if (pcbddc->ChangeOfBasisMatrix) work = pcbddc->work_change;
2495af140850Sstefano_zampini   else work = standard_sol;
2496229984c5Sstefano_zampini   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,work,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2497229984c5Sstefano_zampini   ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,work,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
24988eeda7d8SStefano Zampini   if (!pcbddc->switch_static) {
24993425bc38SStefano Zampini     /* compute values into the interior if solved for the partially subassembled Schur complement */
25003425bc38SStefano Zampini     ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec1_D);CHKERRQ(ierr);
250100f6b531SStefano Zampini     ierr = VecAYPX(pcis->vec1_D,-1.0,mat_ctx->temp_solution_D);CHKERRQ(ierr);
250200f6b531SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr);
2503c0decd05SBarry Smith     /* Cannot propagate up error in KSPSolve() because there is no access to the PC */
25043425bc38SStefano Zampini   }
2505229984c5Sstefano_zampini 
2506229984c5Sstefano_zampini   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec1_D,work,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2507229984c5Sstefano_zampini   ierr = VecScatterEnd(pcis->global_to_D,pcis->vec1_D,work,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2508266e20e9SStefano Zampini   /* add p0 solution to final solution */
2509229984c5Sstefano_zampini   ierr = PCBDDCBenignGetOrSetP0(mat_ctx->pc,work,PETSC_FALSE);CHKERRQ(ierr);
2510fc17d649SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
2511af140850Sstefano_zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,work,standard_sol);CHKERRQ(ierr);
2512fc17d649SStefano Zampini   }
2513af140850Sstefano_zampini   ierr = PCPostSolve_BDDC(mat_ctx->pc,NULL,NULL,standard_sol);CHKERRQ(ierr);
2514af140850Sstefano_zampini   if (mat_ctx->g2g_p) {
2515229984c5Sstefano_zampini     ierr = VecScatterBegin(mat_ctx->g2g_p,fetidp_flux_sol,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2516229984c5Sstefano_zampini     ierr = VecScatterEnd(mat_ctx->g2g_p,fetidp_flux_sol,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2517229984c5Sstefano_zampini   }
25183425bc38SStefano Zampini   PetscFunctionReturn(0);
25193425bc38SStefano Zampini }
25201e6b0712SBarry Smith 
25215a1e936bSStefano Zampini static PetscErrorCode PCView_BDDCIPC(PC pc, PetscViewer viewer)
25225a1e936bSStefano Zampini {
25235a1e936bSStefano Zampini   PetscErrorCode ierr;
25245a1e936bSStefano Zampini   BDDCIPC_ctx    bddcipc_ctx;
25255a1e936bSStefano Zampini   PetscBool      isascii;
25265a1e936bSStefano Zampini 
25275a1e936bSStefano Zampini   PetscFunctionBegin;
25285a1e936bSStefano Zampini   ierr = PCShellGetContext(pc,(void **)&bddcipc_ctx);CHKERRQ(ierr);
25295a1e936bSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
25305a1e936bSStefano Zampini   if (isascii) {
25315a1e936bSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"BDDC interface preconditioner\n");CHKERRQ(ierr);
25325a1e936bSStefano Zampini   }
25335a1e936bSStefano Zampini   ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
25345a1e936bSStefano Zampini   ierr = PCView(bddcipc_ctx->bddc,viewer);CHKERRQ(ierr);
25355a1e936bSStefano Zampini   ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
25365a1e936bSStefano Zampini   PetscFunctionReturn(0);
25375a1e936bSStefano Zampini }
25385a1e936bSStefano Zampini 
25395a1e936bSStefano Zampini static PetscErrorCode PCSetUp_BDDCIPC(PC pc)
25405a1e936bSStefano Zampini {
25415a1e936bSStefano Zampini   PetscErrorCode ierr;
25425a1e936bSStefano Zampini   BDDCIPC_ctx    bddcipc_ctx;
25435a1e936bSStefano Zampini   PetscBool      isbddc;
25445a1e936bSStefano Zampini   Vec            vv;
25455a1e936bSStefano Zampini   IS             is;
25465a1e936bSStefano Zampini   PC_IS          *pcis;
25475a1e936bSStefano Zampini 
25485a1e936bSStefano Zampini   PetscFunctionBegin;
25495a1e936bSStefano Zampini   ierr = PCShellGetContext(pc,(void **)&bddcipc_ctx);CHKERRQ(ierr);
25505a1e936bSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)bddcipc_ctx->bddc,PCBDDC,&isbddc);CHKERRQ(ierr);
25515a1e936bSStefano Zampini   if (!isbddc) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid type %s. Must be of type bddc",((PetscObject)bddcipc_ctx->bddc)->type_name);
25525a1e936bSStefano Zampini   ierr = PCSetUp(bddcipc_ctx->bddc);CHKERRQ(ierr);
25535a1e936bSStefano Zampini 
25545a1e936bSStefano Zampini   /* create interface scatter */
25555a1e936bSStefano Zampini   pcis = (PC_IS*)(bddcipc_ctx->bddc->data);
25565a1e936bSStefano Zampini   ierr = VecScatterDestroy(&bddcipc_ctx->g2l);CHKERRQ(ierr);
25575a1e936bSStefano Zampini   ierr = MatCreateVecs(pc->pmat,&vv,NULL);CHKERRQ(ierr);
25585a1e936bSStefano Zampini   ierr = ISRenumber(pcis->is_B_global,NULL,NULL,&is);CHKERRQ(ierr);
25599448b7f1SJunchao Zhang   ierr = VecScatterCreate(vv,is,pcis->vec1_B,NULL,&bddcipc_ctx->g2l);CHKERRQ(ierr);
25605a1e936bSStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
25615a1e936bSStefano Zampini   ierr = VecDestroy(&vv);CHKERRQ(ierr);
25625a1e936bSStefano Zampini   PetscFunctionReturn(0);
25635a1e936bSStefano Zampini }
25645a1e936bSStefano Zampini 
25655a1e936bSStefano Zampini static PetscErrorCode PCApply_BDDCIPC(PC pc, Vec r, Vec x)
25665a1e936bSStefano Zampini {
25675a1e936bSStefano Zampini   PetscErrorCode ierr;
25685a1e936bSStefano Zampini   BDDCIPC_ctx    bddcipc_ctx;
25695a1e936bSStefano Zampini   PC_IS          *pcis;
25705a1e936bSStefano Zampini   VecScatter     tmps;
25715a1e936bSStefano Zampini 
25725a1e936bSStefano Zampini   PetscFunctionBegin;
25735a1e936bSStefano Zampini   ierr = PCShellGetContext(pc,(void **)&bddcipc_ctx);CHKERRQ(ierr);
25745a1e936bSStefano Zampini   pcis = (PC_IS*)(bddcipc_ctx->bddc->data);
25755a1e936bSStefano Zampini   tmps = pcis->global_to_B;
25765a1e936bSStefano Zampini   pcis->global_to_B = bddcipc_ctx->g2l;
25775a1e936bSStefano Zampini   ierr = PCBDDCScalingRestriction(bddcipc_ctx->bddc,r,pcis->vec1_B);CHKERRQ(ierr);
25785a1e936bSStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(bddcipc_ctx->bddc,PETSC_FALSE);CHKERRQ(ierr);
25795a1e936bSStefano Zampini   ierr = PCBDDCScalingExtension(bddcipc_ctx->bddc,pcis->vec1_B,x);CHKERRQ(ierr);
25805a1e936bSStefano Zampini   pcis->global_to_B = tmps;
25815a1e936bSStefano Zampini   PetscFunctionReturn(0);
25825a1e936bSStefano Zampini }
25835a1e936bSStefano Zampini 
25845a1e936bSStefano Zampini static PetscErrorCode PCApplyTranspose_BDDCIPC(PC pc, Vec r, Vec x)
25855a1e936bSStefano Zampini {
25865a1e936bSStefano Zampini   PetscErrorCode ierr;
25875a1e936bSStefano Zampini   BDDCIPC_ctx    bddcipc_ctx;
25885a1e936bSStefano Zampini   PC_IS          *pcis;
25895a1e936bSStefano Zampini   VecScatter     tmps;
25905a1e936bSStefano Zampini 
25915a1e936bSStefano Zampini   PetscFunctionBegin;
25925a1e936bSStefano Zampini   ierr = PCShellGetContext(pc,(void **)&bddcipc_ctx);CHKERRQ(ierr);
25935a1e936bSStefano Zampini   pcis = (PC_IS*)(bddcipc_ctx->bddc->data);
25945a1e936bSStefano Zampini   tmps = pcis->global_to_B;
25955a1e936bSStefano Zampini   pcis->global_to_B = bddcipc_ctx->g2l;
25965a1e936bSStefano Zampini   ierr = PCBDDCScalingRestriction(bddcipc_ctx->bddc,r,pcis->vec1_B);CHKERRQ(ierr);
25975a1e936bSStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(bddcipc_ctx->bddc,PETSC_TRUE);CHKERRQ(ierr);
25985a1e936bSStefano Zampini   ierr = PCBDDCScalingExtension(bddcipc_ctx->bddc,pcis->vec1_B,x);CHKERRQ(ierr);
25995a1e936bSStefano Zampini   pcis->global_to_B = tmps;
26005a1e936bSStefano Zampini   PetscFunctionReturn(0);
26015a1e936bSStefano Zampini }
26025a1e936bSStefano Zampini 
26035a1e936bSStefano Zampini static PetscErrorCode PCDestroy_BDDCIPC(PC pc)
26045a1e936bSStefano Zampini {
26055a1e936bSStefano Zampini   PetscErrorCode ierr;
26065a1e936bSStefano Zampini   BDDCIPC_ctx    bddcipc_ctx;
26075a1e936bSStefano Zampini 
26085a1e936bSStefano Zampini   PetscFunctionBegin;
26095a1e936bSStefano Zampini   ierr = PCShellGetContext(pc,(void **)&bddcipc_ctx);CHKERRQ(ierr);
26105a1e936bSStefano Zampini   ierr = PCDestroy(&bddcipc_ctx->bddc);CHKERRQ(ierr);
26115a1e936bSStefano Zampini   ierr = VecScatterDestroy(&bddcipc_ctx->g2l);CHKERRQ(ierr);
26125a1e936bSStefano Zampini   ierr = PetscFree(bddcipc_ctx);CHKERRQ(ierr);
26135a1e936bSStefano Zampini   PetscFunctionReturn(0);
26145a1e936bSStefano Zampini }
26155a1e936bSStefano Zampini 
26163425bc38SStefano Zampini /*@
26170f202f7eSStefano Zampini  PCBDDCMatFETIDPGetSolution - Compute the physical solution using the solution of the FETI-DP linear system
26183425bc38SStefano Zampini 
26193425bc38SStefano Zampini    Collective
26203425bc38SStefano Zampini 
26213425bc38SStefano Zampini    Input Parameters:
26220f202f7eSStefano Zampini +  fetidp_mat      - the FETI-DP matrix obtained by a call to PCBDDCCreateFETIDPOperators
26230f202f7eSStefano Zampini -  fetidp_flux_sol - the solution of the FETI-DP linear system
26243425bc38SStefano Zampini 
26253425bc38SStefano Zampini    Output Parameters:
26260f202f7eSStefano Zampini .  standard_sol    - the solution defined on the physical domain
26273425bc38SStefano Zampini 
26283425bc38SStefano Zampini    Level: developer
26293425bc38SStefano Zampini 
26303425bc38SStefano Zampini    Notes:
26313425bc38SStefano Zampini 
26320f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCCreateFETIDPOperators, PCBDDCMatFETIDPGetRHS
26333425bc38SStefano Zampini @*/
26343425bc38SStefano Zampini PetscErrorCode PCBDDCMatFETIDPGetSolution(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
26353425bc38SStefano Zampini {
2636674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
26373425bc38SStefano Zampini   PetscErrorCode ierr;
26383425bc38SStefano Zampini 
26393425bc38SStefano Zampini   PetscFunctionBegin;
2640266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_mat,MAT_CLASSID,1);
2641266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_flux_sol,VEC_CLASSID,2);
2642266e20e9SStefano Zampini   PetscValidHeaderSpecific(standard_sol,VEC_CLASSID,3);
26433425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
2644163d334eSBarry Smith   ierr = PetscUseMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetSolution_C",(Mat,Vec,Vec),(fetidp_mat,fetidp_flux_sol,standard_sol));CHKERRQ(ierr);
26453425bc38SStefano Zampini   PetscFunctionReturn(0);
26463425bc38SStefano Zampini }
26471e6b0712SBarry Smith 
2648547c9a8eSstefano_zampini static PetscErrorCode PCBDDCCreateFETIDPOperators_BDDC(PC pc, PetscBool fully_redundant, const char* prefix, Mat *fetidp_mat, PC *fetidp_pc)
26493425bc38SStefano Zampini {
2650674ae819SStefano Zampini 
2651674ae819SStefano Zampini   FETIDPMat_ctx  fetidpmat_ctx;
26523425bc38SStefano Zampini   Mat            newmat;
2653674ae819SStefano Zampini   FETIDPPC_ctx   fetidppc_ctx;
26543425bc38SStefano Zampini   PC             newpc;
2655ce94432eSBarry Smith   MPI_Comm       comm;
26563425bc38SStefano Zampini   PetscErrorCode ierr;
26573425bc38SStefano Zampini 
26583425bc38SStefano Zampini   PetscFunctionBegin;
2659ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
266015579a77SStefano Zampini   /* FETI-DP matrix */
26613425bc38SStefano Zampini   ierr = PCBDDCCreateFETIDPMatContext(pc,&fetidpmat_ctx);CHKERRQ(ierr);
26621720468bSStefano Zampini   fetidpmat_ctx->fully_redundant = fully_redundant;
26633425bc38SStefano Zampini   ierr = PCBDDCSetupFETIDPMatContext(fetidpmat_ctx);CHKERRQ(ierr);
2664a5bb87b3Sstefano_zampini   ierr = MatCreateShell(comm,fetidpmat_ctx->n,fetidpmat_ctx->n,fetidpmat_ctx->N,fetidpmat_ctx->N,fetidpmat_ctx,&newmat);CHKERRQ(ierr);
266515579a77SStefano Zampini   ierr = PetscObjectSetName((PetscObject)newmat,!fetidpmat_ctx->l2g_lambda_only ? "F" : "G");CHKERRQ(ierr);
26663425bc38SStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_MULT,(void (*)(void))FETIDPMatMult);CHKERRQ(ierr);
2667edf7251bSStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_MULT_TRANSPOSE,(void (*)(void))FETIDPMatMultTranspose);CHKERRQ(ierr);
26683425bc38SStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_DESTROY,(void (*)(void))PCBDDCDestroyFETIDPMat);CHKERRQ(ierr);
266915579a77SStefano Zampini   /* propagate MatOptions */
267015579a77SStefano Zampini   {
267115579a77SStefano Zampini     PC_BDDC   *pcbddc = (PC_BDDC*)fetidpmat_ctx->pc->data;
267215579a77SStefano Zampini     PetscBool issym;
267315579a77SStefano Zampini 
267415579a77SStefano Zampini     ierr = MatGetOption(pc->mat,MAT_SYMMETRIC,&issym);CHKERRQ(ierr);
267515579a77SStefano Zampini     if (issym || pcbddc->symmetric_primal) {
267615579a77SStefano Zampini       ierr = MatSetOption(newmat,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
267715579a77SStefano Zampini     }
267815579a77SStefano Zampini   }
2679547c9a8eSstefano_zampini   ierr = MatSetOptionsPrefix(newmat,prefix);CHKERRQ(ierr);
2680547c9a8eSstefano_zampini   ierr = MatAppendOptionsPrefix(newmat,"fetidp_");CHKERRQ(ierr);
26813425bc38SStefano Zampini   ierr = MatSetUp(newmat);CHKERRQ(ierr);
268215579a77SStefano Zampini   /* FETI-DP preconditioner */
26833425bc38SStefano Zampini   ierr = PCBDDCCreateFETIDPPCContext(pc,&fetidppc_ctx);CHKERRQ(ierr);
26843425bc38SStefano Zampini   ierr = PCBDDCSetupFETIDPPCContext(newmat,fetidppc_ctx);CHKERRQ(ierr);
26853425bc38SStefano Zampini   ierr = PCCreate(comm,&newpc);CHKERRQ(ierr);
2686e1214c54Sstefano_zampini   ierr = PCSetOperators(newpc,newmat,newmat);CHKERRQ(ierr);
2687e1214c54Sstefano_zampini   ierr = PCSetOptionsPrefix(newpc,prefix);CHKERRQ(ierr);
2688e1214c54Sstefano_zampini   ierr = PCAppendOptionsPrefix(newpc,"fetidp_");CHKERRQ(ierr);
2689399ffe99SStefano Zampini   ierr = PCSetErrorIfFailure(newpc,pc->erroriffailure);CHKERRQ(ierr);
269015579a77SStefano Zampini   if (!fetidpmat_ctx->l2g_lambda_only) { /* standard FETI-DP */
26913425bc38SStefano Zampini     ierr = PCSetType(newpc,PCSHELL);CHKERRQ(ierr);
269215579a77SStefano Zampini     ierr = PCShellSetName(newpc,"FETI-DP multipliers");CHKERRQ(ierr);
26933425bc38SStefano Zampini     ierr = PCShellSetContext(newpc,fetidppc_ctx);CHKERRQ(ierr);
26943425bc38SStefano Zampini     ierr = PCShellSetApply(newpc,FETIDPPCApply);CHKERRQ(ierr);
2695edf7251bSStefano Zampini     ierr = PCShellSetApplyTranspose(newpc,FETIDPPCApplyTranspose);CHKERRQ(ierr);
2696c45b8d2dSstefano_zampini     ierr = PCShellSetView(newpc,FETIDPPCView);CHKERRQ(ierr);
26973425bc38SStefano Zampini     ierr = PCShellSetDestroy(newpc,PCBDDCDestroyFETIDPPC);CHKERRQ(ierr);
26985a1e936bSStefano Zampini   } else { /* saddle-point FETI-DP */
26995a1e936bSStefano Zampini     Mat       M;
27005a1e936bSStefano Zampini     PetscInt  psize;
27015a1e936bSStefano Zampini     PetscBool fake = PETSC_FALSE, isfieldsplit;
2702e1214c54Sstefano_zampini 
270315579a77SStefano Zampini     ierr = ISViewFromOptions(fetidpmat_ctx->lagrange,NULL,"-lag_view");CHKERRQ(ierr);
270415579a77SStefano Zampini     ierr = ISViewFromOptions(fetidpmat_ctx->pressure,NULL,"-press_view");CHKERRQ(ierr);
2705e1214c54Sstefano_zampini     ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_PPmat",(PetscObject*)&M);CHKERRQ(ierr);
2706e1214c54Sstefano_zampini     ierr = PCSetType(newpc,PCFIELDSPLIT);CHKERRQ(ierr);
2707e1214c54Sstefano_zampini     ierr = PCFieldSplitSetIS(newpc,"lag",fetidpmat_ctx->lagrange);CHKERRQ(ierr);
2708e1214c54Sstefano_zampini     ierr = PCFieldSplitSetIS(newpc,"p",fetidpmat_ctx->pressure);CHKERRQ(ierr);
2709e1214c54Sstefano_zampini     ierr = PCFieldSplitSetType(newpc,PC_COMPOSITE_SCHUR);CHKERRQ(ierr);
271040c75d76SStefano Zampini     ierr = PCFieldSplitSetSchurFactType(newpc,PC_FIELDSPLIT_SCHUR_FACT_DIAG);CHKERRQ(ierr);
27115a1e936bSStefano Zampini     ierr = ISGetSize(fetidpmat_ctx->pressure,&psize);CHKERRQ(ierr);
27125a1e936bSStefano Zampini     if (psize != M->rmap->N) {
27135a1e936bSStefano Zampini       Mat      M2;
27145a1e936bSStefano Zampini       PetscInt lpsize;
27155a1e936bSStefano Zampini 
27165a1e936bSStefano Zampini       fake = PETSC_TRUE;
27175a1e936bSStefano Zampini       ierr = ISGetLocalSize(fetidpmat_ctx->pressure,&lpsize);CHKERRQ(ierr);
27185a1e936bSStefano Zampini       ierr = MatCreate(comm,&M2);CHKERRQ(ierr);
27195a1e936bSStefano Zampini       ierr = MatSetType(M2,MATAIJ);CHKERRQ(ierr);
27205a1e936bSStefano Zampini       ierr = MatSetSizes(M2,lpsize,lpsize,psize,psize);CHKERRQ(ierr);
27215a1e936bSStefano Zampini       ierr = MatSetUp(M2);CHKERRQ(ierr);
27225a1e936bSStefano Zampini       ierr = MatAssemblyBegin(M2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
27235a1e936bSStefano Zampini       ierr = MatAssemblyEnd(M2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
27245a1e936bSStefano Zampini       ierr = PCFieldSplitSetSchurPre(newpc,PC_FIELDSPLIT_SCHUR_PRE_USER,M2);CHKERRQ(ierr);
27255a1e936bSStefano Zampini       ierr = MatDestroy(&M2);CHKERRQ(ierr);
27265a1e936bSStefano Zampini     } else {
2727e1214c54Sstefano_zampini       ierr = PCFieldSplitSetSchurPre(newpc,PC_FIELDSPLIT_SCHUR_PRE_USER,M);CHKERRQ(ierr);
27285a1e936bSStefano Zampini     }
2729c096484dSStefano Zampini     ierr = PCFieldSplitSetSchurScale(newpc,1.0);CHKERRQ(ierr);
273015579a77SStefano Zampini 
273115579a77SStefano Zampini     /* we need to setfromoptions and setup here to access the blocks */
2732e1214c54Sstefano_zampini     ierr = PCSetFromOptions(newpc);CHKERRQ(ierr);
2733e1214c54Sstefano_zampini     ierr = PCSetUp(newpc);CHKERRQ(ierr);
2734e1214c54Sstefano_zampini 
27355a1e936bSStefano Zampini     /* user may have changed the type (e.g. -fetidp_pc_type none) */
27365a1e936bSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)newpc,PCFIELDSPLIT,&isfieldsplit);CHKERRQ(ierr);
27375a1e936bSStefano Zampini     if (isfieldsplit) {
27385a1e936bSStefano Zampini       KSP       *ksps;
27395a1e936bSStefano Zampini       PC        ppc,lagpc;
27405a1e936bSStefano Zampini       PetscInt  nn;
2741064a4176SStefano Zampini       PetscBool ismatis,matisok = PETSC_FALSE,check = PETSC_FALSE;
27425a1e936bSStefano Zampini 
2743e1214c54Sstefano_zampini       /* set the solver for the (0,0) block */
27445a1e936bSStefano Zampini       ierr = PCFieldSplitSchurGetSubKSP(newpc,&nn,&ksps);CHKERRQ(ierr);
27455a1e936bSStefano Zampini       if (!nn) { /* not of type PC_COMPOSITE_SCHUR */
274640c75d76SStefano Zampini         ierr = PCFieldSplitGetSubKSP(newpc,&nn,&ksps);CHKERRQ(ierr);
27475a1e936bSStefano Zampini         if (!fake) { /* pass pmat to the pressure solver */
27485a1e936bSStefano Zampini           Mat F;
27495a1e936bSStefano Zampini 
27505a1e936bSStefano Zampini           ierr = KSPGetOperators(ksps[1],&F,NULL);CHKERRQ(ierr);
27515a1e936bSStefano Zampini           ierr = KSPSetOperators(ksps[1],F,M);CHKERRQ(ierr);
27525a1e936bSStefano Zampini         }
27535a1e936bSStefano Zampini       } else {
27545a1e936bSStefano Zampini         PetscBool issym;
27555a1e936bSStefano Zampini         Mat       S;
27565a1e936bSStefano Zampini 
27575a1e936bSStefano Zampini         ierr = PCFieldSplitSchurGetS(newpc,&S);CHKERRQ(ierr);
27585a1e936bSStefano Zampini 
27595a1e936bSStefano Zampini         ierr = MatGetOption(newmat,MAT_SYMMETRIC,&issym);CHKERRQ(ierr);
27605a1e936bSStefano Zampini         if (issym) {
27615a1e936bSStefano Zampini           ierr = MatSetOption(S,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
27625a1e936bSStefano Zampini         }
27635a1e936bSStefano Zampini       }
27645a1e936bSStefano Zampini       ierr = KSPGetPC(ksps[0],&lagpc);CHKERRQ(ierr);
2765e1214c54Sstefano_zampini       ierr = PCSetType(lagpc,PCSHELL);CHKERRQ(ierr);
27665a1e936bSStefano Zampini       ierr = PCShellSetName(lagpc,"FETI-DP multipliers");CHKERRQ(ierr);
2767e1214c54Sstefano_zampini       ierr = PCShellSetContext(lagpc,fetidppc_ctx);CHKERRQ(ierr);
2768e1214c54Sstefano_zampini       ierr = PCShellSetApply(lagpc,FETIDPPCApply);CHKERRQ(ierr);
2769e1214c54Sstefano_zampini       ierr = PCShellSetApplyTranspose(lagpc,FETIDPPCApplyTranspose);CHKERRQ(ierr);
2770e1214c54Sstefano_zampini       ierr = PCShellSetView(lagpc,FETIDPPCView);CHKERRQ(ierr);
2771e1214c54Sstefano_zampini       ierr = PCShellSetDestroy(lagpc,PCBDDCDestroyFETIDPPC);CHKERRQ(ierr);
27725a1e936bSStefano Zampini 
27735a1e936bSStefano Zampini       /* Olof's idea: interface Schur complement preconditioner for the mass matrix */
27745a1e936bSStefano Zampini       ierr = KSPGetPC(ksps[1],&ppc);CHKERRQ(ierr);
27755a1e936bSStefano Zampini       if (fake) {
27765a1e936bSStefano Zampini         BDDCIPC_ctx    bddcipc_ctx;
2777ff11fd76SStefano Zampini         PetscContainer c;
27785a1e936bSStefano Zampini 
27795a1e936bSStefano Zampini         matisok = PETSC_TRUE;
27805a1e936bSStefano Zampini 
27815a1e936bSStefano Zampini         /* create inner BDDC solver */
27825a1e936bSStefano Zampini         ierr = PetscNew(&bddcipc_ctx);CHKERRQ(ierr);
27835a1e936bSStefano Zampini         ierr = PCCreate(comm,&bddcipc_ctx->bddc);CHKERRQ(ierr);
27845a1e936bSStefano Zampini         ierr = PCSetType(bddcipc_ctx->bddc,PCBDDC);CHKERRQ(ierr);
27855a1e936bSStefano Zampini         ierr = PCSetOperators(bddcipc_ctx->bddc,M,M);CHKERRQ(ierr);
2786ff11fd76SStefano Zampini         ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_pCSR",(PetscObject*)&c);CHKERRQ(ierr);
2787ff11fd76SStefano Zampini         ierr = PetscObjectTypeCompare((PetscObject)M,MATIS,&ismatis);CHKERRQ(ierr);
2788ff11fd76SStefano Zampini         if (c && ismatis) {
2789ff11fd76SStefano Zampini           Mat      lM;
2790ff11fd76SStefano Zampini           PetscInt *csr,n;
2791ff11fd76SStefano Zampini 
2792ff11fd76SStefano Zampini           ierr = MatISGetLocalMat(M,&lM);CHKERRQ(ierr);
2793ff11fd76SStefano Zampini           ierr = MatGetSize(lM,&n,NULL);CHKERRQ(ierr);
2794ff11fd76SStefano Zampini           ierr = PetscContainerGetPointer(c,(void**)&csr);CHKERRQ(ierr);
2795ff11fd76SStefano Zampini           ierr = PCBDDCSetLocalAdjacencyGraph(bddcipc_ctx->bddc,n,csr,csr + (n + 1),PETSC_COPY_VALUES);CHKERRQ(ierr);
2796ff11fd76SStefano Zampini           ierr = MatISRestoreLocalMat(M,&lM);CHKERRQ(ierr);
2797ff11fd76SStefano Zampini         }
27985a1e936bSStefano Zampini         ierr = PCSetOptionsPrefix(bddcipc_ctx->bddc,((PetscObject)ksps[1])->prefix);CHKERRQ(ierr);
27995a1e936bSStefano Zampini         ierr = PCSetErrorIfFailure(bddcipc_ctx->bddc,pc->erroriffailure);CHKERRQ(ierr);
28005a1e936bSStefano Zampini         ierr = PCSetFromOptions(bddcipc_ctx->bddc);CHKERRQ(ierr);
28015a1e936bSStefano Zampini 
28025a1e936bSStefano Zampini         /* wrap the interface application */
28035a1e936bSStefano Zampini         ierr = PCSetType(ppc,PCSHELL);CHKERRQ(ierr);
28045a1e936bSStefano Zampini         ierr = PCShellSetName(ppc,"FETI-DP pressure");CHKERRQ(ierr);
28055a1e936bSStefano Zampini         ierr = PCShellSetContext(ppc,bddcipc_ctx);CHKERRQ(ierr);
28065a1e936bSStefano Zampini         ierr = PCShellSetSetUp(ppc,PCSetUp_BDDCIPC);CHKERRQ(ierr);
28075a1e936bSStefano Zampini         ierr = PCShellSetApply(ppc,PCApply_BDDCIPC);CHKERRQ(ierr);
28085a1e936bSStefano Zampini         ierr = PCShellSetApplyTranspose(ppc,PCApplyTranspose_BDDCIPC);CHKERRQ(ierr);
28095a1e936bSStefano Zampini         ierr = PCShellSetView(ppc,PCView_BDDCIPC);CHKERRQ(ierr);
28105a1e936bSStefano Zampini         ierr = PCShellSetDestroy(ppc,PCDestroy_BDDCIPC);CHKERRQ(ierr);
28115a1e936bSStefano Zampini       }
28125a1e936bSStefano Zampini 
28135a1e936bSStefano Zampini       /* determine if we need to assemble M to construct a preconditioner */
28145a1e936bSStefano Zampini       if (!matisok) {
28155a1e936bSStefano Zampini         ierr = PetscObjectTypeCompare((PetscObject)M,MATIS,&ismatis);CHKERRQ(ierr);
28165a1e936bSStefano Zampini         ierr = PetscObjectTypeCompareAny((PetscObject)ppc,&matisok,PCBDDC,PCJACOBI,PCNONE,PCMG,"");CHKERRQ(ierr);
28175a1e936bSStefano Zampini         if (ismatis && !matisok) {
28185a1e936bSStefano Zampini           ierr = MatConvert(M,MATAIJ,MAT_INPLACE_MATRIX,&M);CHKERRQ(ierr);
28195a1e936bSStefano Zampini         }
28205a1e936bSStefano Zampini       }
2821064a4176SStefano Zampini 
2822064a4176SStefano Zampini       /* run the subproblems to check convergence */
2823064a4176SStefano Zampini       ierr = PetscOptionsGetBool(NULL,((PetscObject)newmat)->prefix,"-check_saddlepoint",&check,NULL);CHKERRQ(ierr);
2824064a4176SStefano Zampini       if (check) {
2825064a4176SStefano Zampini         PetscInt i;
2826064a4176SStefano Zampini 
2827064a4176SStefano Zampini         for (i=0;i<nn;i++) {
2828064a4176SStefano Zampini           KSP       kspC;
2829064a4176SStefano Zampini           PC        pc;
2830064a4176SStefano Zampini           Mat       F,pF;
2831064a4176SStefano Zampini           Vec       x,y;
2832064a4176SStefano Zampini           PetscBool isschur,prec = PETSC_TRUE;
2833064a4176SStefano Zampini 
2834064a4176SStefano Zampini           ierr = KSPCreate(PetscObjectComm((PetscObject)ksps[i]),&kspC);CHKERRQ(ierr);
2835064a4176SStefano Zampini           ierr = KSPSetOptionsPrefix(kspC,((PetscObject)ksps[i])->prefix);CHKERRQ(ierr);
2836064a4176SStefano Zampini           ierr = KSPAppendOptionsPrefix(kspC,"check_");CHKERRQ(ierr);
2837064a4176SStefano Zampini           ierr = KSPGetOperators(ksps[i],&F,&pF);CHKERRQ(ierr);
2838064a4176SStefano Zampini           ierr = PetscObjectTypeCompare((PetscObject)F,MATSCHURCOMPLEMENT,&isschur);CHKERRQ(ierr);
2839064a4176SStefano Zampini           if (isschur) {
2840064a4176SStefano Zampini             KSP  kspS,kspS2;
2841064a4176SStefano Zampini             Mat  A00,pA00,A10,A01,A11;
2842064a4176SStefano Zampini             char prefix[256];
2843064a4176SStefano Zampini 
2844064a4176SStefano Zampini             ierr = MatSchurComplementGetKSP(F,&kspS);CHKERRQ(ierr);
2845064a4176SStefano Zampini             ierr = MatSchurComplementGetSubMatrices(F,&A00,&pA00,&A01,&A10,&A11);CHKERRQ(ierr);
2846064a4176SStefano Zampini             ierr = MatCreateSchurComplement(A00,pA00,A01,A10,A11,&F);CHKERRQ(ierr);
2847064a4176SStefano Zampini             ierr = MatSchurComplementGetKSP(F,&kspS2);CHKERRQ(ierr);
2848064a4176SStefano Zampini             ierr = PetscSNPrintf(prefix,sizeof(prefix),"%sschur_",((PetscObject)kspC)->prefix);CHKERRQ(ierr);
2849064a4176SStefano Zampini             ierr = KSPSetOptionsPrefix(kspS2,prefix);CHKERRQ(ierr);
2850064a4176SStefano Zampini             ierr = KSPGetPC(kspS2,&pc);CHKERRQ(ierr);
2851064a4176SStefano Zampini             ierr = PCSetType(pc,PCKSP);CHKERRQ(ierr);
2852064a4176SStefano Zampini             ierr = PCKSPSetKSP(pc,kspS);CHKERRQ(ierr);
2853064a4176SStefano Zampini             ierr = KSPSetFromOptions(kspS2);CHKERRQ(ierr);
2854064a4176SStefano Zampini             ierr = KSPGetPC(kspS2,&pc);CHKERRQ(ierr);
2855064a4176SStefano Zampini             ierr = PCSetUseAmat(pc,PETSC_TRUE);CHKERRQ(ierr);
2856064a4176SStefano Zampini           } else {
2857064a4176SStefano Zampini             ierr = PetscObjectReference((PetscObject)F);CHKERRQ(ierr);
2858064a4176SStefano Zampini           }
2859064a4176SStefano Zampini           ierr = KSPSetFromOptions(kspC);CHKERRQ(ierr);
2860064a4176SStefano Zampini           ierr = PetscOptionsGetBool(NULL,((PetscObject)kspC)->prefix,"-preconditioned",&prec,NULL);CHKERRQ(ierr);
2861064a4176SStefano Zampini           if (prec)  {
2862064a4176SStefano Zampini             ierr = KSPGetPC(ksps[i],&pc);CHKERRQ(ierr);
2863064a4176SStefano Zampini             ierr = KSPSetPC(kspC,pc);CHKERRQ(ierr);
2864064a4176SStefano Zampini           }
2865064a4176SStefano Zampini           ierr = KSPSetOperators(kspC,F,pF);CHKERRQ(ierr);
2866064a4176SStefano Zampini           ierr = MatCreateVecs(F,&x,&y);CHKERRQ(ierr);
2867064a4176SStefano Zampini           ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
2868064a4176SStefano Zampini           ierr = MatMult(F,x,y);CHKERRQ(ierr);
2869064a4176SStefano Zampini           ierr = KSPSolve(kspC,y,x);CHKERRQ(ierr);
2870c0decd05SBarry Smith           ierr = KSPCheckSolve(kspC,pc,x);CHKERRQ(ierr);
2871064a4176SStefano Zampini           ierr = KSPDestroy(&kspC);CHKERRQ(ierr);
2872064a4176SStefano Zampini           ierr = MatDestroy(&F);CHKERRQ(ierr);
2873064a4176SStefano Zampini           ierr = VecDestroy(&x);CHKERRQ(ierr);
2874064a4176SStefano Zampini           ierr = VecDestroy(&y);CHKERRQ(ierr);
2875064a4176SStefano Zampini         }
2876064a4176SStefano Zampini       }
2877e1214c54Sstefano_zampini       ierr = PetscFree(ksps);CHKERRQ(ierr);
2878e1214c54Sstefano_zampini     }
28795a1e936bSStefano Zampini   }
28803425bc38SStefano Zampini   /* return pointers for objects created */
28813425bc38SStefano Zampini   *fetidp_mat = newmat;
28823425bc38SStefano Zampini   *fetidp_pc  = newpc;
28833425bc38SStefano Zampini   PetscFunctionReturn(0);
28843425bc38SStefano Zampini }
28851e6b0712SBarry Smith 
288694ef8ddeSSatish Balay /*@C
28870f202f7eSStefano Zampini  PCBDDCCreateFETIDPOperators - Create FETI-DP operators
28883425bc38SStefano Zampini 
28893425bc38SStefano Zampini    Collective
28903425bc38SStefano Zampini 
28913425bc38SStefano Zampini    Input Parameters:
28921720468bSStefano Zampini +  pc - the BDDC preconditioning context (setup should have been called before)
2893547c9a8eSstefano_zampini .  fully_redundant - true for a fully redundant set of Lagrange multipliers
2894547c9a8eSstefano_zampini -  prefix - optional options database prefix for the objects to be created (can be NULL)
289528509bceSStefano Zampini 
289628509bceSStefano Zampini    Output Parameters:
28970f202f7eSStefano Zampini +  fetidp_mat - shell FETI-DP matrix object
28980f202f7eSStefano Zampini -  fetidp_pc  - shell Dirichlet preconditioner for FETI-DP matrix
289928509bceSStefano Zampini 
29003425bc38SStefano Zampini    Level: developer
29013425bc38SStefano Zampini 
29023425bc38SStefano Zampini    Notes:
29030f202f7eSStefano Zampini      Currently the only operations provided for FETI-DP matrix are MatMult and MatMultTranspose
29043425bc38SStefano Zampini 
29050f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCMatFETIDPGetRHS, PCBDDCMatFETIDPGetSolution
29063425bc38SStefano Zampini @*/
2907547c9a8eSstefano_zampini PetscErrorCode PCBDDCCreateFETIDPOperators(PC pc, PetscBool fully_redundant, const char *prefix, Mat *fetidp_mat, PC *fetidp_pc)
29083425bc38SStefano Zampini {
29093425bc38SStefano Zampini   PetscErrorCode ierr;
29103425bc38SStefano Zampini 
29113425bc38SStefano Zampini   PetscFunctionBegin;
29123425bc38SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
29133425bc38SStefano Zampini   if (pc->setupcalled) {
2914547c9a8eSstefano_zampini     ierr = PetscUseMethod(pc,"PCBDDCCreateFETIDPOperators_C",(PC,PetscBool,const char*,Mat*,PC*),(pc,fully_redundant,prefix,fetidp_mat,fetidp_pc));CHKERRQ(ierr);
29156080607fSStefano Zampini   } else SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"You must call PCSetup_BDDC() first");
29163425bc38SStefano Zampini   PetscFunctionReturn(0);
29173425bc38SStefano Zampini }
29180c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
2919da1bb401SStefano Zampini /*MC
2920da1bb401SStefano Zampini    PCBDDC - Balancing Domain Decomposition by Constraints.
29210c7d97c5SJed Brown 
292228509bceSStefano Zampini    An implementation of the BDDC preconditioner based on
292328509bceSStefano Zampini 
292428509bceSStefano Zampini .vb
292528509bceSStefano Zampini    [1] C. R. Dohrmann. "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149-168, March 2007
2926a8d69d7bSBarry Smith    [2] A. Klawonn and O. B. Widlund. "Dual-Primal FETI Methods for Linear Elasticity", https://cs.nyu.edu/dynamic/reports/?year=all
2927a8d69d7bSBarry Smith    [3] J. Mandel, B. Sousedik, C. R. Dohrmann. "Multispace and Multilevel BDDC", https://arxiv.org/abs/0712.3977
29280f202f7eSStefano Zampini    [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
292928509bceSStefano Zampini .ve
293028509bceSStefano Zampini 
293128509bceSStefano Zampini    The matrix to be preconditioned (Pmat) must be of type MATIS.
293228509bceSStefano Zampini 
29330f202f7eSStefano Zampini    Currently works with MATIS matrices with local matrices of type MATSEQAIJ, MATSEQBAIJ or MATSEQSBAIJ, either with real or complex numbers.
293428509bceSStefano Zampini 
293528509bceSStefano Zampini    It also works with unsymmetric and indefinite problems.
293628509bceSStefano Zampini 
2937b6fdb6dfSStefano Zampini    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.
2938b6fdb6dfSStefano Zampini 
2939c7017625SStefano Zampini    Approximate local solvers are automatically adapted (see [1]) if the user has attached a nullspace object to the subdomain matrices, and informed BDDC of using approximate solvers (via the command line).
294028509bceSStefano Zampini 
29410f202f7eSStefano Zampini    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()
294230368db7SStefano Zampini    Additional information on dofs can be provided by using PCBDDCSetDofsSplitting(), PCBDDCSetDirichletBoundaries(), PCBDDCSetNeumannBoundaries(), and PCBDDCSetPrimalVerticesIS() and their local counterparts.
294328509bceSStefano Zampini 
29440f202f7eSStefano Zampini    Constraints can be customized by attaching a MatNullSpace object to the MATIS matrix via MatSetNearNullSpace(). Non-singular modes are retained via SVD.
294528509bceSStefano Zampini 
29460f202f7eSStefano Zampini    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.
29470f202f7eSStefano Zampini    User defined change of basis can be passed to PCBDDC by using PCBDDCSetChangeOfBasisMat()
294828509bceSStefano Zampini 
29490f202f7eSStefano Zampini    The PETSc implementation also supports multilevel BDDC [3]. Coarse grids are partitioned using a MatPartitioning object.
295028509bceSStefano Zampini 
2951df4d28bfSStefano Zampini    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.
295228509bceSStefano Zampini 
29530f202f7eSStefano Zampini    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.
29540f202f7eSStefano Zampini    Deluxe scaling is not supported yet for FETI-DP.
29550f202f7eSStefano Zampini 
29560f202f7eSStefano Zampini    Options Database Keys (some of them, run with -h for a complete list):
29570f202f7eSStefano Zampini 
2958a2b725a8SWilliam Gropp +    -pc_bddc_use_vertices <true> - use or not vertices in primal space
29590f202f7eSStefano Zampini .    -pc_bddc_use_edges <true> - use or not edges in primal space
29600f202f7eSStefano Zampini .    -pc_bddc_use_faces <false> - use or not faces in primal space
29610f202f7eSStefano Zampini .    -pc_bddc_symmetric <true> - symmetric computation of primal basis functions. Specify false for unsymmetric problems
29620f202f7eSStefano Zampini .    -pc_bddc_use_change_of_basis <false> - use change of basis approach (on edges only)
29630f202f7eSStefano Zampini .    -pc_bddc_use_change_on_faces <false> - use change of basis approach on faces if change of basis has been requested
29640f202f7eSStefano Zampini .    -pc_bddc_switch_static <false> - switches from M_2 (default) to M_3 operator (see reference article [1])
296528509bceSStefano Zampini .    -pc_bddc_levels <0> - maximum number of levels for multilevel
29660f202f7eSStefano Zampini .    -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)
29675459c157SBarry Smith .    -pc_bddc_coarse_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)
29680f202f7eSStefano Zampini .    -pc_bddc_use_deluxe_scaling <false> - use deluxe scaling
29690f202f7eSStefano Zampini .    -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)
2970bd2a564bSStefano Zampini .    -pc_bddc_adaptive_threshold <0.0> - when a value different than zero is specified, adaptive selection of constraints is performed on edges and faces (requires deluxe scaling and MUMPS or MKL_PARDISO installed)
297128509bceSStefano Zampini -    -pc_bddc_check_level <0> - set verbosity level of debugging output
297228509bceSStefano Zampini 
297328509bceSStefano Zampini    Options for Dirichlet, Neumann or coarse solver can be set with
297428509bceSStefano Zampini .vb
297528509bceSStefano Zampini       -pc_bddc_dirichlet_
297628509bceSStefano Zampini       -pc_bddc_neumann_
297728509bceSStefano Zampini       -pc_bddc_coarse_
297828509bceSStefano Zampini .ve
297928d58a37SPierre Jolivet    e.g. -pc_bddc_dirichlet_ksp_type richardson -pc_bddc_dirichlet_pc_type gamg. PCBDDC uses by default KPSPREONLY and PCLU.
298028509bceSStefano Zampini 
29810f202f7eSStefano Zampini    When using a multilevel approach, solvers' options at the N-th level (N > 1) can be specified as
298228509bceSStefano Zampini .vb
2983312be037SStefano Zampini       -pc_bddc_dirichlet_lN_
2984312be037SStefano Zampini       -pc_bddc_neumann_lN_
2985312be037SStefano Zampini       -pc_bddc_coarse_lN_
298628509bceSStefano Zampini .ve
29870f202f7eSStefano Zampini    Note that level number ranges from the finest (0) to the coarsest (N).
29880f202f7eSStefano Zampini    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.
29890f202f7eSStefano Zampini .vb
29900f202f7eSStefano Zampini      -pc_bddc_coarse_pc_bddc_adaptive_threshold 5 -pc_bddc_coarse_l1_pc_bddc_redistribute 3
29910f202f7eSStefano Zampini .ve
29920f202f7eSStefano Zampini    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
2993da1bb401SStefano Zampini 
2994da1bb401SStefano Zampini    Level: intermediate
2995da1bb401SStefano Zampini 
2996e94cfbe0SPatrick Sanan    Developer Notes:
2997da1bb401SStefano Zampini 
2998da1bb401SStefano Zampini    Contributed by Stefano Zampini
2999da1bb401SStefano Zampini 
3000da1bb401SStefano Zampini .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,  MATIS
3001da1bb401SStefano Zampini M*/
3002b2573a8aSBarry Smith 
30038cc058d9SJed Brown PETSC_EXTERN PetscErrorCode PCCreate_BDDC(PC pc)
3004da1bb401SStefano Zampini {
3005da1bb401SStefano Zampini   PetscErrorCode      ierr;
3006da1bb401SStefano Zampini   PC_BDDC             *pcbddc;
3007da1bb401SStefano Zampini 
3008da1bb401SStefano Zampini   PetscFunctionBegin;
3009b00a9115SJed Brown   ierr     = PetscNewLog(pc,&pcbddc);CHKERRQ(ierr);
3010da1bb401SStefano Zampini   pc->data = (void*)pcbddc;
3011da1bb401SStefano Zampini 
3012da1bb401SStefano Zampini   /* create PCIS data structure */
3013da1bb401SStefano Zampini   ierr = PCISCreate(pc);CHKERRQ(ierr);
3014da1bb401SStefano Zampini 
30159326c5c6Sstefano_zampini   /* create local graph structure */
30169326c5c6Sstefano_zampini   ierr = PCBDDCGraphCreate(&pcbddc->mat_graph);CHKERRQ(ierr);
30179326c5c6Sstefano_zampini 
30189326c5c6Sstefano_zampini   /* BDDC nonzero defaults */
30196d9e27e4SStefano Zampini   pcbddc->use_nnsp                  = PETSC_TRUE;
302008a5cf49SStefano Zampini   pcbddc->use_local_adj             = PETSC_TRUE;
302147d04d0dSStefano Zampini   pcbddc->use_vertices              = PETSC_TRUE;
302247d04d0dSStefano Zampini   pcbddc->use_edges                 = PETSC_TRUE;
30233301b35fSStefano Zampini   pcbddc->symmetric_primal          = PETSC_TRUE;
302414f95afaSStefano Zampini   pcbddc->vertex_size               = 1;
3025c703fcc7SStefano Zampini   pcbddc->recompute_topography      = PETSC_TRUE;
302668457ee5SStefano Zampini   pcbddc->coarse_size               = -1;
302785c4d303SStefano Zampini   pcbddc->use_exact_dirichlet_trick = PETSC_TRUE;
302847d04d0dSStefano Zampini   pcbddc->coarsening_ratio          = 8;
302957de7509SStefano Zampini   pcbddc->coarse_eqs_per_proc       = 1;
303027b6a85dSStefano Zampini   pcbddc->benign_compute_correction = PETSC_TRUE;
30311e0482f5SStefano Zampini   pcbddc->nedfield                  = -1;
30321e0482f5SStefano Zampini   pcbddc->nedglobal                 = PETSC_TRUE;
3033be12c134Sstefano_zampini   pcbddc->graphmaxcount             = PETSC_MAX_INT;
3034b96c3477SStefano Zampini   pcbddc->sub_schurs_layers         = -1;
3035bd2a564bSStefano Zampini   pcbddc->adaptive_threshold[0]     = 0.0;
3036bd2a564bSStefano Zampini   pcbddc->adaptive_threshold[1]     = 0.0;
3037b7eb3628SStefano Zampini 
3038da1bb401SStefano Zampini   /* function pointers */
3039da1bb401SStefano Zampini   pc->ops->apply               = PCApply_BDDC;
304093bd9ae7SStefano Zampini   pc->ops->applytranspose      = PCApplyTranspose_BDDC;
3041da1bb401SStefano Zampini   pc->ops->setup               = PCSetUp_BDDC;
3042da1bb401SStefano Zampini   pc->ops->destroy             = PCDestroy_BDDC;
3043da1bb401SStefano Zampini   pc->ops->setfromoptions      = PCSetFromOptions_BDDC;
30446b78500eSPatrick Sanan   pc->ops->view                = PCView_BDDC;
3045da1bb401SStefano Zampini   pc->ops->applyrichardson     = 0;
3046da1bb401SStefano Zampini   pc->ops->applysymmetricleft  = 0;
3047da1bb401SStefano Zampini   pc->ops->applysymmetricright = 0;
3048534831adSStefano Zampini   pc->ops->presolve            = PCPreSolve_BDDC;
3049534831adSStefano Zampini   pc->ops->postsolve           = PCPostSolve_BDDC;
30509326c5c6Sstefano_zampini   pc->ops->reset               = PCReset_BDDC;
3051da1bb401SStefano Zampini 
3052da1bb401SStefano Zampini   /* composing function */
3053a13144ffSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDiscreteGradient_C",PCBDDCSetDiscreteGradient_BDDC);CHKERRQ(ierr);
3054a198735bSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDivergenceMat_C",PCBDDCSetDivergenceMat_BDDC);CHKERRQ(ierr);
3055906d46d4SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",PCBDDCSetChangeOfBasisMat_BDDC);CHKERRQ(ierr);
3056674ae819SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",PCBDDCSetPrimalVerticesLocalIS_BDDC);CHKERRQ(ierr);
305730368db7SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesIS_C",PCBDDCSetPrimalVerticesIS_BDDC);CHKERRQ(ierr);
30583100ebe3SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetPrimalVerticesLocalIS_C",PCBDDCGetPrimalVerticesLocalIS_BDDC);CHKERRQ(ierr);
30593100ebe3SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetPrimalVerticesIS_C",PCBDDCGetPrimalVerticesIS_BDDC);CHKERRQ(ierr);
3060bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",PCBDDCSetCoarseningRatio_BDDC);CHKERRQ(ierr);
30612b510759SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",PCBDDCSetLevel_BDDC);CHKERRQ(ierr);
3062b8ffe317SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",PCBDDCSetUseExactDirichlet_BDDC);CHKERRQ(ierr);
30632b510759SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",PCBDDCSetLevels_BDDC);CHKERRQ(ierr);
3064bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",PCBDDCSetDirichletBoundaries_BDDC);CHKERRQ(ierr);
306582ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",PCBDDCSetDirichletBoundariesLocal_BDDC);CHKERRQ(ierr);
3066bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",PCBDDCSetNeumannBoundaries_BDDC);CHKERRQ(ierr);
306782ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",PCBDDCSetNeumannBoundariesLocal_BDDC);CHKERRQ(ierr);
3068bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",PCBDDCGetDirichletBoundaries_BDDC);CHKERRQ(ierr);
306982ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",PCBDDCGetDirichletBoundariesLocal_BDDC);CHKERRQ(ierr);
3070bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",PCBDDCGetNeumannBoundaries_BDDC);CHKERRQ(ierr);
307182ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",PCBDDCGetNeumannBoundariesLocal_BDDC);CHKERRQ(ierr);
3072bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",PCBDDCSetDofsSplitting_BDDC);CHKERRQ(ierr);
307363602bcaSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",PCBDDCSetDofsSplittingLocal_BDDC);CHKERRQ(ierr);
3074bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",PCBDDCSetLocalAdjacencyGraph_BDDC);CHKERRQ(ierr);
3075bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",PCBDDCCreateFETIDPOperators_BDDC);CHKERRQ(ierr);
3076bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",PCBDDCMatFETIDPGetRHS_BDDC);CHKERRQ(ierr);
3077bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",PCBDDCMatFETIDPGetSolution_BDDC);CHKERRQ(ierr);
3078a06fd7f2SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCPreSolveChangeRHS_C",PCPreSolveChangeRHS_BDDC);CHKERRQ(ierr);
3079ab8c8b98SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCSetCoordinates_C",PCSetCoordinates_BDDC);CHKERRQ(ierr);
3080da1bb401SStefano Zampini   PetscFunctionReturn(0);
3081da1bb401SStefano Zampini }
308243371fb9SStefano Zampini 
308343371fb9SStefano Zampini /*@C
308443371fb9SStefano Zampini  PCBDDCInitializePackage - This function initializes everything in the PCBDDC package. It is called
30858a690491SBarry Smith     from PCInitializePackage().
308643371fb9SStefano Zampini 
308743371fb9SStefano Zampini  Level: developer
308843371fb9SStefano Zampini 
308943371fb9SStefano Zampini  .seealso: PetscInitialize()
309043371fb9SStefano Zampini @*/
309143371fb9SStefano Zampini PetscErrorCode PCBDDCInitializePackage(void)
309243371fb9SStefano Zampini {
309343371fb9SStefano Zampini   PetscErrorCode ierr;
309443371fb9SStefano Zampini   int            i;
309543371fb9SStefano Zampini 
309643371fb9SStefano Zampini   PetscFunctionBegin;
309743371fb9SStefano Zampini   if (PCBDDCPackageInitialized) PetscFunctionReturn(0);
309843371fb9SStefano Zampini   PCBDDCPackageInitialized = PETSC_TRUE;
309943371fb9SStefano Zampini   ierr = PetscRegisterFinalize(PCBDDCFinalizePackage);CHKERRQ(ierr);
310043371fb9SStefano Zampini 
310143371fb9SStefano Zampini   /* general events */
310243371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCTopo",PC_CLASSID,&PC_BDDC_Topology[0]);CHKERRQ(ierr);
310343371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCLKSP",PC_CLASSID,&PC_BDDC_LocalSolvers[0]);CHKERRQ(ierr);
310443371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCLWor",PC_CLASSID,&PC_BDDC_LocalWork[0]);CHKERRQ(ierr);
310543371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCCorr",PC_CLASSID,&PC_BDDC_CorrectionSetUp[0]);CHKERRQ(ierr);
31068ead10e4SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCASet",PC_CLASSID,&PC_BDDC_ApproxSetUp[0]);CHKERRQ(ierr);
31078ead10e4SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCAApp",PC_CLASSID,&PC_BDDC_ApproxApply[0]);CHKERRQ(ierr);
310843371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCCSet",PC_CLASSID,&PC_BDDC_CoarseSetUp[0]);CHKERRQ(ierr);
310943371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCCKSP",PC_CLASSID,&PC_BDDC_CoarseSolver[0]);CHKERRQ(ierr);
311043371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCAdap",PC_CLASSID,&PC_BDDC_AdaptiveSetUp[0]);CHKERRQ(ierr);
311143371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCScal",PC_CLASSID,&PC_BDDC_Scaling[0]);CHKERRQ(ierr);
311243371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCSchr",PC_CLASSID,&PC_BDDC_Schurs[0]);CHKERRQ(ierr);
311343371fb9SStefano Zampini   for (i=1;i<PETSC_PCBDDC_MAXLEVELS;i++) {
311443371fb9SStefano Zampini     char ename[32];
311543371fb9SStefano Zampini 
311643371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCTopo l%02d",i);CHKERRQ(ierr);
311743371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Topology[i]);CHKERRQ(ierr);
311843371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCLKSP l%02d",i);CHKERRQ(ierr);
311943371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_LocalSolvers[i]);CHKERRQ(ierr);
312043371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCLWor l%02d",i);CHKERRQ(ierr);
312143371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_LocalWork[i]);CHKERRQ(ierr);
312243371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCCorr l%02d",i);CHKERRQ(ierr);
312343371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_CorrectionSetUp[i]);CHKERRQ(ierr);
31248ead10e4SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCASet l%02d",i);CHKERRQ(ierr);
31258ead10e4SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_ApproxSetUp[i]);CHKERRQ(ierr);
31268ead10e4SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCAApp l%02d",i);CHKERRQ(ierr);
31278ead10e4SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_ApproxApply[i]);CHKERRQ(ierr);
312843371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCCSet l%02d",i);CHKERRQ(ierr);
312943371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_CoarseSetUp[i]);CHKERRQ(ierr);
313043371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCCKSP l%02d",i);CHKERRQ(ierr);
313143371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_CoarseSolver[i]);CHKERRQ(ierr);
313243371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCAdap l%02d",i);CHKERRQ(ierr);
313343371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_AdaptiveSetUp[i]);CHKERRQ(ierr);
313443371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCScal l%02d",i);CHKERRQ(ierr);
313543371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Scaling[i]);CHKERRQ(ierr);
313643371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCSchr l%02d",i);CHKERRQ(ierr);
313743371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Schurs[i]);CHKERRQ(ierr);
313843371fb9SStefano Zampini   }
313943371fb9SStefano Zampini   PetscFunctionReturn(0);
314043371fb9SStefano Zampini }
314143371fb9SStefano Zampini 
314243371fb9SStefano Zampini /*@C
314343371fb9SStefano Zampini  PCBDDCFinalizePackage - This function frees everything from the PCBDDC package. It is
314443371fb9SStefano Zampini     called from PetscFinalize() automatically.
314543371fb9SStefano Zampini 
314643371fb9SStefano Zampini  Level: developer
314743371fb9SStefano Zampini 
314843371fb9SStefano Zampini  .seealso: PetscFinalize()
314943371fb9SStefano Zampini @*/
315043371fb9SStefano Zampini PetscErrorCode PCBDDCFinalizePackage(void)
315143371fb9SStefano Zampini {
315243371fb9SStefano Zampini   PetscFunctionBegin;
315343371fb9SStefano Zampini   PCBDDCPackageInitialized = PETSC_FALSE;
315443371fb9SStefano Zampini   PetscFunctionReturn(0);
315543371fb9SStefano Zampini }
3156