xref: /petsc/src/ksp/pc/impls/bddc/bddc.c (revision 1633d1f06bc0664befc1cc92554a5c7a286bf6b0)
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 
260369aaf7SStefano Zampini /* temporarily declare it */
270369aaf7SStefano Zampini PetscErrorCode PCApply_BDDC(PC,Vec,Vec);
280369aaf7SStefano Zampini 
290c7d97c5SJed Brown #undef __FUNCT__
300c7d97c5SJed Brown #define __FUNCT__ "PCSetFromOptions_BDDC"
314416b707SBarry Smith PetscErrorCode PCSetFromOptions_BDDC(PetscOptionItems *PetscOptionsObject,PC pc)
320c7d97c5SJed Brown {
330c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
340c7d97c5SJed Brown   PetscErrorCode ierr;
350c7d97c5SJed Brown 
360c7d97c5SJed Brown   PetscFunctionBegin;
37e55864a3SBarry Smith   ierr = PetscOptionsHead(PetscOptionsObject,"BDDC options");CHKERRQ(ierr);
388eeda7d8SStefano Zampini   /* Verbose debugging */
39a13144ffSStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_check_level","Verbose output for PCBDDC (intended for debug)","none",pcbddc->dbg_flag,&pcbddc->dbg_flag,NULL);CHKERRQ(ierr);
40a13144ffSStefano Zampini   /* Approximate solvers */
41c7017625SStefano 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);
42c7017625SStefano 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);
43c7017625SStefano 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);
44c7017625SStefano 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);
456b78500eSPatrick Sanan   /* Primal space customization */
4608a5cf49SStefano 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);
47be12c134Sstefano_zampini   ierr = PetscOptionsInt("-pc_bddc_graph_maxcount","Maximum number of shared subdomains for a connected component","none",pcbddc->graphmaxcount,&pcbddc->graphmaxcount,NULL);CHKERRQ(ierr);
488eeda7d8SStefano 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);
498eeda7d8SStefano 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);
508eeda7d8SStefano 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);
5114f95afaSStefano 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);
526661aa1dSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_use_true_nnsp","Use near null space attached to the matrix without modifications","none",pcbddc->use_nnsp_true,&pcbddc->use_nnsp_true,NULL);CHKERRQ(ierr);
5314f95afaSStefano 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);
548eeda7d8SStefano Zampini   /* Change of basis */
55b9b85e73SStefano 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);
56b9b85e73SStefano 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);
57674ae819SStefano Zampini   if (!pcbddc->use_change_of_basis) {
58674ae819SStefano Zampini     pcbddc->use_change_on_faces = PETSC_FALSE;
59674ae819SStefano Zampini   }
608eeda7d8SStefano Zampini   /* Switch between M_2 (default) and M_3 preconditioners (as defined by C. Dohrmann in the ref. article) */
618eeda7d8SStefano 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);
6257de7509SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_coarse_eqs_per_proc","Number of equations per process for coarse problem redistribution (significant only at the coarsest level)","none",pcbddc->coarse_eqs_per_proc,&pcbddc->coarse_eqs_per_proc,NULL);CHKERRQ(ierr);
630298fd71SBarry Smith   ierr = PetscOptionsInt("-pc_bddc_coarsening_ratio","Set coarsening ratio used in multilevel coarsening","none",pcbddc->coarsening_ratio,&pcbddc->coarsening_ratio,NULL);CHKERRQ(ierr);
642b510759SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_levels","Set maximum number of levels for multilevel","none",pcbddc->max_levels,&pcbddc->max_levels,NULL);CHKERRQ(ierr);
65323d395dSStefano 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);
66674ae819SStefano 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);
67b96c3477SStefano 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);
68b96c3477SStefano 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);
69b96c3477SStefano 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);
70683d3df6SStefano 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);
71bf3a8328SStefano 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);
72bf3a8328SStefano 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);
734c6709b3SStefano Zampini   ierr = PetscOptionsReal("-pc_bddc_adaptive_threshold","Threshold to be used for adaptive selection of constraints","none",pcbddc->adaptive_threshold,&pcbddc->adaptive_threshold,NULL);CHKERRQ(ierr);
7408122e43SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_adaptive_nmin","Minimum number of constraints per connected components","none",pcbddc->adaptive_nmin,&pcbddc->adaptive_nmin,NULL);CHKERRQ(ierr);
7508122e43SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_adaptive_nmax","Maximum number of constraints per connected components","none",pcbddc->adaptive_nmax,&pcbddc->adaptive_nmax,NULL);CHKERRQ(ierr);
763301b35fSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_symmetric","Symmetric computation of primal basis functions","none",pcbddc->symmetric_primal,&pcbddc->symmetric_primal,NULL);CHKERRQ(ierr);
77b0c7d250SStefano 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);
78b3afcdbeSStefano 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);
79e9627c49SStefano 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);
8027b6a85dSStefano 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);
81a198735bSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_nonetflux","Automatic computation of no-net-flux quadrature weights","none",pcbddc->compute_nonetflux,&pcbddc->compute_nonetflux,NULL);CHKERRQ(ierr);
824f1b2e48SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_detect_disconnected","Detects disconnected subdomains","none",pcbddc->detect_disconnected,&pcbddc->detect_disconnected,NULL);CHKERRQ(ierr);
8370c64980SStefano 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);
840c7d97c5SJed Brown   ierr = PetscOptionsTail();CHKERRQ(ierr);
850c7d97c5SJed Brown   PetscFunctionReturn(0);
860c7d97c5SJed Brown }
876b78500eSPatrick Sanan 
886b78500eSPatrick Sanan #undef __FUNCT__
896b78500eSPatrick Sanan #define __FUNCT__ "PCView_BDDC"
906b78500eSPatrick Sanan static PetscErrorCode PCView_BDDC(PC pc,PetscViewer viewer)
916b78500eSPatrick Sanan {
926b78500eSPatrick Sanan   PC_BDDC              *pcbddc = (PC_BDDC*)pc->data;
93e9627c49SStefano Zampini   PC_IS                *pcis = (PC_IS*)pc->data;
946b78500eSPatrick Sanan   PetscErrorCode       ierr;
956b78500eSPatrick Sanan   PetscBool            isascii,isstring;
96e9627c49SStefano Zampini   PetscSubcomm         subcomm;
97e9627c49SStefano Zampini   PetscViewer          subviewer;
986b78500eSPatrick Sanan 
996b78500eSPatrick Sanan   PetscFunctionBegin;
1006b78500eSPatrick Sanan   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
1016b78500eSPatrick Sanan   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring);CHKERRQ(ierr);
1026b78500eSPatrick Sanan   /* Nothing printed for the String viewer */
1036b78500eSPatrick Sanan   /* ASCII viewer */
1046b78500eSPatrick Sanan   if (isascii) {
1054b2aedd3SStefano Zampini     PetscMPIInt   color,rank,size;
106fbad9177SStefano Zampini     PetscInt64    loc[7],gsum[6],gmax[6],gmin[6],totbenign;
107e9627c49SStefano Zampini     PetscScalar   interface_size;
108e9627c49SStefano Zampini     PetscReal     ratio1=0.,ratio2=0.;
109e9627c49SStefano Zampini     Vec           counter;
1106b78500eSPatrick Sanan 
111e9627c49SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Use verbose output: %d\n",pcbddc->dbg_flag);CHKERRQ(ierr);
112e9627c49SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Use user-defined CSR: %d\n",!!pcbddc->mat_graph->nvtxs_csr);CHKERRQ(ierr);
1136b78500eSPatrick Sanan     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Use local mat graph: %d\n",pcbddc->use_local_adj);CHKERRQ(ierr);
114e9627c49SStefano Zampini     if (pcbddc->mat_graph->twodim) {
115e9627c49SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Connectivity graph topological dimension: 2\n");CHKERRQ(ierr);
116e9627c49SStefano Zampini     } else {
117e9627c49SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Connectivity graph topological dimension: 3\n");CHKERRQ(ierr);
118e9627c49SStefano Zampini     }
119a70d66d9SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Graph max count: %d\n",pcbddc->graphmaxcount);CHKERRQ(ierr);
120a198735bSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Use vertices: %d (vertex size %d)\n",pcbddc->use_vertices,pcbddc->vertex_size);CHKERRQ(ierr);
1216b78500eSPatrick Sanan     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Use edges: %d\n",pcbddc->use_edges);CHKERRQ(ierr);
1226b78500eSPatrick Sanan     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Use faces: %d\n",pcbddc->use_faces);CHKERRQ(ierr);
1236b78500eSPatrick Sanan     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Use true near null space: %d\n",pcbddc->use_nnsp_true);CHKERRQ(ierr);
1246b78500eSPatrick Sanan     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Use QR for single constraints on cc: %d\n",pcbddc->use_qr_single);CHKERRQ(ierr);
1256b78500eSPatrick Sanan     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Use change of basis on local edge nodes: %d\n",pcbddc->use_change_of_basis);CHKERRQ(ierr);
1266b78500eSPatrick Sanan     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Use change of basis on local face nodes: %d\n",pcbddc->use_change_on_faces);CHKERRQ(ierr);
12727b6a85dSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: User defined change of basis matrix: %d\n",!!pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
12827b6a85dSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Has change of basis matrix: %d\n",!!pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
12927b6a85dSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Eliminate dirichlet boundary dofs: %d\n",pcbddc->eliminate_dirdofs);CHKERRQ(ierr);
1306b78500eSPatrick Sanan     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Switch on static condensation ops around the interface preconditioner: %d\n",pcbddc->switch_static);CHKERRQ(ierr);
13127b6a85dSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Use exact dirichlet trick: %d\n",pcbddc->use_exact_dirichlet_trick);CHKERRQ(ierr);
1326b78500eSPatrick Sanan     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Multilevel max levels: %d\n",pcbddc->max_levels);CHKERRQ(ierr);
133e9627c49SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Multilevel coarsening ratio: %d\n",pcbddc->coarsening_ratio);CHKERRQ(ierr);
1346b78500eSPatrick Sanan     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Use estimated eigs for coarse problem: %d\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
1356b78500eSPatrick Sanan     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Use deluxe scaling: %d\n",pcbddc->use_deluxe_scaling);CHKERRQ(ierr);
136e9627c49SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Use deluxe zerorows: %d\n",pcbddc->deluxe_zerorows);CHKERRQ(ierr);
1376b78500eSPatrick Sanan     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Rebuild interface graph for Schur principal minors: %d\n",pcbddc->sub_schurs_rebuild);CHKERRQ(ierr);
1386b78500eSPatrick Sanan     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Number of dofs' layers for the computation of principal minors: %d\n",pcbddc->sub_schurs_layers);CHKERRQ(ierr);
1396b78500eSPatrick Sanan     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Use user CSR graph to compute successive layers: %d\n",pcbddc->sub_schurs_use_useradj);CHKERRQ(ierr);
140e9627c49SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Adaptive constraint selection threshold (active %d, userdefined %d): %g\n",pcbddc->adaptive_threshold,pcbddc->adaptive_selection,pcbddc->adaptive_userdefined);CHKERRQ(ierr);
1416b78500eSPatrick Sanan     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Min constraints / connected component: %d\n",pcbddc->adaptive_nmin);CHKERRQ(ierr);
1426b78500eSPatrick Sanan     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Max constraints / connected component: %d\n",pcbddc->adaptive_nmax);CHKERRQ(ierr);
143e9627c49SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Invert exact Schur complement for adaptive selection: %d\n",pcbddc->sub_schurs_exact_schur);CHKERRQ(ierr);
1446b78500eSPatrick Sanan     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Symmetric computation of primal basis functions: %d\n",pcbddc->symmetric_primal);CHKERRQ(ierr);
1456b78500eSPatrick Sanan     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Num. Procs. to map coarse adjacency list: %d\n",pcbddc->coarse_adj_red);CHKERRQ(ierr);
146e9627c49SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Coarse eqs per proc (significant at the coarsest level): %d\n",pcbddc->coarse_eqs_per_proc);CHKERRQ(ierr);
147e9627c49SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Detect disconnected: %d\n",pcbddc->detect_disconnected);CHKERRQ(ierr);
148fc17d649SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Benign subspace trick: %d (change explicit %d)\n",pcbddc->benign_saddle_point,pcbddc->benign_change_explicit);CHKERRQ(ierr);
149a198735bSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Benign subspace trick is active: %d\n",pcbddc->benign_have_null);CHKERRQ(ierr);
150a198735bSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Algebraic computation of no-net-flux %d\n",pcbddc->compute_nonetflux);CHKERRQ(ierr);
1516b78500eSPatrick Sanan 
152fbad9177SStefano Zampini     /* compute interface size */
153e9627c49SStefano Zampini     ierr = VecSet(pcis->vec1_B,1.0);CHKERRQ(ierr);
154e9627c49SStefano Zampini     ierr = MatCreateVecs(pc->pmat,&counter,0);CHKERRQ(ierr);
155e9627c49SStefano Zampini     ierr = VecSet(counter,0.0);CHKERRQ(ierr);
156e9627c49SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,counter,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
157e9627c49SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,counter,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
158e9627c49SStefano Zampini     ierr = VecSum(counter,&interface_size);CHKERRQ(ierr);
159e9627c49SStefano Zampini     ierr = VecDestroy(&counter);CHKERRQ(ierr);
160fbad9177SStefano Zampini 
161fbad9177SStefano Zampini     /* compute some statistics on the domain decomposition */
162e9627c49SStefano Zampini     gsum[0] = 1;
163fbad9177SStefano Zampini     gsum[1] = gsum[2] = gsum[3] = gsum[4] = gsum[5] = 0;
164e9627c49SStefano Zampini     loc[0]  = !!pcis->n;
165e9627c49SStefano Zampini     loc[1]  = pcis->n - pcis->n_B;
166e9627c49SStefano Zampini     loc[2]  = pcis->n_B;
167e9627c49SStefano Zampini     loc[3]  = pcbddc->local_primal_size;
168345ecf6cSStefano Zampini     loc[4]  = pcis->n;
169fbad9177SStefano Zampini     loc[5]  = pcbddc->n_local_subs > 0 ? pcbddc->n_local_subs : (pcis->n ? 1 : 0);
170fbad9177SStefano Zampini     loc[6]  = pcbddc->benign_n;
171fbad9177SStefano Zampini     ierr = MPI_Reduce(loc,gsum,6,MPIU_INT64,MPI_SUM,0,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
172fbad9177SStefano Zampini     if (!loc[0]) loc[1] = loc[2] = loc[3] = loc[4] = loc[5] = -1;
173fbad9177SStefano Zampini     ierr = MPI_Reduce(loc,gmax,6,MPIU_INT64,MPI_MAX,0,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
174fbad9177SStefano Zampini     if (!loc[0]) loc[1] = loc[2] = loc[3] = loc[4] = loc[5] = PETSC_MAX_INT;
175fbad9177SStefano Zampini     ierr = MPI_Reduce(loc,gmin,6,MPIU_INT64,MPI_MIN,0,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
176fbad9177SStefano Zampini     ierr = MPI_Reduce(&loc[6],&totbenign,1,MPIU_INT64,MPI_SUM,0,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
177e9627c49SStefano Zampini     if (pcbddc->coarse_size) {
178e9627c49SStefano Zampini       ratio1 = pc->pmat->rmap->N/(1.*pcbddc->coarse_size);
179e9627c49SStefano Zampini       ratio2 = PetscRealPart(interface_size)/pcbddc->coarse_size;
180e9627c49SStefano Zampini     }
181e9627c49SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: ********************************** STATISTICS AT LEVEL %d **********************************\n",pcbddc->current_level);CHKERRQ(ierr);
182e9627c49SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Global dofs sizes: all %d interface %d coarse %d\n",pc->pmat->rmap->N,(PetscInt)PetscRealPart(interface_size),pcbddc->coarse_size);CHKERRQ(ierr);
183e9627c49SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Coarsening ratios: all/coarse %d interface/coarse %d\n",(PetscInt)ratio1,(PetscInt)ratio2);CHKERRQ(ierr);
184e9627c49SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Active processes : %d\n",(PetscInt)gsum[0]);CHKERRQ(ierr);
185fbad9177SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Total subdomains : %d\n",(PetscInt)gsum[5]);CHKERRQ(ierr);
186345ecf6cSStefano Zampini     if (pcbddc->benign_have_null) {
187345ecf6cSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Benign subs      : %d\n",(PetscInt)totbenign);CHKERRQ(ierr);
188345ecf6cSStefano Zampini     }
189e9627c49SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Dofs type        :\tMIN\tMAX\tMEAN\n",(PetscInt)gmin[1],(PetscInt)gmax[1],(PetscInt)(gsum[1]/gsum[0]));CHKERRQ(ierr);
190e9627c49SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Interior  dofs   :\t%d\t%d\t%d\n",(PetscInt)gmin[1],(PetscInt)gmax[1],(PetscInt)(gsum[1]/gsum[0]));CHKERRQ(ierr);
191e9627c49SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Interface dofs   :\t%d\t%d\t%d\n",(PetscInt)gmin[2],(PetscInt)gmax[2],(PetscInt)(gsum[2]/gsum[0]));CHKERRQ(ierr);
192e9627c49SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Primal    dofs   :\t%d\t%d\t%d\n",(PetscInt)gmin[3],(PetscInt)gmax[3],(PetscInt)(gsum[3]/gsum[0]));CHKERRQ(ierr);
193345ecf6cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Local     dofs   :\t%d\t%d\t%d\n",(PetscInt)gmin[4],(PetscInt)gmax[4],(PetscInt)(gsum[4]/gsum[0]));CHKERRQ(ierr);
194fbad9177SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Local     subs   :\t%d\t%d\n",(PetscInt)gmin[5],(PetscInt)gmax[5]);CHKERRQ(ierr);
19527b6a85dSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: ********************************** COARSE PROBLEM DETAILS *********************************\n",pcbddc->current_level);CHKERRQ(ierr);
19627b6a85dSStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
197e9627c49SStefano Zampini 
198fbad9177SStefano Zampini     /* the coarse problem can be handled by a different communicator */
199e9627c49SStefano Zampini     if (pcbddc->coarse_ksp) color = 1;
200e9627c49SStefano Zampini     else color = 0;
201e9627c49SStefano Zampini     ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
2024b2aedd3SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
203e9627c49SStefano Zampini     ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)pc),&subcomm);CHKERRQ(ierr);
2044b2aedd3SStefano Zampini     ierr = PetscSubcommSetNumber(subcomm,PetscMin(size,2));CHKERRQ(ierr);
205e9627c49SStefano Zampini     ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
206e9627c49SStefano Zampini     ierr = PetscViewerGetSubViewer(viewer,PetscSubcommChild(subcomm),&subviewer);CHKERRQ(ierr);
207e9627c49SStefano Zampini     if (color == 1) {
208e9627c49SStefano Zampini       ierr = KSPView(pcbddc->coarse_ksp,subviewer);CHKERRQ(ierr);
209e9627c49SStefano Zampini       ierr = PetscViewerFlush(subviewer);CHKERRQ(ierr);
210e9627c49SStefano Zampini     }
211e9627c49SStefano Zampini     ierr = PetscViewerRestoreSubViewer(viewer,PetscSubcommChild(subcomm),&subviewer);CHKERRQ(ierr);
212e9627c49SStefano Zampini     ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
213e9627c49SStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
214e9627c49SStefano Zampini   }
2156b78500eSPatrick Sanan   PetscFunctionReturn(0);
2166b78500eSPatrick Sanan }
217a13144ffSStefano Zampini 
218a13144ffSStefano Zampini #undef __FUNCT__
219a13144ffSStefano Zampini #define __FUNCT__ "PCBDDCSetDiscreteGradient_BDDC"
2201e0482f5SStefano Zampini static PetscErrorCode PCBDDCSetDiscreteGradient_BDDC(PC pc, Mat G, PetscInt order, PetscInt field, PetscBool global, PetscBool conforming)
221a13144ffSStefano Zampini {
222a13144ffSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
223a13144ffSStefano Zampini   PetscErrorCode ierr;
224a13144ffSStefano Zampini 
225a13144ffSStefano Zampini   PetscFunctionBegin;
226a13144ffSStefano Zampini   ierr = PetscObjectReference((PetscObject)G);CHKERRQ(ierr);
227a13144ffSStefano Zampini   ierr = MatDestroy(&pcbddc->discretegradient);CHKERRQ(ierr);
228a13144ffSStefano Zampini   pcbddc->discretegradient = G;
229a13144ffSStefano Zampini   pcbddc->nedorder         = order > 0 ? order : -order;
230495a2a07SStefano Zampini   pcbddc->nedfield         = field;
2311e0482f5SStefano Zampini   pcbddc->nedglobal        = global;
2321e0482f5SStefano Zampini   pcbddc->conforming       = conforming;
233a13144ffSStefano Zampini   PetscFunctionReturn(0);
234a13144ffSStefano Zampini }
235a13144ffSStefano Zampini 
236a13144ffSStefano Zampini #undef __FUNCT__
237a13144ffSStefano Zampini #define __FUNCT__ "PCBDDCSetDiscreteGradient"
238a13144ffSStefano Zampini /*@
239a13144ffSStefano Zampini  PCBDDCSetDiscreteGradient - Sets the discrete gradient
240a13144ffSStefano Zampini 
241a13144ffSStefano Zampini    Collective on PC
242a13144ffSStefano Zampini 
243a13144ffSStefano Zampini    Input Parameters:
244a13144ffSStefano Zampini +  pc         - the preconditioning context
245a13144ffSStefano Zampini .  G          - the discrete gradient matrix (should be in AIJ format)
246a13144ffSStefano Zampini .  order      - the order of the Nedelec space (1 for the lowest order)
247495a2a07SStefano Zampini .  field      - the field id of the Nedelec dofs (not used if the fields have not been specified)
2481e0482f5SStefano Zampini .  global     - the type of global ordering for the rows of G
249a13144ffSStefano Zampini -  conforming - whether the mesh is conforming or not
250a13144ffSStefano Zampini 
251a13144ffSStefano Zampini    Level: advanced
252a13144ffSStefano Zampini 
253a13144ffSStefano Zampini    Notes: The discrete gradient matrix G is used to analyze the subdomain edges, and it should not contain any zero entry.
254495a2a07SStefano Zampini           For variable order spaces, the order should be set to zero.
2551e0482f5SStefano Zampini           If global is true, the rows of G should be given in global ordering for the whole dofs;
2561e0482f5SStefano Zampini           if false, the ordering should be global for the Nedelec field.
2571e0482f5SStefano 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
2581e0482f5SStefano Zampini           and geid the one for the Nedelec field.
259a13144ffSStefano Zampini 
260495a2a07SStefano Zampini .seealso: PCBDDC,PCBDDCSetDofsSplitting(),PCBDDCSetDofsSplittingLocal()
261a13144ffSStefano Zampini @*/
2621e0482f5SStefano Zampini PetscErrorCode PCBDDCSetDiscreteGradient(PC pc, Mat G, PetscInt order, PetscInt field, PetscBool global, PetscBool conforming)
263a13144ffSStefano Zampini {
264a13144ffSStefano Zampini   PetscErrorCode ierr;
265a13144ffSStefano Zampini 
266a13144ffSStefano Zampini   PetscFunctionBegin;
267a13144ffSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
268a13144ffSStefano Zampini   PetscValidHeaderSpecific(G,MAT_CLASSID,2);
269a13144ffSStefano Zampini   PetscValidLogicalCollectiveInt(pc,order,3);
2701e0482f5SStefano Zampini   PetscValidLogicalCollectiveInt(pc,field,4);
2711e0482f5SStefano Zampini   PetscValidLogicalCollectiveBool(pc,global,5);
2721e0482f5SStefano Zampini   PetscValidLogicalCollectiveBool(pc,conforming,6);
2731e0482f5SStefano Zampini   PetscCheckSameComm(pc,1,G,2);
2741e0482f5SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDiscreteGradient_C",(PC,Mat,PetscInt,PetscInt,PetscBool,PetscBool),(pc,G,order,field,global,conforming));CHKERRQ(ierr);
275a13144ffSStefano Zampini   PetscFunctionReturn(0);
276a13144ffSStefano Zampini }
277a13144ffSStefano Zampini 
278a198735bSStefano Zampini #undef __FUNCT__
279a198735bSStefano Zampini #define __FUNCT__ "PCBDDCSetDivergenceMat_BDDC"
2808ae0ca82SStefano Zampini static PetscErrorCode PCBDDCSetDivergenceMat_BDDC(PC pc, Mat divudotp, PetscBool trans, IS vl2l)
281a198735bSStefano Zampini {
282a198735bSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
283a198735bSStefano Zampini   PetscErrorCode ierr;
2846b78500eSPatrick Sanan 
285a198735bSStefano Zampini   PetscFunctionBegin;
286a198735bSStefano Zampini   ierr = PetscObjectReference((PetscObject)divudotp);CHKERRQ(ierr);
287a198735bSStefano Zampini   ierr = MatDestroy(&pcbddc->divudotp);CHKERRQ(ierr);
288a198735bSStefano Zampini   pcbddc->divudotp = divudotp;
2898ae0ca82SStefano Zampini   pcbddc->divudotp_trans = trans;
290a198735bSStefano Zampini   pcbddc->compute_nonetflux = PETSC_TRUE;
291a198735bSStefano Zampini   if (vl2l) {
292a198735bSStefano Zampini     ierr = PetscObjectReference((PetscObject)vl2l);CHKERRQ(ierr);
293fa23a32eSStefano Zampini     ierr = ISDestroy(&pcbddc->divudotp_vl2l);CHKERRQ(ierr);
294a198735bSStefano Zampini     pcbddc->divudotp_vl2l = vl2l;
295a198735bSStefano Zampini   }
296a198735bSStefano Zampini   PetscFunctionReturn(0);
297a198735bSStefano Zampini }
2983d996552SStefano Zampini 
299a198735bSStefano Zampini #undef __FUNCT__
300a198735bSStefano Zampini #define __FUNCT__ "PCBDDCSetDivergenceMat"
301a198735bSStefano Zampini /*@
302a198735bSStefano Zampini  PCBDDCSetDivergenceMat - Sets the linear operator representing \int_\Omega \div {\bf u} \cdot p dx
303a198735bSStefano Zampini 
304a198735bSStefano Zampini    Collective on PC
305a198735bSStefano Zampini 
306a198735bSStefano Zampini    Input Parameters:
307a198735bSStefano Zampini +  pc - the preconditioning context
308a198735bSStefano Zampini .  divudotp - the matrix (must be of type MATIS)
3098ae0ca82SStefano Zampini .  trans - if trans if false (resp. true), then pressures are in the test (trial) space and velocities are in the trial (test) space.
310bb05f991SStefano Zampini -  vl2l - optional IS describing the local (wrt the local mat in divudotp) to local (wrt the local mat in pc->pmat) map for the velocities
311a198735bSStefano Zampini 
312a198735bSStefano Zampini    Level: advanced
313a198735bSStefano Zampini 
3148ae0ca82SStefano Zampini    Notes: This auxiliary matrix is used to compute quadrature weights representing the net-flux across subdomain boundaries
315a198735bSStefano Zampini 
316a198735bSStefano Zampini .seealso: PCBDDC
317a198735bSStefano Zampini @*/
3188ae0ca82SStefano Zampini PetscErrorCode PCBDDCSetDivergenceMat(PC pc, Mat divudotp, PetscBool trans, IS vl2l)
319a198735bSStefano Zampini {
320a198735bSStefano Zampini   PetscBool      ismatis;
321a198735bSStefano Zampini   PetscErrorCode ierr;
322a198735bSStefano Zampini 
323a198735bSStefano Zampini   PetscFunctionBegin;
324a198735bSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
325a198735bSStefano Zampini   PetscValidHeaderSpecific(divudotp,MAT_CLASSID,2);
326a198735bSStefano Zampini   PetscCheckSameComm(pc,1,divudotp,2);
3278ae0ca82SStefano Zampini   PetscValidLogicalCollectiveBool(pc,trans,3);
3288ae0ca82SStefano Zampini   if (vl2l) PetscValidHeaderSpecific(divudotp,IS_CLASSID,4);
329a198735bSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)divudotp,MATIS,&ismatis);CHKERRQ(ierr);
330a198735bSStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"Divergence matrix needs to be of type MATIS");
3318ae0ca82SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDivergenceMat_C",(PC,Mat,PetscBool,IS),(pc,divudotp,trans,vl2l));CHKERRQ(ierr);
332a198735bSStefano Zampini   PetscFunctionReturn(0);
333a198735bSStefano Zampini }
3342d505d7fSStefano Zampini 
335674ae819SStefano Zampini #undef __FUNCT__
336906d46d4SStefano Zampini #define __FUNCT__ "PCBDDCSetChangeOfBasisMat_BDDC"
3371dd7afcfSStefano Zampini static PetscErrorCode PCBDDCSetChangeOfBasisMat_BDDC(PC pc, Mat change, PetscBool interior)
338b9b85e73SStefano Zampini {
339b9b85e73SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
340b9b85e73SStefano Zampini   PetscErrorCode ierr;
341b9b85e73SStefano Zampini 
342b9b85e73SStefano Zampini   PetscFunctionBegin;
343b9b85e73SStefano Zampini   ierr = PetscObjectReference((PetscObject)change);CHKERRQ(ierr);
34456282151SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
345b9b85e73SStefano Zampini   pcbddc->user_ChangeOfBasisMatrix = change;
3461dd7afcfSStefano Zampini   pcbddc->change_interior = interior;
347b9b85e73SStefano Zampini   PetscFunctionReturn(0);
348b9b85e73SStefano Zampini }
349b9b85e73SStefano Zampini #undef __FUNCT__
350906d46d4SStefano Zampini #define __FUNCT__ "PCBDDCSetChangeOfBasisMat"
351b9b85e73SStefano Zampini /*@
352906d46d4SStefano Zampini  PCBDDCSetChangeOfBasisMat - Set user defined change of basis for dofs
353b9b85e73SStefano Zampini 
354b9b85e73SStefano Zampini    Collective on PC
355b9b85e73SStefano Zampini 
356b9b85e73SStefano Zampini    Input Parameters:
357b9b85e73SStefano Zampini +  pc - the preconditioning context
3581dd7afcfSStefano Zampini .  change - the change of basis matrix
3591dd7afcfSStefano Zampini -  interior - whether or not the change of basis modifies interior dofs
360b9b85e73SStefano Zampini 
361b9b85e73SStefano Zampini    Level: intermediate
362b9b85e73SStefano Zampini 
363b9b85e73SStefano Zampini    Notes:
364b9b85e73SStefano Zampini 
365b9b85e73SStefano Zampini .seealso: PCBDDC
366b9b85e73SStefano Zampini @*/
3671dd7afcfSStefano Zampini PetscErrorCode PCBDDCSetChangeOfBasisMat(PC pc, Mat change, PetscBool interior)
368b9b85e73SStefano Zampini {
369b9b85e73SStefano Zampini   PetscErrorCode ierr;
370b9b85e73SStefano Zampini 
371b9b85e73SStefano Zampini   PetscFunctionBegin;
372b9b85e73SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
373b9b85e73SStefano Zampini   PetscValidHeaderSpecific(change,MAT_CLASSID,2);
374906d46d4SStefano Zampini   PetscCheckSameComm(pc,1,change,2);
375906d46d4SStefano Zampini   if (pc->mat) {
376906d46d4SStefano Zampini     PetscInt rows_c,cols_c,rows,cols;
377906d46d4SStefano Zampini     ierr = MatGetSize(pc->mat,&rows,&cols);CHKERRQ(ierr);
378906d46d4SStefano Zampini     ierr = MatGetSize(change,&rows_c,&cols_c);CHKERRQ(ierr);
3796c4ed002SBarry Smith     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);
3806c4ed002SBarry Smith     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);
381906d46d4SStefano Zampini     ierr = MatGetLocalSize(pc->mat,&rows,&cols);CHKERRQ(ierr);
382906d46d4SStefano Zampini     ierr = MatGetLocalSize(change,&rows_c,&cols_c);CHKERRQ(ierr);
3836c4ed002SBarry Smith     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);
3846c4ed002SBarry Smith     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);
385906d46d4SStefano Zampini   }
3861dd7afcfSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetChangeOfBasisMat_C",(PC,Mat,PetscBool),(pc,change,interior));CHKERRQ(ierr);
387b9b85e73SStefano Zampini   PetscFunctionReturn(0);
388b9b85e73SStefano Zampini }
3892d505d7fSStefano Zampini 
390b9b85e73SStefano Zampini #undef __FUNCT__
39130368db7SStefano Zampini #define __FUNCT__ "PCBDDCSetPrimalVerticesIS_BDDC"
39230368db7SStefano Zampini static PetscErrorCode PCBDDCSetPrimalVerticesIS_BDDC(PC pc, IS PrimalVertices)
39330368db7SStefano Zampini {
39430368db7SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
39556282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
39630368db7SStefano Zampini   PetscErrorCode ierr;
39730368db7SStefano Zampini 
39830368db7SStefano Zampini   PetscFunctionBegin;
39956282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)PrimalVertices);CHKERRQ(ierr);
40056282151SStefano Zampini   if (pcbddc->user_primal_vertices) {
40156282151SStefano Zampini     ierr = ISEqual(PrimalVertices,pcbddc->user_primal_vertices,&isequal);CHKERRQ(ierr);
40256282151SStefano Zampini   }
40330368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
40430368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
40530368db7SStefano Zampini   pcbddc->user_primal_vertices = PrimalVertices;
40656282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
40730368db7SStefano Zampini   PetscFunctionReturn(0);
40830368db7SStefano Zampini }
40930368db7SStefano Zampini #undef __FUNCT__
41030368db7SStefano Zampini #define __FUNCT__ "PCBDDCSetPrimalVerticesIS"
41130368db7SStefano Zampini /*@
41230368db7SStefano Zampini  PCBDDCSetPrimalVerticesIS - Set additional user defined primal vertices in PCBDDC
41330368db7SStefano Zampini 
41430368db7SStefano Zampini    Collective
41530368db7SStefano Zampini 
41630368db7SStefano Zampini    Input Parameters:
41730368db7SStefano Zampini +  pc - the preconditioning context
41830368db7SStefano Zampini -  PrimalVertices - index set of primal vertices in global numbering (can be empty)
41930368db7SStefano Zampini 
42030368db7SStefano Zampini    Level: intermediate
42130368db7SStefano Zampini 
42230368db7SStefano Zampini    Notes:
42330368db7SStefano Zampini      Any process can list any global node
42430368db7SStefano Zampini 
42530368db7SStefano Zampini .seealso: PCBDDC
42630368db7SStefano Zampini @*/
42730368db7SStefano Zampini PetscErrorCode PCBDDCSetPrimalVerticesIS(PC pc, IS PrimalVertices)
42830368db7SStefano Zampini {
42930368db7SStefano Zampini   PetscErrorCode ierr;
43030368db7SStefano Zampini 
43130368db7SStefano Zampini   PetscFunctionBegin;
43230368db7SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
43330368db7SStefano Zampini   PetscValidHeaderSpecific(PrimalVertices,IS_CLASSID,2);
43430368db7SStefano Zampini   PetscCheckSameComm(pc,1,PrimalVertices,2);
43530368db7SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetPrimalVerticesIS_C",(PC,IS),(pc,PrimalVertices));CHKERRQ(ierr);
43630368db7SStefano Zampini   PetscFunctionReturn(0);
43730368db7SStefano Zampini }
4382d505d7fSStefano Zampini 
43930368db7SStefano Zampini #undef __FUNCT__
440674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSetPrimalVerticesLocalIS_BDDC"
441674ae819SStefano Zampini static PetscErrorCode PCBDDCSetPrimalVerticesLocalIS_BDDC(PC pc, IS PrimalVertices)
442674ae819SStefano Zampini {
443674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
44456282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
445674ae819SStefano Zampini   PetscErrorCode ierr;
4461e6b0712SBarry Smith 
447674ae819SStefano Zampini   PetscFunctionBegin;
44856282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)PrimalVertices);CHKERRQ(ierr);
44956282151SStefano Zampini   if (pcbddc->user_primal_vertices_local) {
45056282151SStefano Zampini     ierr = ISEqual(PrimalVertices,pcbddc->user_primal_vertices_local,&isequal);CHKERRQ(ierr);
45156282151SStefano Zampini   }
452674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
45330368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
45430368db7SStefano Zampini   pcbddc->user_primal_vertices_local = PrimalVertices;
45556282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
456674ae819SStefano Zampini   PetscFunctionReturn(0);
457674ae819SStefano Zampini }
458674ae819SStefano Zampini #undef __FUNCT__
459674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSetPrimalVerticesLocalIS"
460674ae819SStefano Zampini /*@
46128509bceSStefano Zampini  PCBDDCSetPrimalVerticesLocalIS - Set additional user defined primal vertices in PCBDDC
462674ae819SStefano Zampini 
46317eb1463SStefano Zampini    Collective
464674ae819SStefano Zampini 
465674ae819SStefano Zampini    Input Parameters:
466674ae819SStefano Zampini +  pc - the preconditioning context
46717eb1463SStefano Zampini -  PrimalVertices - index set of primal vertices in local numbering (can be empty)
468674ae819SStefano Zampini 
469674ae819SStefano Zampini    Level: intermediate
470674ae819SStefano Zampini 
471674ae819SStefano Zampini    Notes:
472674ae819SStefano Zampini 
473674ae819SStefano Zampini .seealso: PCBDDC
474674ae819SStefano Zampini @*/
475674ae819SStefano Zampini PetscErrorCode PCBDDCSetPrimalVerticesLocalIS(PC pc, IS PrimalVertices)
476674ae819SStefano Zampini {
477674ae819SStefano Zampini   PetscErrorCode ierr;
478674ae819SStefano Zampini 
479674ae819SStefano Zampini   PetscFunctionBegin;
480674ae819SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
481674ae819SStefano Zampini   PetscValidHeaderSpecific(PrimalVertices,IS_CLASSID,2);
48217eb1463SStefano Zampini   PetscCheckSameComm(pc,1,PrimalVertices,2);
483674ae819SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetPrimalVerticesLocalIS_C",(PC,IS),(pc,PrimalVertices));CHKERRQ(ierr);
484674ae819SStefano Zampini   PetscFunctionReturn(0);
485674ae819SStefano Zampini }
4862d505d7fSStefano Zampini 
4870c7d97c5SJed Brown #undef __FUNCT__
4884fad6a16SStefano Zampini #define __FUNCT__ "PCBDDCSetCoarseningRatio_BDDC"
4894fad6a16SStefano Zampini static PetscErrorCode PCBDDCSetCoarseningRatio_BDDC(PC pc,PetscInt k)
4904fad6a16SStefano Zampini {
4914fad6a16SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
4924fad6a16SStefano Zampini 
4934fad6a16SStefano Zampini   PetscFunctionBegin;
4944fad6a16SStefano Zampini   pcbddc->coarsening_ratio = k;
4954fad6a16SStefano Zampini   PetscFunctionReturn(0);
4964fad6a16SStefano Zampini }
4971e6b0712SBarry Smith 
4984fad6a16SStefano Zampini #undef __FUNCT__
4994fad6a16SStefano Zampini #define __FUNCT__ "PCBDDCSetCoarseningRatio"
5004fad6a16SStefano Zampini /*@
50128509bceSStefano Zampini  PCBDDCSetCoarseningRatio - Set coarsening ratio used in multilevel
5024fad6a16SStefano Zampini 
5034fad6a16SStefano Zampini    Logically collective on PC
5044fad6a16SStefano Zampini 
5054fad6a16SStefano Zampini    Input Parameters:
5064fad6a16SStefano Zampini +  pc - the preconditioning context
50728509bceSStefano Zampini -  k - coarsening ratio (H/h at the coarser level)
5084fad6a16SStefano Zampini 
5090f202f7eSStefano Zampini    Options Database Keys:
5100f202f7eSStefano Zampini .    -pc_bddc_coarsening_ratio
5114fad6a16SStefano Zampini 
5124fad6a16SStefano Zampini    Level: intermediate
5134fad6a16SStefano Zampini 
5144fad6a16SStefano Zampini    Notes:
5150f202f7eSStefano Zampini      Approximatively k subdomains at the finer level will be aggregated into a single subdomain at the coarser level
5164fad6a16SStefano Zampini 
5170f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetLevels()
5184fad6a16SStefano Zampini @*/
5194fad6a16SStefano Zampini PetscErrorCode PCBDDCSetCoarseningRatio(PC pc,PetscInt k)
5204fad6a16SStefano Zampini {
5214fad6a16SStefano Zampini   PetscErrorCode ierr;
5224fad6a16SStefano Zampini 
5234fad6a16SStefano Zampini   PetscFunctionBegin;
5244fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
5252b510759SStefano Zampini   PetscValidLogicalCollectiveInt(pc,k,2);
5264fad6a16SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetCoarseningRatio_C",(PC,PetscInt),(pc,k));CHKERRQ(ierr);
5274fad6a16SStefano Zampini   PetscFunctionReturn(0);
5284fad6a16SStefano Zampini }
5292b510759SStefano Zampini 
530b8ffe317SStefano Zampini /* The following functions (PCBDDCSetUseExactDirichlet PCBDDCSetLevel) are not public */
5312b510759SStefano Zampini #undef __FUNCT__
532b8ffe317SStefano Zampini #define __FUNCT__ "PCBDDCSetUseExactDirichlet_BDDC"
533b8ffe317SStefano Zampini static PetscErrorCode PCBDDCSetUseExactDirichlet_BDDC(PC pc,PetscBool flg)
534b8ffe317SStefano Zampini {
535b8ffe317SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
536b8ffe317SStefano Zampini 
537b8ffe317SStefano Zampini   PetscFunctionBegin;
53885c4d303SStefano Zampini   pcbddc->use_exact_dirichlet_trick = flg;
539b8ffe317SStefano Zampini   PetscFunctionReturn(0);
540b8ffe317SStefano Zampini }
541b8ffe317SStefano Zampini 
542b8ffe317SStefano Zampini #undef __FUNCT__
543b8ffe317SStefano Zampini #define __FUNCT__ "PCBDDCSetUseExactDirichlet"
544b8ffe317SStefano Zampini PetscErrorCode PCBDDCSetUseExactDirichlet(PC pc,PetscBool flg)
5452b510759SStefano Zampini {
5462b510759SStefano Zampini   PetscErrorCode ierr;
5472b510759SStefano Zampini 
5482b510759SStefano Zampini   PetscFunctionBegin;
5492b510759SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
550b8ffe317SStefano Zampini   PetscValidLogicalCollectiveBool(pc,flg,2);
551b8ffe317SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetUseExactDirichlet_C",(PC,PetscBool),(pc,flg));CHKERRQ(ierr);
5522b510759SStefano Zampini   PetscFunctionReturn(0);
5532b510759SStefano Zampini }
5541e6b0712SBarry Smith 
5554fad6a16SStefano Zampini #undef __FUNCT__
5562b510759SStefano Zampini #define __FUNCT__ "PCBDDCSetLevel_BDDC"
5572b510759SStefano Zampini static PetscErrorCode PCBDDCSetLevel_BDDC(PC pc,PetscInt level)
5584fad6a16SStefano Zampini {
5594fad6a16SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
5604fad6a16SStefano Zampini 
5614fad6a16SStefano Zampini   PetscFunctionBegin;
5622b510759SStefano Zampini   pcbddc->current_level = level;
5634fad6a16SStefano Zampini   PetscFunctionReturn(0);
5644fad6a16SStefano Zampini }
5651e6b0712SBarry Smith 
5664fad6a16SStefano Zampini #undef __FUNCT__
567b8ffe317SStefano Zampini #define __FUNCT__ "PCBDDCSetLevel"
568b8ffe317SStefano Zampini PetscErrorCode PCBDDCSetLevel(PC pc,PetscInt level)
569b8ffe317SStefano Zampini {
570b8ffe317SStefano Zampini   PetscErrorCode ierr;
571b8ffe317SStefano Zampini 
572b8ffe317SStefano Zampini   PetscFunctionBegin;
573b8ffe317SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
574b8ffe317SStefano Zampini   PetscValidLogicalCollectiveInt(pc,level,2);
575b8ffe317SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetLevel_C",(PC,PetscInt),(pc,level));CHKERRQ(ierr);
576b8ffe317SStefano Zampini   PetscFunctionReturn(0);
577b8ffe317SStefano Zampini }
578b8ffe317SStefano Zampini 
579b8ffe317SStefano Zampini #undef __FUNCT__
5802b510759SStefano Zampini #define __FUNCT__ "PCBDDCSetLevels_BDDC"
5812b510759SStefano Zampini static PetscErrorCode PCBDDCSetLevels_BDDC(PC pc,PetscInt levels)
5822b510759SStefano Zampini {
5832b510759SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
5842b510759SStefano Zampini 
5852b510759SStefano Zampini   PetscFunctionBegin;
5862b510759SStefano Zampini   pcbddc->max_levels = levels;
5872b510759SStefano Zampini   PetscFunctionReturn(0);
5882b510759SStefano Zampini }
5892b510759SStefano Zampini 
5902b510759SStefano Zampini #undef __FUNCT__
5912b510759SStefano Zampini #define __FUNCT__ "PCBDDCSetLevels"
5924fad6a16SStefano Zampini /*@
59328509bceSStefano Zampini  PCBDDCSetLevels - Sets the maximum number of levels for multilevel
5944fad6a16SStefano Zampini 
5954fad6a16SStefano Zampini    Logically collective on PC
5964fad6a16SStefano Zampini 
5974fad6a16SStefano Zampini    Input Parameters:
5984fad6a16SStefano Zampini +  pc - the preconditioning context
59928509bceSStefano Zampini -  levels - the maximum number of levels (max 9)
6004fad6a16SStefano Zampini 
6010f202f7eSStefano Zampini    Options Database Keys:
6020f202f7eSStefano Zampini .    -pc_bddc_levels
6034fad6a16SStefano Zampini 
6044fad6a16SStefano Zampini    Level: intermediate
6054fad6a16SStefano Zampini 
6064fad6a16SStefano Zampini    Notes:
6070f202f7eSStefano Zampini      Default value is 0, i.e. traditional one-level BDDC
6084fad6a16SStefano Zampini 
6090f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetCoarseningRatio()
6104fad6a16SStefano Zampini @*/
6112b510759SStefano Zampini PetscErrorCode PCBDDCSetLevels(PC pc,PetscInt levels)
6124fad6a16SStefano Zampini {
6134fad6a16SStefano Zampini   PetscErrorCode ierr;
6144fad6a16SStefano Zampini 
6154fad6a16SStefano Zampini   PetscFunctionBegin;
6164fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
6172b510759SStefano Zampini   PetscValidLogicalCollectiveInt(pc,levels,2);
618312be037SStefano Zampini   if (levels > 99) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Maximum number of levels for bddc is 99\n");
6192b510759SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetLevels_C",(PC,PetscInt),(pc,levels));CHKERRQ(ierr);
6204fad6a16SStefano Zampini   PetscFunctionReturn(0);
6214fad6a16SStefano Zampini }
6221e6b0712SBarry Smith 
6234fad6a16SStefano Zampini #undef __FUNCT__
6243b03a366Sstefano_zampini #define __FUNCT__ "PCBDDCSetDirichletBoundaries_BDDC"
6253b03a366Sstefano_zampini static PetscErrorCode PCBDDCSetDirichletBoundaries_BDDC(PC pc,IS DirichletBoundaries)
6263b03a366Sstefano_zampini {
6273b03a366Sstefano_zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
62856282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
6293b03a366Sstefano_zampini   PetscErrorCode ierr;
6303b03a366Sstefano_zampini 
6313b03a366Sstefano_zampini   PetscFunctionBegin;
63256282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)DirichletBoundaries);CHKERRQ(ierr);
63356282151SStefano Zampini   if (pcbddc->DirichletBoundaries) {
63456282151SStefano Zampini     ierr = ISEqual(DirichletBoundaries,pcbddc->DirichletBoundaries,&isequal);CHKERRQ(ierr);
63556282151SStefano Zampini   }
636785d1243SStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
637785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
6383b03a366Sstefano_zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
63936e030ebSStefano Zampini   pcbddc->DirichletBoundaries = DirichletBoundaries;
64056282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
6413b03a366Sstefano_zampini   PetscFunctionReturn(0);
6423b03a366Sstefano_zampini }
6431e6b0712SBarry Smith 
6443b03a366Sstefano_zampini #undef __FUNCT__
6453b03a366Sstefano_zampini #define __FUNCT__ "PCBDDCSetDirichletBoundaries"
6463b03a366Sstefano_zampini /*@
64728509bceSStefano Zampini  PCBDDCSetDirichletBoundaries - Set IS defining Dirichlet boundaries for the global problem.
6483b03a366Sstefano_zampini 
649785d1243SStefano Zampini    Collective
6503b03a366Sstefano_zampini 
6513b03a366Sstefano_zampini    Input Parameters:
6523b03a366Sstefano_zampini +  pc - the preconditioning context
653785d1243SStefano Zampini -  DirichletBoundaries - parallel IS defining the Dirichlet boundaries
6543b03a366Sstefano_zampini 
6553b03a366Sstefano_zampini    Level: intermediate
6563b03a366Sstefano_zampini 
6570f202f7eSStefano Zampini    Notes:
6580f202f7eSStefano Zampini      Provide the information if you used MatZeroRows/Columns routines. Any process can list any global node
6593b03a366Sstefano_zampini 
6600f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetDirichletBoundariesLocal(), MatZeroRows(), MatZeroRowsColumns()
6613b03a366Sstefano_zampini @*/
6623b03a366Sstefano_zampini PetscErrorCode PCBDDCSetDirichletBoundaries(PC pc,IS DirichletBoundaries)
6633b03a366Sstefano_zampini {
6643b03a366Sstefano_zampini   PetscErrorCode ierr;
6653b03a366Sstefano_zampini 
6663b03a366Sstefano_zampini   PetscFunctionBegin;
6673b03a366Sstefano_zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
668674ae819SStefano Zampini   PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2);
669785d1243SStefano Zampini   PetscCheckSameComm(pc,1,DirichletBoundaries,2);
6703b03a366Sstefano_zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDirichletBoundaries_C",(PC,IS),(pc,DirichletBoundaries));CHKERRQ(ierr);
6713b03a366Sstefano_zampini   PetscFunctionReturn(0);
6723b03a366Sstefano_zampini }
6731e6b0712SBarry Smith 
6743b03a366Sstefano_zampini #undef __FUNCT__
67582ba6b80SStefano Zampini #define __FUNCT__ "PCBDDCSetDirichletBoundariesLocal_BDDC"
67682ba6b80SStefano Zampini static PetscErrorCode PCBDDCSetDirichletBoundariesLocal_BDDC(PC pc,IS DirichletBoundaries)
6770c7d97c5SJed Brown {
6780c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
67956282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
6800c7d97c5SJed Brown   PetscErrorCode ierr;
6810c7d97c5SJed Brown 
6820c7d97c5SJed Brown   PetscFunctionBegin;
68356282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)DirichletBoundaries);CHKERRQ(ierr);
68456282151SStefano Zampini   if (pcbddc->DirichletBoundariesLocal) {
68556282151SStefano Zampini     ierr = ISEqual(DirichletBoundaries,pcbddc->DirichletBoundariesLocal,&isequal);CHKERRQ(ierr);
68656282151SStefano Zampini   }
687785d1243SStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
688785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
6890c7d97c5SJed Brown   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
690785d1243SStefano Zampini   pcbddc->DirichletBoundariesLocal = DirichletBoundaries;
69156282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
6920c7d97c5SJed Brown   PetscFunctionReturn(0);
6930c7d97c5SJed Brown }
6940c7d97c5SJed Brown 
6950c7d97c5SJed Brown #undef __FUNCT__
69682ba6b80SStefano Zampini #define __FUNCT__ "PCBDDCSetDirichletBoundariesLocal"
6979c0446d6SStefano Zampini /*@
69882ba6b80SStefano Zampini  PCBDDCSetDirichletBoundariesLocal - Set IS defining Dirichlet boundaries for the global problem in local ordering.
6999c0446d6SStefano Zampini 
700785d1243SStefano Zampini    Collective
70153cdbc3dSStefano Zampini 
70253cdbc3dSStefano Zampini    Input Parameters:
70353cdbc3dSStefano Zampini +  pc - the preconditioning context
70482ba6b80SStefano Zampini -  DirichletBoundaries - parallel IS defining the Dirichlet boundaries (in local ordering)
70553cdbc3dSStefano Zampini 
70653cdbc3dSStefano Zampini    Level: intermediate
70753cdbc3dSStefano Zampini 
7089c0446d6SStefano Zampini    Notes:
70953cdbc3dSStefano Zampini 
7100f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetDirichletBoundaries(), MatZeroRows(), MatZeroRowsColumns()
71153cdbc3dSStefano Zampini @*/
71282ba6b80SStefano Zampini PetscErrorCode PCBDDCSetDirichletBoundariesLocal(PC pc,IS DirichletBoundaries)
7130c7d97c5SJed Brown {
7140c7d97c5SJed Brown   PetscErrorCode ierr;
7150c7d97c5SJed Brown 
7160c7d97c5SJed Brown   PetscFunctionBegin;
7170c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
7180c7d97c5SJed Brown   PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2);
71982ba6b80SStefano Zampini   PetscCheckSameComm(pc,1,DirichletBoundaries,2);
72082ba6b80SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDirichletBoundariesLocal_C",(PC,IS),(pc,DirichletBoundaries));CHKERRQ(ierr);
7210c7d97c5SJed Brown   PetscFunctionReturn(0);
7220c7d97c5SJed Brown }
7230c7d97c5SJed Brown 
7240c7d97c5SJed Brown #undef __FUNCT__
7250c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetNeumannBoundaries_BDDC"
72653cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc,IS NeumannBoundaries)
7270c7d97c5SJed Brown {
7280c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
72956282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
73053cdbc3dSStefano Zampini   PetscErrorCode ierr;
7310c7d97c5SJed Brown 
7320c7d97c5SJed Brown   PetscFunctionBegin;
73356282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr);
73456282151SStefano Zampini   if (pcbddc->NeumannBoundaries) {
73556282151SStefano Zampini     ierr = ISEqual(NeumannBoundaries,pcbddc->NeumannBoundaries,&isequal);CHKERRQ(ierr);
73656282151SStefano Zampini   }
737785d1243SStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
738785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
73953cdbc3dSStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
74036e030ebSStefano Zampini   pcbddc->NeumannBoundaries = NeumannBoundaries;
74156282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
7420c7d97c5SJed Brown   PetscFunctionReturn(0);
7430c7d97c5SJed Brown }
7441e6b0712SBarry Smith 
7450c7d97c5SJed Brown #undef __FUNCT__
7460c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetNeumannBoundaries"
74757527edcSJed Brown /*@
74828509bceSStefano Zampini  PCBDDCSetNeumannBoundaries - Set IS defining Neumann boundaries for the global problem.
74957527edcSJed Brown 
750785d1243SStefano Zampini    Collective
75157527edcSJed Brown 
75257527edcSJed Brown    Input Parameters:
75357527edcSJed Brown +  pc - the preconditioning context
754785d1243SStefano Zampini -  NeumannBoundaries - parallel IS defining the Neumann boundaries
75557527edcSJed Brown 
75657527edcSJed Brown    Level: intermediate
75757527edcSJed Brown 
7580f202f7eSStefano Zampini    Notes:
7590f202f7eSStefano Zampini      Any process can list any global node
76057527edcSJed Brown 
7610f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetNeumannBoundariesLocal()
76257527edcSJed Brown @*/
76353cdbc3dSStefano Zampini PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc,IS NeumannBoundaries)
7640c7d97c5SJed Brown {
7650c7d97c5SJed Brown   PetscErrorCode ierr;
7660c7d97c5SJed Brown 
7670c7d97c5SJed Brown   PetscFunctionBegin;
7680c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
769674ae819SStefano Zampini   PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2);
770785d1243SStefano Zampini   PetscCheckSameComm(pc,1,NeumannBoundaries,2);
77153cdbc3dSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundaries_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr);
77253cdbc3dSStefano Zampini   PetscFunctionReturn(0);
77353cdbc3dSStefano Zampini }
7741e6b0712SBarry Smith 
77553cdbc3dSStefano Zampini #undef __FUNCT__
77682ba6b80SStefano Zampini #define __FUNCT__ "PCBDDCSetNeumannBoundariesLocal_BDDC"
77782ba6b80SStefano Zampini static PetscErrorCode PCBDDCSetNeumannBoundariesLocal_BDDC(PC pc,IS NeumannBoundaries)
7780c7d97c5SJed Brown {
7790c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
78056282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
7810c7d97c5SJed Brown   PetscErrorCode ierr;
7820c7d97c5SJed Brown 
7830c7d97c5SJed Brown   PetscFunctionBegin;
78456282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr);
78556282151SStefano Zampini   if (pcbddc->NeumannBoundariesLocal) {
78656282151SStefano Zampini     ierr = ISEqual(NeumannBoundaries,pcbddc->NeumannBoundariesLocal,&isequal);CHKERRQ(ierr);
78756282151SStefano Zampini   }
788785d1243SStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
789785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
7900c7d97c5SJed Brown   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
791785d1243SStefano Zampini   pcbddc->NeumannBoundariesLocal = NeumannBoundaries;
79256282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
7930c7d97c5SJed Brown   PetscFunctionReturn(0);
7940c7d97c5SJed Brown }
7950c7d97c5SJed Brown 
7960c7d97c5SJed Brown #undef __FUNCT__
79782ba6b80SStefano Zampini #define __FUNCT__ "PCBDDCSetNeumannBoundariesLocal"
7980c7d97c5SJed Brown /*@
79982ba6b80SStefano Zampini  PCBDDCSetNeumannBoundariesLocal - Set IS defining Neumann boundaries for the global problem in local ordering.
8000c7d97c5SJed Brown 
801785d1243SStefano Zampini    Collective
8020c7d97c5SJed Brown 
8030c7d97c5SJed Brown    Input Parameters:
8040c7d97c5SJed Brown +  pc - the preconditioning context
80582ba6b80SStefano Zampini -  NeumannBoundaries - parallel IS defining the subdomain part of Neumann boundaries (in local ordering)
8060c7d97c5SJed Brown 
8070c7d97c5SJed Brown    Level: intermediate
8080c7d97c5SJed Brown 
8090c7d97c5SJed Brown    Notes:
8100c7d97c5SJed Brown 
8110f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetNeumannBoundaries()
8120c7d97c5SJed Brown @*/
81382ba6b80SStefano Zampini PetscErrorCode PCBDDCSetNeumannBoundariesLocal(PC pc,IS NeumannBoundaries)
8140c7d97c5SJed Brown {
8150c7d97c5SJed Brown   PetscErrorCode ierr;
8160c7d97c5SJed Brown 
8170c7d97c5SJed Brown   PetscFunctionBegin;
8180c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
8190c7d97c5SJed Brown   PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2);
82082ba6b80SStefano Zampini   PetscCheckSameComm(pc,1,NeumannBoundaries,2);
82182ba6b80SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundariesLocal_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr);
82253cdbc3dSStefano Zampini   PetscFunctionReturn(0);
82353cdbc3dSStefano Zampini }
82453cdbc3dSStefano Zampini 
82553cdbc3dSStefano Zampini #undef __FUNCT__
826da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCGetDirichletBoundaries_BDDC"
827da1bb401SStefano Zampini static PetscErrorCode PCBDDCGetDirichletBoundaries_BDDC(PC pc,IS *DirichletBoundaries)
828da1bb401SStefano Zampini {
829da1bb401SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
830da1bb401SStefano Zampini 
831da1bb401SStefano Zampini   PetscFunctionBegin;
832da1bb401SStefano Zampini   *DirichletBoundaries = pcbddc->DirichletBoundaries;
833da1bb401SStefano Zampini   PetscFunctionReturn(0);
834da1bb401SStefano Zampini }
8351e6b0712SBarry Smith 
836da1bb401SStefano Zampini #undef __FUNCT__
837da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCGetDirichletBoundaries"
838da1bb401SStefano Zampini /*@
839785d1243SStefano Zampini  PCBDDCGetDirichletBoundaries - Get parallel IS for Dirichlet boundaries
840da1bb401SStefano Zampini 
841785d1243SStefano Zampini    Collective
842785d1243SStefano Zampini 
843785d1243SStefano Zampini    Input Parameters:
844785d1243SStefano Zampini .  pc - the preconditioning context
845785d1243SStefano Zampini 
846785d1243SStefano Zampini    Output Parameters:
847785d1243SStefano Zampini .  DirichletBoundaries - index set defining the Dirichlet boundaries
848785d1243SStefano Zampini 
849785d1243SStefano Zampini    Level: intermediate
850785d1243SStefano Zampini 
8510f202f7eSStefano Zampini    Notes:
8520f202f7eSStefano Zampini      The IS returned (if any) is the same passed in earlier by the user with PCBDDCSetDirichletBoundaries
853785d1243SStefano Zampini 
854785d1243SStefano Zampini .seealso: PCBDDC
855785d1243SStefano Zampini @*/
856785d1243SStefano Zampini PetscErrorCode PCBDDCGetDirichletBoundaries(PC pc,IS *DirichletBoundaries)
857785d1243SStefano Zampini {
858785d1243SStefano Zampini   PetscErrorCode ierr;
859785d1243SStefano Zampini 
860785d1243SStefano Zampini   PetscFunctionBegin;
861785d1243SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
862785d1243SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetDirichletBoundaries_C",(PC,IS*),(pc,DirichletBoundaries));CHKERRQ(ierr);
863785d1243SStefano Zampini   PetscFunctionReturn(0);
864785d1243SStefano Zampini }
865785d1243SStefano Zampini 
866785d1243SStefano Zampini #undef __FUNCT__
867785d1243SStefano Zampini #define __FUNCT__ "PCBDDCGetDirichletBoundariesLocal_BDDC"
868785d1243SStefano Zampini static PetscErrorCode PCBDDCGetDirichletBoundariesLocal_BDDC(PC pc,IS *DirichletBoundaries)
869785d1243SStefano Zampini {
870785d1243SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
871785d1243SStefano Zampini 
872785d1243SStefano Zampini   PetscFunctionBegin;
873785d1243SStefano Zampini   *DirichletBoundaries = pcbddc->DirichletBoundariesLocal;
874785d1243SStefano Zampini   PetscFunctionReturn(0);
875785d1243SStefano Zampini }
876785d1243SStefano Zampini 
877785d1243SStefano Zampini #undef __FUNCT__
87882ba6b80SStefano Zampini #define __FUNCT__ "PCBDDCGetDirichletBoundariesLocal"
879da1bb401SStefano Zampini /*@
88082ba6b80SStefano Zampini  PCBDDCGetDirichletBoundariesLocal - Get parallel IS for Dirichlet boundaries (in local ordering)
881da1bb401SStefano Zampini 
882785d1243SStefano Zampini    Collective
883da1bb401SStefano Zampini 
884da1bb401SStefano Zampini    Input Parameters:
88528509bceSStefano Zampini .  pc - the preconditioning context
886da1bb401SStefano Zampini 
887da1bb401SStefano Zampini    Output Parameters:
88828509bceSStefano Zampini .  DirichletBoundaries - index set defining the subdomain part of Dirichlet boundaries
889da1bb401SStefano Zampini 
890da1bb401SStefano Zampini    Level: intermediate
891da1bb401SStefano Zampini 
892da1bb401SStefano Zampini    Notes:
8930f202f7eSStefano 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).
8940f202f7eSStefano Zampini           In the latter case, the IS will be available after PCSetUp.
895da1bb401SStefano Zampini 
896da1bb401SStefano Zampini .seealso: PCBDDC
897da1bb401SStefano Zampini @*/
89882ba6b80SStefano Zampini PetscErrorCode PCBDDCGetDirichletBoundariesLocal(PC pc,IS *DirichletBoundaries)
899da1bb401SStefano Zampini {
900da1bb401SStefano Zampini   PetscErrorCode ierr;
901da1bb401SStefano Zampini 
902da1bb401SStefano Zampini   PetscFunctionBegin;
903da1bb401SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
90482ba6b80SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetDirichletBoundariesLocal_C",(PC,IS*),(pc,DirichletBoundaries));CHKERRQ(ierr);
905da1bb401SStefano Zampini   PetscFunctionReturn(0);
906da1bb401SStefano Zampini }
9071e6b0712SBarry Smith 
908da1bb401SStefano Zampini #undef __FUNCT__
90953cdbc3dSStefano Zampini #define __FUNCT__ "PCBDDCGetNeumannBoundaries_BDDC"
91053cdbc3dSStefano Zampini static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc,IS *NeumannBoundaries)
91153cdbc3dSStefano Zampini {
91253cdbc3dSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
91353cdbc3dSStefano Zampini 
91453cdbc3dSStefano Zampini   PetscFunctionBegin;
91553cdbc3dSStefano Zampini   *NeumannBoundaries = pcbddc->NeumannBoundaries;
91653cdbc3dSStefano Zampini   PetscFunctionReturn(0);
91753cdbc3dSStefano Zampini }
9181e6b0712SBarry Smith 
91953cdbc3dSStefano Zampini #undef __FUNCT__
92053cdbc3dSStefano Zampini #define __FUNCT__ "PCBDDCGetNeumannBoundaries"
92153cdbc3dSStefano Zampini /*@
922785d1243SStefano Zampini  PCBDDCGetNeumannBoundaries - Get parallel IS for Neumann boundaries
92353cdbc3dSStefano Zampini 
924785d1243SStefano Zampini    Collective
925785d1243SStefano Zampini 
926785d1243SStefano Zampini    Input Parameters:
927785d1243SStefano Zampini .  pc - the preconditioning context
928785d1243SStefano Zampini 
929785d1243SStefano Zampini    Output Parameters:
930785d1243SStefano Zampini .  NeumannBoundaries - index set defining the Neumann boundaries
931785d1243SStefano Zampini 
932785d1243SStefano Zampini    Level: intermediate
933785d1243SStefano Zampini 
9340f202f7eSStefano Zampini    Notes:
9350f202f7eSStefano Zampini      The IS returned (if any) is the same passed in earlier by the user with PCBDDCSetNeumannBoundaries
936785d1243SStefano Zampini 
937785d1243SStefano Zampini .seealso: PCBDDC
938785d1243SStefano Zampini @*/
939785d1243SStefano Zampini PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc,IS *NeumannBoundaries)
940785d1243SStefano Zampini {
941785d1243SStefano Zampini   PetscErrorCode ierr;
942785d1243SStefano Zampini 
943785d1243SStefano Zampini   PetscFunctionBegin;
944785d1243SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
945785d1243SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundaries_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr);
946785d1243SStefano Zampini   PetscFunctionReturn(0);
947785d1243SStefano Zampini }
948785d1243SStefano Zampini 
949785d1243SStefano Zampini #undef __FUNCT__
950785d1243SStefano Zampini #define __FUNCT__ "PCBDDCGetNeumannBoundariesLocal_BDDC"
951785d1243SStefano Zampini static PetscErrorCode PCBDDCGetNeumannBoundariesLocal_BDDC(PC pc,IS *NeumannBoundaries)
952785d1243SStefano Zampini {
953785d1243SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
954785d1243SStefano Zampini 
955785d1243SStefano Zampini   PetscFunctionBegin;
956785d1243SStefano Zampini   *NeumannBoundaries = pcbddc->NeumannBoundariesLocal;
957785d1243SStefano Zampini   PetscFunctionReturn(0);
958785d1243SStefano Zampini }
959785d1243SStefano Zampini 
960785d1243SStefano Zampini #undef __FUNCT__
96182ba6b80SStefano Zampini #define __FUNCT__ "PCBDDCGetNeumannBoundariesLocal"
96253cdbc3dSStefano Zampini /*@
96382ba6b80SStefano Zampini  PCBDDCGetNeumannBoundariesLocal - Get parallel IS for Neumann boundaries (in local ordering)
96453cdbc3dSStefano Zampini 
965785d1243SStefano Zampini    Collective
96653cdbc3dSStefano Zampini 
96753cdbc3dSStefano Zampini    Input Parameters:
96828509bceSStefano Zampini .  pc - the preconditioning context
96953cdbc3dSStefano Zampini 
97053cdbc3dSStefano Zampini    Output Parameters:
97128509bceSStefano Zampini .  NeumannBoundaries - index set defining the subdomain part of Neumann boundaries
97253cdbc3dSStefano Zampini 
97353cdbc3dSStefano Zampini    Level: intermediate
97453cdbc3dSStefano Zampini 
97553cdbc3dSStefano Zampini    Notes:
9760f202f7eSStefano 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).
9770f202f7eSStefano Zampini           In the latter case, the IS will be available after PCSetUp.
97853cdbc3dSStefano Zampini 
97953cdbc3dSStefano Zampini .seealso: PCBDDC
98053cdbc3dSStefano Zampini @*/
98182ba6b80SStefano Zampini PetscErrorCode PCBDDCGetNeumannBoundariesLocal(PC pc,IS *NeumannBoundaries)
98253cdbc3dSStefano Zampini {
98353cdbc3dSStefano Zampini   PetscErrorCode ierr;
98453cdbc3dSStefano Zampini 
98553cdbc3dSStefano Zampini   PetscFunctionBegin;
98653cdbc3dSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
98782ba6b80SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundariesLocal_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr);
9880c7d97c5SJed Brown   PetscFunctionReturn(0);
9890c7d97c5SJed Brown }
9901e6b0712SBarry Smith 
99136e030ebSStefano Zampini #undef __FUNCT__
992da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCSetLocalAdjacencyGraph_BDDC"
9931a83f524SJed Brown static PetscErrorCode PCBDDCSetLocalAdjacencyGraph_BDDC(PC pc, PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode)
99436e030ebSStefano Zampini {
99536e030ebSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
996da1bb401SStefano Zampini   PCBDDCGraph    mat_graph = pcbddc->mat_graph;
99756282151SStefano Zampini   PetscBool      same_data = PETSC_FALSE;
998da1bb401SStefano Zampini   PetscErrorCode ierr;
99936e030ebSStefano Zampini 
100036e030ebSStefano Zampini   PetscFunctionBegin;
10018687889aSStefano Zampini   if (!nvtxs) {
100204194a47SStefano Zampini     if (copymode == PETSC_OWN_POINTER) {
100304194a47SStefano Zampini       ierr = PetscFree(xadj);CHKERRQ(ierr);
100404194a47SStefano Zampini       ierr = PetscFree(adjncy);CHKERRQ(ierr);
100504194a47SStefano Zampini     }
10068687889aSStefano Zampini     ierr = PCBDDCGraphResetCSR(mat_graph);CHKERRQ(ierr);
10078687889aSStefano Zampini     PetscFunctionReturn(0);
10088687889aSStefano Zampini   }
10092d505d7fSStefano Zampini   if (mat_graph->nvtxs_csr == nvtxs && mat_graph->freecsr) { /* we own the data */
101056282151SStefano Zampini     if (mat_graph->xadj == xadj && mat_graph->adjncy == adjncy) same_data = PETSC_TRUE;
101156282151SStefano Zampini     if (!same_data && mat_graph->xadj[nvtxs] == xadj[nvtxs]) {
10122d505d7fSStefano Zampini       ierr = PetscMemcmp(xadj,mat_graph->xadj,(nvtxs+1)*sizeof(PetscInt),&same_data);CHKERRQ(ierr);
10132d505d7fSStefano Zampini       if (same_data) {
10142d505d7fSStefano Zampini         ierr = PetscMemcmp(adjncy,mat_graph->adjncy,xadj[nvtxs]*sizeof(PetscInt),&same_data);CHKERRQ(ierr);
10152d505d7fSStefano Zampini       }
101656282151SStefano Zampini     }
101756282151SStefano Zampini   }
101856282151SStefano Zampini   if (!same_data) {
1019674ae819SStefano Zampini     /* free old CSR */
1020674ae819SStefano Zampini     ierr = PCBDDCGraphResetCSR(mat_graph);CHKERRQ(ierr);
1021674ae819SStefano Zampini     /* get CSR into graph structure */
1022da1bb401SStefano Zampini     if (copymode == PETSC_COPY_VALUES) {
1023854ce69bSBarry Smith       ierr = PetscMalloc1(nvtxs+1,&mat_graph->xadj);CHKERRQ(ierr);
1024785e854fSJed Brown       ierr = PetscMalloc1(xadj[nvtxs],&mat_graph->adjncy);CHKERRQ(ierr);
1025674ae819SStefano Zampini       ierr = PetscMemcpy(mat_graph->xadj,xadj,(nvtxs+1)*sizeof(PetscInt));CHKERRQ(ierr);
1026674ae819SStefano Zampini       ierr = PetscMemcpy(mat_graph->adjncy,adjncy,xadj[nvtxs]*sizeof(PetscInt));CHKERRQ(ierr);
1027a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_TRUE;
1028da1bb401SStefano Zampini     } else if (copymode == PETSC_OWN_POINTER) {
10291a83f524SJed Brown       mat_graph->xadj    = (PetscInt*)xadj;
10301a83f524SJed Brown       mat_graph->adjncy  = (PetscInt*)adjncy;
1031a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_TRUE;
1032a1dbd327SStefano Zampini     } else if (copymode == PETSC_USE_POINTER) {
1033a1dbd327SStefano Zampini       mat_graph->xadj    = (PetscInt*)xadj;
1034a1dbd327SStefano Zampini       mat_graph->adjncy  = (PetscInt*)adjncy;
1035a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_FALSE;
1036a1dbd327SStefano Zampini     } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported copy mode %d",copymode);
1037575ad6abSStefano Zampini     mat_graph->nvtxs_csr = nvtxs;
103856282151SStefano Zampini     pcbddc->recompute_topography = PETSC_TRUE;
103956282151SStefano Zampini   }
104036e030ebSStefano Zampini   PetscFunctionReturn(0);
104136e030ebSStefano Zampini }
10421e6b0712SBarry Smith 
104336e030ebSStefano Zampini #undef __FUNCT__
1044da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCSetLocalAdjacencyGraph"
104536e030ebSStefano Zampini /*@
104654fffbccSStefano Zampini  PCBDDCSetLocalAdjacencyGraph - Set adjacency structure (CSR graph) of the local degrees of freedom.
104736e030ebSStefano Zampini 
104836e030ebSStefano Zampini    Not collective
104936e030ebSStefano Zampini 
105036e030ebSStefano Zampini    Input Parameters:
105154fffbccSStefano Zampini +  pc - the preconditioning context.
105254fffbccSStefano Zampini .  nvtxs - number of local vertices of the graph (i.e., the number of local dofs).
105354fffbccSStefano Zampini .  xadj, adjncy - the connectivity of the dofs in CSR format.
105454fffbccSStefano Zampini -  copymode - supported modes are PETSC_COPY_VALUES, PETSC_USE_POINTER or PETSC_OWN_POINTER.
105536e030ebSStefano Zampini 
105636e030ebSStefano Zampini    Level: intermediate
105736e030ebSStefano Zampini 
105854fffbccSStefano Zampini    Notes: A dof is considered connected with all local dofs if xadj[dof+1]-xadj[dof] == 1 and adjncy[xadj[dof]] is negative.
105936e030ebSStefano Zampini 
106028509bceSStefano Zampini .seealso: PCBDDC,PetscCopyMode
106136e030ebSStefano Zampini @*/
10621a83f524SJed Brown PetscErrorCode PCBDDCSetLocalAdjacencyGraph(PC pc,PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode)
106336e030ebSStefano Zampini {
1064575ad6abSStefano Zampini   void (*f)(void) = 0;
106536e030ebSStefano Zampini   PetscErrorCode ierr;
106636e030ebSStefano Zampini 
106736e030ebSStefano Zampini   PetscFunctionBegin;
106836e030ebSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
10698687889aSStefano Zampini   if (nvtxs) {
1070674ae819SStefano Zampini     PetscValidIntPointer(xadj,3);
1071*1633d1f0SStefano Zampini     if (xadj[nvtxs]) PetscValidIntPointer(adjncy,4);
10728687889aSStefano Zampini   }
10731a83f524SJed Brown   ierr = PetscTryMethod(pc,"PCBDDCSetLocalAdjacencyGraph_C",(PC,PetscInt,const PetscInt[],const PetscInt[],PetscCopyMode),(pc,nvtxs,xadj,adjncy,copymode));CHKERRQ(ierr);
1074575ad6abSStefano Zampini   /* free arrays if PCBDDC is not the PC type */
1075575ad6abSStefano Zampini   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",&f);CHKERRQ(ierr);
1076575ad6abSStefano Zampini   if (!f && copymode == PETSC_OWN_POINTER) {
1077575ad6abSStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
1078575ad6abSStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
1079da1bb401SStefano Zampini   }
108036e030ebSStefano Zampini   PetscFunctionReturn(0);
108136e030ebSStefano Zampini }
10821e6b0712SBarry Smith 
10839c0446d6SStefano Zampini #undef __FUNCT__
108463602bcaSStefano Zampini #define __FUNCT__ "PCBDDCSetDofsSplittingLocal_BDDC"
108563602bcaSStefano Zampini static PetscErrorCode PCBDDCSetDofsSplittingLocal_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
108663602bcaSStefano Zampini {
108763602bcaSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
108863602bcaSStefano Zampini   PetscInt       i;
108956282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
109063602bcaSStefano Zampini   PetscErrorCode ierr;
109163602bcaSStefano Zampini 
109263602bcaSStefano Zampini   PetscFunctionBegin;
109356282151SStefano Zampini   if (pcbddc->n_ISForDofsLocal == n_is) {
109456282151SStefano Zampini     for (i=0;i<n_is;i++) {
109556282151SStefano Zampini       PetscBool isequalt;
109656282151SStefano Zampini       ierr = ISEqual(ISForDofs[i],pcbddc->ISForDofsLocal[i],&isequalt);CHKERRQ(ierr);
109756282151SStefano Zampini       if (!isequalt) break;
109856282151SStefano Zampini     }
109956282151SStefano Zampini     if (i == n_is) isequal = PETSC_TRUE;
110056282151SStefano Zampini   }
110156282151SStefano Zampini   for (i=0;i<n_is;i++) {
110256282151SStefano Zampini     ierr = PetscObjectReference((PetscObject)ISForDofs[i]);CHKERRQ(ierr);
110356282151SStefano Zampini   }
110463602bcaSStefano Zampini   /* Destroy ISes if they were already set */
110563602bcaSStefano Zampini   for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
110663602bcaSStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
110763602bcaSStefano Zampini   }
110863602bcaSStefano Zampini   ierr = PetscFree(pcbddc->ISForDofsLocal);CHKERRQ(ierr);
110963602bcaSStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
111063602bcaSStefano Zampini   for (i=0;i<pcbddc->n_ISForDofs;i++) {
111163602bcaSStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
111263602bcaSStefano Zampini   }
111363602bcaSStefano Zampini   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
111463602bcaSStefano Zampini   pcbddc->n_ISForDofs = 0;
111563602bcaSStefano Zampini   /* allocate space then set */
1116d02579f5SStefano Zampini   if (n_is) {
1117d02579f5SStefano Zampini     ierr = PetscMalloc1(n_is,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
1118d02579f5SStefano Zampini   }
111963602bcaSStefano Zampini   for (i=0;i<n_is;i++) {
112063602bcaSStefano Zampini     pcbddc->ISForDofsLocal[i] = ISForDofs[i];
112163602bcaSStefano Zampini   }
112263602bcaSStefano Zampini   pcbddc->n_ISForDofsLocal = n_is;
112363602bcaSStefano Zampini   if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE;
112456282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
112563602bcaSStefano Zampini   PetscFunctionReturn(0);
112663602bcaSStefano Zampini }
112763602bcaSStefano Zampini 
112863602bcaSStefano Zampini #undef __FUNCT__
112963602bcaSStefano Zampini #define __FUNCT__ "PCBDDCSetDofsSplittingLocal"
113063602bcaSStefano Zampini /*@
113163602bcaSStefano Zampini  PCBDDCSetDofsSplittingLocal - Set index sets defining fields of the local subdomain matrix
113263602bcaSStefano Zampini 
113363602bcaSStefano Zampini    Collective
113463602bcaSStefano Zampini 
113563602bcaSStefano Zampini    Input Parameters:
113663602bcaSStefano Zampini +  pc - the preconditioning context
11370f202f7eSStefano Zampini .  n_is - number of index sets defining the fields
11380f202f7eSStefano Zampini -  ISForDofs - array of IS describing the fields in local ordering
113963602bcaSStefano Zampini 
114063602bcaSStefano Zampini    Level: intermediate
114163602bcaSStefano Zampini 
11420f202f7eSStefano Zampini    Notes:
11430f202f7eSStefano Zampini      n_is should be the same among processes. Not all nodes need to be listed: unlisted nodes will belong to the complement field.
114463602bcaSStefano Zampini 
114563602bcaSStefano Zampini .seealso: PCBDDC
114663602bcaSStefano Zampini @*/
114763602bcaSStefano Zampini PetscErrorCode PCBDDCSetDofsSplittingLocal(PC pc,PetscInt n_is, IS ISForDofs[])
114863602bcaSStefano Zampini {
114963602bcaSStefano Zampini   PetscInt       i;
115063602bcaSStefano Zampini   PetscErrorCode ierr;
115163602bcaSStefano Zampini 
115263602bcaSStefano Zampini   PetscFunctionBegin;
115363602bcaSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
115463602bcaSStefano Zampini   PetscValidLogicalCollectiveInt(pc,n_is,2);
115563602bcaSStefano Zampini   for (i=0;i<n_is;i++) {
115663602bcaSStefano Zampini     PetscCheckSameComm(pc,1,ISForDofs[i],3);
115763602bcaSStefano Zampini     PetscValidHeaderSpecific(ISForDofs[i],IS_CLASSID,3);
115863602bcaSStefano Zampini   }
1159e71e7a71SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplittingLocal_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr);
116063602bcaSStefano Zampini   PetscFunctionReturn(0);
116163602bcaSStefano Zampini }
116263602bcaSStefano Zampini 
116363602bcaSStefano Zampini #undef __FUNCT__
11649c0446d6SStefano Zampini #define __FUNCT__ "PCBDDCSetDofsSplitting_BDDC"
11659c0446d6SStefano Zampini static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
11669c0446d6SStefano Zampini {
11679c0446d6SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
11689c0446d6SStefano Zampini   PetscInt       i;
116956282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
11709c0446d6SStefano Zampini   PetscErrorCode ierr;
11719c0446d6SStefano Zampini 
11729c0446d6SStefano Zampini   PetscFunctionBegin;
117356282151SStefano Zampini   if (pcbddc->n_ISForDofs == n_is) {
117456282151SStefano Zampini     for (i=0;i<n_is;i++) {
117556282151SStefano Zampini       PetscBool isequalt;
117656282151SStefano Zampini       ierr = ISEqual(ISForDofs[i],pcbddc->ISForDofs[i],&isequalt);CHKERRQ(ierr);
117756282151SStefano Zampini       if (!isequalt) break;
117856282151SStefano Zampini     }
117956282151SStefano Zampini     if (i == n_is) isequal = PETSC_TRUE;
118056282151SStefano Zampini   }
118156282151SStefano Zampini   for (i=0;i<n_is;i++) {
118256282151SStefano Zampini     ierr = PetscObjectReference((PetscObject)ISForDofs[i]);CHKERRQ(ierr);
118356282151SStefano Zampini   }
1184da1bb401SStefano Zampini   /* Destroy ISes if they were already set */
11859c0446d6SStefano Zampini   for (i=0;i<pcbddc->n_ISForDofs;i++) {
11869c0446d6SStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
11879c0446d6SStefano Zampini   }
1188d11ae9bbSstefano_zampini   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
118963602bcaSStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
119063602bcaSStefano Zampini   for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
119163602bcaSStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
119263602bcaSStefano Zampini   }
119363602bcaSStefano Zampini   ierr = PetscFree(pcbddc->ISForDofsLocal);CHKERRQ(ierr);
119463602bcaSStefano Zampini   pcbddc->n_ISForDofsLocal = 0;
1195da1bb401SStefano Zampini   /* allocate space then set */
1196d02579f5SStefano Zampini   if (n_is) {
1197785e854fSJed Brown     ierr = PetscMalloc1(n_is,&pcbddc->ISForDofs);CHKERRQ(ierr);
1198d02579f5SStefano Zampini   }
11999c0446d6SStefano Zampini   for (i=0;i<n_is;i++) {
1200da1bb401SStefano Zampini     pcbddc->ISForDofs[i] = ISForDofs[i];
12019c0446d6SStefano Zampini   }
12029c0446d6SStefano Zampini   pcbddc->n_ISForDofs = n_is;
120363602bcaSStefano Zampini   if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE;
120456282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
12059c0446d6SStefano Zampini   PetscFunctionReturn(0);
12069c0446d6SStefano Zampini }
12071e6b0712SBarry Smith 
12089c0446d6SStefano Zampini #undef __FUNCT__
12099c0446d6SStefano Zampini #define __FUNCT__ "PCBDDCSetDofsSplitting"
12109c0446d6SStefano Zampini /*@
121163602bcaSStefano Zampini  PCBDDCSetDofsSplitting - Set index sets defining fields of the global matrix
12129c0446d6SStefano Zampini 
121363602bcaSStefano Zampini    Collective
12149c0446d6SStefano Zampini 
12159c0446d6SStefano Zampini    Input Parameters:
12169c0446d6SStefano Zampini +  pc - the preconditioning context
12170f202f7eSStefano Zampini .  n_is - number of index sets defining the fields
12180f202f7eSStefano Zampini -  ISForDofs - array of IS describing the fields in global ordering
12199c0446d6SStefano Zampini 
12209c0446d6SStefano Zampini    Level: intermediate
12219c0446d6SStefano Zampini 
12220f202f7eSStefano Zampini    Notes:
12230f202f7eSStefano Zampini      Any process can list any global node. Not all nodes need to be listed: unlisted nodes will belong to the complement field.
12249c0446d6SStefano Zampini 
12259c0446d6SStefano Zampini .seealso: PCBDDC
12269c0446d6SStefano Zampini @*/
12279c0446d6SStefano Zampini PetscErrorCode PCBDDCSetDofsSplitting(PC pc,PetscInt n_is, IS ISForDofs[])
12289c0446d6SStefano Zampini {
12292b510759SStefano Zampini   PetscInt       i;
12309c0446d6SStefano Zampini   PetscErrorCode ierr;
12319c0446d6SStefano Zampini 
12329c0446d6SStefano Zampini   PetscFunctionBegin;
12339c0446d6SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
123463602bcaSStefano Zampini   PetscValidLogicalCollectiveInt(pc,n_is,2);
12352b510759SStefano Zampini   for (i=0;i<n_is;i++) {
123663602bcaSStefano Zampini     PetscCheckSameComm(pc,1,ISForDofs[i],3);
123763602bcaSStefano Zampini     PetscValidHeaderSpecific(ISForDofs[i],IS_CLASSID,3);
12382b510759SStefano Zampini   }
12399c0446d6SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplitting_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr);
12409c0446d6SStefano Zampini   PetscFunctionReturn(0);
12419c0446d6SStefano Zampini }
1242906d46d4SStefano Zampini 
1243534831adSStefano Zampini #undef __FUNCT__
1244534831adSStefano Zampini #define __FUNCT__ "PCPreSolve_BDDC"
1245534831adSStefano Zampini /*
1246534831adSStefano Zampini    PCPreSolve_BDDC - Changes the right hand side and (if necessary) the initial
1247534831adSStefano Zampini                      guess if a transformation of basis approach has been selected.
12489c0446d6SStefano Zampini 
1249534831adSStefano Zampini    Input Parameter:
1250534831adSStefano Zampini +  pc - the preconditioner contex
1251534831adSStefano Zampini 
1252534831adSStefano Zampini    Application Interface Routine: PCPreSolve()
1253534831adSStefano Zampini 
1254534831adSStefano Zampini    Notes:
1255534831adSStefano Zampini      The interface routine PCPreSolve() is not usually called directly by
1256534831adSStefano Zampini    the user, but instead is called by KSPSolve().
1257534831adSStefano Zampini */
1258534831adSStefano Zampini static PetscErrorCode PCPreSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
1259534831adSStefano Zampini {
1260534831adSStefano Zampini   PetscErrorCode ierr;
1261534831adSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1262534831adSStefano Zampini   PC_IS          *pcis = (PC_IS*)(pc->data);
12633972b0daSStefano Zampini   Vec            used_vec;
126427b6a85dSStefano Zampini   PetscBool      save_rhs = PETSC_TRUE, benign_correction_computed;
1265534831adSStefano Zampini 
1266534831adSStefano Zampini   PetscFunctionBegin;
12671f4df5f7SStefano Zampini   /* if we are working with CG, one dirichlet solve can be avoided during Krylov iterations */
126885c4d303SStefano Zampini   if (ksp) {
12691f4df5f7SStefano Zampini     PetscBool iscg, isgroppcg, ispipecg, ispipecgrr;
127085c4d303SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPCG,&iscg);CHKERRQ(ierr);
127127b6a85dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPGROPPCG,&isgroppcg);CHKERRQ(ierr);
127227b6a85dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPPIPECG,&ispipecg);CHKERRQ(ierr);
1273f94e96cbSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPPIPECGRR,&ispipecgrr);CHKERRQ(ierr);
12741f4df5f7SStefano Zampini     if (pcbddc->benign_apply_coarse_only || pcbddc->switch_static || (!iscg && !isgroppcg && !ispipecg && !ispipecgrr)) {
127585c4d303SStefano Zampini       ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
127685c4d303SStefano Zampini     }
127785c4d303SStefano Zampini   }
1278fc17d649SStefano Zampini   if (pcbddc->benign_apply_coarse_only || pcbddc->switch_static) {
1279fc17d649SStefano Zampini     ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
1280fc17d649SStefano Zampini   }
12811f4df5f7SStefano Zampini 
128285c4d303SStefano Zampini   /* Creates parallel work vectors used in presolve */
128362a6ff1dSStefano Zampini   if (!pcbddc->original_rhs) {
128462a6ff1dSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs);CHKERRQ(ierr);
128562a6ff1dSStefano Zampini   }
128662a6ff1dSStefano Zampini   if (!pcbddc->temp_solution) {
128762a6ff1dSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->temp_solution);CHKERRQ(ierr);
128862a6ff1dSStefano Zampini   }
12898d00608fSStefano Zampini 
129027b6a85dSStefano Zampini   pcbddc->temp_solution_used = PETSC_FALSE;
12913972b0daSStefano Zampini   if (x) {
12923972b0daSStefano Zampini     ierr = PetscObjectReference((PetscObject)x);CHKERRQ(ierr);
12933972b0daSStefano Zampini     used_vec = x;
12948d00608fSStefano Zampini   } else { /* it can only happen when calling PCBDDCMatFETIDPGetRHS */
12953972b0daSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->temp_solution);CHKERRQ(ierr);
12963972b0daSStefano Zampini     used_vec = pcbddc->temp_solution;
12973972b0daSStefano Zampini     ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
129827b6a85dSStefano Zampini     pcbddc->temp_solution_used = PETSC_TRUE;
1299266e20e9SStefano Zampini     ierr = VecCopy(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
1300266e20e9SStefano Zampini     save_rhs = PETSC_FALSE;
1301266e20e9SStefano Zampini     pcbddc->eliminate_dirdofs = PETSC_TRUE;
13023972b0daSStefano Zampini   }
13038efcfb23SStefano Zampini 
13048efcfb23SStefano Zampini   /* hack into ksp data structure since PCPreSolve comes earlier than setting to zero the guess in src/ksp/ksp/interface/itfunc.c */
13053972b0daSStefano Zampini   if (ksp) {
1306a0cb1b98SStefano Zampini     /* store the flag for the initial guess since it will be restored back during PCPostSolve_BDDC */
13078efcfb23SStefano Zampini     ierr = KSPGetInitialGuessNonzero(ksp,&pcbddc->ksp_guess_nonzero);CHKERRQ(ierr);
13088efcfb23SStefano Zampini     if (!pcbddc->ksp_guess_nonzero) {
13093972b0daSStefano Zampini       ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
13103972b0daSStefano Zampini     }
13113972b0daSStefano Zampini   }
13123308cffdSStefano Zampini 
13138d00608fSStefano Zampini   pcbddc->rhs_change = PETSC_FALSE;
13143972b0daSStefano Zampini   /* Take into account zeroed rows -> change rhs and store solution removed */
131570c64980SStefano Zampini   if (rhs && pcbddc->eliminate_dirdofs) {
13163975b054SStefano Zampini     IS dirIS = NULL;
13173975b054SStefano Zampini 
1318a07ea27aSStefano Zampini     /* DirichletBoundariesLocal may not be consistent among neighbours; gets a dirichlet dofs IS from graph (may be cached) */
13193975b054SStefano Zampini     ierr = PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS);CHKERRQ(ierr);
13203975b054SStefano Zampini     if (dirIS) {
1321906d46d4SStefano Zampini       Mat_IS            *matis = (Mat_IS*)pc->pmat->data;
1322785d1243SStefano Zampini       PetscInt          dirsize,i,*is_indices;
13232b095fd8SStefano Zampini       PetscScalar       *array_x;
13242b095fd8SStefano Zampini       const PetscScalar *array_diagonal;
1325785d1243SStefano Zampini 
13263972b0daSStefano Zampini       ierr = MatGetDiagonal(pc->pmat,pcis->vec1_global);CHKERRQ(ierr);
13273972b0daSStefano Zampini       ierr = VecPointwiseDivide(pcis->vec1_global,rhs,pcis->vec1_global);CHKERRQ(ierr);
1328e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1329e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1330e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1331e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
133282ba6b80SStefano Zampini       ierr = ISGetLocalSize(dirIS,&dirsize);CHKERRQ(ierr);
13333972b0daSStefano Zampini       ierr = VecGetArray(pcis->vec1_N,&array_x);CHKERRQ(ierr);
13342b095fd8SStefano Zampini       ierr = VecGetArrayRead(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr);
13353972b0daSStefano Zampini       ierr = ISGetIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
13362fa5cd67SKarl Rupp       for (i=0; i<dirsize; i++) array_x[is_indices[i]] = array_diagonal[is_indices[i]];
13373972b0daSStefano Zampini       ierr = ISRestoreIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
13382b095fd8SStefano Zampini       ierr = VecRestoreArrayRead(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr);
13393972b0daSStefano Zampini       ierr = VecRestoreArray(pcis->vec1_N,&array_x);CHKERRQ(ierr);
1340e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1341e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
13428d00608fSStefano Zampini       pcbddc->rhs_change = PETSC_TRUE;
13431b968477SStefano Zampini       ierr = ISDestroy(&dirIS);CHKERRQ(ierr);
13448efcfb23SStefano Zampini     }
1345a07ea27aSStefano Zampini   }
1346b76ba322SStefano Zampini 
13478efcfb23SStefano Zampini   /* remove the computed solution or the initial guess from the rhs */
13488d00608fSStefano Zampini   if (pcbddc->rhs_change || (ksp && pcbddc->ksp_guess_nonzero) ) {
134927b6a85dSStefano Zampini     /* save the original rhs */
135027b6a85dSStefano Zampini     if (save_rhs) {
135127b6a85dSStefano Zampini       ierr = VecSwap(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
135227b6a85dSStefano Zampini       save_rhs = PETSC_FALSE;
13538d00608fSStefano Zampini     }
13548d00608fSStefano Zampini     pcbddc->rhs_change = PETSC_TRUE;
13553972b0daSStefano Zampini     ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr);
135627b6a85dSStefano Zampini     ierr = MatMultAdd(pc->mat,used_vec,pcbddc->original_rhs,rhs);CHKERRQ(ierr);
13573972b0daSStefano Zampini     ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr);
13588efcfb23SStefano Zampini     ierr = VecCopy(used_vec,pcbddc->temp_solution);CHKERRQ(ierr);
135927b6a85dSStefano Zampini     pcbddc->temp_solution_used = PETSC_TRUE;
13607acc28cbSStefano Zampini     if (ksp) {
13617acc28cbSStefano Zampini       ierr = KSPSetInitialGuessNonzero(ksp,PETSC_FALSE);CHKERRQ(ierr);
13627acc28cbSStefano Zampini     }
13633308cffdSStefano Zampini   }
13648efcfb23SStefano Zampini   ierr = VecDestroy(&used_vec);CHKERRQ(ierr);
1365b76ba322SStefano Zampini 
1366fc17d649SStefano Zampini   /* compute initial vector in benign space if needed
136727b6a85dSStefano Zampini      and remove non-benign solution from the rhs */
136827b6a85dSStefano Zampini   benign_correction_computed = PETSC_FALSE;
136927b6a85dSStefano Zampini   if (rhs && pcbddc->benign_compute_correction && pcbddc->benign_have_null) {
13701f4df5f7SStefano Zampini     /* compute u^*_h using ideas similar to those in Xuemin Tu's PhD thesis (see Section 4.8.1)
13711f4df5f7SStefano Zampini        Recursively apply BDDC in the multilevel case */
13720369aaf7SStefano Zampini     if (!pcbddc->benign_vec) {
13730369aaf7SStefano Zampini       ierr = VecDuplicate(rhs,&pcbddc->benign_vec);CHKERRQ(ierr);
13740369aaf7SStefano Zampini     }
13754fee134fSStefano Zampini     pcbddc->benign_apply_coarse_only = PETSC_TRUE;
137627b6a85dSStefano Zampini     if (!pcbddc->benign_skip_correction) {
13771dd7afcfSStefano Zampini       ierr = PCApply_BDDC(pc,rhs,pcbddc->benign_vec);CHKERRQ(ierr);
13783bca92a6SStefano Zampini       benign_correction_computed = PETSC_TRUE;
13791f4df5f7SStefano Zampini       if (pcbddc->temp_solution_used) {
13801f4df5f7SStefano Zampini         ierr = VecAXPY(pcbddc->temp_solution,1.0,pcbddc->benign_vec);CHKERRQ(ierr);
13811f4df5f7SStefano Zampini       }
13821f4df5f7SStefano Zampini       ierr = VecScale(pcbddc->benign_vec,-1.0);CHKERRQ(ierr);
138327b6a85dSStefano Zampini       /* store the original rhs if not done earlier */
138427b6a85dSStefano Zampini       if (save_rhs) {
138527b6a85dSStefano Zampini         ierr = VecSwap(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
138692e3dcfbSStefano Zampini       }
138727b6a85dSStefano Zampini       if (pcbddc->rhs_change) {
13880369aaf7SStefano Zampini         ierr = MatMultAdd(pc->mat,pcbddc->benign_vec,rhs,rhs);CHKERRQ(ierr);
138927b6a85dSStefano Zampini       } else {
139027b6a85dSStefano Zampini         ierr = MatMultAdd(pc->mat,pcbddc->benign_vec,pcbddc->original_rhs,rhs);CHKERRQ(ierr);
139127b6a85dSStefano Zampini       }
13920369aaf7SStefano Zampini       pcbddc->rhs_change = PETSC_TRUE;
139327b6a85dSStefano Zampini     }
139427b6a85dSStefano Zampini     pcbddc->benign_apply_coarse_only = PETSC_FALSE;
13950369aaf7SStefano Zampini   }
13962d4c4fecSStefano Zampini 
13972d4c4fecSStefano Zampini   /* dbg output */
1398a198735bSStefano Zampini   if (pcbddc->dbg_flag && benign_correction_computed) {
13991f4df5f7SStefano Zampini     Vec v;
14001f4df5f7SStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&v);CHKERRQ(ierr);
14011f4df5f7SStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,rhs,v);CHKERRQ(ierr);
14021f4df5f7SStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,v,PETSC_TRUE);CHKERRQ(ierr);
1403a198735bSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"LEVEL %d: is the correction benign?\n",pcbddc->current_level);CHKERRQ(ierr);
14042d4c4fecSStefano Zampini     ierr = PetscScalarView(pcbddc->benign_n,pcbddc->benign_p0,PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pc)));CHKERRQ(ierr);
14051f4df5f7SStefano Zampini     ierr = VecDestroy(&v);CHKERRQ(ierr);
14061f4df5f7SStefano Zampini   }
14070369aaf7SStefano Zampini 
14080369aaf7SStefano Zampini   /* set initial guess if using PCG */
14098ae0ca82SStefano Zampini   pcbddc->exact_dirichlet_trick_app = PETSC_FALSE;
14100369aaf7SStefano Zampini   if (x && pcbddc->use_exact_dirichlet_trick) {
14110369aaf7SStefano Zampini     ierr = VecSet(x,0.0);CHKERRQ(ierr);
14121dd7afcfSStefano Zampini     if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) {
141327b6a85dSStefano Zampini       if (benign_correction_computed) { /* we have already saved the changed rhs */
14141dd7afcfSStefano Zampini         ierr = VecLockPop(pcis->vec1_global);CHKERRQ(ierr);
14151dd7afcfSStefano Zampini       } else {
14161dd7afcfSStefano Zampini         ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,rhs,pcis->vec1_global);CHKERRQ(ierr);
14171dd7afcfSStefano Zampini       }
14181dd7afcfSStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,pcis->vec1_global,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
14191dd7afcfSStefano Zampini       ierr = VecScatterEnd(pcis->global_to_D,pcis->vec1_global,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
14201dd7afcfSStefano Zampini     } else {
14210369aaf7SStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
14220369aaf7SStefano Zampini       ierr = VecScatterEnd(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
14231dd7afcfSStefano Zampini     }
14240369aaf7SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
14251dd7afcfSStefano Zampini     if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) {
14261dd7afcfSStefano Zampini       ierr = VecSet(pcis->vec1_global,0.);CHKERRQ(ierr);
14271dd7afcfSStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,pcis->vec1_global,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
14281dd7afcfSStefano Zampini       ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,pcis->vec1_global,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
14291dd7afcfSStefano Zampini       ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x);CHKERRQ(ierr);
14301dd7afcfSStefano Zampini     } else {
14310369aaf7SStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
14320369aaf7SStefano Zampini       ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
14331dd7afcfSStefano Zampini     }
14340369aaf7SStefano Zampini     if (ksp) {
14350369aaf7SStefano Zampini       ierr = KSPSetInitialGuessNonzero(ksp,PETSC_TRUE);CHKERRQ(ierr);
14360369aaf7SStefano Zampini     }
14378ae0ca82SStefano Zampini     pcbddc->exact_dirichlet_trick_app = PETSC_TRUE;
1438266e20e9SStefano Zampini   } else if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior && benign_correction_computed && pcbddc->use_exact_dirichlet_trick) {
1439266e20e9SStefano Zampini     ierr = VecLockPop(pcis->vec1_global);CHKERRQ(ierr);
14400369aaf7SStefano Zampini   }
1441534831adSStefano Zampini   PetscFunctionReturn(0);
1442534831adSStefano Zampini }
1443906d46d4SStefano Zampini 
1444534831adSStefano Zampini #undef __FUNCT__
1445534831adSStefano Zampini #define __FUNCT__ "PCPostSolve_BDDC"
1446534831adSStefano Zampini /*
1447534831adSStefano Zampini    PCPostSolve_BDDC - Changes the computed solution if a transformation of basis
1448534831adSStefano Zampini                      approach has been selected. Also, restores rhs to its original state.
1449534831adSStefano Zampini 
1450534831adSStefano Zampini    Input Parameter:
1451534831adSStefano Zampini +  pc - the preconditioner contex
1452534831adSStefano Zampini 
1453534831adSStefano Zampini    Application Interface Routine: PCPostSolve()
1454534831adSStefano Zampini 
1455534831adSStefano Zampini    Notes:
1456534831adSStefano Zampini      The interface routine PCPostSolve() is not usually called directly by
1457534831adSStefano Zampini      the user, but instead is called by KSPSolve().
1458534831adSStefano Zampini */
1459534831adSStefano Zampini static PetscErrorCode PCPostSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
1460534831adSStefano Zampini {
1461534831adSStefano Zampini   PetscErrorCode ierr;
1462534831adSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1463534831adSStefano Zampini 
1464534831adSStefano Zampini   PetscFunctionBegin;
14653972b0daSStefano Zampini   /* add solution removed in presolve */
14666bcfc461SStefano Zampini   if (x && pcbddc->rhs_change) {
146727b6a85dSStefano Zampini     if (pcbddc->temp_solution_used) {
14683425bc38SStefano Zampini       ierr = VecAXPY(x,1.0,pcbddc->temp_solution);CHKERRQ(ierr);
146927b6a85dSStefano Zampini     } else if (pcbddc->benign_compute_correction) {
147027b6a85dSStefano Zampini       ierr = VecAXPY(x,-1.0,pcbddc->benign_vec);CHKERRQ(ierr);
14713425bc38SStefano Zampini     }
147227b6a85dSStefano Zampini   }
147327b6a85dSStefano Zampini   pcbddc->temp_solution_used = PETSC_FALSE;
147427b6a85dSStefano Zampini 
1475266e20e9SStefano Zampini   /* restore rhs to its original state (not needed for FETI-DP) */
14768d00608fSStefano Zampini   if (rhs && pcbddc->rhs_change) {
147727b6a85dSStefano Zampini     ierr = VecSwap(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
1478fb223d50SStefano Zampini   }
14798d00608fSStefano Zampini   pcbddc->rhs_change = PETSC_FALSE;
14808efcfb23SStefano Zampini   /* restore ksp guess state */
14818efcfb23SStefano Zampini   if (ksp) {
14828efcfb23SStefano Zampini     ierr = KSPSetInitialGuessNonzero(ksp,pcbddc->ksp_guess_nonzero);CHKERRQ(ierr);
14838efcfb23SStefano Zampini   }
14848ae0ca82SStefano Zampini   /* reset flag for exact dirichlet trick */
14858ae0ca82SStefano Zampini   pcbddc->exact_dirichlet_trick_app = PETSC_FALSE;
1486534831adSStefano Zampini   PetscFunctionReturn(0);
1487534831adSStefano Zampini }
148853cdbc3dSStefano Zampini #undef __FUNCT__
148953cdbc3dSStefano Zampini #define __FUNCT__ "PCSetUp_BDDC"
14900c7d97c5SJed Brown /*
14910c7d97c5SJed Brown    PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner
14920c7d97c5SJed Brown                   by setting data structures and options.
14930c7d97c5SJed Brown 
14940c7d97c5SJed Brown    Input Parameter:
149553cdbc3dSStefano Zampini +  pc - the preconditioner context
14960c7d97c5SJed Brown 
14970c7d97c5SJed Brown    Application Interface Routine: PCSetUp()
14980c7d97c5SJed Brown 
14990c7d97c5SJed Brown    Notes:
15000c7d97c5SJed Brown      The interface routine PCSetUp() is not usually called directly by
15010c7d97c5SJed Brown      the user, but instead is called by PCApply() if necessary.
15020c7d97c5SJed Brown */
150353cdbc3dSStefano Zampini PetscErrorCode PCSetUp_BDDC(PC pc)
15040c7d97c5SJed Brown {
15050c7d97c5SJed Brown   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
1506c703fcc7SStefano Zampini   PCBDDCSubSchurs sub_schurs;
15075e8657edSStefano Zampini   Mat_IS*         matis;
150808122e43SStefano Zampini   MatNullSpace    nearnullspace;
1509c9ed8603SStefano Zampini   IS              zerodiag = NULL;
151091e8d312SStefano Zampini   PetscInt        nrows,ncols;
1511c703fcc7SStefano Zampini   PetscBool       computesubschurs;
15128de1fae6SStefano Zampini   PetscBool       computeconstraintsmatrix;
15135e8657edSStefano Zampini   PetscBool       new_nearnullspace_provided,ismatis;
1514c703fcc7SStefano Zampini   PetscErrorCode  ierr;
15150c7d97c5SJed Brown 
15160c7d97c5SJed Brown   PetscFunctionBegin;
15175e8657edSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc->pmat,MATIS,&ismatis);CHKERRQ(ierr);
15186c4ed002SBarry Smith   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"PCBDDC preconditioner requires matrix of type MATIS");
151991e8d312SStefano Zampini   ierr = MatGetSize(pc->pmat,&nrows,&ncols);CHKERRQ(ierr);
15206c4ed002SBarry Smith   if (nrows != ncols) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PCBDDC preconditioner requires a square preconditioning matrix");
15215e8657edSStefano Zampini   matis = (Mat_IS*)pc->pmat->data;
1522f4ddd8eeSStefano Zampini   /* the following lines of code should be replaced by a better logic between PCIS, PCNN, PCBDDC and other future nonoverlapping preconditioners */
15233b03a366Sstefano_zampini   /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup
152471582508SStefano Zampini      Also, BDDC builds its own KSP for the Dirichlet problem */
1525c703fcc7SStefano Zampini   if (pc->setupcalled && pc->flag != SAME_NONZERO_PATTERN) pcbddc->recompute_topography = PETSC_TRUE;
1526c83e1ba7SStefano Zampini   if (pcbddc->recompute_topography) {
1527c83e1ba7SStefano Zampini     pcbddc->graphanalyzed    = PETSC_FALSE;
1528c83e1ba7SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1529c83e1ba7SStefano Zampini   } else {
15308de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_FALSE;
1531c83e1ba7SStefano Zampini   }
1532b087196eSStefano Zampini 
1533b087196eSStefano Zampini   /* check parameters' compatibility */
1534b7ab4a40SStefano Zampini   if (!pcbddc->use_deluxe_scaling) pcbddc->deluxe_zerorows = PETSC_FALSE;
15359d54b7f4SStefano Zampini   pcbddc->adaptive_selection = (PetscBool)(pcbddc->adaptive_threshold > 0.0);
1536bf3a8328SStefano Zampini   pcbddc->adaptive_userdefined = (PetscBool)(pcbddc->adaptive_selection && pcbddc->adaptive_userdefined);
1537862806e4SStefano Zampini   if (pcbddc->adaptive_selection) pcbddc->use_faces = PETSC_TRUE;
1538862806e4SStefano Zampini 
15395a95e1ceSStefano Zampini   computesubschurs = (PetscBool)(pcbddc->adaptive_selection || pcbddc->use_deluxe_scaling);
154016909a7fSStefano Zampini   if (pcbddc->switch_static) {
154116909a7fSStefano Zampini     PetscBool ismatis;
154216909a7fSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc->mat,MATIS,&ismatis);CHKERRQ(ierr);
154316909a7fSStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"When the static switch is one, the iteration matrix should be of type MATIS");
154416909a7fSStefano Zampini   }
154516909a7fSStefano Zampini 
154671582508SStefano Zampini   /* activate all connected components if the netflux has been requested */
1547bb05f991SStefano Zampini   if (pcbddc->compute_nonetflux) {
1548bb05f991SStefano Zampini     pcbddc->use_vertices = PETSC_TRUE;
1549bb05f991SStefano Zampini     pcbddc->use_edges = PETSC_TRUE;
1550bb05f991SStefano Zampini     pcbddc->use_faces = PETSC_TRUE;
1551bb05f991SStefano Zampini   }
1552bb05f991SStefano Zampini 
1553f4ddd8eeSStefano Zampini   /* Get stdout for dbg */
155470cf5478SStefano Zampini   if (pcbddc->dbg_flag) {
155570cf5478SStefano Zampini     if (!pcbddc->dbg_viewer) {
155658a03d70SStefano Zampini       pcbddc->dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pc));
15571575c14dSBarry Smith       ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
1558f4ddd8eeSStefano Zampini     }
155958a03d70SStefano Zampini     ierr = PetscViewerASCIIAddTab(pcbddc->dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
1560f4ddd8eeSStefano Zampini   }
1561f4ddd8eeSStefano Zampini 
1562c703fcc7SStefano Zampini   /* process topology information */
156371582508SStefano Zampini   if (pcbddc->recompute_topography) {
156471582508SStefano Zampini     ierr = PCBDDCComputeLocalTopologyInfo(pc);CHKERRQ(ierr);
1565c83e1ba7SStefano Zampini     /* detect local disconnected subdomains if requested (use matis->A) */
1566c83e1ba7SStefano Zampini     if (pcbddc->detect_disconnected) {
1567c83e1ba7SStefano Zampini       PetscInt i;
1568c83e1ba7SStefano Zampini       for (i=0;i<pcbddc->n_local_subs;i++) {
1569c83e1ba7SStefano Zampini         ierr = ISDestroy(&pcbddc->local_subs[i]);CHKERRQ(ierr);
1570c83e1ba7SStefano Zampini       }
1571c83e1ba7SStefano Zampini       ierr = PetscFree(pcbddc->local_subs);CHKERRQ(ierr);
1572c83e1ba7SStefano Zampini       ierr = MatDetectDisconnectedComponents(matis->A,PETSC_FALSE,&pcbddc->n_local_subs,&pcbddc->local_subs);CHKERRQ(ierr);
1573c83e1ba7SStefano Zampini     }
1574c703fcc7SStefano Zampini     if (pcbddc->discretegradient) {
1575a13144ffSStefano Zampini       ierr = PCBDDCNedelecSupport(pc);CHKERRQ(ierr);
1576a13144ffSStefano Zampini     }
1577c703fcc7SStefano Zampini   }
1578a13144ffSStefano Zampini 
1579c703fcc7SStefano Zampini   /* change basis if requested by the user */
15805e8657edSStefano Zampini   if (pcbddc->user_ChangeOfBasisMatrix) {
15815e8657edSStefano Zampini     /* use_change_of_basis flag is used to automatically compute a change of basis from constraints */
15825e8657edSStefano Zampini     pcbddc->use_change_of_basis = PETSC_FALSE;
15835e8657edSStefano Zampini     ierr = PCBDDCComputeLocalMatrix(pc,pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
15845e8657edSStefano Zampini   } else {
1585b96c3477SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
15865e8657edSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
15875e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
1588d16cbb6bSStefano Zampini   }
1589d16cbb6bSStefano Zampini 
15904f1b2e48SStefano Zampini   /*
1591c703fcc7SStefano Zampini      Compute change of basis on local pressures (aka zerodiag dofs) with the benign trick
15924f1b2e48SStefano Zampini      This should come earlier then PCISSetUp for extracting the correct subdomain matrices
15934f1b2e48SStefano Zampini   */
15941dd7afcfSStefano Zampini   ierr = PCBDDCBenignShellMat(pc,PETSC_TRUE);CHKERRQ(ierr);
1595d16cbb6bSStefano Zampini   if (pcbddc->benign_saddle_point) {
15969f47a83aSStefano Zampini     PC_IS* pcis = (PC_IS*)pc->data;
15979f47a83aSStefano Zampini 
159805b28244SStefano Zampini     if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->use_change_of_basis || !computesubschurs) pcbddc->benign_change_explicit = PETSC_TRUE;
1599669cc0f4SStefano Zampini     /* detect local saddle point and change the basis in pcbddc->local_mat (TODO: reuse case) */
1600339f8db1SStefano Zampini     ierr = PCBDDCBenignDetectSaddlePoint(pc,&zerodiag);CHKERRQ(ierr);
1601a3df083aSStefano Zampini     /* pop B0 mat from local mat */
1602c263805aSStefano Zampini     ierr = PCBDDCBenignPopOrPushB0(pc,PETSC_TRUE);CHKERRQ(ierr);
16031dd7afcfSStefano Zampini     /* give pcis a hint to not reuse submatrices during PCISCreate */
16041dd7afcfSStefano Zampini     if (pc->flag == SAME_NONZERO_PATTERN && pcis->reusesubmatrices == PETSC_TRUE) {
16051dd7afcfSStefano Zampini       if (pcbddc->benign_n && (pcbddc->benign_change_explicit || pcbddc->dbg_flag)) {
16061dd7afcfSStefano Zampini         pcis->reusesubmatrices = PETSC_FALSE;
16071dd7afcfSStefano Zampini       } else {
1608a3df083aSStefano Zampini         pcis->reusesubmatrices = PETSC_TRUE;
16091dd7afcfSStefano Zampini       }
1610a3df083aSStefano Zampini     } else {
16119f47a83aSStefano Zampini       pcis->reusesubmatrices = PETSC_FALSE;
1612674ae819SStefano Zampini     }
1613a3df083aSStefano Zampini   }
161427b6a85dSStefano Zampini 
1615c703fcc7SStefano Zampini   /* propagate relevant information -> TODO remove*/
16164f1b2e48SStefano Zampini #if !defined(PETSC_USE_COMPLEX) /* workaround for reals */
16173301b35fSStefano Zampini   if (matis->A->symmetric_set) {
16183301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_HERMITIAN,matis->A->symmetric);CHKERRQ(ierr);
16193301b35fSStefano Zampini   }
1620e496cd5dSStefano Zampini #endif
162106a4e24aSStefano Zampini   if (matis->A->symmetric_set) {
162206a4e24aSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
162306a4e24aSStefano Zampini   }
162406a4e24aSStefano Zampini   if (matis->A->spd_set) {
162506a4e24aSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SPD,matis->A->spd);CHKERRQ(ierr);
162606a4e24aSStefano Zampini   }
1627e496cd5dSStefano Zampini 
16285e8657edSStefano Zampini   /* Set up all the "iterative substructuring" common block without computing solvers */
16295e8657edSStefano Zampini   {
16305e8657edSStefano Zampini     Mat temp_mat;
16315e8657edSStefano Zampini 
16325e8657edSStefano Zampini     temp_mat = matis->A;
16335e8657edSStefano Zampini     matis->A = pcbddc->local_mat;
16345e8657edSStefano Zampini     ierr = PCISSetUp(pc,PETSC_FALSE);CHKERRQ(ierr);
16355e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
16365e8657edSStefano Zampini     matis->A = temp_mat;
16375e8657edSStefano Zampini   }
1638684f6988SStefano Zampini 
163981d14e9dSStefano Zampini   /* Analyze interface */
164064ac59b8SStefano Zampini   if (!pcbddc->graphanalyzed) {
1641674ae819SStefano Zampini     ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
16428de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1643345ecf6cSStefano Zampini     if (pcbddc->adaptive_selection && !pcbddc->use_deluxe_scaling && !pcbddc->mat_graph->twodim) {
1644345ecf6cSStefano Zampini       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot compute the adaptive primal space for a problem with 3D edges without deluxe scaling");
1645345ecf6cSStefano Zampini     }
1646a198735bSStefano Zampini     if (pcbddc->compute_nonetflux) {
1647669cc0f4SStefano Zampini       MatNullSpace nnfnnsp;
1648669cc0f4SStefano Zampini 
16498ae0ca82SStefano Zampini       ierr = PCBDDCComputeNoNetFlux(pc->pmat,pcbddc->divudotp,pcbddc->divudotp_trans,pcbddc->divudotp_vl2l,pcbddc->mat_graph,&nnfnnsp);CHKERRQ(ierr);
165071582508SStefano Zampini       /* TODO what if a nearnullspace is already attached? */
1651669cc0f4SStefano Zampini       ierr = MatSetNearNullSpace(pc->pmat,nnfnnsp);CHKERRQ(ierr);
1652669cc0f4SStefano Zampini       ierr = MatNullSpaceDestroy(&nnfnnsp);CHKERRQ(ierr);
1653669cc0f4SStefano Zampini     }
1654674ae819SStefano Zampini   }
1655fb8d54d4SStefano Zampini 
16565408967cSStefano Zampini   /* check existence of a divergence free extension, i.e.
16575408967cSStefano Zampini      b(v_I,p_0) = 0 for all v_I (raise error if not).
16585408967cSStefano Zampini      Also, check that PCBDDCBenignGetOrSetP0 works */
16595408967cSStefano Zampini #if defined(PETSC_USE_DEBUG)
166009f581a4SStefano Zampini   if (pcbddc->benign_saddle_point) {
16615408967cSStefano Zampini     ierr = PCBDDCBenignCheck(pc,zerodiag);CHKERRQ(ierr);
166209f581a4SStefano Zampini   }
16635408967cSStefano Zampini #endif
16644f1b2e48SStefano Zampini   ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
166506f24817SStefano Zampini 
1666b96c3477SStefano Zampini   /* Setup local dirichlet solver ksp_D and sub_schurs solvers */
1667c703fcc7SStefano Zampini   if (computesubschurs && pcbddc->recompute_topography) {
166808122e43SStefano Zampini     ierr = PCBDDCInitSubSchurs(pc);CHKERRQ(ierr);
1669b1b3d7a2SStefano Zampini   }
16709d54b7f4SStefano Zampini   /* SetUp Scaling operator (scaling matrices could be needed in SubSchursSetUp)*/
16719d54b7f4SStefano Zampini   if (!pcbddc->use_deluxe_scaling) {
16729d54b7f4SStefano Zampini     ierr = PCBDDCScalingSetUp(pc);CHKERRQ(ierr);
16739d54b7f4SStefano Zampini   }
1674c703fcc7SStefano Zampini 
1675c703fcc7SStefano Zampini   /* finish setup solvers and do adaptive selection of constraints */
1676b334f244SStefano Zampini   sub_schurs = pcbddc->sub_schurs;
1677b334f244SStefano Zampini   if (sub_schurs && sub_schurs->schur_explicit) {
16782070dbb6SStefano Zampini     if (computesubschurs) {
167908122e43SStefano Zampini       ierr = PCBDDCSetUpSubSchurs(pc);CHKERRQ(ierr);
16802070dbb6SStefano Zampini     }
1681d5574798SStefano Zampini     ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr);
1682d5574798SStefano Zampini   } else {
1683d5574798SStefano Zampini     ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr);
16842070dbb6SStefano Zampini     if (computesubschurs) {
1685d5574798SStefano Zampini       ierr = PCBDDCSetUpSubSchurs(pc);CHKERRQ(ierr);
1686d5574798SStefano Zampini     }
16872070dbb6SStefano Zampini   }
168808122e43SStefano Zampini   if (pcbddc->adaptive_selection) {
168908122e43SStefano Zampini     ierr = PCBDDCAdaptiveSelection(pc);CHKERRQ(ierr);
16908de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1691b7eb3628SStefano Zampini   }
1692684f6988SStefano Zampini 
1693f4ddd8eeSStefano Zampini   /* infer if NullSpace object attached to Mat via MatSetNearNullSpace has changed */
1694fb8d54d4SStefano Zampini   new_nearnullspace_provided = PETSC_FALSE;
1695f4ddd8eeSStefano Zampini   ierr = MatGetNearNullSpace(pc->pmat,&nearnullspace);CHKERRQ(ierr);
1696f4ddd8eeSStefano Zampini   if (pcbddc->onearnullspace) { /* already used nearnullspace */
1697f4ddd8eeSStefano Zampini     if (!nearnullspace) { /* near null space attached to mat has been destroyed */
1698f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_TRUE;
1699f4ddd8eeSStefano Zampini     } else {
1700f4ddd8eeSStefano Zampini       /* determine if the two nullspaces are different (should be lightweight) */
1701f4ddd8eeSStefano Zampini       if (nearnullspace != pcbddc->onearnullspace) {
1702f4ddd8eeSStefano Zampini         new_nearnullspace_provided = PETSC_TRUE;
1703165b64e2SStefano Zampini       } else { /* maybe the user has changed the content of the nearnullspace so check vectors ObjectStateId */
1704f4ddd8eeSStefano Zampini         PetscInt         i;
1705165b64e2SStefano Zampini         const Vec        *nearnullvecs;
1706165b64e2SStefano Zampini         PetscObjectState state;
1707165b64e2SStefano Zampini         PetscInt         nnsp_size;
1708165b64e2SStefano Zampini         ierr = MatNullSpaceGetVecs(nearnullspace,NULL,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
1709f4ddd8eeSStefano Zampini         for (i=0;i<nnsp_size;i++) {
1710f4ddd8eeSStefano Zampini           ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&state);CHKERRQ(ierr);
1711165b64e2SStefano Zampini           if (pcbddc->onearnullvecs_state[i] != state) {
1712f4ddd8eeSStefano Zampini             new_nearnullspace_provided = PETSC_TRUE;
1713f4ddd8eeSStefano Zampini             break;
1714f4ddd8eeSStefano Zampini           }
1715f4ddd8eeSStefano Zampini         }
1716f4ddd8eeSStefano Zampini       }
1717f4ddd8eeSStefano Zampini     }
1718f4ddd8eeSStefano Zampini   } else {
1719f4ddd8eeSStefano Zampini     if (!nearnullspace) { /* both nearnullspaces are null */
1720f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_FALSE;
1721f4ddd8eeSStefano Zampini     } else { /* nearnullspace attached later */
1722f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_TRUE;
1723f4ddd8eeSStefano Zampini     }
1724f4ddd8eeSStefano Zampini   }
1725f4ddd8eeSStefano Zampini 
1726f4ddd8eeSStefano Zampini   /* Setup constraints and related work vectors */
1727727cdba6SStefano Zampini   /* reset primal space flags */
1728f4ddd8eeSStefano Zampini   pcbddc->new_primal_space = PETSC_FALSE;
1729727cdba6SStefano Zampini   pcbddc->new_primal_space_local = PETSC_FALSE;
17308de1fae6SStefano Zampini   if (computeconstraintsmatrix || new_nearnullspace_provided) {
1731727cdba6SStefano Zampini     /* It also sets the primal space flags */
1732674ae819SStefano Zampini     ierr = PCBDDCConstraintsSetUp(pc);CHKERRQ(ierr);
17339543d0ffSStefano Zampini   }
1734e7b262bdSStefano Zampini   /* Allocate needed local vectors (which depends on quantities defined during ConstraintsSetUp) */
1735f4ddd8eeSStefano Zampini   ierr = PCBDDCSetUpLocalWorkVectors(pc);CHKERRQ(ierr);
17365e8657edSStefano Zampini 
17375e8657edSStefano Zampini   if (pcbddc->use_change_of_basis) {
17385e8657edSStefano Zampini     PC_IS *pcis = (PC_IS*)(pc->data);
17395e8657edSStefano Zampini 
17405e8657edSStefano Zampini     ierr = PCBDDCComputeLocalMatrix(pc,pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
17414f1b2e48SStefano Zampini     if (pcbddc->benign_change) {
17421dd7afcfSStefano Zampini       ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
1743c263805aSStefano Zampini       /* pop B0 from pcbddc->local_mat */
1744c263805aSStefano Zampini       ierr = PCBDDCBenignPopOrPushB0(pc,PETSC_TRUE);CHKERRQ(ierr);
1745c263805aSStefano Zampini     }
17465e8657edSStefano Zampini     /* get submatrices */
17475e8657edSStefano Zampini     ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr);
17485e8657edSStefano Zampini     ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr);
17495e8657edSStefano Zampini     ierr = MatDestroy(&pcis->A_BB);CHKERRQ(ierr);
17505e8657edSStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_BB);CHKERRQ(ierr);
17515e8657edSStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_IB);CHKERRQ(ierr);
17525e8657edSStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&pcis->A_BI);CHKERRQ(ierr);
17533975b054SStefano Zampini     /* set flag in pcis to not reuse submatrices during PCISCreate */
17543975b054SStefano Zampini     pcis->reusesubmatrices = PETSC_FALSE;
17559c6a02ceSStefano Zampini   } else if (!pcbddc->user_ChangeOfBasisMatrix && !pcbddc->benign_change) {
1756b96c3477SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
17575e8657edSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
17585e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
17595e8657edSStefano Zampini   }
1760b96c3477SStefano Zampini   /* SetUp coarse and local Neumann solvers */
176199cc7994SStefano Zampini   ierr = PCBDDCSetUpSolvers(pc);CHKERRQ(ierr);
1762b96c3477SStefano Zampini   /* SetUp Scaling operator */
17639d54b7f4SStefano Zampini   if (pcbddc->use_deluxe_scaling) {
1764674ae819SStefano Zampini     ierr = PCBDDCScalingSetUp(pc);CHKERRQ(ierr);
17650c7d97c5SJed Brown   }
1766c703fcc7SStefano Zampini 
17671dd7afcfSStefano Zampini   /* mark topography as done */
176856282151SStefano Zampini   pcbddc->recompute_topography = PETSC_FALSE;
17690369aaf7SStefano Zampini 
17701dd7afcfSStefano Zampini   /* wrap pcis->A_IB and pcis->A_BI if we did not change explicitly the variables on the pressures */
17711dd7afcfSStefano Zampini   ierr = PCBDDCBenignShellMat(pc,PETSC_FALSE);CHKERRQ(ierr);
17721dd7afcfSStefano Zampini 
177358a03d70SStefano Zampini   if (pcbddc->dbg_flag) {
177458a03d70SStefano Zampini     ierr = PetscViewerASCIISubtractTab(pcbddc->dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
17752b510759SStefano Zampini   }
17760c7d97c5SJed Brown   PetscFunctionReturn(0);
17770c7d97c5SJed Brown }
17780c7d97c5SJed Brown 
17790c7d97c5SJed Brown /*
178050efa1b5SStefano Zampini    PCApply_BDDC - Applies the BDDC operator to a vector.
17810c7d97c5SJed Brown 
17820c7d97c5SJed Brown    Input Parameters:
17830f202f7eSStefano Zampini +  pc - the preconditioner context
17840f202f7eSStefano Zampini -  r - input vector (global)
17850c7d97c5SJed Brown 
17860c7d97c5SJed Brown    Output Parameter:
17870c7d97c5SJed Brown .  z - output vector (global)
17880c7d97c5SJed Brown 
17890c7d97c5SJed Brown    Application Interface Routine: PCApply()
17900c7d97c5SJed Brown  */
17910c7d97c5SJed Brown #undef __FUNCT__
17920c7d97c5SJed Brown #define __FUNCT__ "PCApply_BDDC"
179353cdbc3dSStefano Zampini PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z)
17940c7d97c5SJed Brown {
17950c7d97c5SJed Brown   PC_IS             *pcis = (PC_IS*)(pc->data);
17960c7d97c5SJed Brown   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
1797b097fa66SStefano Zampini   PetscInt          n_B = pcis->n_B, n_D = pcis->n - n_B;
17980c7d97c5SJed Brown   PetscErrorCode    ierr;
17993b03a366Sstefano_zampini   const PetscScalar one = 1.0;
18003b03a366Sstefano_zampini   const PetscScalar m_one = -1.0;
18012617d88aSStefano Zampini   const PetscScalar zero = 0.0;
18020c7d97c5SJed Brown 
18030c7d97c5SJed Brown /* This code is similar to that provided in nn.c for PCNN
18040c7d97c5SJed Brown    NN interface preconditioner changed to BDDC
1805b097fa66SStefano Zampini    Added support for M_3 preconditioner in the reference article (code is active if pcbddc->switch_static == PETSC_TRUE) */
18060c7d97c5SJed Brown 
18070c7d97c5SJed Brown   PetscFunctionBegin;
18081dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
18091dd7afcfSStefano Zampini     Vec swap;
181027b6a85dSStefano Zampini 
181127b6a85dSStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change);CHKERRQ(ierr);
18121dd7afcfSStefano Zampini     swap = pcbddc->work_change;
18131dd7afcfSStefano Zampini     pcbddc->work_change = r;
18141dd7afcfSStefano Zampini     r = swap;
18151dd7afcfSStefano Zampini     /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */
18168ae0ca82SStefano Zampini     if (pcbddc->benign_apply_coarse_only && pcbddc->exact_dirichlet_trick_app && pcbddc->change_interior) {
18171dd7afcfSStefano Zampini       ierr = VecCopy(r,pcis->vec1_global);CHKERRQ(ierr);
18181dd7afcfSStefano Zampini       ierr = VecLockPush(pcis->vec1_global);CHKERRQ(ierr);
18191dd7afcfSStefano Zampini     }
18201dd7afcfSStefano Zampini   }
182127b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* get p0 from r */
1822015636ebSStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,r,PETSC_TRUE);CHKERRQ(ierr);
1823efc2fbd9SStefano Zampini   }
18248ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
1825b097fa66SStefano Zampini     ierr = VecCopy(r,z);CHKERRQ(ierr);
18260c7d97c5SJed Brown     /* First Dirichlet solve */
18270c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
18280c7d97c5SJed Brown     ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
18290c7d97c5SJed Brown     /*
18300c7d97c5SJed Brown       Assembling right hand side for BDDC operator
1831b097fa66SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE)
1832674ae819SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
18330c7d97c5SJed Brown     */
1834b097fa66SStefano Zampini     if (n_D) {
1835b097fa66SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
18360c7d97c5SJed Brown       ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
183716909a7fSStefano Zampini       if (pcbddc->switch_static) {
183816909a7fSStefano Zampini         Mat_IS *matis = (Mat_IS*)(pc->mat->data);
183916909a7fSStefano Zampini 
184016909a7fSStefano Zampini         ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
184116909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
184216909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
184316909a7fSStefano Zampini         if (!pcbddc->switch_static_change) {
184416909a7fSStefano Zampini           ierr = MatMult(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
184516909a7fSStefano Zampini         } else {
184616909a7fSStefano Zampini           ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
184716909a7fSStefano Zampini           ierr = MatMult(matis->A,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr);
184816909a7fSStefano Zampini           ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
184916909a7fSStefano Zampini         }
185016909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
185116909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
185216909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
185316909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
185416909a7fSStefano Zampini       } else {
1855b097fa66SStefano Zampini         ierr = MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
185616909a7fSStefano Zampini       }
1857b097fa66SStefano Zampini     } else {
1858b097fa66SStefano Zampini       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
1859b097fa66SStefano Zampini     }
18600c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
18610c7d97c5SJed Brown     ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1862674ae819SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr);
1863b76ba322SStefano Zampini   } else {
18644fee134fSStefano Zampini     if (!pcbddc->benign_apply_coarse_only) {
1865674ae819SStefano Zampini       ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr);
1866b76ba322SStefano Zampini     }
18674fee134fSStefano Zampini   }
1868b76ba322SStefano Zampini 
18692617d88aSStefano Zampini   /* Apply interface preconditioner
18702617d88aSStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
1871dc359a40SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
18722617d88aSStefano Zampini 
1873674ae819SStefano Zampini   /* Apply transpose of partition of unity operator */
1874674ae819SStefano Zampini   ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr);
18750c7d97c5SJed Brown 
18763b03a366Sstefano_zampini   /* Second Dirichlet solve and assembling of output */
18770c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
18780c7d97c5SJed Brown   ierr = VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1879b097fa66SStefano Zampini   if (n_B) {
188016909a7fSStefano Zampini     if (pcbddc->switch_static) {
188116909a7fSStefano Zampini       Mat_IS *matis = (Mat_IS*)(pc->mat->data);
188216909a7fSStefano Zampini 
188316909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
188416909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
188516909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
188616909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
188716909a7fSStefano Zampini       if (!pcbddc->switch_static_change) {
188816909a7fSStefano Zampini         ierr = MatMult(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
188916909a7fSStefano Zampini       } else {
189016909a7fSStefano Zampini         ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
189116909a7fSStefano Zampini         ierr = MatMult(matis->A,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr);
189216909a7fSStefano Zampini         ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
189316909a7fSStefano Zampini       }
189416909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
189516909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
189616909a7fSStefano Zampini     } else {
18970c7d97c5SJed Brown       ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
189816909a7fSStefano Zampini     }
189916909a7fSStefano Zampini   } else if (pcbddc->switch_static) { /* n_B is zero */
190016909a7fSStefano Zampini     Mat_IS *matis = (Mat_IS*)(pc->mat->data);
190116909a7fSStefano Zampini 
190216909a7fSStefano Zampini     if (!pcbddc->switch_static_change) {
190316909a7fSStefano Zampini       ierr = MatMult(matis->A,pcis->vec1_D,pcis->vec3_D);CHKERRQ(ierr);
190416909a7fSStefano Zampini     } else {
190516909a7fSStefano Zampini       ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_D,pcis->vec1_N);CHKERRQ(ierr);
190616909a7fSStefano Zampini       ierr = MatMult(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
190716909a7fSStefano Zampini       ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec2_N,pcis->vec3_D);CHKERRQ(ierr);
190816909a7fSStefano Zampini     }
1909b097fa66SStefano Zampini   }
1910df187020SStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D);CHKERRQ(ierr);
1911efc2fbd9SStefano Zampini 
19128ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
1913b097fa66SStefano Zampini     if (pcbddc->switch_static) {
1914b097fa66SStefano Zampini       ierr = VecAXPBYPCZ(pcis->vec2_D,m_one,one,m_one,pcis->vec4_D,pcis->vec1_D);CHKERRQ(ierr);
1915b097fa66SStefano Zampini     } else {
1916b097fa66SStefano Zampini       ierr = VecAXPBY(pcis->vec2_D,m_one,m_one,pcis->vec4_D);CHKERRQ(ierr);
1917b097fa66SStefano Zampini     }
19180c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
19190c7d97c5SJed Brown     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1920b097fa66SStefano Zampini   } else {
1921b097fa66SStefano Zampini     if (pcbddc->switch_static) {
1922b097fa66SStefano Zampini       ierr = VecAXPBY(pcis->vec4_D,one,m_one,pcis->vec1_D);CHKERRQ(ierr);
1923b097fa66SStefano Zampini     } else {
1924b097fa66SStefano Zampini       ierr = VecScale(pcis->vec4_D,m_one);CHKERRQ(ierr);
1925b097fa66SStefano Zampini     }
1926b097fa66SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1927b097fa66SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1928b097fa66SStefano Zampini   }
192927b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */
19301dd7afcfSStefano Zampini     if (pcbddc->benign_apply_coarse_only) {
19311dd7afcfSStefano Zampini       ierr = PetscMemzero(pcbddc->benign_p0,pcbddc->benign_n*sizeof(PetscScalar));CHKERRQ(ierr);
19321dd7afcfSStefano Zampini     }
1933015636ebSStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,z,PETSC_FALSE);CHKERRQ(ierr);
1934efc2fbd9SStefano Zampini   }
19351f4df5f7SStefano Zampini 
19361dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
1937f913dca9SStefano Zampini     pcbddc->work_change = r;
19381dd7afcfSStefano Zampini     ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr);
19391dd7afcfSStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr);
19401dd7afcfSStefano Zampini   }
19410c7d97c5SJed Brown   PetscFunctionReturn(0);
19420c7d97c5SJed Brown }
194350efa1b5SStefano Zampini 
194450efa1b5SStefano Zampini /*
194550efa1b5SStefano Zampini    PCApplyTranspose_BDDC - Applies the transpose of the BDDC operator to a vector.
194650efa1b5SStefano Zampini 
194750efa1b5SStefano Zampini    Input Parameters:
19480f202f7eSStefano Zampini +  pc - the preconditioner context
19490f202f7eSStefano Zampini -  r - input vector (global)
195050efa1b5SStefano Zampini 
195150efa1b5SStefano Zampini    Output Parameter:
195250efa1b5SStefano Zampini .  z - output vector (global)
195350efa1b5SStefano Zampini 
195450efa1b5SStefano Zampini    Application Interface Routine: PCApplyTranspose()
195550efa1b5SStefano Zampini  */
195650efa1b5SStefano Zampini #undef __FUNCT__
195750efa1b5SStefano Zampini #define __FUNCT__ "PCApplyTranspose_BDDC"
195850efa1b5SStefano Zampini PetscErrorCode PCApplyTranspose_BDDC(PC pc,Vec r,Vec z)
195950efa1b5SStefano Zampini {
196050efa1b5SStefano Zampini   PC_IS             *pcis = (PC_IS*)(pc->data);
196150efa1b5SStefano Zampini   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
1962b097fa66SStefano Zampini   PetscInt          n_B = pcis->n_B, n_D = pcis->n - n_B;
196350efa1b5SStefano Zampini   PetscErrorCode    ierr;
196450efa1b5SStefano Zampini   const PetscScalar one = 1.0;
196550efa1b5SStefano Zampini   const PetscScalar m_one = -1.0;
196650efa1b5SStefano Zampini   const PetscScalar zero = 0.0;
196750efa1b5SStefano Zampini 
196850efa1b5SStefano Zampini   PetscFunctionBegin;
19691dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
19701dd7afcfSStefano Zampini     Vec swap;
197127b6a85dSStefano Zampini 
197227b6a85dSStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change);CHKERRQ(ierr);
19731dd7afcfSStefano Zampini     swap = pcbddc->work_change;
19741dd7afcfSStefano Zampini     pcbddc->work_change = r;
19751dd7afcfSStefano Zampini     r = swap;
197627b6a85dSStefano Zampini     /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */
19778ae0ca82SStefano Zampini     if (pcbddc->benign_apply_coarse_only && pcbddc->exact_dirichlet_trick_app && pcbddc->change_interior) {
197827b6a85dSStefano Zampini       ierr = VecCopy(r,pcis->vec1_global);CHKERRQ(ierr);
197927b6a85dSStefano Zampini       ierr = VecLockPush(pcis->vec1_global);CHKERRQ(ierr);
19801dd7afcfSStefano Zampini     }
198127b6a85dSStefano Zampini   }
198227b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* get p0 from r */
1983537c1cdfSStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,r,PETSC_TRUE);CHKERRQ(ierr);
1984537c1cdfSStefano Zampini   }
19858ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
1986b097fa66SStefano Zampini     ierr = VecCopy(r,z);CHKERRQ(ierr);
198750efa1b5SStefano Zampini     /* First Dirichlet solve */
198850efa1b5SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
198950efa1b5SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
199050efa1b5SStefano Zampini     /*
199150efa1b5SStefano Zampini       Assembling right hand side for BDDC operator
1992b097fa66SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE)
199350efa1b5SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
199450efa1b5SStefano Zampini     */
1995b097fa66SStefano Zampini     if (n_D) {
1996b097fa66SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
199750efa1b5SStefano Zampini       ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
199816909a7fSStefano Zampini       if (pcbddc->switch_static) {
199916909a7fSStefano Zampini         Mat_IS *matis = (Mat_IS*)(pc->mat->data);
200016909a7fSStefano Zampini 
200116909a7fSStefano Zampini         ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
200216909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
200316909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
200416909a7fSStefano Zampini         if (!pcbddc->switch_static_change) {
200516909a7fSStefano Zampini           ierr = MatMultTranspose(matis->A,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);
200816909a7fSStefano Zampini           ierr = MatMultTranspose(matis->A,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->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
201216909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
201316909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
201416909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
201516909a7fSStefano Zampini       } else {
2016b097fa66SStefano Zampini         ierr = MatMultTranspose(pcis->A_IB,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
201716909a7fSStefano Zampini       }
2018b097fa66SStefano Zampini     } else {
2019b097fa66SStefano Zampini       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
2020b097fa66SStefano Zampini     }
202150efa1b5SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
202250efa1b5SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
202350efa1b5SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr);
202450efa1b5SStefano Zampini   } else {
202550efa1b5SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr);
202650efa1b5SStefano Zampini   }
202750efa1b5SStefano Zampini 
202850efa1b5SStefano Zampini   /* Apply interface preconditioner
202950efa1b5SStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
2030dc359a40SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_TRUE);CHKERRQ(ierr);
203150efa1b5SStefano Zampini 
203250efa1b5SStefano Zampini   /* Apply transpose of partition of unity operator */
203350efa1b5SStefano Zampini   ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr);
203450efa1b5SStefano Zampini 
203550efa1b5SStefano Zampini   /* Second Dirichlet solve and assembling of output */
203650efa1b5SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
203750efa1b5SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2038b097fa66SStefano Zampini   if (n_B) {
203916909a7fSStefano Zampini     if (pcbddc->switch_static) {
204016909a7fSStefano Zampini       Mat_IS *matis = (Mat_IS*)(pc->mat->data);
204116909a7fSStefano Zampini 
204216909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
204316909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
204416909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
204516909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
204616909a7fSStefano Zampini       if (!pcbddc->switch_static_change) {
204716909a7fSStefano Zampini         ierr = MatMultTranspose(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
204816909a7fSStefano Zampini       } else {
204916909a7fSStefano Zampini         ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
205016909a7fSStefano Zampini         ierr = MatMultTranspose(matis->A,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr);
205116909a7fSStefano Zampini         ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
205216909a7fSStefano Zampini       }
205316909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
205416909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
205516909a7fSStefano Zampini     } else {
205650efa1b5SStefano Zampini       ierr = MatMultTranspose(pcis->A_BI,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
205716909a7fSStefano Zampini     }
205816909a7fSStefano Zampini   } else if (pcbddc->switch_static) { /* n_B is zero */
205916909a7fSStefano Zampini     Mat_IS *matis = (Mat_IS*)(pc->mat->data);
206016909a7fSStefano Zampini 
206116909a7fSStefano Zampini     if (!pcbddc->switch_static_change) {
206216909a7fSStefano Zampini       ierr = MatMultTranspose(matis->A,pcis->vec1_D,pcis->vec3_D);CHKERRQ(ierr);
206316909a7fSStefano Zampini     } else {
206416909a7fSStefano Zampini       ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_D,pcis->vec1_N);CHKERRQ(ierr);
206516909a7fSStefano Zampini       ierr = MatMultTranspose(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
206616909a7fSStefano Zampini       ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec2_N,pcis->vec3_D);CHKERRQ(ierr);
206716909a7fSStefano Zampini     }
2068b097fa66SStefano Zampini   }
2069b0147a47SStefano Zampini   ierr = KSPSolveTranspose(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D);CHKERRQ(ierr);
20708ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
2071b097fa66SStefano Zampini     if (pcbddc->switch_static) {
2072b097fa66SStefano Zampini       ierr = VecAXPBYPCZ(pcis->vec2_D,m_one,one,m_one,pcis->vec4_D,pcis->vec1_D);CHKERRQ(ierr);
2073b097fa66SStefano Zampini     } else {
2074b097fa66SStefano Zampini       ierr = VecAXPBY(pcis->vec2_D,m_one,m_one,pcis->vec4_D);CHKERRQ(ierr);
2075b097fa66SStefano Zampini     }
207650efa1b5SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
207750efa1b5SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2078b097fa66SStefano Zampini   } else {
2079b097fa66SStefano Zampini     if (pcbddc->switch_static) {
2080b097fa66SStefano Zampini       ierr = VecAXPBY(pcis->vec4_D,one,m_one,pcis->vec1_D);CHKERRQ(ierr);
2081b097fa66SStefano Zampini     } else {
2082b097fa66SStefano Zampini       ierr = VecScale(pcis->vec4_D,m_one);CHKERRQ(ierr);
2083b097fa66SStefano Zampini     }
2084b097fa66SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2085b097fa66SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2086b097fa66SStefano Zampini   }
208727b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */
2088537c1cdfSStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,z,PETSC_FALSE);CHKERRQ(ierr);
2089537c1cdfSStefano Zampini   }
20901dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
2091f913dca9SStefano Zampini     pcbddc->work_change = r;
20921dd7afcfSStefano Zampini     ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr);
20931dd7afcfSStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr);
20941dd7afcfSStefano Zampini   }
209550efa1b5SStefano Zampini   PetscFunctionReturn(0);
209650efa1b5SStefano Zampini }
2097674ae819SStefano Zampini 
2098da1bb401SStefano Zampini #undef __FUNCT__
2099da1bb401SStefano Zampini #define __FUNCT__ "PCDestroy_BDDC"
2100da1bb401SStefano Zampini PetscErrorCode PCDestroy_BDDC(PC pc)
2101da1bb401SStefano Zampini {
2102da1bb401SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2103da1bb401SStefano Zampini   PetscErrorCode ierr;
2104da1bb401SStefano Zampini 
2105da1bb401SStefano Zampini   PetscFunctionBegin;
2106674ae819SStefano Zampini   /* free BDDC custom data  */
2107674ae819SStefano Zampini   ierr = PCBDDCResetCustomization(pc);CHKERRQ(ierr);
2108674ae819SStefano Zampini   /* destroy objects related to topography */
2109674ae819SStefano Zampini   ierr = PCBDDCResetTopography(pc);CHKERRQ(ierr);
2110674ae819SStefano Zampini   /* free allocated graph structure */
2111da1bb401SStefano Zampini   ierr = PetscFree(pcbddc->mat_graph);CHKERRQ(ierr);
2112b96c3477SStefano Zampini   /* free allocated sub schurs structure */
2113b96c3477SStefano Zampini   ierr = PetscFree(pcbddc->sub_schurs);CHKERRQ(ierr);
211434a97f8cSStefano Zampini   /* destroy objects for scaling operator */
2115674ae819SStefano Zampini   ierr = PCBDDCScalingDestroy(pc);CHKERRQ(ierr);
211634a97f8cSStefano Zampini   ierr = PetscFree(pcbddc->deluxe_ctx);CHKERRQ(ierr);
2117674ae819SStefano Zampini   /* free solvers stuff */
2118674ae819SStefano Zampini   ierr = PCBDDCResetSolvers(pc);CHKERRQ(ierr);
211962a6ff1dSStefano Zampini   /* free global vectors needed in presolve */
212062a6ff1dSStefano Zampini   ierr = VecDestroy(&pcbddc->temp_solution);CHKERRQ(ierr);
212162a6ff1dSStefano Zampini   ierr = VecDestroy(&pcbddc->original_rhs);CHKERRQ(ierr);
21221dd7afcfSStefano Zampini   /* free data created by PCIS */
21231dd7afcfSStefano Zampini   ierr = PCISDestroy(pc);CHKERRQ(ierr);
21243425bc38SStefano Zampini   /* remove functions */
2125a13144ffSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDiscreteGradient_C",NULL);CHKERRQ(ierr);
2126a198735bSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDivergenceMat_C",NULL);CHKERRQ(ierr);
2127906d46d4SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",NULL);CHKERRQ(ierr);
2128674ae819SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",NULL);CHKERRQ(ierr);
212930368db7SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesIS_C",NULL);CHKERRQ(ierr);
2130bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",NULL);CHKERRQ(ierr);
21312b510759SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",NULL);CHKERRQ(ierr);
2132b8ffe317SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",NULL);CHKERRQ(ierr);
21332b510759SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",NULL);CHKERRQ(ierr);
2134bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",NULL);CHKERRQ(ierr);
213582ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",NULL);CHKERRQ(ierr);
2136bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",NULL);CHKERRQ(ierr);
213782ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",NULL);CHKERRQ(ierr);
2138bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",NULL);CHKERRQ(ierr);
213982ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",NULL);CHKERRQ(ierr);
2140bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",NULL);CHKERRQ(ierr);
2141785d1243SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",NULL);CHKERRQ(ierr);
2142bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",NULL);CHKERRQ(ierr);
214363602bcaSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",NULL);CHKERRQ(ierr);
2144bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",NULL);CHKERRQ(ierr);
2145bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",NULL);CHKERRQ(ierr);
2146bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",NULL);CHKERRQ(ierr);
2147bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",NULL);CHKERRQ(ierr);
2148a06fd7f2SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCPreSolveChangeRHS_C",NULL);CHKERRQ(ierr);
2149674ae819SStefano Zampini   /* Free the private data structure */
2150674ae819SStefano Zampini   ierr = PetscFree(pc->data);CHKERRQ(ierr);
2151da1bb401SStefano Zampini   PetscFunctionReturn(0);
2152da1bb401SStefano Zampini }
21531e6b0712SBarry Smith 
21543425bc38SStefano Zampini #undef __FUNCT__
2155a06fd7f2SStefano Zampini #define __FUNCT__ "PCPreSolveChangeRHS_BDDC"
2156a06fd7f2SStefano Zampini static PetscErrorCode PCPreSolveChangeRHS_BDDC(PC pc, PetscBool* change)
2157a06fd7f2SStefano Zampini {
2158a06fd7f2SStefano Zampini   PetscFunctionBegin;
2159a06fd7f2SStefano Zampini   *change = PETSC_TRUE;
2160a06fd7f2SStefano Zampini   PetscFunctionReturn(0);
2161a06fd7f2SStefano Zampini }
2162a06fd7f2SStefano Zampini 
2163a06fd7f2SStefano Zampini #undef __FUNCT__
21643425bc38SStefano Zampini #define __FUNCT__ "PCBDDCMatFETIDPGetRHS_BDDC"
21653425bc38SStefano Zampini static PetscErrorCode PCBDDCMatFETIDPGetRHS_BDDC(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
21663425bc38SStefano Zampini {
2167674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
2168266e20e9SStefano Zampini   Vec            work;
21693425bc38SStefano Zampini   PC_IS*         pcis;
21703425bc38SStefano Zampini   PC_BDDC*       pcbddc;
21713425bc38SStefano Zampini   PetscErrorCode ierr;
21720c7d97c5SJed Brown 
21733425bc38SStefano Zampini   PetscFunctionBegin;
21743425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
21753425bc38SStefano Zampini   pcis = (PC_IS*)mat_ctx->pc->data;
21763425bc38SStefano Zampini   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
21773425bc38SStefano Zampini 
2178c08af4c6SStefano Zampini   /*
2179c08af4c6SStefano Zampini      change of basis for physical rhs if needed
2180c08af4c6SStefano Zampini      It also changes the rhs in case of dirichlet boundaries
2181c08af4c6SStefano Zampini   */
21823738a8e6SStefano Zampini   if (!pcbddc->original_rhs) {
21833738a8e6SStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs);CHKERRQ(ierr);
21843738a8e6SStefano Zampini   }
21853738a8e6SStefano Zampini   ierr = VecCopy(standard_rhs,pcbddc->original_rhs);CHKERRQ(ierr);
21863738a8e6SStefano Zampini   ierr = PCPreSolve_BDDC(mat_ctx->pc,NULL,pcbddc->original_rhs,NULL);CHKERRQ(ierr);
2187fc17d649SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
21883738a8e6SStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,pcbddc->original_rhs,pcbddc->work_change);CHKERRQ(ierr);
21893738a8e6SStefano Zampini     work = pcbddc->work_change;
2190fc17d649SStefano Zampini    } else {
21913738a8e6SStefano Zampini     work = pcbddc->original_rhs;
2192fc17d649SStefano Zampini   }
21933425bc38SStefano Zampini   /* store vectors for computation of fetidp final solution */
2194266e20e9SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,work,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2195266e20e9SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,work,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2196fb223d50SStefano Zampini   /* scale rhs since it should be unassembled */
2197fb223d50SStefano Zampini   /* TODO use counter scaling? (also below) */
2198266e20e9SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2199266e20e9SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2200674ae819SStefano Zampini   /* Apply partition of unity */
22013425bc38SStefano Zampini   ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr);
2202266e20e9SStefano Zampini   /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,work,mat_ctx->temp_solution_B);CHKERRQ(ierr); */
22038eeda7d8SStefano Zampini   if (!pcbddc->switch_static) {
22043425bc38SStefano Zampini     /* compute partially subassembled Schur complement right-hand side */
22053425bc38SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
22063425bc38SStefano Zampini     ierr = MatMult(pcis->A_BI,pcis->vec1_D,pcis->vec1_B);CHKERRQ(ierr);
22073425bc38SStefano Zampini     ierr = VecAXPY(mat_ctx->temp_solution_B,-1.0,pcis->vec1_B);CHKERRQ(ierr);
2208266e20e9SStefano Zampini     ierr = VecSet(work,0.0);CHKERRQ(ierr);
2209266e20e9SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,mat_ctx->temp_solution_B,work,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2210266e20e9SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,mat_ctx->temp_solution_B,work,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2211266e20e9SStefano Zampini     /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,work,mat_ctx->temp_solution_B);CHKERRQ(ierr); */
2212266e20e9SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2213266e20e9SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
22143425bc38SStefano Zampini     ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr);
22153425bc38SStefano Zampini   }
22163425bc38SStefano Zampini   /* BDDC rhs */
22173425bc38SStefano Zampini   ierr = VecCopy(mat_ctx->temp_solution_B,pcis->vec1_B);CHKERRQ(ierr);
22188eeda7d8SStefano Zampini   if (pcbddc->switch_static) {
22193425bc38SStefano Zampini     ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
22203425bc38SStefano Zampini   }
2221fc17d649SStefano Zampini   ierr = PetscMemzero(pcbddc->benign_p0,pcbddc->benign_n*sizeof(PetscScalar));CHKERRQ(ierr);
22223425bc38SStefano Zampini   /* apply BDDC */
2223dc359a40SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE);CHKERRQ(ierr);
2224266e20e9SStefano Zampini   ierr = PetscMemzero(pcbddc->benign_p0,pcbddc->benign_n*sizeof(PetscScalar));CHKERRQ(ierr);
22253425bc38SStefano Zampini   /* Application of B_delta and assembling of rhs for fetidp fluxes */
22263425bc38SStefano Zampini   ierr = VecSet(fetidp_flux_rhs,0.0);CHKERRQ(ierr);
22273425bc38SStefano Zampini   ierr = MatMult(mat_ctx->B_delta,pcis->vec1_B,mat_ctx->lambda_local);CHKERRQ(ierr);
22283425bc38SStefano Zampini   ierr = VecScatterBegin(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
22293425bc38SStefano Zampini   ierr = VecScatterEnd(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
22303425bc38SStefano Zampini   PetscFunctionReturn(0);
22313425bc38SStefano Zampini }
22321e6b0712SBarry Smith 
22333425bc38SStefano Zampini #undef __FUNCT__
22343425bc38SStefano Zampini #define __FUNCT__ "PCBDDCMatFETIDPGetRHS"
22353425bc38SStefano Zampini /*@
22360f202f7eSStefano Zampini  PCBDDCMatFETIDPGetRHS - Compute the right-hand side for FETI-DP linear system using the physical right-hand side
22373425bc38SStefano Zampini 
22383425bc38SStefano Zampini    Collective
22393425bc38SStefano Zampini 
22403425bc38SStefano Zampini    Input Parameters:
22410f202f7eSStefano Zampini +  fetidp_mat      - the FETI-DP matrix object obtained by a call to PCBDDCCreateFETIDPOperators
22420f202f7eSStefano Zampini -  standard_rhs    - the right-hand side of the original linear system
22433425bc38SStefano Zampini 
22443425bc38SStefano Zampini    Output Parameters:
22450f202f7eSStefano Zampini .  fetidp_flux_rhs - the right-hand side for the FETI-DP linear system
22463425bc38SStefano Zampini 
22473425bc38SStefano Zampini    Level: developer
22483425bc38SStefano Zampini 
22493425bc38SStefano Zampini    Notes:
22503425bc38SStefano Zampini 
22510f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCCreateFETIDPOperators, PCBDDCMatFETIDPGetSolution
22523425bc38SStefano Zampini @*/
22533425bc38SStefano Zampini PetscErrorCode PCBDDCMatFETIDPGetRHS(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
22543425bc38SStefano Zampini {
2255674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
22563425bc38SStefano Zampini   PetscErrorCode ierr;
22573425bc38SStefano Zampini 
22583425bc38SStefano Zampini   PetscFunctionBegin;
2259266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_mat,MAT_CLASSID,1);
2260266e20e9SStefano Zampini   PetscValidHeaderSpecific(standard_rhs,VEC_CLASSID,2);
2261266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_flux_rhs,VEC_CLASSID,3);
22623425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
2263163d334eSBarry Smith   ierr = PetscUseMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetRHS_C",(Mat,Vec,Vec),(fetidp_mat,standard_rhs,fetidp_flux_rhs));CHKERRQ(ierr);
22643425bc38SStefano Zampini   PetscFunctionReturn(0);
22653425bc38SStefano Zampini }
22661e6b0712SBarry Smith 
22673425bc38SStefano Zampini #undef __FUNCT__
22683425bc38SStefano Zampini #define __FUNCT__ "PCBDDCMatFETIDPGetSolution_BDDC"
22693425bc38SStefano Zampini static PetscErrorCode PCBDDCMatFETIDPGetSolution_BDDC(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
22703425bc38SStefano Zampini {
2271674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
22723425bc38SStefano Zampini   PC_IS*         pcis;
22733425bc38SStefano Zampini   PC_BDDC*       pcbddc;
22743425bc38SStefano Zampini   PetscErrorCode ierr;
22753425bc38SStefano Zampini 
22763425bc38SStefano Zampini   PetscFunctionBegin;
22773425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
22783425bc38SStefano Zampini   pcis = (PC_IS*)mat_ctx->pc->data;
22793425bc38SStefano Zampini   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
22803425bc38SStefano Zampini 
22813425bc38SStefano Zampini   /* apply B_delta^T */
22823425bc38SStefano Zampini   ierr = VecScatterBegin(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
22833425bc38SStefano Zampini   ierr = VecScatterEnd(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
22843425bc38SStefano Zampini   ierr = MatMultTranspose(mat_ctx->B_delta,mat_ctx->lambda_local,pcis->vec1_B);CHKERRQ(ierr);
22853425bc38SStefano Zampini   /* compute rhs for BDDC application */
22863425bc38SStefano Zampini   ierr = VecAYPX(pcis->vec1_B,-1.0,mat_ctx->temp_solution_B);CHKERRQ(ierr);
22878eeda7d8SStefano Zampini   if (pcbddc->switch_static) {
22883425bc38SStefano Zampini     ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
22893425bc38SStefano Zampini   }
2290fc17d649SStefano Zampini   ierr = PetscMemzero(pcbddc->benign_p0,pcbddc->benign_n*sizeof(PetscScalar));CHKERRQ(ierr);
22913425bc38SStefano Zampini   /* apply BDDC */
2292dc359a40SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE);CHKERRQ(ierr);
22933425bc38SStefano Zampini   /* put values into standard global vector */
22943425bc38SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
22953425bc38SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
22968eeda7d8SStefano Zampini   if (!pcbddc->switch_static) {
22973425bc38SStefano Zampini     /* compute values into the interior if solved for the partially subassembled Schur complement */
22983425bc38SStefano Zampini     ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec1_D);CHKERRQ(ierr);
229900f6b531SStefano Zampini     ierr = VecAYPX(pcis->vec1_D,-1.0,mat_ctx->temp_solution_D);CHKERRQ(ierr);
230000f6b531SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr);
23013425bc38SStefano Zampini   }
23023425bc38SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec1_D,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
23033425bc38SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,pcis->vec1_D,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2304266e20e9SStefano Zampini   /* add p0 solution to final solution */
2305266e20e9SStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(mat_ctx->pc,standard_sol,PETSC_FALSE);CHKERRQ(ierr);
2306fc17d649SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
2307fc17d649SStefano Zampini     Vec v2;
2308fc17d649SStefano Zampini     ierr = VecDuplicate(standard_sol,&v2);CHKERRQ(ierr);
2309fc17d649SStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,standard_sol,v2);CHKERRQ(ierr);
2310fc17d649SStefano Zampini     ierr = VecCopy(v2,standard_sol);CHKERRQ(ierr);
2311fc17d649SStefano Zampini     ierr = VecDestroy(&v2);CHKERRQ(ierr);
2312fc17d649SStefano Zampini   }
23133308cffdSStefano Zampini   ierr = PCPostSolve_BDDC(mat_ctx->pc,NULL,NULL,standard_sol);CHKERRQ(ierr);
23143425bc38SStefano Zampini   PetscFunctionReturn(0);
23153425bc38SStefano Zampini }
23161e6b0712SBarry Smith 
23173425bc38SStefano Zampini #undef __FUNCT__
23183425bc38SStefano Zampini #define __FUNCT__ "PCBDDCMatFETIDPGetSolution"
23193425bc38SStefano Zampini /*@
23200f202f7eSStefano Zampini  PCBDDCMatFETIDPGetSolution - Compute the physical solution using the solution of the FETI-DP linear system
23213425bc38SStefano Zampini 
23223425bc38SStefano Zampini    Collective
23233425bc38SStefano Zampini 
23243425bc38SStefano Zampini    Input Parameters:
23250f202f7eSStefano Zampini +  fetidp_mat      - the FETI-DP matrix obtained by a call to PCBDDCCreateFETIDPOperators
23260f202f7eSStefano Zampini -  fetidp_flux_sol - the solution of the FETI-DP linear system
23273425bc38SStefano Zampini 
23283425bc38SStefano Zampini    Output Parameters:
23290f202f7eSStefano Zampini .  standard_sol    - the solution defined on the physical domain
23303425bc38SStefano Zampini 
23313425bc38SStefano Zampini    Level: developer
23323425bc38SStefano Zampini 
23333425bc38SStefano Zampini    Notes:
23343425bc38SStefano Zampini 
23350f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCCreateFETIDPOperators, PCBDDCMatFETIDPGetRHS
23363425bc38SStefano Zampini @*/
23373425bc38SStefano Zampini PetscErrorCode PCBDDCMatFETIDPGetSolution(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
23383425bc38SStefano Zampini {
2339674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
23403425bc38SStefano Zampini   PetscErrorCode ierr;
23413425bc38SStefano Zampini 
23423425bc38SStefano Zampini   PetscFunctionBegin;
2343266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_mat,MAT_CLASSID,1);
2344266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_flux_sol,VEC_CLASSID,2);
2345266e20e9SStefano Zampini   PetscValidHeaderSpecific(standard_sol,VEC_CLASSID,3);
23463425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
2347163d334eSBarry Smith   ierr = PetscUseMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetSolution_C",(Mat,Vec,Vec),(fetidp_mat,fetidp_flux_sol,standard_sol));CHKERRQ(ierr);
23483425bc38SStefano Zampini   PetscFunctionReturn(0);
23493425bc38SStefano Zampini }
23501e6b0712SBarry Smith 
2351f23aa3ddSBarry Smith extern PetscErrorCode FETIDPMatMult(Mat,Vec,Vec);
2352edf7251bSStefano Zampini extern PetscErrorCode FETIDPMatMultTranspose(Mat,Vec,Vec);
2353f23aa3ddSBarry Smith extern PetscErrorCode PCBDDCDestroyFETIDPMat(Mat);
2354f23aa3ddSBarry Smith extern PetscErrorCode FETIDPPCApply(PC,Vec,Vec);
2355edf7251bSStefano Zampini extern PetscErrorCode FETIDPPCApplyTranspose(PC,Vec,Vec);
2356f23aa3ddSBarry Smith extern PetscErrorCode PCBDDCDestroyFETIDPPC(PC);
2357674ae819SStefano Zampini 
23583425bc38SStefano Zampini #undef __FUNCT__
23593425bc38SStefano Zampini #define __FUNCT__ "PCBDDCCreateFETIDPOperators_BDDC"
23601720468bSStefano Zampini static PetscErrorCode PCBDDCCreateFETIDPOperators_BDDC(PC pc, PetscBool fully_redundant, Mat *fetidp_mat, PC *fetidp_pc)
23613425bc38SStefano Zampini {
2362674ae819SStefano Zampini 
2363674ae819SStefano Zampini   FETIDPMat_ctx  fetidpmat_ctx;
23643425bc38SStefano Zampini   Mat            newmat;
2365674ae819SStefano Zampini   FETIDPPC_ctx   fetidppc_ctx;
23663425bc38SStefano Zampini   PC             newpc;
2367ce94432eSBarry Smith   MPI_Comm       comm;
23683425bc38SStefano Zampini   PetscErrorCode ierr;
23693425bc38SStefano Zampini 
23703425bc38SStefano Zampini   PetscFunctionBegin;
2371ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
23723425bc38SStefano Zampini   /* FETIDP linear matrix */
23733425bc38SStefano Zampini   ierr = PCBDDCCreateFETIDPMatContext(pc,&fetidpmat_ctx);CHKERRQ(ierr);
23741720468bSStefano Zampini   fetidpmat_ctx->fully_redundant = fully_redundant;
23753425bc38SStefano Zampini   ierr = PCBDDCSetupFETIDPMatContext(fetidpmat_ctx);CHKERRQ(ierr);
23763425bc38SStefano Zampini   ierr = MatCreateShell(comm,PETSC_DECIDE,PETSC_DECIDE,fetidpmat_ctx->n_lambda,fetidpmat_ctx->n_lambda,fetidpmat_ctx,&newmat);CHKERRQ(ierr);
23773425bc38SStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_MULT,(void (*)(void))FETIDPMatMult);CHKERRQ(ierr);
2378edf7251bSStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_MULT_TRANSPOSE,(void (*)(void))FETIDPMatMultTranspose);CHKERRQ(ierr);
23793425bc38SStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_DESTROY,(void (*)(void))PCBDDCDestroyFETIDPMat);CHKERRQ(ierr);
23803425bc38SStefano Zampini   ierr = MatSetUp(newmat);CHKERRQ(ierr);
23813425bc38SStefano Zampini   /* FETIDP preconditioner */
23823425bc38SStefano Zampini   ierr = PCBDDCCreateFETIDPPCContext(pc,&fetidppc_ctx);CHKERRQ(ierr);
23833425bc38SStefano Zampini   ierr = PCBDDCSetupFETIDPPCContext(newmat,fetidppc_ctx);CHKERRQ(ierr);
23843425bc38SStefano Zampini   ierr = PCCreate(comm,&newpc);CHKERRQ(ierr);
23853425bc38SStefano Zampini   ierr = PCSetType(newpc,PCSHELL);CHKERRQ(ierr);
23863425bc38SStefano Zampini   ierr = PCShellSetContext(newpc,fetidppc_ctx);CHKERRQ(ierr);
23873425bc38SStefano Zampini   ierr = PCShellSetApply(newpc,FETIDPPCApply);CHKERRQ(ierr);
2388edf7251bSStefano Zampini   ierr = PCShellSetApplyTranspose(newpc,FETIDPPCApplyTranspose);CHKERRQ(ierr);
23893425bc38SStefano Zampini   ierr = PCShellSetDestroy(newpc,PCBDDCDestroyFETIDPPC);CHKERRQ(ierr);
239023ee1639SBarry Smith   ierr = PCSetOperators(newpc,newmat,newmat);CHKERRQ(ierr);
23913425bc38SStefano Zampini   ierr = PCSetUp(newpc);CHKERRQ(ierr);
23923425bc38SStefano Zampini   /* return pointers for objects created */
23933425bc38SStefano Zampini   *fetidp_mat=newmat;
23943425bc38SStefano Zampini   *fetidp_pc=newpc;
23953425bc38SStefano Zampini   PetscFunctionReturn(0);
23963425bc38SStefano Zampini }
23971e6b0712SBarry Smith 
23983425bc38SStefano Zampini #undef __FUNCT__
23993425bc38SStefano Zampini #define __FUNCT__ "PCBDDCCreateFETIDPOperators"
24003425bc38SStefano Zampini /*@
24010f202f7eSStefano Zampini  PCBDDCCreateFETIDPOperators - Create FETI-DP operators
24023425bc38SStefano Zampini 
24033425bc38SStefano Zampini    Collective
24043425bc38SStefano Zampini 
24053425bc38SStefano Zampini    Input Parameters:
24061720468bSStefano Zampini +  pc - the BDDC preconditioning context (setup should have been called before)
24071720468bSStefano Zampini -  fully_redundant - true for a fully redundant set of Lagrange multipliers
240828509bceSStefano Zampini 
240928509bceSStefano Zampini    Output Parameters:
24100f202f7eSStefano Zampini +  fetidp_mat - shell FETI-DP matrix object
24110f202f7eSStefano Zampini -  fetidp_pc  - shell Dirichlet preconditioner for FETI-DP matrix
241228509bceSStefano Zampini 
24133425bc38SStefano Zampini    Level: developer
24143425bc38SStefano Zampini 
24153425bc38SStefano Zampini    Notes:
24160f202f7eSStefano Zampini      Currently the only operations provided for FETI-DP matrix are MatMult and MatMultTranspose
24173425bc38SStefano Zampini 
24180f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCMatFETIDPGetRHS, PCBDDCMatFETIDPGetSolution
24193425bc38SStefano Zampini @*/
24201720468bSStefano Zampini PetscErrorCode PCBDDCCreateFETIDPOperators(PC pc, PetscBool fully_redundant, Mat *fetidp_mat, PC *fetidp_pc)
24213425bc38SStefano Zampini {
24223425bc38SStefano Zampini   PetscErrorCode ierr;
24233425bc38SStefano Zampini 
24243425bc38SStefano Zampini   PetscFunctionBegin;
24253425bc38SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
24263425bc38SStefano Zampini   if (pc->setupcalled) {
24271720468bSStefano Zampini     ierr = PetscUseMethod(pc,"PCBDDCCreateFETIDPOperators_C",(PC,PetscBool,Mat*,PC*),(pc,fully_redundant,fetidp_mat,fetidp_pc));CHKERRQ(ierr);
2428f23aa3ddSBarry Smith   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"You must call PCSetup_BDDC() first \n");
24293425bc38SStefano Zampini   PetscFunctionReturn(0);
24303425bc38SStefano Zampini }
24310c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
2432da1bb401SStefano Zampini /*MC
2433da1bb401SStefano Zampini    PCBDDC - Balancing Domain Decomposition by Constraints.
24340c7d97c5SJed Brown 
243528509bceSStefano Zampini    An implementation of the BDDC preconditioner based on
243628509bceSStefano Zampini 
243728509bceSStefano Zampini .vb
243828509bceSStefano Zampini    [1] C. R. Dohrmann. "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149-168, March 2007
243928509bceSStefano Zampini    [2] A. Klawonn and O. B. Widlund. "Dual-Primal FETI Methods for Linear Elasticity", http://cs.nyu.edu/csweb/Research/TechReports/TR2004-855/TR2004-855.pdf
244028509bceSStefano Zampini    [3] J. Mandel, B. Sousedik, C. R. Dohrmann. "Multispace and Multilevel BDDC", http://arxiv.org/abs/0712.3977
24410f202f7eSStefano 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
244228509bceSStefano Zampini .ve
244328509bceSStefano Zampini 
244428509bceSStefano Zampini    The matrix to be preconditioned (Pmat) must be of type MATIS.
244528509bceSStefano Zampini 
24460f202f7eSStefano Zampini    Currently works with MATIS matrices with local matrices of type MATSEQAIJ, MATSEQBAIJ or MATSEQSBAIJ, either with real or complex numbers.
244728509bceSStefano Zampini 
244828509bceSStefano Zampini    It also works with unsymmetric and indefinite problems.
244928509bceSStefano Zampini 
2450b6fdb6dfSStefano 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.
2451b6fdb6dfSStefano Zampini 
2452c7017625SStefano 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).
245328509bceSStefano Zampini 
24540f202f7eSStefano 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()
245530368db7SStefano Zampini    Additional information on dofs can be provided by using PCBDDCSetDofsSplitting(), PCBDDCSetDirichletBoundaries(), PCBDDCSetNeumannBoundaries(), and PCBDDCSetPrimalVerticesIS() and their local counterparts.
245628509bceSStefano Zampini 
24570f202f7eSStefano Zampini    Constraints can be customized by attaching a MatNullSpace object to the MATIS matrix via MatSetNearNullSpace(). Non-singular modes are retained via SVD.
245828509bceSStefano Zampini 
24590f202f7eSStefano 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.
24600f202f7eSStefano Zampini    User defined change of basis can be passed to PCBDDC by using PCBDDCSetChangeOfBasisMat()
246128509bceSStefano Zampini 
24620f202f7eSStefano Zampini    The PETSc implementation also supports multilevel BDDC [3]. Coarse grids are partitioned using a MatPartitioning object.
246328509bceSStefano Zampini 
2464df4d28bfSStefano 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.
246528509bceSStefano Zampini 
24660f202f7eSStefano 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.
24670f202f7eSStefano Zampini    Deluxe scaling is not supported yet for FETI-DP.
24680f202f7eSStefano Zampini 
24690f202f7eSStefano Zampini    Options Database Keys (some of them, run with -h for a complete list):
24700f202f7eSStefano Zampini 
24710f202f7eSStefano Zampini .    -pc_bddc_use_vertices <true> - use or not vertices in primal space
24720f202f7eSStefano Zampini .    -pc_bddc_use_edges <true> - use or not edges in primal space
24730f202f7eSStefano Zampini .    -pc_bddc_use_faces <false> - use or not faces in primal space
24740f202f7eSStefano Zampini .    -pc_bddc_symmetric <true> - symmetric computation of primal basis functions. Specify false for unsymmetric problems
24750f202f7eSStefano Zampini .    -pc_bddc_use_change_of_basis <false> - use change of basis approach (on edges only)
24760f202f7eSStefano Zampini .    -pc_bddc_use_change_on_faces <false> - use change of basis approach on faces if change of basis has been requested
24770f202f7eSStefano Zampini .    -pc_bddc_switch_static <false> - switches from M_2 (default) to M_3 operator (see reference article [1])
247828509bceSStefano Zampini .    -pc_bddc_levels <0> - maximum number of levels for multilevel
24790f202f7eSStefano 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)
24800f202f7eSStefano Zampini .    -pc_bddc_redistribute <0> - size of a subset of processors where the coarse problem will be remapped (the value is ignored if not at the coarsest level)
24810f202f7eSStefano Zampini .    -pc_bddc_use_deluxe_scaling <false> - use deluxe scaling
24820f202f7eSStefano 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)
2483df4d28bfSStefano Zampini .    -pc_bddc_adaptive_threshold <0.0> - when a value greater than one is specified, adaptive selection of constraints is performed on edges and faces (requires deluxe scaling and MUMPS or MKL_PARDISO installed)
248428509bceSStefano Zampini -    -pc_bddc_check_level <0> - set verbosity level of debugging output
248528509bceSStefano Zampini 
248628509bceSStefano Zampini    Options for Dirichlet, Neumann or coarse solver can be set with
248728509bceSStefano Zampini .vb
248828509bceSStefano Zampini       -pc_bddc_dirichlet_
248928509bceSStefano Zampini       -pc_bddc_neumann_
249028509bceSStefano Zampini       -pc_bddc_coarse_
249128509bceSStefano Zampini .ve
24920f202f7eSStefano Zampini    e.g -pc_bddc_dirichlet_ksp_type richardson -pc_bddc_dirichlet_pc_type gamg. PCBDDC uses by default KPSPREONLY and PCLU.
249328509bceSStefano Zampini 
24940f202f7eSStefano Zampini    When using a multilevel approach, solvers' options at the N-th level (N > 1) can be specified as
249528509bceSStefano Zampini .vb
2496312be037SStefano Zampini       -pc_bddc_dirichlet_lN_
2497312be037SStefano Zampini       -pc_bddc_neumann_lN_
2498312be037SStefano Zampini       -pc_bddc_coarse_lN_
249928509bceSStefano Zampini .ve
25000f202f7eSStefano Zampini    Note that level number ranges from the finest (0) to the coarsest (N).
25010f202f7eSStefano 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.
25020f202f7eSStefano Zampini .vb
25030f202f7eSStefano Zampini      -pc_bddc_coarse_pc_bddc_adaptive_threshold 5 -pc_bddc_coarse_l1_pc_bddc_redistribute 3
25040f202f7eSStefano Zampini .ve
25050f202f7eSStefano 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
2506da1bb401SStefano Zampini 
2507da1bb401SStefano Zampini    Level: intermediate
2508da1bb401SStefano Zampini 
2509b6fdb6dfSStefano Zampini    Developer notes:
2510da1bb401SStefano Zampini 
2511da1bb401SStefano Zampini    Contributed by Stefano Zampini
2512da1bb401SStefano Zampini 
2513da1bb401SStefano Zampini .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,  MATIS
2514da1bb401SStefano Zampini M*/
2515b2573a8aSBarry Smith 
2516da1bb401SStefano Zampini #undef __FUNCT__
2517da1bb401SStefano Zampini #define __FUNCT__ "PCCreate_BDDC"
25188cc058d9SJed Brown PETSC_EXTERN PetscErrorCode PCCreate_BDDC(PC pc)
2519da1bb401SStefano Zampini {
2520da1bb401SStefano Zampini   PetscErrorCode      ierr;
2521da1bb401SStefano Zampini   PC_BDDC             *pcbddc;
2522da1bb401SStefano Zampini 
2523da1bb401SStefano Zampini   PetscFunctionBegin;
2524da1bb401SStefano Zampini   /* Creates the private data structure for this preconditioner and attach it to the PC object. */
2525b00a9115SJed Brown   ierr      = PetscNewLog(pc,&pcbddc);CHKERRQ(ierr);
2526da1bb401SStefano Zampini   pc->data  = (void*)pcbddc;
2527da1bb401SStefano Zampini 
2528da1bb401SStefano Zampini   /* create PCIS data structure */
2529da1bb401SStefano Zampini   ierr = PCISCreate(pc);CHKERRQ(ierr);
2530da1bb401SStefano Zampini 
253147d04d0dSStefano Zampini   /* BDDC customization */
253208a5cf49SStefano Zampini   pcbddc->use_local_adj       = PETSC_TRUE;
253347d04d0dSStefano Zampini   pcbddc->use_vertices        = PETSC_TRUE;
253447d04d0dSStefano Zampini   pcbddc->use_edges           = PETSC_TRUE;
253547d04d0dSStefano Zampini   pcbddc->use_faces           = PETSC_FALSE;
253647d04d0dSStefano Zampini   pcbddc->use_change_of_basis = PETSC_FALSE;
253747d04d0dSStefano Zampini   pcbddc->use_change_on_faces = PETSC_FALSE;
253847d04d0dSStefano Zampini   pcbddc->switch_static       = PETSC_FALSE;
2539fa434743SStefano Zampini   pcbddc->use_nnsp_true       = PETSC_FALSE;
2540fa434743SStefano Zampini   pcbddc->use_qr_single       = PETSC_FALSE;
25413301b35fSStefano Zampini   pcbddc->symmetric_primal    = PETSC_TRUE;
254206a4e24aSStefano Zampini   pcbddc->benign_saddle_point = PETSC_FALSE;
254327b6a85dSStefano Zampini   pcbddc->benign_have_null    = PETSC_FALSE;
254414f95afaSStefano Zampini   pcbddc->vertex_size         = 1;
254547d04d0dSStefano Zampini   pcbddc->dbg_flag            = 0;
2546b9d89cd5SStefano Zampini   /* private */
2547727cdba6SStefano Zampini   pcbddc->local_primal_size          = 0;
25480e6343abSStefano Zampini   pcbddc->local_primal_size_cc       = 0;
25490e6343abSStefano Zampini   pcbddc->local_primal_ref_node      = 0;
25500e6343abSStefano Zampini   pcbddc->local_primal_ref_mult      = 0;
2551e9189074SStefano Zampini   pcbddc->n_vertices                 = 0;
2552727cdba6SStefano Zampini   pcbddc->primal_indices_local_idxs  = 0;
2553c703fcc7SStefano Zampini   pcbddc->recompute_topography       = PETSC_TRUE;
255468457ee5SStefano Zampini   pcbddc->coarse_size                = -1;
2555f4ddd8eeSStefano Zampini   pcbddc->new_primal_space           = PETSC_FALSE;
2556727cdba6SStefano Zampini   pcbddc->new_primal_space_local     = PETSC_FALSE;
2557f4ddd8eeSStefano Zampini   pcbddc->global_primal_indices      = 0;
2558f4ddd8eeSStefano Zampini   pcbddc->onearnullspace             = 0;
2559f4ddd8eeSStefano Zampini   pcbddc->onearnullvecs_state        = 0;
2560674ae819SStefano Zampini   pcbddc->user_primal_vertices       = 0;
256130368db7SStefano Zampini   pcbddc->user_primal_vertices_local = 0;
25623972b0daSStefano Zampini   pcbddc->temp_solution              = 0;
2563534831adSStefano Zampini   pcbddc->original_rhs               = 0;
2564534831adSStefano Zampini   pcbddc->local_mat                  = 0;
2565534831adSStefano Zampini   pcbddc->ChangeOfBasisMatrix        = 0;
2566b9b85e73SStefano Zampini   pcbddc->user_ChangeOfBasisMatrix   = 0;
2567da1bb401SStefano Zampini   pcbddc->coarse_vec                 = 0;
2568da1bb401SStefano Zampini   pcbddc->coarse_ksp                 = 0;
2569da1bb401SStefano Zampini   pcbddc->coarse_phi_B               = 0;
2570da1bb401SStefano Zampini   pcbddc->coarse_phi_D               = 0;
257115aaf578SStefano Zampini   pcbddc->coarse_psi_B               = 0;
257215aaf578SStefano Zampini   pcbddc->coarse_psi_D               = 0;
2573da1bb401SStefano Zampini   pcbddc->vec1_P                     = 0;
2574da1bb401SStefano Zampini   pcbddc->vec1_R                     = 0;
2575da1bb401SStefano Zampini   pcbddc->vec2_R                     = 0;
2576da1bb401SStefano Zampini   pcbddc->local_auxmat1              = 0;
2577da1bb401SStefano Zampini   pcbddc->local_auxmat2              = 0;
2578da1bb401SStefano Zampini   pcbddc->R_to_B                     = 0;
2579da1bb401SStefano Zampini   pcbddc->R_to_D                     = 0;
2580da1bb401SStefano Zampini   pcbddc->ksp_D                      = 0;
2581da1bb401SStefano Zampini   pcbddc->ksp_R                      = 0;
2582da1bb401SStefano Zampini   pcbddc->NeumannBoundaries          = 0;
2583785d1243SStefano Zampini   pcbddc->NeumannBoundariesLocal     = 0;
2584785d1243SStefano Zampini   pcbddc->DirichletBoundaries        = 0;
2585785d1243SStefano Zampini   pcbddc->DirichletBoundariesLocal   = 0;
258660d44989SStefano Zampini   pcbddc->user_provided_isfordofs    = PETSC_FALSE;
258760d44989SStefano Zampini   pcbddc->n_ISForDofs                = 0;
258863602bcaSStefano Zampini   pcbddc->n_ISForDofsLocal           = 0;
2589da1bb401SStefano Zampini   pcbddc->ISForDofs                  = 0;
259063602bcaSStefano Zampini   pcbddc->ISForDofsLocal             = 0;
2591da1bb401SStefano Zampini   pcbddc->ConstraintMatrix           = 0;
259285c4d303SStefano Zampini   pcbddc->use_exact_dirichlet_trick  = PETSC_TRUE;
25938ae0ca82SStefano Zampini   pcbddc->exact_dirichlet_trick_app  = PETSC_FALSE;
259447d04d0dSStefano Zampini   pcbddc->coarse_loc_to_glob         = 0;
259547d04d0dSStefano Zampini   pcbddc->coarsening_ratio           = 8;
2596b0c7d250SStefano Zampini   pcbddc->coarse_adj_red             = 0;
25974fad6a16SStefano Zampini   pcbddc->current_level              = 0;
25982b510759SStefano Zampini   pcbddc->max_levels                 = 0;
2599323d395dSStefano Zampini   pcbddc->use_coarse_estimates       = PETSC_FALSE;
260057de7509SStefano Zampini   pcbddc->coarse_eqs_per_proc        = 1;
2601f3bde8b3SStefano Zampini   pcbddc->coarse_subassembling       = 0;
26024f1b2e48SStefano Zampini   pcbddc->detect_disconnected        = PETSC_FALSE;
26034f1b2e48SStefano Zampini   pcbddc->n_local_subs               = 0;
26044f1b2e48SStefano Zampini   pcbddc->local_subs                 = NULL;
260581d14e9dSStefano Zampini 
260681d14e9dSStefano Zampini   /* benign subspace trick */
260781d14e9dSStefano Zampini   pcbddc->benign_change              = 0;
260827b6a85dSStefano Zampini   pcbddc->benign_compute_correction  = PETSC_TRUE;
26090369aaf7SStefano Zampini   pcbddc->benign_vec                 = 0;
26100369aaf7SStefano Zampini   pcbddc->benign_original_mat        = 0;
26110369aaf7SStefano Zampini   pcbddc->benign_sf                  = 0;
26124f1b2e48SStefano Zampini   pcbddc->benign_B0                  = 0;
26134f1b2e48SStefano Zampini   pcbddc->benign_n                   = 0;
26144f1b2e48SStefano Zampini   pcbddc->benign_p0                  = NULL;
26154f1b2e48SStefano Zampini   pcbddc->benign_p0_lidx             = NULL;
26164f1b2e48SStefano Zampini   pcbddc->benign_p0_gidx             = NULL;
2617b0f5fe93SStefano Zampini   pcbddc->benign_null                = PETSC_FALSE;
261881d14e9dSStefano Zampini 
26191e0482f5SStefano Zampini   /* Nedelec */
26201e0482f5SStefano Zampini   pcbddc->nedfield  = -1;
26211e0482f5SStefano Zampini   pcbddc->nedglobal = PETSC_TRUE;
26221e0482f5SStefano Zampini 
2623674ae819SStefano Zampini   /* create local graph structure */
2624674ae819SStefano Zampini   ierr = PCBDDCGraphCreate(&pcbddc->mat_graph);CHKERRQ(ierr);
2625be12c134Sstefano_zampini   pcbddc->graphmaxcount = PETSC_MAX_INT;
2626674ae819SStefano Zampini 
2627674ae819SStefano Zampini   /* scaling */
2628674ae819SStefano Zampini   pcbddc->work_scaling          = 0;
262934a97f8cSStefano Zampini   pcbddc->use_deluxe_scaling    = PETSC_FALSE;
2630b96c3477SStefano Zampini 
2631b334f244SStefano Zampini   /* sub schurs options */
2632b96c3477SStefano Zampini   pcbddc->sub_schurs_rebuild     = PETSC_FALSE;
2633b96c3477SStefano Zampini   pcbddc->sub_schurs_layers      = -1;
2634b96c3477SStefano Zampini   pcbddc->sub_schurs_use_useradj = PETSC_FALSE;
2635b96c3477SStefano Zampini 
2636b96c3477SStefano Zampini   pcbddc->computed_rowadj = PETSC_FALSE;
2637da1bb401SStefano Zampini 
2638b7eb3628SStefano Zampini   /* adaptivity */
2639f6f667cfSStefano Zampini   pcbddc->adaptive_threshold      = 0.0;
264008122e43SStefano Zampini   pcbddc->adaptive_nmax           = 0;
2641f6f667cfSStefano Zampini   pcbddc->adaptive_nmin           = 0;
2642b7eb3628SStefano Zampini 
2643da1bb401SStefano Zampini   /* function pointers */
2644da1bb401SStefano Zampini   pc->ops->apply               = PCApply_BDDC;
264593bd9ae7SStefano Zampini   pc->ops->applytranspose      = PCApplyTranspose_BDDC;
2646da1bb401SStefano Zampini   pc->ops->setup               = PCSetUp_BDDC;
2647da1bb401SStefano Zampini   pc->ops->destroy             = PCDestroy_BDDC;
2648da1bb401SStefano Zampini   pc->ops->setfromoptions      = PCSetFromOptions_BDDC;
26496b78500eSPatrick Sanan   pc->ops->view                = PCView_BDDC;
2650da1bb401SStefano Zampini   pc->ops->applyrichardson     = 0;
2651da1bb401SStefano Zampini   pc->ops->applysymmetricleft  = 0;
2652da1bb401SStefano Zampini   pc->ops->applysymmetricright = 0;
2653534831adSStefano Zampini   pc->ops->presolve            = PCPreSolve_BDDC;
2654534831adSStefano Zampini   pc->ops->postsolve           = PCPostSolve_BDDC;
2655da1bb401SStefano Zampini 
2656da1bb401SStefano Zampini   /* composing function */
2657a13144ffSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDiscreteGradient_C",PCBDDCSetDiscreteGradient_BDDC);CHKERRQ(ierr);
2658a198735bSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDivergenceMat_C",PCBDDCSetDivergenceMat_BDDC);CHKERRQ(ierr);
2659906d46d4SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",PCBDDCSetChangeOfBasisMat_BDDC);CHKERRQ(ierr);
2660674ae819SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",PCBDDCSetPrimalVerticesLocalIS_BDDC);CHKERRQ(ierr);
266130368db7SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesIS_C",PCBDDCSetPrimalVerticesIS_BDDC);CHKERRQ(ierr);
2662bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",PCBDDCSetCoarseningRatio_BDDC);CHKERRQ(ierr);
26632b510759SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",PCBDDCSetLevel_BDDC);CHKERRQ(ierr);
2664b8ffe317SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",PCBDDCSetUseExactDirichlet_BDDC);CHKERRQ(ierr);
26652b510759SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",PCBDDCSetLevels_BDDC);CHKERRQ(ierr);
2666bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",PCBDDCSetDirichletBoundaries_BDDC);CHKERRQ(ierr);
266782ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",PCBDDCSetDirichletBoundariesLocal_BDDC);CHKERRQ(ierr);
2668bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",PCBDDCSetNeumannBoundaries_BDDC);CHKERRQ(ierr);
266982ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",PCBDDCSetNeumannBoundariesLocal_BDDC);CHKERRQ(ierr);
2670bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",PCBDDCGetDirichletBoundaries_BDDC);CHKERRQ(ierr);
267182ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",PCBDDCGetDirichletBoundariesLocal_BDDC);CHKERRQ(ierr);
2672bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",PCBDDCGetNeumannBoundaries_BDDC);CHKERRQ(ierr);
267382ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",PCBDDCGetNeumannBoundariesLocal_BDDC);CHKERRQ(ierr);
2674bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",PCBDDCSetDofsSplitting_BDDC);CHKERRQ(ierr);
267563602bcaSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",PCBDDCSetDofsSplittingLocal_BDDC);CHKERRQ(ierr);
2676bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",PCBDDCSetLocalAdjacencyGraph_BDDC);CHKERRQ(ierr);
2677bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",PCBDDCCreateFETIDPOperators_BDDC);CHKERRQ(ierr);
2678bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",PCBDDCMatFETIDPGetRHS_BDDC);CHKERRQ(ierr);
2679bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",PCBDDCMatFETIDPGetSolution_BDDC);CHKERRQ(ierr);
2680a06fd7f2SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCPreSolveChangeRHS_C",PCPreSolveChangeRHS_BDDC);CHKERRQ(ierr);
2681da1bb401SStefano Zampini   PetscFunctionReturn(0);
2682da1bb401SStefano Zampini }
26833425bc38SStefano Zampini 
2684