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 225e5bbd0aSStefano Zampini #include <petsc/private/pcbddcimpl.h> /*I "petscpc.h" I*/ /* includes for fortran wrappers */ 235e5bbd0aSStefano Zampini #include <petsc/private/pcbddcprivateimpl.h> 243b03a366Sstefano_zampini #include <petscblaslapack.h> 25674ae819SStefano Zampini 2643371fb9SStefano Zampini static PetscBool PCBDDCPackageInitialized = PETSC_FALSE; 2743371fb9SStefano Zampini 28f3d41395Sstefano_zampini static PetscBool cited = PETSC_FALSE; 299371c9d4SSatish Balay static const char citation[] = "@article{ZampiniPCBDDC,\n" 30f3d41395Sstefano_zampini "author = {Stefano Zampini},\n" 31f3d41395Sstefano_zampini "title = {{PCBDDC}: A Class of Robust Dual-Primal Methods in {PETS}c},\n" 32f3d41395Sstefano_zampini "journal = {SIAM Journal on Scientific Computing},\n" 33f3d41395Sstefano_zampini "volume = {38},\n" 34f3d41395Sstefano_zampini "number = {5},\n" 35f3d41395Sstefano_zampini "pages = {S282-S306},\n" 36f3d41395Sstefano_zampini "year = {2016},\n" 37f3d41395Sstefano_zampini "doi = {10.1137/15M1025785},\n" 38f3d41395Sstefano_zampini "URL = {http://dx.doi.org/10.1137/15M1025785},\n" 39f3d41395Sstefano_zampini "eprint = {http://dx.doi.org/10.1137/15M1025785}\n" 40f3d41395Sstefano_zampini "}\n"; 41f3d41395Sstefano_zampini 4243371fb9SStefano Zampini PetscLogEvent PC_BDDC_Topology[PETSC_PCBDDC_MAXLEVELS]; 4343371fb9SStefano Zampini PetscLogEvent PC_BDDC_LocalSolvers[PETSC_PCBDDC_MAXLEVELS]; 4443371fb9SStefano Zampini PetscLogEvent PC_BDDC_LocalWork[PETSC_PCBDDC_MAXLEVELS]; 4543371fb9SStefano Zampini PetscLogEvent PC_BDDC_CorrectionSetUp[PETSC_PCBDDC_MAXLEVELS]; 468ead10e4SStefano Zampini PetscLogEvent PC_BDDC_ApproxSetUp[PETSC_PCBDDC_MAXLEVELS]; 478ead10e4SStefano Zampini PetscLogEvent PC_BDDC_ApproxApply[PETSC_PCBDDC_MAXLEVELS]; 4843371fb9SStefano Zampini PetscLogEvent PC_BDDC_CoarseSetUp[PETSC_PCBDDC_MAXLEVELS]; 4943371fb9SStefano Zampini PetscLogEvent PC_BDDC_CoarseSolver[PETSC_PCBDDC_MAXLEVELS]; 5043371fb9SStefano Zampini PetscLogEvent PC_BDDC_AdaptiveSetUp[PETSC_PCBDDC_MAXLEVELS]; 5143371fb9SStefano Zampini PetscLogEvent PC_BDDC_Scaling[PETSC_PCBDDC_MAXLEVELS]; 5243371fb9SStefano Zampini PetscLogEvent PC_BDDC_Schurs[PETSC_PCBDDC_MAXLEVELS]; 5355c176c0SStefano Zampini PetscLogEvent PC_BDDC_Solves[PETSC_PCBDDC_MAXLEVELS][3]; 5443371fb9SStefano Zampini 55bc960bbfSJed Brown const char *const PCBDDCInterfaceExtTypes[] = {"DIRICHLET", "LUMP", "PCBDDCInterfaceExtType", "PC_BDDC_INTERFACE_EXT_", NULL}; 56bc960bbfSJed Brown 570369aaf7SStefano Zampini PetscErrorCode PCApply_BDDC(PC, Vec, Vec); 580369aaf7SStefano Zampini 599371c9d4SSatish Balay PetscErrorCode PCSetFromOptions_BDDC(PC pc, PetscOptionItems *PetscOptionsObject) { 600c7d97c5SJed Brown PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 61e569e4e1SStefano Zampini PetscInt nt, i; 620c7d97c5SJed Brown 630c7d97c5SJed Brown PetscFunctionBegin; 64d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "BDDC options"); 658eeda7d8SStefano Zampini /* Verbose debugging */ 669566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-pc_bddc_check_level", "Verbose output for PCBDDC (intended for debug)", "none", pcbddc->dbg_flag, &pcbddc->dbg_flag, NULL)); 67a13144ffSStefano Zampini /* Approximate solvers */ 689566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-pc_bddc_interface_ext_type", "Use DIRICHLET or LUMP to extend interface corrections to interior", "PCBDDCSetInterfaceExtType", PCBDDCInterfaceExtTypes, (PetscEnum)pcbddc->interface_extension, (PetscEnum *)&pcbddc->interface_extension, NULL)); 69bc960bbfSJed Brown if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_DIRICHLET) { 709566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_dirichlet_approximate", "Inform PCBDDC that we are using approximate Dirichlet solvers", "none", pcbddc->NullSpace_corr[0], &pcbddc->NullSpace_corr[0], NULL)); 719566063dSJacob Faibussowitsch PetscCall(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)); 72bc960bbfSJed Brown } else { 73bc960bbfSJed Brown /* This flag is needed/implied by lumping */ 74bc960bbfSJed Brown pcbddc->switch_static = PETSC_TRUE; 75bc960bbfSJed Brown } 769566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_neumann_approximate", "Inform PCBDDC that we are using approximate Neumann solvers", "none", pcbddc->NullSpace_corr[2], &pcbddc->NullSpace_corr[2], NULL)); 779566063dSJacob Faibussowitsch PetscCall(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)); 786b78500eSPatrick Sanan /* Primal space customization */ 799566063dSJacob Faibussowitsch PetscCall(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)); 809566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-pc_bddc_graph_maxcount", "Maximum number of shared subdomains for a connected component", "none", pcbddc->graphmaxcount, &pcbddc->graphmaxcount, NULL)); 819566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_corner_selection", "Activates face-based corner selection", "none", pcbddc->corner_selection, &pcbddc->corner_selection, NULL)); 829566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_use_vertices", "Use or not corner dofs in coarse space", "none", pcbddc->use_vertices, &pcbddc->use_vertices, NULL)); 839566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_use_edges", "Use or not edge constraints in coarse space", "none", pcbddc->use_edges, &pcbddc->use_edges, NULL)); 849566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_use_faces", "Use or not face constraints in coarse space", "none", pcbddc->use_faces, &pcbddc->use_faces, NULL)); 859566063dSJacob Faibussowitsch PetscCall(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)); 869566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_use_nnsp", "Use near null space attached to the matrix to compute constraints", "none", pcbddc->use_nnsp, &pcbddc->use_nnsp, NULL)); 879566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_use_nnsp_true", "Use near null space attached to the matrix to compute constraints as is", "none", pcbddc->use_nnsp_true, &pcbddc->use_nnsp_true, NULL)); 889566063dSJacob Faibussowitsch PetscCall(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)); 898eeda7d8SStefano Zampini /* Change of basis */ 909566063dSJacob Faibussowitsch PetscCall(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)); 919566063dSJacob Faibussowitsch PetscCall(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)); 929371c9d4SSatish Balay if (!pcbddc->use_change_of_basis) { pcbddc->use_change_on_faces = PETSC_FALSE; } 938eeda7d8SStefano Zampini /* Switch between M_2 (default) and M_3 preconditioners (as defined by C. Dohrmann in the ref. article) */ 949566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_switch_static", "Switch on static condensation ops around the interface preconditioner", "none", pcbddc->switch_static, &pcbddc->switch_static, NULL)); 959566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-pc_bddc_coarse_eqs_per_proc", "Target number of equations per process for coarse problem redistribution (significant only at the coarsest level)", "none", pcbddc->coarse_eqs_per_proc, &pcbddc->coarse_eqs_per_proc, NULL)); 96e569e4e1SStefano Zampini i = pcbddc->coarsening_ratio; 979566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-pc_bddc_coarsening_ratio", "Set coarsening ratio used in multilevel coarsening", "PCBDDCSetCoarseningRatio", i, &i, NULL)); 989566063dSJacob Faibussowitsch PetscCall(PCBDDCSetCoarseningRatio(pc, i)); 99e569e4e1SStefano Zampini i = pcbddc->max_levels; 1009566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-pc_bddc_levels", "Set maximum number of levels for multilevel", "PCBDDCSetLevels", i, &i, NULL)); 1019566063dSJacob Faibussowitsch PetscCall(PCBDDCSetLevels(pc, i)); 1029566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-pc_bddc_coarse_eqs_limit", "Set maximum number of equations on coarsest grid to aim for", "none", pcbddc->coarse_eqs_limit, &pcbddc->coarse_eqs_limit, NULL)); 1039566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_use_coarse_estimates", "Use estimated eigenvalues for coarse problem", "none", pcbddc->use_coarse_estimates, &pcbddc->use_coarse_estimates, NULL)); 1049566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_use_deluxe_scaling", "Use deluxe scaling for BDDC", "none", pcbddc->use_deluxe_scaling, &pcbddc->use_deluxe_scaling, NULL)); 1059566063dSJacob Faibussowitsch PetscCall(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)); 1069566063dSJacob Faibussowitsch PetscCall(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)); 1079566063dSJacob Faibussowitsch PetscCall(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)); 1089566063dSJacob Faibussowitsch PetscCall(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)); 1099566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_deluxe_zerorows", "Zero rows and columns of deluxe operators associated with primal dofs", "none", pcbddc->deluxe_zerorows, &pcbddc->deluxe_zerorows, NULL)); 1109566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_deluxe_singlemat", "Collapse deluxe operators", "none", pcbddc->deluxe_singlemat, &pcbddc->deluxe_singlemat, NULL)); 1119566063dSJacob Faibussowitsch PetscCall(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)); 112bd2a564bSStefano Zampini nt = 2; 1139566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-pc_bddc_adaptive_threshold", "Thresholds to be used for adaptive selection of constraints", "none", pcbddc->adaptive_threshold, &nt, NULL)); 114bd2a564bSStefano Zampini if (nt == 1) pcbddc->adaptive_threshold[1] = pcbddc->adaptive_threshold[0]; 1159566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-pc_bddc_adaptive_nmin", "Minimum number of constraints per connected components", "none", pcbddc->adaptive_nmin, &pcbddc->adaptive_nmin, NULL)); 1169566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-pc_bddc_adaptive_nmax", "Maximum number of constraints per connected components", "none", pcbddc->adaptive_nmax, &pcbddc->adaptive_nmax, NULL)); 1179566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_symmetric", "Symmetric computation of primal basis functions", "none", pcbddc->symmetric_primal, &pcbddc->symmetric_primal, NULL)); 1189566063dSJacob Faibussowitsch PetscCall(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)); 1199566063dSJacob Faibussowitsch PetscCall(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)); 1209566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_benign_change", "Compute the pressure change of basis explicitly", "none", pcbddc->benign_change_explicit, &pcbddc->benign_change_explicit, NULL)); 1219566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_benign_compute_correction", "Compute the benign correction during PreSolve", "none", pcbddc->benign_compute_correction, &pcbddc->benign_compute_correction, NULL)); 1229566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_nonetflux", "Automatic computation of no-net-flux quadrature weights", "none", pcbddc->compute_nonetflux, &pcbddc->compute_nonetflux, NULL)); 1239566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_detect_disconnected", "Detects disconnected subdomains", "none", pcbddc->detect_disconnected, &pcbddc->detect_disconnected, NULL)); 1249566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_detect_disconnected_filter", "Filters out small entries in the local matrix when detecting disconnected subdomains", "none", pcbddc->detect_disconnected_filter, &pcbddc->detect_disconnected_filter, NULL)); 1259566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_eliminate_dirichlet", "Whether or not we want to eliminate dirichlet dofs during presolve", "none", pcbddc->eliminate_dirdofs, &pcbddc->eliminate_dirdofs, NULL)); 126d0609cedSBarry Smith PetscOptionsHeadEnd(); 1270c7d97c5SJed Brown PetscFunctionReturn(0); 1280c7d97c5SJed Brown } 1296b78500eSPatrick Sanan 1309371c9d4SSatish Balay static PetscErrorCode PCView_BDDC(PC pc, PetscViewer viewer) { 1316b78500eSPatrick Sanan PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 132e9627c49SStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 13371783a16SStefano Zampini PetscBool isascii; 134e9627c49SStefano Zampini PetscSubcomm subcomm; 135e9627c49SStefano Zampini PetscViewer subviewer; 1366b78500eSPatrick Sanan 1376b78500eSPatrick Sanan PetscFunctionBegin; 1389566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1396b78500eSPatrick Sanan /* ASCII viewer */ 1406b78500eSPatrick Sanan if (isascii) { 1414b2aedd3SStefano Zampini PetscMPIInt color, rank, size; 142fbad9177SStefano Zampini PetscInt64 loc[7], gsum[6], gmax[6], gmin[6], totbenign; 143e9627c49SStefano Zampini PetscScalar interface_size; 144e9627c49SStefano Zampini PetscReal ratio1 = 0., ratio2 = 0.; 145e9627c49SStefano Zampini Vec counter; 1466b78500eSPatrick Sanan 147*48a46eb9SPierre Jolivet if (!pc->setupcalled) PetscCall(PetscViewerASCIIPrintf(viewer, " Partial information available: preconditioner has not been setup yet\n")); 14863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use verbose output: %" PetscInt_FMT "\n", pcbddc->dbg_flag)); 1499566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use user-defined CSR: %d\n", !!pcbddc->mat_graph->nvtxs_csr)); 1509566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use local mat graph: %d\n", pcbddc->use_local_adj && !pcbddc->mat_graph->nvtxs_csr)); 151e9627c49SStefano Zampini if (pcbddc->mat_graph->twodim) { 1529566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Connectivity graph topological dimension: 2\n")); 153e9627c49SStefano Zampini } else { 1549566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Connectivity graph topological dimension: 3\n")); 155e9627c49SStefano Zampini } 156*48a46eb9SPierre Jolivet if (pcbddc->graphmaxcount != PETSC_MAX_INT) PetscCall(PetscViewerASCIIPrintf(viewer, " Graph max count: %" PetscInt_FMT "\n", pcbddc->graphmaxcount)); 1579566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Corner selection: %d (selected %d)\n", pcbddc->corner_selection, pcbddc->corner_selected)); 15863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use vertices: %d (vertex size %" PetscInt_FMT ")\n", pcbddc->use_vertices, pcbddc->vertex_size)); 1599566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use edges: %d\n", pcbddc->use_edges)); 1609566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use faces: %d\n", pcbddc->use_faces)); 1619566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use true near null space: %d\n", pcbddc->use_nnsp_true)); 1629566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use QR for single constraints on cc: %d\n", pcbddc->use_qr_single)); 1639566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use change of basis on local edge nodes: %d\n", pcbddc->use_change_of_basis)); 1649566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use change of basis on local face nodes: %d\n", pcbddc->use_change_on_faces)); 1659566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " User defined change of basis matrix: %d\n", !!pcbddc->user_ChangeOfBasisMatrix)); 1669566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Has change of basis matrix: %d\n", !!pcbddc->ChangeOfBasisMatrix)); 1679566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Eliminate dirichlet boundary dofs: %d\n", pcbddc->eliminate_dirdofs)); 1689566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Switch on static condensation ops around the interface preconditioner: %d\n", pcbddc->switch_static)); 1699566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use exact dirichlet trick: %d\n", pcbddc->use_exact_dirichlet_trick)); 1709566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Interface extension: %s\n", PCBDDCInterfaceExtTypes[pcbddc->interface_extension])); 17163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Multilevel max levels: %" PetscInt_FMT "\n", pcbddc->max_levels)); 17263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Multilevel coarsening ratio: %" PetscInt_FMT "\n", pcbddc->coarsening_ratio)); 1739566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use estimated eigs for coarse problem: %d\n", pcbddc->use_coarse_estimates)); 1749566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use deluxe scaling: %d\n", pcbddc->use_deluxe_scaling)); 1759566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use deluxe zerorows: %d\n", pcbddc->deluxe_zerorows)); 1769566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use deluxe singlemat: %d\n", pcbddc->deluxe_singlemat)); 1779566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Rebuild interface graph for Schur principal minors: %d\n", pcbddc->sub_schurs_rebuild)); 17863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Number of dofs' layers for the computation of principal minors: %" PetscInt_FMT "\n", pcbddc->sub_schurs_layers)); 1799566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use user CSR graph to compute successive layers: %d\n", pcbddc->sub_schurs_use_useradj)); 180bd2a564bSStefano Zampini if (pcbddc->adaptive_threshold[1] != pcbddc->adaptive_threshold[0]) { 18163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Adaptive constraint selection thresholds (active %d, userdefined %d): %g,%g\n", pcbddc->adaptive_selection, pcbddc->adaptive_userdefined, (double)pcbddc->adaptive_threshold[0], (double)pcbddc->adaptive_threshold[1])); 182bd2a564bSStefano Zampini } else { 18363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Adaptive constraint selection threshold (active %d, userdefined %d): %g\n", pcbddc->adaptive_selection, pcbddc->adaptive_userdefined, (double)pcbddc->adaptive_threshold[0])); 184bd2a564bSStefano Zampini } 18563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Min constraints / connected component: %" PetscInt_FMT "\n", pcbddc->adaptive_nmin)); 18663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Max constraints / connected component: %" PetscInt_FMT "\n", pcbddc->adaptive_nmax)); 1879566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Invert exact Schur complement for adaptive selection: %d\n", pcbddc->sub_schurs_exact_schur)); 1889566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Symmetric computation of primal basis functions: %d\n", pcbddc->symmetric_primal)); 18963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Num. Procs. to map coarse adjacency list: %" PetscInt_FMT "\n", pcbddc->coarse_adj_red)); 19063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Coarse eqs per proc (significant at the coarsest level): %" PetscInt_FMT "\n", pcbddc->coarse_eqs_per_proc)); 1919566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Detect disconnected: %d (filter %d)\n", pcbddc->detect_disconnected, pcbddc->detect_disconnected_filter)); 1929566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Benign subspace trick: %d (change explicit %d)\n", pcbddc->benign_saddle_point, pcbddc->benign_change_explicit)); 1939566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Benign subspace trick is active: %d\n", pcbddc->benign_have_null)); 1949566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Algebraic computation of no-net-flux: %d\n", pcbddc->compute_nonetflux)); 195b74ba07aSstefano_zampini if (!pc->setupcalled) PetscFunctionReturn(0); 1966b78500eSPatrick Sanan 197fbad9177SStefano Zampini /* compute interface size */ 1989566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_B, 1.0)); 1999566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(pc->pmat, &counter, NULL)); 2009566063dSJacob Faibussowitsch PetscCall(VecSet(counter, 0.0)); 2019566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_B, pcis->vec1_B, counter, INSERT_VALUES, SCATTER_REVERSE)); 2029566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_B, pcis->vec1_B, counter, INSERT_VALUES, SCATTER_REVERSE)); 2039566063dSJacob Faibussowitsch PetscCall(VecSum(counter, &interface_size)); 2049566063dSJacob Faibussowitsch PetscCall(VecDestroy(&counter)); 205fbad9177SStefano Zampini 206fbad9177SStefano Zampini /* compute some statistics on the domain decomposition */ 207e9627c49SStefano Zampini gsum[0] = 1; 208fbad9177SStefano Zampini gsum[1] = gsum[2] = gsum[3] = gsum[4] = gsum[5] = 0; 209e9627c49SStefano Zampini loc[0] = !!pcis->n; 210e9627c49SStefano Zampini loc[1] = pcis->n - pcis->n_B; 211e9627c49SStefano Zampini loc[2] = pcis->n_B; 212e9627c49SStefano Zampini loc[3] = pcbddc->local_primal_size; 213345ecf6cSStefano Zampini loc[4] = pcis->n; 214fbad9177SStefano Zampini loc[5] = pcbddc->n_local_subs > 0 ? pcbddc->n_local_subs : (pcis->n ? 1 : 0); 215fbad9177SStefano Zampini loc[6] = pcbddc->benign_n; 2169566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(loc, gsum, 6, MPIU_INT64, MPI_SUM, 0, PetscObjectComm((PetscObject)pc))); 217fbad9177SStefano Zampini if (!loc[0]) loc[1] = loc[2] = loc[3] = loc[4] = loc[5] = -1; 2189566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(loc, gmax, 6, MPIU_INT64, MPI_MAX, 0, PetscObjectComm((PetscObject)pc))); 219fbad9177SStefano Zampini if (!loc[0]) loc[1] = loc[2] = loc[3] = loc[4] = loc[5] = PETSC_MAX_INT; 2209566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(loc, gmin, 6, MPIU_INT64, MPI_MIN, 0, PetscObjectComm((PetscObject)pc))); 2219566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&loc[6], &totbenign, 1, MPIU_INT64, MPI_SUM, 0, PetscObjectComm((PetscObject)pc))); 222e9627c49SStefano Zampini if (pcbddc->coarse_size) { 223e9627c49SStefano Zampini ratio1 = pc->pmat->rmap->N / (1. * pcbddc->coarse_size); 224e9627c49SStefano Zampini ratio2 = PetscRealPart(interface_size) / pcbddc->coarse_size; 225e9627c49SStefano Zampini } 22663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "********************************** STATISTICS AT LEVEL %" PetscInt_FMT " **********************************\n", pcbddc->current_level)); 22763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Global dofs sizes: all %" PetscInt_FMT " interface %" PetscInt_FMT " coarse %" PetscInt_FMT "\n", pc->pmat->rmap->N, (PetscInt)PetscRealPart(interface_size), pcbddc->coarse_size)); 22863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Coarsening ratios: all/coarse %" PetscInt_FMT " interface/coarse %" PetscInt_FMT "\n", (PetscInt)ratio1, (PetscInt)ratio2)); 22963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Active processes : %" PetscInt_FMT "\n", (PetscInt)gsum[0])); 23063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Total subdomains : %" PetscInt_FMT "\n", (PetscInt)gsum[5])); 231*48a46eb9SPierre Jolivet if (pcbddc->benign_have_null) PetscCall(PetscViewerASCIIPrintf(viewer, " Benign subs : %" PetscInt_FMT "\n", (PetscInt)totbenign)); 2329566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Dofs type :\tMIN\tMAX\tMEAN\n")); 23363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Interior dofs :\t%" PetscInt_FMT "\t%" PetscInt_FMT "\t%" PetscInt_FMT "\n", (PetscInt)gmin[1], (PetscInt)gmax[1], (PetscInt)(gsum[1] / gsum[0]))); 23463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Interface dofs :\t%" PetscInt_FMT "\t%" PetscInt_FMT "\t%" PetscInt_FMT "\n", (PetscInt)gmin[2], (PetscInt)gmax[2], (PetscInt)(gsum[2] / gsum[0]))); 23563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Primal dofs :\t%" PetscInt_FMT "\t%" PetscInt_FMT "\t%" PetscInt_FMT "\n", (PetscInt)gmin[3], (PetscInt)gmax[3], (PetscInt)(gsum[3] / gsum[0]))); 23663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Local dofs :\t%" PetscInt_FMT "\t%" PetscInt_FMT "\t%" PetscInt_FMT "\n", (PetscInt)gmin[4], (PetscInt)gmax[4], (PetscInt)(gsum[4] / gsum[0]))); 23763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Local subs :\t%" PetscInt_FMT "\t%" PetscInt_FMT "\n", (PetscInt)gmin[5], (PetscInt)gmax[5])); 2389566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 23915579a77SStefano Zampini 2409566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)pc), &rank)); 24115579a77SStefano Zampini 24215579a77SStefano Zampini /* local solvers */ 2439566063dSJacob Faibussowitsch PetscCall(PetscViewerGetSubViewer(viewer, PetscObjectComm((PetscObject)pcbddc->ksp_D), &subviewer)); 244dd400576SPatrick Sanan if (rank == 0) { 2459566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(subviewer, "--- Interior solver (rank 0)\n")); 2469566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(subviewer)); 2479566063dSJacob Faibussowitsch PetscCall(KSPView(pcbddc->ksp_D, subviewer)); 2489566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(subviewer)); 2499566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(subviewer, "--- Correction solver (rank 0)\n")); 2509566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(subviewer)); 2519566063dSJacob Faibussowitsch PetscCall(KSPView(pcbddc->ksp_R, subviewer)); 2529566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(subviewer)); 2539566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(subviewer)); 25415579a77SStefano Zampini } 2559566063dSJacob Faibussowitsch PetscCall(PetscViewerRestoreSubViewer(viewer, PetscObjectComm((PetscObject)pcbddc->ksp_D), &subviewer)); 2569566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 257e9627c49SStefano Zampini 258fbad9177SStefano Zampini /* the coarse problem can be handled by a different communicator */ 259e9627c49SStefano Zampini if (pcbddc->coarse_ksp) color = 1; 260e9627c49SStefano Zampini else color = 0; 2619566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc), &size)); 2629566063dSJacob Faibussowitsch PetscCall(PetscSubcommCreate(PetscObjectComm((PetscObject)pc), &subcomm)); 2639566063dSJacob Faibussowitsch PetscCall(PetscSubcommSetNumber(subcomm, PetscMin(size, 2))); 2649566063dSJacob Faibussowitsch PetscCall(PetscSubcommSetTypeGeneral(subcomm, color, rank)); 2659566063dSJacob Faibussowitsch PetscCall(PetscViewerGetSubViewer(viewer, PetscSubcommChild(subcomm), &subviewer)); 266e9627c49SStefano Zampini if (color == 1) { 2679566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(subviewer, "--- Coarse solver\n")); 2689566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(subviewer)); 2699566063dSJacob Faibussowitsch PetscCall(KSPView(pcbddc->coarse_ksp, subviewer)); 2709566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(subviewer)); 2719566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(subviewer)); 272e9627c49SStefano Zampini } 2739566063dSJacob Faibussowitsch PetscCall(PetscViewerRestoreSubViewer(viewer, PetscSubcommChild(subcomm), &subviewer)); 2749566063dSJacob Faibussowitsch PetscCall(PetscSubcommDestroy(&subcomm)); 2759566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 276e9627c49SStefano Zampini } 2776b78500eSPatrick Sanan PetscFunctionReturn(0); 2786b78500eSPatrick Sanan } 279a13144ffSStefano Zampini 2809371c9d4SSatish Balay static PetscErrorCode PCBDDCSetDiscreteGradient_BDDC(PC pc, Mat G, PetscInt order, PetscInt field, PetscBool global, PetscBool conforming) { 281a13144ffSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 282a13144ffSStefano Zampini 283a13144ffSStefano Zampini PetscFunctionBegin; 2849566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)G)); 2859566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->discretegradient)); 286a13144ffSStefano Zampini pcbddc->discretegradient = G; 287a13144ffSStefano Zampini pcbddc->nedorder = order > 0 ? order : -order; 288495a2a07SStefano Zampini pcbddc->nedfield = field; 2891e0482f5SStefano Zampini pcbddc->nedglobal = global; 2901e0482f5SStefano Zampini pcbddc->conforming = conforming; 291a13144ffSStefano Zampini PetscFunctionReturn(0); 292a13144ffSStefano Zampini } 293a13144ffSStefano Zampini 294a13144ffSStefano Zampini /*@ 295a13144ffSStefano Zampini PCBDDCSetDiscreteGradient - Sets the discrete gradient 296a13144ffSStefano Zampini 297a13144ffSStefano Zampini Collective on PC 298a13144ffSStefano Zampini 299a13144ffSStefano Zampini Input Parameters: 300a13144ffSStefano Zampini + pc - the preconditioning context 301a13144ffSStefano Zampini . G - the discrete gradient matrix (should be in AIJ format) 302a13144ffSStefano Zampini . order - the order of the Nedelec space (1 for the lowest order) 303495a2a07SStefano Zampini . field - the field id of the Nedelec dofs (not used if the fields have not been specified) 3041e0482f5SStefano Zampini . global - the type of global ordering for the rows of G 305a13144ffSStefano Zampini - conforming - whether the mesh is conforming or not 306a13144ffSStefano Zampini 307a13144ffSStefano Zampini Level: advanced 308a13144ffSStefano Zampini 30995452b02SPatrick Sanan Notes: 31095452b02SPatrick Sanan The discrete gradient matrix G is used to analyze the subdomain edges, and it should not contain any zero entry. 311495a2a07SStefano Zampini For variable order spaces, the order should be set to zero. 3121e0482f5SStefano Zampini If global is true, the rows of G should be given in global ordering for the whole dofs; 3131e0482f5SStefano Zampini if false, the ordering should be global for the Nedelec field. 3141e0482f5SStefano 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 3151e0482f5SStefano Zampini and geid the one for the Nedelec field. 316a13144ffSStefano Zampini 31716b07851SJed Brown .seealso: `PCBDDC`, `PCBDDCSetDofsSplitting()`, `PCBDDCSetDofsSplittingLocal()` 318a13144ffSStefano Zampini @*/ 3199371c9d4SSatish Balay PetscErrorCode PCBDDCSetDiscreteGradient(PC pc, Mat G, PetscInt order, PetscInt field, PetscBool global, PetscBool conforming) { 320a13144ffSStefano Zampini PetscFunctionBegin; 321a13144ffSStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 322a13144ffSStefano Zampini PetscValidHeaderSpecific(G, MAT_CLASSID, 2); 323a13144ffSStefano Zampini PetscValidLogicalCollectiveInt(pc, order, 3); 3241e0482f5SStefano Zampini PetscValidLogicalCollectiveInt(pc, field, 4); 3251e0482f5SStefano Zampini PetscValidLogicalCollectiveBool(pc, global, 5); 3261e0482f5SStefano Zampini PetscValidLogicalCollectiveBool(pc, conforming, 6); 3271e0482f5SStefano Zampini PetscCheckSameComm(pc, 1, G, 2); 328cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetDiscreteGradient_C", (PC, Mat, PetscInt, PetscInt, PetscBool, PetscBool), (pc, G, order, field, global, conforming)); 329a13144ffSStefano Zampini PetscFunctionReturn(0); 330a13144ffSStefano Zampini } 331a13144ffSStefano Zampini 3329371c9d4SSatish Balay static PetscErrorCode PCBDDCSetDivergenceMat_BDDC(PC pc, Mat divudotp, PetscBool trans, IS vl2l) { 333a198735bSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 3346b78500eSPatrick Sanan 335a198735bSStefano Zampini PetscFunctionBegin; 3369566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)divudotp)); 3379566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->divudotp)); 338a198735bSStefano Zampini pcbddc->divudotp = divudotp; 3398ae0ca82SStefano Zampini pcbddc->divudotp_trans = trans; 340a198735bSStefano Zampini pcbddc->compute_nonetflux = PETSC_TRUE; 341a198735bSStefano Zampini if (vl2l) { 3429566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)vl2l)); 3439566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->divudotp_vl2l)); 344a198735bSStefano Zampini pcbddc->divudotp_vl2l = vl2l; 345a198735bSStefano Zampini } 346a198735bSStefano Zampini PetscFunctionReturn(0); 347a198735bSStefano Zampini } 3483d996552SStefano Zampini 349a198735bSStefano Zampini /*@ 350a198735bSStefano Zampini PCBDDCSetDivergenceMat - Sets the linear operator representing \int_\Omega \div {\bf u} \cdot p dx 351a198735bSStefano Zampini 352a198735bSStefano Zampini Collective on PC 353a198735bSStefano Zampini 354a198735bSStefano Zampini Input Parameters: 355a198735bSStefano Zampini + pc - the preconditioning context 356a198735bSStefano Zampini . divudotp - the matrix (must be of type MATIS) 3578ae0ca82SStefano Zampini . trans - if trans if false (resp. true), then pressures are in the test (trial) space and velocities are in the trial (test) space. 35805a3bf82SStefano Zampini - vl2l - optional index set describing the local (wrt the local matrix in divudotp) to local (wrt the local matrix in the preconditioning matrix) map for the velocities 359a198735bSStefano Zampini 360a198735bSStefano Zampini Level: advanced 361a198735bSStefano Zampini 36295452b02SPatrick Sanan Notes: 36395452b02SPatrick Sanan This auxiliary matrix is used to compute quadrature weights representing the net-flux across subdomain boundaries 36405a3bf82SStefano Zampini If vl2l is NULL, the local ordering for velocities in divudotp should match that of the preconditioning matrix 365a198735bSStefano Zampini 366db781477SPatrick Sanan .seealso: `PCBDDC` 367a198735bSStefano Zampini @*/ 3689371c9d4SSatish Balay PetscErrorCode PCBDDCSetDivergenceMat(PC pc, Mat divudotp, PetscBool trans, IS vl2l) { 369a198735bSStefano Zampini PetscBool ismatis; 370a198735bSStefano Zampini 371a198735bSStefano Zampini PetscFunctionBegin; 372a198735bSStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 373a198735bSStefano Zampini PetscValidHeaderSpecific(divudotp, MAT_CLASSID, 2); 374a198735bSStefano Zampini PetscCheckSameComm(pc, 1, divudotp, 2); 3758ae0ca82SStefano Zampini PetscValidLogicalCollectiveBool(pc, trans, 3); 3761b24a7afSStefano Zampini if (vl2l) PetscValidHeaderSpecific(vl2l, IS_CLASSID, 4); 3779566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)divudotp, MATIS, &ismatis)); 37828b400f6SJacob Faibussowitsch PetscCheck(ismatis, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "Divergence matrix needs to be of type MATIS"); 379cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetDivergenceMat_C", (PC, Mat, PetscBool, IS), (pc, divudotp, trans, vl2l)); 380a198735bSStefano Zampini PetscFunctionReturn(0); 381a198735bSStefano Zampini } 3822d505d7fSStefano Zampini 3839371c9d4SSatish Balay static PetscErrorCode PCBDDCSetChangeOfBasisMat_BDDC(PC pc, Mat change, PetscBool interior) { 384b9b85e73SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 385b9b85e73SStefano Zampini 386b9b85e73SStefano Zampini PetscFunctionBegin; 3879566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)change)); 3889566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->user_ChangeOfBasisMatrix)); 389b9b85e73SStefano Zampini pcbddc->user_ChangeOfBasisMatrix = change; 3901dd7afcfSStefano Zampini pcbddc->change_interior = interior; 391b9b85e73SStefano Zampini PetscFunctionReturn(0); 392b9b85e73SStefano Zampini } 39332fe681dSStefano Zampini 394b9b85e73SStefano Zampini /*@ 395906d46d4SStefano Zampini PCBDDCSetChangeOfBasisMat - Set user defined change of basis for dofs 396b9b85e73SStefano Zampini 397b9b85e73SStefano Zampini Collective on PC 398b9b85e73SStefano Zampini 399b9b85e73SStefano Zampini Input Parameters: 400b9b85e73SStefano Zampini + pc - the preconditioning context 4011dd7afcfSStefano Zampini . change - the change of basis matrix 4021dd7afcfSStefano Zampini - interior - whether or not the change of basis modifies interior dofs 403b9b85e73SStefano Zampini 404b9b85e73SStefano Zampini Level: intermediate 405b9b85e73SStefano Zampini 406b9b85e73SStefano Zampini Notes: 407b9b85e73SStefano Zampini 408db781477SPatrick Sanan .seealso: `PCBDDC` 409b9b85e73SStefano Zampini @*/ 4109371c9d4SSatish Balay PetscErrorCode PCBDDCSetChangeOfBasisMat(PC pc, Mat change, PetscBool interior) { 411b9b85e73SStefano Zampini PetscFunctionBegin; 412b9b85e73SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 413b9b85e73SStefano Zampini PetscValidHeaderSpecific(change, MAT_CLASSID, 2); 414906d46d4SStefano Zampini PetscCheckSameComm(pc, 1, change, 2); 415906d46d4SStefano Zampini if (pc->mat) { 416906d46d4SStefano Zampini PetscInt rows_c, cols_c, rows, cols; 4179566063dSJacob Faibussowitsch PetscCall(MatGetSize(pc->mat, &rows, &cols)); 4189566063dSJacob Faibussowitsch PetscCall(MatGetSize(change, &rows_c, &cols_c)); 41963a3b9bcSJacob Faibussowitsch PetscCheck(rows_c == rows, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Invalid number of rows for change of basis matrix! %" PetscInt_FMT " != %" PetscInt_FMT, rows_c, rows); 42063a3b9bcSJacob Faibussowitsch PetscCheck(cols_c == cols, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Invalid number of columns for change of basis matrix! %" PetscInt_FMT " != %" PetscInt_FMT, cols_c, cols); 4219566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(pc->mat, &rows, &cols)); 4229566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(change, &rows_c, &cols_c)); 42363a3b9bcSJacob Faibussowitsch PetscCheck(rows_c == rows, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Invalid number of local rows for change of basis matrix! %" PetscInt_FMT " != %" PetscInt_FMT, rows_c, rows); 42463a3b9bcSJacob Faibussowitsch PetscCheck(cols_c == cols, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Invalid number of local columns for change of basis matrix! %" PetscInt_FMT " != %" PetscInt_FMT, cols_c, cols); 425906d46d4SStefano Zampini } 426cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetChangeOfBasisMat_C", (PC, Mat, PetscBool), (pc, change, interior)); 427b9b85e73SStefano Zampini PetscFunctionReturn(0); 428b9b85e73SStefano Zampini } 4292d505d7fSStefano Zampini 4309371c9d4SSatish Balay static PetscErrorCode PCBDDCSetPrimalVerticesIS_BDDC(PC pc, IS PrimalVertices) { 43130368db7SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 43256282151SStefano Zampini PetscBool isequal = PETSC_FALSE; 43330368db7SStefano Zampini 43430368db7SStefano Zampini PetscFunctionBegin; 4359566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)PrimalVertices)); 436*48a46eb9SPierre Jolivet if (pcbddc->user_primal_vertices) PetscCall(ISEqual(PrimalVertices, pcbddc->user_primal_vertices, &isequal)); 4379566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->user_primal_vertices)); 4389566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->user_primal_vertices_local)); 43930368db7SStefano Zampini pcbddc->user_primal_vertices = PrimalVertices; 44056282151SStefano Zampini if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 44130368db7SStefano Zampini PetscFunctionReturn(0); 44230368db7SStefano Zampini } 443ab8c8b98SStefano Zampini 44430368db7SStefano Zampini /*@ 44530368db7SStefano Zampini PCBDDCSetPrimalVerticesIS - Set additional user defined primal vertices in PCBDDC 44630368db7SStefano Zampini 44730368db7SStefano Zampini Collective 44830368db7SStefano Zampini 44930368db7SStefano Zampini Input Parameters: 45030368db7SStefano Zampini + pc - the preconditioning context 45130368db7SStefano Zampini - PrimalVertices - index set of primal vertices in global numbering (can be empty) 45230368db7SStefano Zampini 45330368db7SStefano Zampini Level: intermediate 45430368db7SStefano Zampini 45530368db7SStefano Zampini Notes: 45630368db7SStefano Zampini Any process can list any global node 45730368db7SStefano Zampini 458db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCGetPrimalVerticesIS()`, `PCBDDCSetPrimalVerticesLocalIS()`, `PCBDDCGetPrimalVerticesLocalIS()` 45930368db7SStefano Zampini @*/ 4609371c9d4SSatish Balay PetscErrorCode PCBDDCSetPrimalVerticesIS(PC pc, IS PrimalVertices) { 46130368db7SStefano Zampini PetscFunctionBegin; 46230368db7SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 46330368db7SStefano Zampini PetscValidHeaderSpecific(PrimalVertices, IS_CLASSID, 2); 46430368db7SStefano Zampini PetscCheckSameComm(pc, 1, PrimalVertices, 2); 465cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetPrimalVerticesIS_C", (PC, IS), (pc, PrimalVertices)); 46630368db7SStefano Zampini PetscFunctionReturn(0); 46730368db7SStefano Zampini } 4682d505d7fSStefano Zampini 4699371c9d4SSatish Balay static PetscErrorCode PCBDDCGetPrimalVerticesIS_BDDC(PC pc, IS *is) { 4703100ebe3SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 4713100ebe3SStefano Zampini 4723100ebe3SStefano Zampini PetscFunctionBegin; 4733100ebe3SStefano Zampini *is = pcbddc->user_primal_vertices; 4743100ebe3SStefano Zampini PetscFunctionReturn(0); 4753100ebe3SStefano Zampini } 4763100ebe3SStefano Zampini 4773100ebe3SStefano Zampini /*@ 4783100ebe3SStefano Zampini PCBDDCGetPrimalVerticesIS - Get user defined primal vertices set with PCBDDCSetPrimalVerticesIS() 4793100ebe3SStefano Zampini 4803100ebe3SStefano Zampini Collective 4813100ebe3SStefano Zampini 4823100ebe3SStefano Zampini Input Parameters: 4833100ebe3SStefano Zampini . pc - the preconditioning context 4843100ebe3SStefano Zampini 4853100ebe3SStefano Zampini Output Parameters: 4863100ebe3SStefano Zampini . is - index set of primal vertices in global numbering (NULL if not set) 4873100ebe3SStefano Zampini 4883100ebe3SStefano Zampini Level: intermediate 4893100ebe3SStefano Zampini 4903100ebe3SStefano Zampini Notes: 4913100ebe3SStefano Zampini 492db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetPrimalVerticesIS()`, `PCBDDCSetPrimalVerticesLocalIS()`, `PCBDDCGetPrimalVerticesLocalIS()` 4933100ebe3SStefano Zampini @*/ 4949371c9d4SSatish Balay PetscErrorCode PCBDDCGetPrimalVerticesIS(PC pc, IS *is) { 4953100ebe3SStefano Zampini PetscFunctionBegin; 4963100ebe3SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 4973100ebe3SStefano Zampini PetscValidPointer(is, 2); 498cac4c232SBarry Smith PetscUseMethod(pc, "PCBDDCGetPrimalVerticesIS_C", (PC, IS *), (pc, is)); 4993100ebe3SStefano Zampini PetscFunctionReturn(0); 5003100ebe3SStefano Zampini } 5013100ebe3SStefano Zampini 5029371c9d4SSatish Balay static PetscErrorCode PCBDDCSetPrimalVerticesLocalIS_BDDC(PC pc, IS PrimalVertices) { 503674ae819SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 50456282151SStefano Zampini PetscBool isequal = PETSC_FALSE; 5051e6b0712SBarry Smith 506674ae819SStefano Zampini PetscFunctionBegin; 5079566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)PrimalVertices)); 508*48a46eb9SPierre Jolivet if (pcbddc->user_primal_vertices_local) PetscCall(ISEqual(PrimalVertices, pcbddc->user_primal_vertices_local, &isequal)); 5099566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->user_primal_vertices)); 5109566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->user_primal_vertices_local)); 51130368db7SStefano Zampini pcbddc->user_primal_vertices_local = PrimalVertices; 51256282151SStefano Zampini if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 513674ae819SStefano Zampini PetscFunctionReturn(0); 514674ae819SStefano Zampini } 5153100ebe3SStefano Zampini 516674ae819SStefano Zampini /*@ 51728509bceSStefano Zampini PCBDDCSetPrimalVerticesLocalIS - Set additional user defined primal vertices in PCBDDC 518674ae819SStefano Zampini 51917eb1463SStefano Zampini Collective 520674ae819SStefano Zampini 521674ae819SStefano Zampini Input Parameters: 522674ae819SStefano Zampini + pc - the preconditioning context 52317eb1463SStefano Zampini - PrimalVertices - index set of primal vertices in local numbering (can be empty) 524674ae819SStefano Zampini 525674ae819SStefano Zampini Level: intermediate 526674ae819SStefano Zampini 527674ae819SStefano Zampini Notes: 528674ae819SStefano Zampini 529db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetPrimalVerticesIS()`, `PCBDDCGetPrimalVerticesIS()`, `PCBDDCGetPrimalVerticesLocalIS()` 530674ae819SStefano Zampini @*/ 5319371c9d4SSatish Balay PetscErrorCode PCBDDCSetPrimalVerticesLocalIS(PC pc, IS PrimalVertices) { 532674ae819SStefano Zampini PetscFunctionBegin; 533674ae819SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 534674ae819SStefano Zampini PetscValidHeaderSpecific(PrimalVertices, IS_CLASSID, 2); 53517eb1463SStefano Zampini PetscCheckSameComm(pc, 1, PrimalVertices, 2); 536cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetPrimalVerticesLocalIS_C", (PC, IS), (pc, PrimalVertices)); 537674ae819SStefano Zampini PetscFunctionReturn(0); 538674ae819SStefano Zampini } 5392d505d7fSStefano Zampini 5409371c9d4SSatish Balay static PetscErrorCode PCBDDCGetPrimalVerticesLocalIS_BDDC(PC pc, IS *is) { 5413100ebe3SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 5423100ebe3SStefano Zampini 5433100ebe3SStefano Zampini PetscFunctionBegin; 5443100ebe3SStefano Zampini *is = pcbddc->user_primal_vertices_local; 5453100ebe3SStefano Zampini PetscFunctionReturn(0); 5463100ebe3SStefano Zampini } 5473100ebe3SStefano Zampini 5483100ebe3SStefano Zampini /*@ 5493100ebe3SStefano Zampini PCBDDCGetPrimalVerticesLocalIS - Get user defined primal vertices set with PCBDDCSetPrimalVerticesLocalIS() 5503100ebe3SStefano Zampini 5513100ebe3SStefano Zampini Collective 5523100ebe3SStefano Zampini 5533100ebe3SStefano Zampini Input Parameters: 5543100ebe3SStefano Zampini . pc - the preconditioning context 5553100ebe3SStefano Zampini 5563100ebe3SStefano Zampini Output Parameters: 5573100ebe3SStefano Zampini . is - index set of primal vertices in local numbering (NULL if not set) 5583100ebe3SStefano Zampini 5593100ebe3SStefano Zampini Level: intermediate 5603100ebe3SStefano Zampini 5613100ebe3SStefano Zampini Notes: 5623100ebe3SStefano Zampini 563db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetPrimalVerticesIS()`, `PCBDDCGetPrimalVerticesIS()`, `PCBDDCSetPrimalVerticesLocalIS()` 5643100ebe3SStefano Zampini @*/ 5659371c9d4SSatish Balay PetscErrorCode PCBDDCGetPrimalVerticesLocalIS(PC pc, IS *is) { 5663100ebe3SStefano Zampini PetscFunctionBegin; 5673100ebe3SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 5683100ebe3SStefano Zampini PetscValidPointer(is, 2); 569cac4c232SBarry Smith PetscUseMethod(pc, "PCBDDCGetPrimalVerticesLocalIS_C", (PC, IS *), (pc, is)); 5703100ebe3SStefano Zampini PetscFunctionReturn(0); 5713100ebe3SStefano Zampini } 5723100ebe3SStefano Zampini 5739371c9d4SSatish Balay static PetscErrorCode PCBDDCSetCoarseningRatio_BDDC(PC pc, PetscInt k) { 5744fad6a16SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 5754fad6a16SStefano Zampini 5764fad6a16SStefano Zampini PetscFunctionBegin; 5774fad6a16SStefano Zampini pcbddc->coarsening_ratio = k; 5784fad6a16SStefano Zampini PetscFunctionReturn(0); 5794fad6a16SStefano Zampini } 5801e6b0712SBarry Smith 5814fad6a16SStefano Zampini /*@ 58228509bceSStefano Zampini PCBDDCSetCoarseningRatio - Set coarsening ratio used in multilevel 5834fad6a16SStefano Zampini 5844fad6a16SStefano Zampini Logically collective on PC 5854fad6a16SStefano Zampini 5864fad6a16SStefano Zampini Input Parameters: 5874fad6a16SStefano Zampini + pc - the preconditioning context 58828509bceSStefano Zampini - k - coarsening ratio (H/h at the coarser level) 5894fad6a16SStefano Zampini 5900f202f7eSStefano Zampini Options Database Keys: 59167b8a455SSatish Balay . -pc_bddc_coarsening_ratio <int> - Set coarsening ratio used in multilevel coarsening 5924fad6a16SStefano Zampini 5934fad6a16SStefano Zampini Level: intermediate 5944fad6a16SStefano Zampini 5954fad6a16SStefano Zampini Notes: 5960f202f7eSStefano Zampini Approximatively k subdomains at the finer level will be aggregated into a single subdomain at the coarser level 5974fad6a16SStefano Zampini 598db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetLevels()` 5994fad6a16SStefano Zampini @*/ 6009371c9d4SSatish Balay PetscErrorCode PCBDDCSetCoarseningRatio(PC pc, PetscInt k) { 6014fad6a16SStefano Zampini PetscFunctionBegin; 6024fad6a16SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 6032b510759SStefano Zampini PetscValidLogicalCollectiveInt(pc, k, 2); 604cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetCoarseningRatio_C", (PC, PetscInt), (pc, k)); 6054fad6a16SStefano Zampini PetscFunctionReturn(0); 6064fad6a16SStefano Zampini } 6072b510759SStefano Zampini 608b8ffe317SStefano Zampini /* The following functions (PCBDDCSetUseExactDirichlet PCBDDCSetLevel) are not public */ 6099371c9d4SSatish Balay static PetscErrorCode PCBDDCSetUseExactDirichlet_BDDC(PC pc, PetscBool flg) { 610b8ffe317SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 611b8ffe317SStefano Zampini 612b8ffe317SStefano Zampini PetscFunctionBegin; 61385c4d303SStefano Zampini pcbddc->use_exact_dirichlet_trick = flg; 614b8ffe317SStefano Zampini PetscFunctionReturn(0); 615b8ffe317SStefano Zampini } 616b8ffe317SStefano Zampini 6179371c9d4SSatish Balay PetscErrorCode PCBDDCSetUseExactDirichlet(PC pc, PetscBool flg) { 6182b510759SStefano Zampini PetscFunctionBegin; 6192b510759SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 620b8ffe317SStefano Zampini PetscValidLogicalCollectiveBool(pc, flg, 2); 621cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetUseExactDirichlet_C", (PC, PetscBool), (pc, flg)); 6222b510759SStefano Zampini PetscFunctionReturn(0); 6232b510759SStefano Zampini } 6241e6b0712SBarry Smith 6259371c9d4SSatish Balay static PetscErrorCode PCBDDCSetLevel_BDDC(PC pc, PetscInt level) { 6264fad6a16SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 6274fad6a16SStefano Zampini 6284fad6a16SStefano Zampini PetscFunctionBegin; 6292b510759SStefano Zampini pcbddc->current_level = level; 6304fad6a16SStefano Zampini PetscFunctionReturn(0); 6314fad6a16SStefano Zampini } 6321e6b0712SBarry Smith 6339371c9d4SSatish Balay PetscErrorCode PCBDDCSetLevel(PC pc, PetscInt level) { 634b8ffe317SStefano Zampini PetscFunctionBegin; 635b8ffe317SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 636b8ffe317SStefano Zampini PetscValidLogicalCollectiveInt(pc, level, 2); 637cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetLevel_C", (PC, PetscInt), (pc, level)); 638b8ffe317SStefano Zampini PetscFunctionReturn(0); 639b8ffe317SStefano Zampini } 640b8ffe317SStefano Zampini 6419371c9d4SSatish Balay static PetscErrorCode PCBDDCSetLevels_BDDC(PC pc, PetscInt levels) { 6422b510759SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 6432b510759SStefano Zampini 6442b510759SStefano Zampini PetscFunctionBegin; 6457827d75bSBarry Smith PetscCheck(levels < PETSC_PCBDDC_MAXLEVELS, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Maximum number of additional levels for BDDC is %d", PETSC_PCBDDC_MAXLEVELS - 1); 6462b510759SStefano Zampini pcbddc->max_levels = levels; 6472b510759SStefano Zampini PetscFunctionReturn(0); 6482b510759SStefano Zampini } 6492b510759SStefano Zampini 6504fad6a16SStefano Zampini /*@ 65137ebbdf7SStefano Zampini PCBDDCSetLevels - Sets the maximum number of additional levels allowed for multilevel BDDC 6524fad6a16SStefano Zampini 6534fad6a16SStefano Zampini Logically collective on PC 6544fad6a16SStefano Zampini 6554fad6a16SStefano Zampini Input Parameters: 6564fad6a16SStefano Zampini + pc - the preconditioning context 65737ebbdf7SStefano Zampini - levels - the maximum number of levels 6584fad6a16SStefano Zampini 6590f202f7eSStefano Zampini Options Database Keys: 66067b8a455SSatish Balay . -pc_bddc_levels <int> - Set maximum number of levels for multilevel 6614fad6a16SStefano Zampini 6624fad6a16SStefano Zampini Level: intermediate 6634fad6a16SStefano Zampini 6644fad6a16SStefano Zampini Notes: 66537ebbdf7SStefano Zampini The default value is 0, that gives the classical two-levels BDDC 6664fad6a16SStefano Zampini 667db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetCoarseningRatio()` 6684fad6a16SStefano Zampini @*/ 6699371c9d4SSatish Balay PetscErrorCode PCBDDCSetLevels(PC pc, PetscInt levels) { 6704fad6a16SStefano Zampini PetscFunctionBegin; 6714fad6a16SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 6722b510759SStefano Zampini PetscValidLogicalCollectiveInt(pc, levels, 2); 673cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetLevels_C", (PC, PetscInt), (pc, levels)); 6744fad6a16SStefano Zampini PetscFunctionReturn(0); 6754fad6a16SStefano Zampini } 6761e6b0712SBarry Smith 6779371c9d4SSatish Balay static PetscErrorCode PCBDDCSetDirichletBoundaries_BDDC(PC pc, IS DirichletBoundaries) { 6783b03a366Sstefano_zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 67956282151SStefano Zampini PetscBool isequal = PETSC_FALSE; 6803b03a366Sstefano_zampini 6813b03a366Sstefano_zampini PetscFunctionBegin; 6829566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)DirichletBoundaries)); 683*48a46eb9SPierre Jolivet if (pcbddc->DirichletBoundaries) PetscCall(ISEqual(DirichletBoundaries, pcbddc->DirichletBoundaries, &isequal)); 684a5b23f4aSJose E. Roman /* last user setting takes precedence -> destroy any other customization */ 6859566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->DirichletBoundariesLocal)); 6869566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->DirichletBoundaries)); 68736e030ebSStefano Zampini pcbddc->DirichletBoundaries = DirichletBoundaries; 68856282151SStefano Zampini if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 6893b03a366Sstefano_zampini PetscFunctionReturn(0); 6903b03a366Sstefano_zampini } 6911e6b0712SBarry Smith 6923b03a366Sstefano_zampini /*@ 69328509bceSStefano Zampini PCBDDCSetDirichletBoundaries - Set IS defining Dirichlet boundaries for the global problem. 6943b03a366Sstefano_zampini 695785d1243SStefano Zampini Collective 6963b03a366Sstefano_zampini 6973b03a366Sstefano_zampini Input Parameters: 6983b03a366Sstefano_zampini + pc - the preconditioning context 699785d1243SStefano Zampini - DirichletBoundaries - parallel IS defining the Dirichlet boundaries 7003b03a366Sstefano_zampini 7013b03a366Sstefano_zampini Level: intermediate 7023b03a366Sstefano_zampini 7030f202f7eSStefano Zampini Notes: 7040f202f7eSStefano Zampini Provide the information if you used MatZeroRows/Columns routines. Any process can list any global node 7053b03a366Sstefano_zampini 706db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetDirichletBoundariesLocal()`, `MatZeroRows()`, `MatZeroRowsColumns()` 7073b03a366Sstefano_zampini @*/ 7089371c9d4SSatish Balay PetscErrorCode PCBDDCSetDirichletBoundaries(PC pc, IS DirichletBoundaries) { 7093b03a366Sstefano_zampini PetscFunctionBegin; 7103b03a366Sstefano_zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 711674ae819SStefano Zampini PetscValidHeaderSpecific(DirichletBoundaries, IS_CLASSID, 2); 712785d1243SStefano Zampini PetscCheckSameComm(pc, 1, DirichletBoundaries, 2); 713cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetDirichletBoundaries_C", (PC, IS), (pc, DirichletBoundaries)); 7143b03a366Sstefano_zampini PetscFunctionReturn(0); 7153b03a366Sstefano_zampini } 7161e6b0712SBarry Smith 7179371c9d4SSatish Balay static PetscErrorCode PCBDDCSetDirichletBoundariesLocal_BDDC(PC pc, IS DirichletBoundaries) { 7183b03a366Sstefano_zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 71956282151SStefano Zampini PetscBool isequal = PETSC_FALSE; 7203b03a366Sstefano_zampini 7213b03a366Sstefano_zampini PetscFunctionBegin; 7229566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)DirichletBoundaries)); 723*48a46eb9SPierre Jolivet if (pcbddc->DirichletBoundariesLocal) PetscCall(ISEqual(DirichletBoundaries, pcbddc->DirichletBoundariesLocal, &isequal)); 724a5b23f4aSJose E. Roman /* last user setting takes precedence -> destroy any other customization */ 7259566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->DirichletBoundariesLocal)); 7269566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->DirichletBoundaries)); 727785d1243SStefano Zampini pcbddc->DirichletBoundariesLocal = DirichletBoundaries; 72856282151SStefano Zampini if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 7293b03a366Sstefano_zampini PetscFunctionReturn(0); 7303b03a366Sstefano_zampini } 7313b03a366Sstefano_zampini 7323b03a366Sstefano_zampini /*@ 73382ba6b80SStefano Zampini PCBDDCSetDirichletBoundariesLocal - Set IS defining Dirichlet boundaries for the global problem in local ordering. 7343b03a366Sstefano_zampini 735785d1243SStefano Zampini Collective 7363b03a366Sstefano_zampini 7373b03a366Sstefano_zampini Input Parameters: 7383b03a366Sstefano_zampini + pc - the preconditioning context 73982ba6b80SStefano Zampini - DirichletBoundaries - parallel IS defining the Dirichlet boundaries (in local ordering) 7403b03a366Sstefano_zampini 7413b03a366Sstefano_zampini Level: intermediate 7423b03a366Sstefano_zampini 7433b03a366Sstefano_zampini Notes: 7443b03a366Sstefano_zampini 745db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetDirichletBoundaries()`, `MatZeroRows()`, `MatZeroRowsColumns()` 7463b03a366Sstefano_zampini @*/ 7479371c9d4SSatish Balay PetscErrorCode PCBDDCSetDirichletBoundariesLocal(PC pc, IS DirichletBoundaries) { 7483b03a366Sstefano_zampini PetscFunctionBegin; 7493b03a366Sstefano_zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 7503b03a366Sstefano_zampini PetscValidHeaderSpecific(DirichletBoundaries, IS_CLASSID, 2); 75182ba6b80SStefano Zampini PetscCheckSameComm(pc, 1, DirichletBoundaries, 2); 752cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetDirichletBoundariesLocal_C", (PC, IS), (pc, DirichletBoundaries)); 7533b03a366Sstefano_zampini PetscFunctionReturn(0); 7543b03a366Sstefano_zampini } 7553b03a366Sstefano_zampini 7569371c9d4SSatish Balay static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc, IS NeumannBoundaries) { 7570c7d97c5SJed Brown PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 75856282151SStefano Zampini PetscBool isequal = PETSC_FALSE; 7590c7d97c5SJed Brown 7600c7d97c5SJed Brown PetscFunctionBegin; 7619566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)NeumannBoundaries)); 762*48a46eb9SPierre Jolivet if (pcbddc->NeumannBoundaries) PetscCall(ISEqual(NeumannBoundaries, pcbddc->NeumannBoundaries, &isequal)); 763a5b23f4aSJose E. Roman /* last user setting takes precedence -> destroy any other customization */ 7649566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->NeumannBoundariesLocal)); 7659566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->NeumannBoundaries)); 76636e030ebSStefano Zampini pcbddc->NeumannBoundaries = NeumannBoundaries; 76756282151SStefano Zampini if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 7680c7d97c5SJed Brown PetscFunctionReturn(0); 7690c7d97c5SJed Brown } 7701e6b0712SBarry Smith 77157527edcSJed Brown /*@ 77228509bceSStefano Zampini PCBDDCSetNeumannBoundaries - Set IS defining Neumann boundaries for the global problem. 77357527edcSJed Brown 774785d1243SStefano Zampini Collective 77557527edcSJed Brown 77657527edcSJed Brown Input Parameters: 77757527edcSJed Brown + pc - the preconditioning context 778785d1243SStefano Zampini - NeumannBoundaries - parallel IS defining the Neumann boundaries 77957527edcSJed Brown 78057527edcSJed Brown Level: intermediate 78157527edcSJed Brown 7820f202f7eSStefano Zampini Notes: 7830f202f7eSStefano Zampini Any process can list any global node 78457527edcSJed Brown 785db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetNeumannBoundariesLocal()` 78657527edcSJed Brown @*/ 7879371c9d4SSatish Balay PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc, IS NeumannBoundaries) { 7880c7d97c5SJed Brown PetscFunctionBegin; 7890c7d97c5SJed Brown PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 790674ae819SStefano Zampini PetscValidHeaderSpecific(NeumannBoundaries, IS_CLASSID, 2); 791785d1243SStefano Zampini PetscCheckSameComm(pc, 1, NeumannBoundaries, 2); 792cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetNeumannBoundaries_C", (PC, IS), (pc, NeumannBoundaries)); 79353cdbc3dSStefano Zampini PetscFunctionReturn(0); 79453cdbc3dSStefano Zampini } 7951e6b0712SBarry Smith 7969371c9d4SSatish Balay static PetscErrorCode PCBDDCSetNeumannBoundariesLocal_BDDC(PC pc, IS NeumannBoundaries) { 7970c7d97c5SJed Brown PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 79856282151SStefano Zampini PetscBool isequal = PETSC_FALSE; 7990c7d97c5SJed Brown 8000c7d97c5SJed Brown PetscFunctionBegin; 8019566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)NeumannBoundaries)); 802*48a46eb9SPierre Jolivet if (pcbddc->NeumannBoundariesLocal) PetscCall(ISEqual(NeumannBoundaries, pcbddc->NeumannBoundariesLocal, &isequal)); 803a5b23f4aSJose E. Roman /* last user setting takes precedence -> destroy any other customization */ 8049566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->NeumannBoundariesLocal)); 8059566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->NeumannBoundaries)); 806785d1243SStefano Zampini pcbddc->NeumannBoundariesLocal = NeumannBoundaries; 80756282151SStefano Zampini if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 8080c7d97c5SJed Brown PetscFunctionReturn(0); 8090c7d97c5SJed Brown } 8100c7d97c5SJed Brown 8110c7d97c5SJed Brown /*@ 81282ba6b80SStefano Zampini PCBDDCSetNeumannBoundariesLocal - Set IS defining Neumann boundaries for the global problem in local ordering. 8130c7d97c5SJed Brown 814785d1243SStefano Zampini Collective 8150c7d97c5SJed Brown 8160c7d97c5SJed Brown Input Parameters: 8170c7d97c5SJed Brown + pc - the preconditioning context 81882ba6b80SStefano Zampini - NeumannBoundaries - parallel IS defining the subdomain part of Neumann boundaries (in local ordering) 8190c7d97c5SJed Brown 8200c7d97c5SJed Brown Level: intermediate 8210c7d97c5SJed Brown 8220c7d97c5SJed Brown Notes: 8230c7d97c5SJed Brown 824db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetNeumannBoundaries()` 8250c7d97c5SJed Brown @*/ 8269371c9d4SSatish Balay PetscErrorCode PCBDDCSetNeumannBoundariesLocal(PC pc, IS NeumannBoundaries) { 8270c7d97c5SJed Brown PetscFunctionBegin; 8280c7d97c5SJed Brown PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 8290c7d97c5SJed Brown PetscValidHeaderSpecific(NeumannBoundaries, IS_CLASSID, 2); 83082ba6b80SStefano Zampini PetscCheckSameComm(pc, 1, NeumannBoundaries, 2); 831cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetNeumannBoundariesLocal_C", (PC, IS), (pc, NeumannBoundaries)); 83253cdbc3dSStefano Zampini PetscFunctionReturn(0); 83353cdbc3dSStefano Zampini } 83453cdbc3dSStefano Zampini 8359371c9d4SSatish Balay static PetscErrorCode PCBDDCGetDirichletBoundaries_BDDC(PC pc, IS *DirichletBoundaries) { 836da1bb401SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 837da1bb401SStefano Zampini 838da1bb401SStefano Zampini PetscFunctionBegin; 839da1bb401SStefano Zampini *DirichletBoundaries = pcbddc->DirichletBoundaries; 840da1bb401SStefano Zampini PetscFunctionReturn(0); 841da1bb401SStefano Zampini } 8421e6b0712SBarry Smith 843da1bb401SStefano Zampini /*@ 844785d1243SStefano Zampini PCBDDCGetDirichletBoundaries - Get parallel IS for Dirichlet boundaries 845da1bb401SStefano Zampini 846785d1243SStefano Zampini Collective 847785d1243SStefano Zampini 848785d1243SStefano Zampini Input Parameters: 849785d1243SStefano Zampini . pc - the preconditioning context 850785d1243SStefano Zampini 851785d1243SStefano Zampini Output Parameters: 852785d1243SStefano Zampini . DirichletBoundaries - index set defining the Dirichlet boundaries 853785d1243SStefano Zampini 854785d1243SStefano Zampini Level: intermediate 855785d1243SStefano Zampini 8560f202f7eSStefano Zampini Notes: 8570f202f7eSStefano Zampini The IS returned (if any) is the same passed in earlier by the user with PCBDDCSetDirichletBoundaries 858785d1243SStefano Zampini 859db781477SPatrick Sanan .seealso: `PCBDDC` 860785d1243SStefano Zampini @*/ 8619371c9d4SSatish Balay PetscErrorCode PCBDDCGetDirichletBoundaries(PC pc, IS *DirichletBoundaries) { 862785d1243SStefano Zampini PetscFunctionBegin; 863785d1243SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 864cac4c232SBarry Smith PetscUseMethod(pc, "PCBDDCGetDirichletBoundaries_C", (PC, IS *), (pc, DirichletBoundaries)); 865785d1243SStefano Zampini PetscFunctionReturn(0); 866785d1243SStefano Zampini } 867785d1243SStefano Zampini 8689371c9d4SSatish Balay static PetscErrorCode PCBDDCGetDirichletBoundariesLocal_BDDC(PC pc, IS *DirichletBoundaries) { 869785d1243SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 870785d1243SStefano Zampini 871785d1243SStefano Zampini PetscFunctionBegin; 872785d1243SStefano Zampini *DirichletBoundaries = pcbddc->DirichletBoundariesLocal; 873785d1243SStefano Zampini PetscFunctionReturn(0); 874785d1243SStefano Zampini } 875785d1243SStefano Zampini 876da1bb401SStefano Zampini /*@ 87782ba6b80SStefano Zampini PCBDDCGetDirichletBoundariesLocal - Get parallel IS for Dirichlet boundaries (in local ordering) 878da1bb401SStefano Zampini 879785d1243SStefano Zampini Collective 880da1bb401SStefano Zampini 881da1bb401SStefano Zampini Input Parameters: 88228509bceSStefano Zampini . pc - the preconditioning context 883da1bb401SStefano Zampini 884da1bb401SStefano Zampini Output Parameters: 88528509bceSStefano Zampini . DirichletBoundaries - index set defining the subdomain part of Dirichlet boundaries 886da1bb401SStefano Zampini 887da1bb401SStefano Zampini Level: intermediate 888da1bb401SStefano Zampini 889da1bb401SStefano Zampini Notes: 8900f202f7eSStefano 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). 8910f202f7eSStefano Zampini In the latter case, the IS will be available after PCSetUp. 892da1bb401SStefano Zampini 893db781477SPatrick Sanan .seealso: `PCBDDC` 894da1bb401SStefano Zampini @*/ 8959371c9d4SSatish Balay PetscErrorCode PCBDDCGetDirichletBoundariesLocal(PC pc, IS *DirichletBoundaries) { 896da1bb401SStefano Zampini PetscFunctionBegin; 897da1bb401SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 898cac4c232SBarry Smith PetscUseMethod(pc, "PCBDDCGetDirichletBoundariesLocal_C", (PC, IS *), (pc, DirichletBoundaries)); 899da1bb401SStefano Zampini PetscFunctionReturn(0); 900da1bb401SStefano Zampini } 9011e6b0712SBarry Smith 9029371c9d4SSatish Balay static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc, IS *NeumannBoundaries) { 90353cdbc3dSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 90453cdbc3dSStefano Zampini 90553cdbc3dSStefano Zampini PetscFunctionBegin; 90653cdbc3dSStefano Zampini *NeumannBoundaries = pcbddc->NeumannBoundaries; 90753cdbc3dSStefano Zampini PetscFunctionReturn(0); 90853cdbc3dSStefano Zampini } 9091e6b0712SBarry Smith 91053cdbc3dSStefano Zampini /*@ 911785d1243SStefano Zampini PCBDDCGetNeumannBoundaries - Get parallel IS for Neumann boundaries 91253cdbc3dSStefano Zampini 913785d1243SStefano Zampini Collective 914785d1243SStefano Zampini 915785d1243SStefano Zampini Input Parameters: 916785d1243SStefano Zampini . pc - the preconditioning context 917785d1243SStefano Zampini 918785d1243SStefano Zampini Output Parameters: 919785d1243SStefano Zampini . NeumannBoundaries - index set defining the Neumann boundaries 920785d1243SStefano Zampini 921785d1243SStefano Zampini Level: intermediate 922785d1243SStefano Zampini 9230f202f7eSStefano Zampini Notes: 9240f202f7eSStefano Zampini The IS returned (if any) is the same passed in earlier by the user with PCBDDCSetNeumannBoundaries 925785d1243SStefano Zampini 926db781477SPatrick Sanan .seealso: `PCBDDC` 927785d1243SStefano Zampini @*/ 9289371c9d4SSatish Balay PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc, IS *NeumannBoundaries) { 929785d1243SStefano Zampini PetscFunctionBegin; 930785d1243SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 931cac4c232SBarry Smith PetscUseMethod(pc, "PCBDDCGetNeumannBoundaries_C", (PC, IS *), (pc, NeumannBoundaries)); 932785d1243SStefano Zampini PetscFunctionReturn(0); 933785d1243SStefano Zampini } 934785d1243SStefano Zampini 9359371c9d4SSatish Balay static PetscErrorCode PCBDDCGetNeumannBoundariesLocal_BDDC(PC pc, IS *NeumannBoundaries) { 936785d1243SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 937785d1243SStefano Zampini 938785d1243SStefano Zampini PetscFunctionBegin; 939785d1243SStefano Zampini *NeumannBoundaries = pcbddc->NeumannBoundariesLocal; 940785d1243SStefano Zampini PetscFunctionReturn(0); 941785d1243SStefano Zampini } 942785d1243SStefano Zampini 94353cdbc3dSStefano Zampini /*@ 94482ba6b80SStefano Zampini PCBDDCGetNeumannBoundariesLocal - Get parallel IS for Neumann boundaries (in local ordering) 94553cdbc3dSStefano Zampini 946785d1243SStefano Zampini Collective 94753cdbc3dSStefano Zampini 94853cdbc3dSStefano Zampini Input Parameters: 94928509bceSStefano Zampini . pc - the preconditioning context 95053cdbc3dSStefano Zampini 95153cdbc3dSStefano Zampini Output Parameters: 95228509bceSStefano Zampini . NeumannBoundaries - index set defining the subdomain part of Neumann boundaries 95353cdbc3dSStefano Zampini 95453cdbc3dSStefano Zampini Level: intermediate 95553cdbc3dSStefano Zampini 95653cdbc3dSStefano Zampini Notes: 9570f202f7eSStefano 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). 9580f202f7eSStefano Zampini In the latter case, the IS will be available after PCSetUp. 95953cdbc3dSStefano Zampini 960db781477SPatrick Sanan .seealso: `PCBDDC` 96153cdbc3dSStefano Zampini @*/ 9629371c9d4SSatish Balay PetscErrorCode PCBDDCGetNeumannBoundariesLocal(PC pc, IS *NeumannBoundaries) { 96353cdbc3dSStefano Zampini PetscFunctionBegin; 96453cdbc3dSStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 965cac4c232SBarry Smith PetscUseMethod(pc, "PCBDDCGetNeumannBoundariesLocal_C", (PC, IS *), (pc, NeumannBoundaries)); 9660c7d97c5SJed Brown PetscFunctionReturn(0); 9670c7d97c5SJed Brown } 9681e6b0712SBarry Smith 9699371c9d4SSatish Balay static PetscErrorCode PCBDDCSetLocalAdjacencyGraph_BDDC(PC pc, PetscInt nvtxs, const PetscInt xadj[], const PetscInt adjncy[], PetscCopyMode copymode) { 97036e030ebSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 971da1bb401SStefano Zampini PCBDDCGraph mat_graph = pcbddc->mat_graph; 97256282151SStefano Zampini PetscBool same_data = PETSC_FALSE; 97336e030ebSStefano Zampini 97436e030ebSStefano Zampini PetscFunctionBegin; 9758687889aSStefano Zampini if (!nvtxs) { 97604194a47SStefano Zampini if (copymode == PETSC_OWN_POINTER) { 9779566063dSJacob Faibussowitsch PetscCall(PetscFree(xadj)); 9789566063dSJacob Faibussowitsch PetscCall(PetscFree(adjncy)); 97904194a47SStefano Zampini } 9809566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphResetCSR(mat_graph)); 9818687889aSStefano Zampini PetscFunctionReturn(0); 9828687889aSStefano Zampini } 98366da6bd7Sstefano_zampini if (mat_graph->nvtxs == nvtxs && mat_graph->freecsr) { /* we own the data */ 98456282151SStefano Zampini if (mat_graph->xadj == xadj && mat_graph->adjncy == adjncy) same_data = PETSC_TRUE; 98556282151SStefano Zampini if (!same_data && mat_graph->xadj[nvtxs] == xadj[nvtxs]) { 9869566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(xadj, mat_graph->xadj, nvtxs + 1, &same_data)); 987*48a46eb9SPierre Jolivet if (same_data) PetscCall(PetscArraycmp(adjncy, mat_graph->adjncy, xadj[nvtxs], &same_data)); 98856282151SStefano Zampini } 98956282151SStefano Zampini } 99056282151SStefano Zampini if (!same_data) { 991674ae819SStefano Zampini /* free old CSR */ 9929566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphResetCSR(mat_graph)); 993674ae819SStefano Zampini /* get CSR into graph structure */ 994da1bb401SStefano Zampini if (copymode == PETSC_COPY_VALUES) { 9959566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nvtxs + 1, &mat_graph->xadj)); 9969566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(xadj[nvtxs], &mat_graph->adjncy)); 9979566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(mat_graph->xadj, xadj, nvtxs + 1)); 9989566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(mat_graph->adjncy, adjncy, xadj[nvtxs])); 999a1dbd327SStefano Zampini mat_graph->freecsr = PETSC_TRUE; 1000da1bb401SStefano Zampini } else if (copymode == PETSC_OWN_POINTER) { 10011a83f524SJed Brown mat_graph->xadj = (PetscInt *)xadj; 10021a83f524SJed Brown mat_graph->adjncy = (PetscInt *)adjncy; 1003a1dbd327SStefano Zampini mat_graph->freecsr = PETSC_TRUE; 1004a1dbd327SStefano Zampini } else if (copymode == PETSC_USE_POINTER) { 1005a1dbd327SStefano Zampini mat_graph->xadj = (PetscInt *)xadj; 1006a1dbd327SStefano Zampini mat_graph->adjncy = (PetscInt *)adjncy; 1007a1dbd327SStefano Zampini mat_graph->freecsr = PETSC_FALSE; 100863a3b9bcSJacob Faibussowitsch } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported copy mode %d", copymode); 1009575ad6abSStefano Zampini mat_graph->nvtxs_csr = nvtxs; 101056282151SStefano Zampini pcbddc->recompute_topography = PETSC_TRUE; 101156282151SStefano Zampini } 101236e030ebSStefano Zampini PetscFunctionReturn(0); 101336e030ebSStefano Zampini } 10141e6b0712SBarry Smith 101536e030ebSStefano Zampini /*@ 101654fffbccSStefano Zampini PCBDDCSetLocalAdjacencyGraph - Set adjacency structure (CSR graph) of the local degrees of freedom. 101736e030ebSStefano Zampini 101836e030ebSStefano Zampini Not collective 101936e030ebSStefano Zampini 102036e030ebSStefano Zampini Input Parameters: 102154fffbccSStefano Zampini + pc - the preconditioning context. 102254fffbccSStefano Zampini . nvtxs - number of local vertices of the graph (i.e., the number of local dofs). 102354fffbccSStefano Zampini . xadj, adjncy - the connectivity of the dofs in CSR format. 102454fffbccSStefano Zampini - copymode - supported modes are PETSC_COPY_VALUES, PETSC_USE_POINTER or PETSC_OWN_POINTER. 102536e030ebSStefano Zampini 102636e030ebSStefano Zampini Level: intermediate 102736e030ebSStefano Zampini 102895452b02SPatrick Sanan Notes: 102995452b02SPatrick Sanan A dof is considered connected with all local dofs if xadj[dof+1]-xadj[dof] == 1 and adjncy[xadj[dof]] is negative. 103036e030ebSStefano Zampini 103116b07851SJed Brown .seealso: `PCBDDC`, `PetscCopyMode` 103236e030ebSStefano Zampini @*/ 10339371c9d4SSatish Balay PetscErrorCode PCBDDCSetLocalAdjacencyGraph(PC pc, PetscInt nvtxs, const PetscInt xadj[], const PetscInt adjncy[], PetscCopyMode copymode) { 10340a545947SLisandro Dalcin void (*f)(void) = NULL; 103536e030ebSStefano Zampini 103636e030ebSStefano Zampini PetscFunctionBegin; 103736e030ebSStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 10388687889aSStefano Zampini if (nvtxs) { 1039674ae819SStefano Zampini PetscValidIntPointer(xadj, 3); 10401633d1f0SStefano Zampini if (xadj[nvtxs]) PetscValidIntPointer(adjncy, 4); 10418687889aSStefano Zampini } 1042cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetLocalAdjacencyGraph_C", (PC, PetscInt, const PetscInt[], const PetscInt[], PetscCopyMode), (pc, nvtxs, xadj, adjncy, copymode)); 1043575ad6abSStefano Zampini /* free arrays if PCBDDC is not the PC type */ 10449566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)pc, "PCBDDCSetLocalAdjacencyGraph_C", &f)); 1045575ad6abSStefano Zampini if (!f && copymode == PETSC_OWN_POINTER) { 10469566063dSJacob Faibussowitsch PetscCall(PetscFree(xadj)); 10479566063dSJacob Faibussowitsch PetscCall(PetscFree(adjncy)); 1048da1bb401SStefano Zampini } 104936e030ebSStefano Zampini PetscFunctionReturn(0); 105036e030ebSStefano Zampini } 10511e6b0712SBarry Smith 10529371c9d4SSatish Balay static PetscErrorCode PCBDDCSetDofsSplittingLocal_BDDC(PC pc, PetscInt n_is, IS ISForDofs[]) { 105363602bcaSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 105463602bcaSStefano Zampini PetscInt i; 105556282151SStefano Zampini PetscBool isequal = PETSC_FALSE; 105663602bcaSStefano Zampini 105763602bcaSStefano Zampini PetscFunctionBegin; 105856282151SStefano Zampini if (pcbddc->n_ISForDofsLocal == n_is) { 105956282151SStefano Zampini for (i = 0; i < n_is; i++) { 106056282151SStefano Zampini PetscBool isequalt; 10619566063dSJacob Faibussowitsch PetscCall(ISEqual(ISForDofs[i], pcbddc->ISForDofsLocal[i], &isequalt)); 106256282151SStefano Zampini if (!isequalt) break; 106356282151SStefano Zampini } 106456282151SStefano Zampini if (i == n_is) isequal = PETSC_TRUE; 106556282151SStefano Zampini } 1066*48a46eb9SPierre Jolivet for (i = 0; i < n_is; i++) PetscCall(PetscObjectReference((PetscObject)ISForDofs[i])); 106763602bcaSStefano Zampini /* Destroy ISes if they were already set */ 1068*48a46eb9SPierre Jolivet for (i = 0; i < pcbddc->n_ISForDofsLocal; i++) PetscCall(ISDestroy(&pcbddc->ISForDofsLocal[i])); 10699566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->ISForDofsLocal)); 1070a5b23f4aSJose E. Roman /* last user setting takes precedence -> destroy any other customization */ 1071*48a46eb9SPierre Jolivet for (i = 0; i < pcbddc->n_ISForDofs; i++) PetscCall(ISDestroy(&pcbddc->ISForDofs[i])); 10729566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->ISForDofs)); 107363602bcaSStefano Zampini pcbddc->n_ISForDofs = 0; 107463602bcaSStefano Zampini /* allocate space then set */ 1075*48a46eb9SPierre Jolivet if (n_is) PetscCall(PetscMalloc1(n_is, &pcbddc->ISForDofsLocal)); 10769371c9d4SSatish Balay for (i = 0; i < n_is; i++) { pcbddc->ISForDofsLocal[i] = ISForDofs[i]; } 107763602bcaSStefano Zampini pcbddc->n_ISForDofsLocal = n_is; 107863602bcaSStefano Zampini if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE; 107956282151SStefano Zampini if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 108063602bcaSStefano Zampini PetscFunctionReturn(0); 108163602bcaSStefano Zampini } 108263602bcaSStefano Zampini 108363602bcaSStefano Zampini /*@ 108463602bcaSStefano Zampini PCBDDCSetDofsSplittingLocal - Set index sets defining fields of the local subdomain matrix 108563602bcaSStefano Zampini 108663602bcaSStefano Zampini Collective 108763602bcaSStefano Zampini 108863602bcaSStefano Zampini Input Parameters: 108963602bcaSStefano Zampini + pc - the preconditioning context 10900f202f7eSStefano Zampini . n_is - number of index sets defining the fields 10910f202f7eSStefano Zampini - ISForDofs - array of IS describing the fields in local ordering 109263602bcaSStefano Zampini 109363602bcaSStefano Zampini Level: intermediate 109463602bcaSStefano Zampini 10950f202f7eSStefano Zampini Notes: 10960f202f7eSStefano Zampini n_is should be the same among processes. Not all nodes need to be listed: unlisted nodes will belong to the complement field. 109763602bcaSStefano Zampini 1098db781477SPatrick Sanan .seealso: `PCBDDC` 109963602bcaSStefano Zampini @*/ 11009371c9d4SSatish Balay PetscErrorCode PCBDDCSetDofsSplittingLocal(PC pc, PetscInt n_is, IS ISForDofs[]) { 110163602bcaSStefano Zampini PetscInt i; 110263602bcaSStefano Zampini 110363602bcaSStefano Zampini PetscFunctionBegin; 110463602bcaSStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 110563602bcaSStefano Zampini PetscValidLogicalCollectiveInt(pc, n_is, 2); 110663602bcaSStefano Zampini for (i = 0; i < n_is; i++) { 110763602bcaSStefano Zampini PetscCheckSameComm(pc, 1, ISForDofs[i], 3); 110863602bcaSStefano Zampini PetscValidHeaderSpecific(ISForDofs[i], IS_CLASSID, 3); 110963602bcaSStefano Zampini } 1110cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetDofsSplittingLocal_C", (PC, PetscInt, IS[]), (pc, n_is, ISForDofs)); 111163602bcaSStefano Zampini PetscFunctionReturn(0); 111263602bcaSStefano Zampini } 111363602bcaSStefano Zampini 11149371c9d4SSatish Balay static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc, PetscInt n_is, IS ISForDofs[]) { 11159c0446d6SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 11169c0446d6SStefano Zampini PetscInt i; 111756282151SStefano Zampini PetscBool isequal = PETSC_FALSE; 11189c0446d6SStefano Zampini 11199c0446d6SStefano Zampini PetscFunctionBegin; 112056282151SStefano Zampini if (pcbddc->n_ISForDofs == n_is) { 112156282151SStefano Zampini for (i = 0; i < n_is; i++) { 112256282151SStefano Zampini PetscBool isequalt; 11239566063dSJacob Faibussowitsch PetscCall(ISEqual(ISForDofs[i], pcbddc->ISForDofs[i], &isequalt)); 112456282151SStefano Zampini if (!isequalt) break; 112556282151SStefano Zampini } 112656282151SStefano Zampini if (i == n_is) isequal = PETSC_TRUE; 112756282151SStefano Zampini } 1128*48a46eb9SPierre Jolivet for (i = 0; i < n_is; i++) PetscCall(PetscObjectReference((PetscObject)ISForDofs[i])); 1129da1bb401SStefano Zampini /* Destroy ISes if they were already set */ 1130*48a46eb9SPierre Jolivet for (i = 0; i < pcbddc->n_ISForDofs; i++) PetscCall(ISDestroy(&pcbddc->ISForDofs[i])); 11319566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->ISForDofs)); 1132a5b23f4aSJose E. Roman /* last user setting takes precedence -> destroy any other customization */ 1133*48a46eb9SPierre Jolivet for (i = 0; i < pcbddc->n_ISForDofsLocal; i++) PetscCall(ISDestroy(&pcbddc->ISForDofsLocal[i])); 11349566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->ISForDofsLocal)); 113563602bcaSStefano Zampini pcbddc->n_ISForDofsLocal = 0; 1136da1bb401SStefano Zampini /* allocate space then set */ 1137*48a46eb9SPierre Jolivet if (n_is) PetscCall(PetscMalloc1(n_is, &pcbddc->ISForDofs)); 11389371c9d4SSatish Balay for (i = 0; i < n_is; i++) { pcbddc->ISForDofs[i] = ISForDofs[i]; } 11399c0446d6SStefano Zampini pcbddc->n_ISForDofs = n_is; 114063602bcaSStefano Zampini if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE; 114156282151SStefano Zampini if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 11429c0446d6SStefano Zampini PetscFunctionReturn(0); 11439c0446d6SStefano Zampini } 11441e6b0712SBarry Smith 11459c0446d6SStefano Zampini /*@ 114663602bcaSStefano Zampini PCBDDCSetDofsSplitting - Set index sets defining fields of the global matrix 11479c0446d6SStefano Zampini 114863602bcaSStefano Zampini Collective 11499c0446d6SStefano Zampini 11509c0446d6SStefano Zampini Input Parameters: 11519c0446d6SStefano Zampini + pc - the preconditioning context 11520f202f7eSStefano Zampini . n_is - number of index sets defining the fields 11530f202f7eSStefano Zampini - ISForDofs - array of IS describing the fields in global ordering 11549c0446d6SStefano Zampini 11559c0446d6SStefano Zampini Level: intermediate 11569c0446d6SStefano Zampini 11570f202f7eSStefano Zampini Notes: 11580f202f7eSStefano Zampini Any process can list any global node. Not all nodes need to be listed: unlisted nodes will belong to the complement field. 11599c0446d6SStefano Zampini 1160db781477SPatrick Sanan .seealso: `PCBDDC` 11619c0446d6SStefano Zampini @*/ 11629371c9d4SSatish Balay PetscErrorCode PCBDDCSetDofsSplitting(PC pc, PetscInt n_is, IS ISForDofs[]) { 11632b510759SStefano Zampini PetscInt i; 11649c0446d6SStefano Zampini 11659c0446d6SStefano Zampini PetscFunctionBegin; 11669c0446d6SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 116763602bcaSStefano Zampini PetscValidLogicalCollectiveInt(pc, n_is, 2); 11682b510759SStefano Zampini for (i = 0; i < n_is; i++) { 116963602bcaSStefano Zampini PetscValidHeaderSpecific(ISForDofs[i], IS_CLASSID, 3); 1170a011d5a7Sstefano_zampini PetscCheckSameComm(pc, 1, ISForDofs[i], 3); 11712b510759SStefano Zampini } 1172cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetDofsSplitting_C", (PC, PetscInt, IS[]), (pc, n_is, ISForDofs)); 11739c0446d6SStefano Zampini PetscFunctionReturn(0); 11749c0446d6SStefano Zampini } 1175906d46d4SStefano Zampini 1176534831adSStefano Zampini /* 1177534831adSStefano Zampini PCPreSolve_BDDC - Changes the right hand side and (if necessary) the initial 1178534831adSStefano Zampini guess if a transformation of basis approach has been selected. 11799c0446d6SStefano Zampini 1180534831adSStefano Zampini Input Parameter: 1181966d8056SPierre Jolivet + pc - the preconditioner context 1182534831adSStefano Zampini 1183534831adSStefano Zampini Application Interface Routine: PCPreSolve() 1184534831adSStefano Zampini 1185534831adSStefano Zampini Notes: 1186534831adSStefano Zampini The interface routine PCPreSolve() is not usually called directly by 1187534831adSStefano Zampini the user, but instead is called by KSPSolve(). 1188534831adSStefano Zampini */ 11899371c9d4SSatish Balay static PetscErrorCode PCPreSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x) { 1190534831adSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 1191534831adSStefano Zampini PC_IS *pcis = (PC_IS *)(pc->data); 11923972b0daSStefano Zampini Vec used_vec; 1193fcb54b1cSPierre Jolivet PetscBool iscg, save_rhs = PETSC_TRUE, benign_correction_computed; 1194534831adSStefano Zampini 1195534831adSStefano Zampini PetscFunctionBegin; 11961f4df5f7SStefano Zampini /* if we are working with CG, one dirichlet solve can be avoided during Krylov iterations */ 119785c4d303SStefano Zampini if (ksp) { 1198fcb54b1cSPierre Jolivet PetscCall(PetscObjectTypeCompareAny((PetscObject)ksp, &iscg, KSPCG, KSPGROPPCG, KSPPIPECG, KSPPIPELCG, KSPPIPECGRR, "")); 1199*48a46eb9SPierre Jolivet if (pcbddc->benign_apply_coarse_only || pcbddc->switch_static || !iscg || pc->mat != pc->pmat) PetscCall(PCBDDCSetUseExactDirichlet(pc, PETSC_FALSE)); 120085c4d303SStefano Zampini } 1201*48a46eb9SPierre Jolivet if (pcbddc->benign_apply_coarse_only || pcbddc->switch_static || pc->mat != pc->pmat) PetscCall(PCBDDCSetUseExactDirichlet(pc, PETSC_FALSE)); 12021f4df5f7SStefano Zampini 120385c4d303SStefano Zampini /* Creates parallel work vectors used in presolve */ 1204*48a46eb9SPierre Jolivet if (!pcbddc->original_rhs) PetscCall(VecDuplicate(pcis->vec1_global, &pcbddc->original_rhs)); 1205*48a46eb9SPierre Jolivet if (!pcbddc->temp_solution) PetscCall(VecDuplicate(pcis->vec1_global, &pcbddc->temp_solution)); 12068d00608fSStefano Zampini 120727b6a85dSStefano Zampini pcbddc->temp_solution_used = PETSC_FALSE; 12083972b0daSStefano Zampini if (x) { 12099566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)x)); 12103972b0daSStefano Zampini used_vec = x; 12118d00608fSStefano Zampini } else { /* it can only happen when calling PCBDDCMatFETIDPGetRHS */ 12129566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)pcbddc->temp_solution)); 12133972b0daSStefano Zampini used_vec = pcbddc->temp_solution; 12149566063dSJacob Faibussowitsch PetscCall(VecSet(used_vec, 0.0)); 121527b6a85dSStefano Zampini pcbddc->temp_solution_used = PETSC_TRUE; 12169566063dSJacob Faibussowitsch PetscCall(VecCopy(rhs, pcbddc->original_rhs)); 1217266e20e9SStefano Zampini save_rhs = PETSC_FALSE; 1218266e20e9SStefano Zampini pcbddc->eliminate_dirdofs = PETSC_TRUE; 12193972b0daSStefano Zampini } 12208efcfb23SStefano Zampini 12218efcfb23SStefano Zampini /* hack into ksp data structure since PCPreSolve comes earlier than setting to zero the guess in src/ksp/ksp/interface/itfunc.c */ 12223972b0daSStefano Zampini if (ksp) { 1223a0cb1b98SStefano Zampini /* store the flag for the initial guess since it will be restored back during PCPostSolve_BDDC */ 12249566063dSJacob Faibussowitsch PetscCall(KSPGetInitialGuessNonzero(ksp, &pcbddc->ksp_guess_nonzero)); 1225*48a46eb9SPierre Jolivet if (!pcbddc->ksp_guess_nonzero) PetscCall(VecSet(used_vec, 0.0)); 12263972b0daSStefano Zampini } 12273308cffdSStefano Zampini 12288d00608fSStefano Zampini pcbddc->rhs_change = PETSC_FALSE; 12293972b0daSStefano Zampini /* Take into account zeroed rows -> change rhs and store solution removed */ 123070c64980SStefano Zampini if (rhs && pcbddc->eliminate_dirdofs) { 12313975b054SStefano Zampini IS dirIS = NULL; 12323975b054SStefano Zampini 1233a07ea27aSStefano Zampini /* DirichletBoundariesLocal may not be consistent among neighbours; gets a dirichlet dofs IS from graph (may be cached) */ 12349566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph, &dirIS)); 12353975b054SStefano Zampini if (dirIS) { 1236906d46d4SStefano Zampini Mat_IS *matis = (Mat_IS *)pc->pmat->data; 1237785d1243SStefano Zampini PetscInt dirsize, i, *is_indices; 12382b095fd8SStefano Zampini PetscScalar *array_x; 12392b095fd8SStefano Zampini const PetscScalar *array_diagonal; 1240785d1243SStefano Zampini 12419566063dSJacob Faibussowitsch PetscCall(MatGetDiagonal(pc->pmat, pcis->vec1_global)); 12429566063dSJacob Faibussowitsch PetscCall(VecPointwiseDivide(pcis->vec1_global, rhs, pcis->vec1_global)); 12439566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx, pcis->vec1_global, pcis->vec2_N, INSERT_VALUES, SCATTER_FORWARD)); 12449566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx, pcis->vec1_global, pcis->vec2_N, INSERT_VALUES, SCATTER_FORWARD)); 12459566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx, used_vec, pcis->vec1_N, INSERT_VALUES, SCATTER_FORWARD)); 12469566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx, used_vec, pcis->vec1_N, INSERT_VALUES, SCATTER_FORWARD)); 12479566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(dirIS, &dirsize)); 12489566063dSJacob Faibussowitsch PetscCall(VecGetArray(pcis->vec1_N, &array_x)); 12499566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(pcis->vec2_N, &array_diagonal)); 12509566063dSJacob Faibussowitsch PetscCall(ISGetIndices(dirIS, (const PetscInt **)&is_indices)); 12512fa5cd67SKarl Rupp for (i = 0; i < dirsize; i++) array_x[is_indices[i]] = array_diagonal[is_indices[i]]; 12529566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(dirIS, (const PetscInt **)&is_indices)); 12539566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(pcis->vec2_N, &array_diagonal)); 12549566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(pcis->vec1_N, &array_x)); 12559566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx, pcis->vec1_N, used_vec, INSERT_VALUES, SCATTER_REVERSE)); 12569566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx, pcis->vec1_N, used_vec, INSERT_VALUES, SCATTER_REVERSE)); 12578d00608fSStefano Zampini pcbddc->rhs_change = PETSC_TRUE; 12589566063dSJacob Faibussowitsch PetscCall(ISDestroy(&dirIS)); 12598efcfb23SStefano Zampini } 1260a07ea27aSStefano Zampini } 1261b76ba322SStefano Zampini 12628efcfb23SStefano Zampini /* remove the computed solution or the initial guess from the rhs */ 12638d00608fSStefano Zampini if (pcbddc->rhs_change || (ksp && pcbddc->ksp_guess_nonzero)) { 126427b6a85dSStefano Zampini /* save the original rhs */ 126527b6a85dSStefano Zampini if (save_rhs) { 12669566063dSJacob Faibussowitsch PetscCall(VecSwap(rhs, pcbddc->original_rhs)); 126727b6a85dSStefano Zampini save_rhs = PETSC_FALSE; 12688d00608fSStefano Zampini } 12698d00608fSStefano Zampini pcbddc->rhs_change = PETSC_TRUE; 12709566063dSJacob Faibussowitsch PetscCall(VecScale(used_vec, -1.0)); 12719566063dSJacob Faibussowitsch PetscCall(MatMultAdd(pc->mat, used_vec, pcbddc->original_rhs, rhs)); 12729566063dSJacob Faibussowitsch PetscCall(VecScale(used_vec, -1.0)); 12739566063dSJacob Faibussowitsch PetscCall(VecCopy(used_vec, pcbddc->temp_solution)); 127427b6a85dSStefano Zampini pcbddc->temp_solution_used = PETSC_TRUE; 12751baa6e33SBarry Smith if (ksp) PetscCall(KSPSetInitialGuessNonzero(ksp, PETSC_FALSE)); 12763308cffdSStefano Zampini } 12779566063dSJacob Faibussowitsch PetscCall(VecDestroy(&used_vec)); 1278b76ba322SStefano Zampini 1279fc17d649SStefano Zampini /* compute initial vector in benign space if needed 128027b6a85dSStefano Zampini and remove non-benign solution from the rhs */ 128127b6a85dSStefano Zampini benign_correction_computed = PETSC_FALSE; 128208af2428SStefano Zampini if (rhs && pcbddc->benign_compute_correction && (pcbddc->benign_have_null || pcbddc->benign_apply_coarse_only)) { 12831f4df5f7SStefano Zampini /* compute u^*_h using ideas similar to those in Xuemin Tu's PhD thesis (see Section 4.8.1) 12841f4df5f7SStefano Zampini Recursively apply BDDC in the multilevel case */ 1285*48a46eb9SPierre Jolivet if (!pcbddc->benign_vec) PetscCall(VecDuplicate(rhs, &pcbddc->benign_vec)); 1286c69e9cc1SStefano Zampini /* keep applying coarse solver unless we no longer have benign subdomains */ 1287c69e9cc1SStefano Zampini pcbddc->benign_apply_coarse_only = pcbddc->benign_have_null ? PETSC_TRUE : PETSC_FALSE; 128827b6a85dSStefano Zampini if (!pcbddc->benign_skip_correction) { 12899566063dSJacob Faibussowitsch PetscCall(PCApply_BDDC(pc, rhs, pcbddc->benign_vec)); 12903bca92a6SStefano Zampini benign_correction_computed = PETSC_TRUE; 12911baa6e33SBarry Smith if (pcbddc->temp_solution_used) PetscCall(VecAXPY(pcbddc->temp_solution, 1.0, pcbddc->benign_vec)); 12929566063dSJacob Faibussowitsch PetscCall(VecScale(pcbddc->benign_vec, -1.0)); 129327b6a85dSStefano Zampini /* store the original rhs if not done earlier */ 12941baa6e33SBarry Smith if (save_rhs) PetscCall(VecSwap(rhs, pcbddc->original_rhs)); 129527b6a85dSStefano Zampini if (pcbddc->rhs_change) { 12969566063dSJacob Faibussowitsch PetscCall(MatMultAdd(pc->mat, pcbddc->benign_vec, rhs, rhs)); 129727b6a85dSStefano Zampini } else { 12989566063dSJacob Faibussowitsch PetscCall(MatMultAdd(pc->mat, pcbddc->benign_vec, pcbddc->original_rhs, rhs)); 129927b6a85dSStefano Zampini } 13000369aaf7SStefano Zampini pcbddc->rhs_change = PETSC_TRUE; 130127b6a85dSStefano Zampini } 130227b6a85dSStefano Zampini pcbddc->benign_apply_coarse_only = PETSC_FALSE; 13034df7a6bfSStefano Zampini } else { 13049566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->benign_vec)); 13050369aaf7SStefano Zampini } 13062d4c4fecSStefano Zampini 13072d4c4fecSStefano Zampini /* dbg output */ 1308a198735bSStefano Zampini if (pcbddc->dbg_flag && benign_correction_computed) { 13091f4df5f7SStefano Zampini Vec v; 1310c69e9cc1SStefano Zampini 13119566063dSJacob Faibussowitsch PetscCall(VecDuplicate(pcis->vec1_global, &v)); 1312c69e9cc1SStefano Zampini if (pcbddc->ChangeOfBasisMatrix) { 13139566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, rhs, v)); 1314c69e9cc1SStefano Zampini } else { 13159566063dSJacob Faibussowitsch PetscCall(VecCopy(rhs, v)); 1316c69e9cc1SStefano Zampini } 13179566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignGetOrSetP0(pc, v, PETSC_TRUE)); 131863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "LEVEL %" PetscInt_FMT ": is the correction benign?\n", pcbddc->current_level)); 13199566063dSJacob Faibussowitsch PetscCall(PetscScalarView(pcbddc->benign_n, pcbddc->benign_p0, pcbddc->dbg_viewer)); 13209566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 13219566063dSJacob Faibussowitsch PetscCall(VecDestroy(&v)); 13221f4df5f7SStefano Zampini } 13230369aaf7SStefano Zampini 13240369aaf7SStefano Zampini /* set initial guess if using PCG */ 13258ae0ca82SStefano Zampini pcbddc->exact_dirichlet_trick_app = PETSC_FALSE; 13260369aaf7SStefano Zampini if (x && pcbddc->use_exact_dirichlet_trick) { 13279566063dSJacob Faibussowitsch PetscCall(VecSet(x, 0.0)); 13281dd7afcfSStefano Zampini if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) { 132927b6a85dSStefano Zampini if (benign_correction_computed) { /* we have already saved the changed rhs */ 13309566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(pcis->vec1_global)); 13311dd7afcfSStefano Zampini } else { 13329566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, rhs, pcis->vec1_global)); 13331dd7afcfSStefano Zampini } 13349566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec1_global, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD)); 13359566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec1_global, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD)); 13361dd7afcfSStefano Zampini } else { 13379566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, rhs, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD)); 13389566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, rhs, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD)); 13391dd7afcfSStefano Zampini } 13409566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0)); 13419566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_D, pcis->vec1_D, pcis->vec2_D)); 13429566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0)); 13439566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec2_D)); 13441dd7afcfSStefano Zampini if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) { 13459566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_global, 0.)); 13469566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec2_D, pcis->vec1_global, INSERT_VALUES, SCATTER_REVERSE)); 13479566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec2_D, pcis->vec1_global, INSERT_VALUES, SCATTER_REVERSE)); 13489566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix, pcis->vec1_global, x)); 13491dd7afcfSStefano Zampini } else { 13509566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec2_D, x, INSERT_VALUES, SCATTER_REVERSE)); 13519566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec2_D, x, INSERT_VALUES, SCATTER_REVERSE)); 13521dd7afcfSStefano Zampini } 13531baa6e33SBarry Smith if (ksp) PetscCall(KSPSetInitialGuessNonzero(ksp, PETSC_TRUE)); 13548ae0ca82SStefano Zampini pcbddc->exact_dirichlet_trick_app = PETSC_TRUE; 1355266e20e9SStefano Zampini } else if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior && benign_correction_computed && pcbddc->use_exact_dirichlet_trick) { 13569566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(pcis->vec1_global)); 13570369aaf7SStefano Zampini } 1358534831adSStefano Zampini PetscFunctionReturn(0); 1359534831adSStefano Zampini } 1360906d46d4SStefano Zampini 1361534831adSStefano Zampini /* 1362534831adSStefano Zampini PCPostSolve_BDDC - Changes the computed solution if a transformation of basis 1363534831adSStefano Zampini approach has been selected. Also, restores rhs to its original state. 1364534831adSStefano Zampini 1365534831adSStefano Zampini Input Parameter: 1366966d8056SPierre Jolivet + pc - the preconditioner context 1367534831adSStefano Zampini 1368534831adSStefano Zampini Application Interface Routine: PCPostSolve() 1369534831adSStefano Zampini 1370534831adSStefano Zampini Notes: 1371534831adSStefano Zampini The interface routine PCPostSolve() is not usually called directly by 1372534831adSStefano Zampini the user, but instead is called by KSPSolve(). 1373534831adSStefano Zampini */ 13749371c9d4SSatish Balay static PetscErrorCode PCPostSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x) { 1375534831adSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 1376534831adSStefano Zampini 1377534831adSStefano Zampini PetscFunctionBegin; 13783972b0daSStefano Zampini /* add solution removed in presolve */ 13796bcfc461SStefano Zampini if (x && pcbddc->rhs_change) { 138027b6a85dSStefano Zampini if (pcbddc->temp_solution_used) { 13819566063dSJacob Faibussowitsch PetscCall(VecAXPY(x, 1.0, pcbddc->temp_solution)); 1382af140850Sstefano_zampini } else if (pcbddc->benign_compute_correction && pcbddc->benign_vec) { 13839566063dSJacob Faibussowitsch PetscCall(VecAXPY(x, -1.0, pcbddc->benign_vec)); 13843425bc38SStefano Zampini } 1385af140850Sstefano_zampini /* restore to original state (not for FETI-DP) */ 1386af140850Sstefano_zampini if (ksp) pcbddc->temp_solution_used = PETSC_FALSE; 138727b6a85dSStefano Zampini } 138827b6a85dSStefano Zampini 1389266e20e9SStefano Zampini /* restore rhs to its original state (not needed for FETI-DP) */ 13908d00608fSStefano Zampini if (rhs && pcbddc->rhs_change) { 13919566063dSJacob Faibussowitsch PetscCall(VecSwap(rhs, pcbddc->original_rhs)); 13928d00608fSStefano Zampini pcbddc->rhs_change = PETSC_FALSE; 1393af140850Sstefano_zampini } 13948efcfb23SStefano Zampini /* restore ksp guess state */ 13958efcfb23SStefano Zampini if (ksp) { 13969566063dSJacob Faibussowitsch PetscCall(KSPSetInitialGuessNonzero(ksp, pcbddc->ksp_guess_nonzero)); 13978ae0ca82SStefano Zampini /* reset flag for exact dirichlet trick */ 13988ae0ca82SStefano Zampini pcbddc->exact_dirichlet_trick_app = PETSC_FALSE; 1399af140850Sstefano_zampini } 1400534831adSStefano Zampini PetscFunctionReturn(0); 1401534831adSStefano Zampini } 1402af140850Sstefano_zampini 14030c7d97c5SJed Brown /* 14040c7d97c5SJed Brown PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner 14050c7d97c5SJed Brown by setting data structures and options. 14060c7d97c5SJed Brown 14070c7d97c5SJed Brown Input Parameter: 140853cdbc3dSStefano Zampini + pc - the preconditioner context 14090c7d97c5SJed Brown 14100c7d97c5SJed Brown Application Interface Routine: PCSetUp() 14110c7d97c5SJed Brown 14120c7d97c5SJed Brown Notes: 14130c7d97c5SJed Brown The interface routine PCSetUp() is not usually called directly by 14140c7d97c5SJed Brown the user, but instead is called by PCApply() if necessary. 14150c7d97c5SJed Brown */ 14169371c9d4SSatish Balay PetscErrorCode PCSetUp_BDDC(PC pc) { 14170c7d97c5SJed Brown PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 1418c703fcc7SStefano Zampini PCBDDCSubSchurs sub_schurs; 14195e8657edSStefano Zampini Mat_IS *matis; 142008122e43SStefano Zampini MatNullSpace nearnullspace; 142135509ce9Sstefano_zampini Mat lA; 142235509ce9Sstefano_zampini IS lP, zerodiag = NULL; 142391e8d312SStefano Zampini PetscInt nrows, ncols; 142486bfa4cfSStefano Zampini PetscMPIInt size; 1425c703fcc7SStefano Zampini PetscBool computesubschurs; 14268de1fae6SStefano Zampini PetscBool computeconstraintsmatrix; 14273b03f7bbSStefano Zampini PetscBool new_nearnullspace_provided, ismatis, rl; 1428b94d7dedSBarry Smith PetscBool isset, issym, isspd; 14290c7d97c5SJed Brown 14300c7d97c5SJed Brown PetscFunctionBegin; 14319566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATIS, &ismatis)); 143228b400f6SJacob Faibussowitsch PetscCheck(ismatis, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "PCBDDC preconditioner requires matrix of type MATIS"); 14339566063dSJacob Faibussowitsch PetscCall(MatGetSize(pc->pmat, &nrows, &ncols)); 14347827d75bSBarry Smith PetscCheck(nrows == ncols, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "PCBDDC preconditioner requires a square preconditioning matrix"); 14359566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc), &size)); 143686bfa4cfSStefano Zampini 14375e8657edSStefano Zampini matis = (Mat_IS *)pc->pmat->data; 1438f4ddd8eeSStefano Zampini /* the following lines of code should be replaced by a better logic between PCIS, PCNN, PCBDDC and other future nonoverlapping preconditioners */ 14393b03a366Sstefano_zampini /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup 144071582508SStefano Zampini Also, BDDC builds its own KSP for the Dirichlet problem */ 14413b03f7bbSStefano Zampini rl = pcbddc->recompute_topography; 14423b03f7bbSStefano Zampini if (!pc->setupcalled || pc->flag == DIFFERENT_NONZERO_PATTERN) rl = PETSC_TRUE; 14431c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&rl, &pcbddc->recompute_topography, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)pc))); 1444c83e1ba7SStefano Zampini if (pcbddc->recompute_topography) { 1445c83e1ba7SStefano Zampini pcbddc->graphanalyzed = PETSC_FALSE; 1446c83e1ba7SStefano Zampini computeconstraintsmatrix = PETSC_TRUE; 1447c83e1ba7SStefano Zampini } else { 14488de1fae6SStefano Zampini computeconstraintsmatrix = PETSC_FALSE; 1449c83e1ba7SStefano Zampini } 1450b087196eSStefano Zampini 1451b087196eSStefano Zampini /* check parameters' compatibility */ 1452b7ab4a40SStefano Zampini if (!pcbddc->use_deluxe_scaling) pcbddc->deluxe_zerorows = PETSC_FALSE; 1453bd2a564bSStefano Zampini pcbddc->adaptive_selection = (PetscBool)(pcbddc->adaptive_threshold[0] != 0.0 || pcbddc->adaptive_threshold[1] != 0.0); 145486bfa4cfSStefano Zampini pcbddc->use_deluxe_scaling = (PetscBool)(pcbddc->use_deluxe_scaling && size > 1); 145586bfa4cfSStefano Zampini pcbddc->adaptive_selection = (PetscBool)(pcbddc->adaptive_selection && size > 1); 1456bf3a8328SStefano Zampini pcbddc->adaptive_userdefined = (PetscBool)(pcbddc->adaptive_selection && pcbddc->adaptive_userdefined); 1457862806e4SStefano Zampini if (pcbddc->adaptive_selection) pcbddc->use_faces = PETSC_TRUE; 1458862806e4SStefano Zampini 14595a95e1ceSStefano Zampini computesubschurs = (PetscBool)(pcbddc->adaptive_selection || pcbddc->use_deluxe_scaling); 146016909a7fSStefano Zampini 146171582508SStefano Zampini /* activate all connected components if the netflux has been requested */ 1462bb05f991SStefano Zampini if (pcbddc->compute_nonetflux) { 1463bb05f991SStefano Zampini pcbddc->use_vertices = PETSC_TRUE; 1464bb05f991SStefano Zampini pcbddc->use_edges = PETSC_TRUE; 1465bb05f991SStefano Zampini pcbddc->use_faces = PETSC_TRUE; 1466bb05f991SStefano Zampini } 1467bb05f991SStefano Zampini 1468f4ddd8eeSStefano Zampini /* Get stdout for dbg */ 146970cf5478SStefano Zampini if (pcbddc->dbg_flag) { 14709371c9d4SSatish Balay if (!pcbddc->dbg_viewer) { pcbddc->dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pc)); } 14719566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 14729566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIAddTab(pcbddc->dbg_viewer, 2 * pcbddc->current_level)); 1473f4ddd8eeSStefano Zampini } 1474f4ddd8eeSStefano Zampini 1475c703fcc7SStefano Zampini /* process topology information */ 14769566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Topology[pcbddc->current_level], pc, 0, 0, 0)); 147771582508SStefano Zampini if (pcbddc->recompute_topography) { 14789566063dSJacob Faibussowitsch PetscCall(PCBDDCComputeLocalTopologyInfo(pc)); 14791baa6e33SBarry Smith if (pcbddc->discretegradient) PetscCall(PCBDDCNedelecSupport(pc)); 1480c703fcc7SStefano Zampini } 14814f819b78SStefano Zampini if (pcbddc->corner_selected) pcbddc->use_vertices = PETSC_TRUE; 1482a13144ffSStefano Zampini 1483c703fcc7SStefano Zampini /* change basis if requested by the user */ 14845e8657edSStefano Zampini if (pcbddc->user_ChangeOfBasisMatrix) { 14855e8657edSStefano Zampini /* use_change_of_basis flag is used to automatically compute a change of basis from constraints */ 14865e8657edSStefano Zampini pcbddc->use_change_of_basis = PETSC_FALSE; 14879566063dSJacob Faibussowitsch PetscCall(PCBDDCComputeLocalMatrix(pc, pcbddc->user_ChangeOfBasisMatrix)); 14885e8657edSStefano Zampini } else { 14899566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_mat)); 14909566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)matis->A)); 14915e8657edSStefano Zampini pcbddc->local_mat = matis->A; 1492d16cbb6bSStefano Zampini } 1493d16cbb6bSStefano Zampini 14944f1b2e48SStefano Zampini /* 1495c703fcc7SStefano Zampini Compute change of basis on local pressures (aka zerodiag dofs) with the benign trick 14964f1b2e48SStefano Zampini This should come earlier then PCISSetUp for extracting the correct subdomain matrices 14974f1b2e48SStefano Zampini */ 14989566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignShellMat(pc, PETSC_TRUE)); 1499d16cbb6bSStefano Zampini if (pcbddc->benign_saddle_point) { 15009f47a83aSStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 15019f47a83aSStefano Zampini 150205b28244SStefano Zampini if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->use_change_of_basis || !computesubschurs) pcbddc->benign_change_explicit = PETSC_TRUE; 15033b03f7bbSStefano Zampini /* detect local saddle point and change the basis in pcbddc->local_mat */ 15049566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignDetectSaddlePoint(pc, (PetscBool)(!pcbddc->recompute_topography), &zerodiag)); 1505a3df083aSStefano Zampini /* pop B0 mat from local mat */ 15069566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignPopOrPushB0(pc, PETSC_TRUE)); 15071dd7afcfSStefano Zampini /* give pcis a hint to not reuse submatrices during PCISCreate */ 15081dd7afcfSStefano Zampini if (pc->flag == SAME_NONZERO_PATTERN && pcis->reusesubmatrices == PETSC_TRUE) { 15091dd7afcfSStefano Zampini if (pcbddc->benign_n && (pcbddc->benign_change_explicit || pcbddc->dbg_flag)) { 15101dd7afcfSStefano Zampini pcis->reusesubmatrices = PETSC_FALSE; 15111dd7afcfSStefano Zampini } else { 1512a3df083aSStefano Zampini pcis->reusesubmatrices = PETSC_TRUE; 15131dd7afcfSStefano Zampini } 1514a3df083aSStefano Zampini } else { 15159f47a83aSStefano Zampini pcis->reusesubmatrices = PETSC_FALSE; 1516674ae819SStefano Zampini } 1517a3df083aSStefano Zampini } 151827b6a85dSStefano Zampini 15198037d520SStefano Zampini /* propagate relevant information */ 1520b94d7dedSBarry Smith PetscCall(MatIsSymmetricKnown(matis->A, &isset, &issym)); 1521b94d7dedSBarry Smith if (isset) PetscCall(MatSetOption(pcbddc->local_mat, MAT_SYMMETRIC, issym)); 1522b94d7dedSBarry Smith PetscCall(MatIsSPDKnown(matis->A, &isset, &isspd)); 1523b94d7dedSBarry Smith if (isset) PetscCall(MatSetOption(pcbddc->local_mat, MAT_SPD, isspd)); 1524e496cd5dSStefano Zampini 15255e8657edSStefano Zampini /* Set up all the "iterative substructuring" common block without computing solvers */ 15265e8657edSStefano Zampini { 15275e8657edSStefano Zampini Mat temp_mat; 15285e8657edSStefano Zampini 15295e8657edSStefano Zampini temp_mat = matis->A; 15305e8657edSStefano Zampini matis->A = pcbddc->local_mat; 15319566063dSJacob Faibussowitsch PetscCall(PCISSetUp(pc, PETSC_TRUE, PETSC_FALSE)); 15325e8657edSStefano Zampini pcbddc->local_mat = matis->A; 15335e8657edSStefano Zampini matis->A = temp_mat; 15345e8657edSStefano Zampini } 1535684f6988SStefano Zampini 153681d14e9dSStefano Zampini /* Analyze interface */ 153764ac59b8SStefano Zampini if (!pcbddc->graphanalyzed) { 15389566063dSJacob Faibussowitsch PetscCall(PCBDDCAnalyzeInterface(pc)); 15398de1fae6SStefano Zampini computeconstraintsmatrix = PETSC_TRUE; 1540345ecf6cSStefano Zampini if (pcbddc->adaptive_selection && !pcbddc->use_deluxe_scaling && !pcbddc->mat_graph->twodim) { 15414247aa23Sstefano_zampini SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Cannot compute the adaptive primal space for a problem with 3D edges without deluxe scaling"); 1542345ecf6cSStefano Zampini } 1543a198735bSStefano Zampini if (pcbddc->compute_nonetflux) { 1544669cc0f4SStefano Zampini MatNullSpace nnfnnsp; 1545669cc0f4SStefano Zampini 154628b400f6SJacob Faibussowitsch PetscCheck(pcbddc->divudotp, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Missing divudotp operator"); 15479566063dSJacob Faibussowitsch PetscCall(PCBDDCComputeNoNetFlux(pc->pmat, pcbddc->divudotp, pcbddc->divudotp_trans, pcbddc->divudotp_vl2l, pcbddc->mat_graph, &nnfnnsp)); 154871582508SStefano Zampini /* TODO what if a nearnullspace is already attached? */ 15498037d520SStefano Zampini if (nnfnnsp) { 15509566063dSJacob Faibussowitsch PetscCall(MatSetNearNullSpace(pc->pmat, nnfnnsp)); 15519566063dSJacob Faibussowitsch PetscCall(MatNullSpaceDestroy(&nnfnnsp)); 1552669cc0f4SStefano Zampini } 1553674ae819SStefano Zampini } 15548037d520SStefano Zampini } 15559566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Topology[pcbddc->current_level], pc, 0, 0, 0)); 1556fb8d54d4SStefano Zampini 15575408967cSStefano Zampini /* check existence of a divergence free extension, i.e. 15585408967cSStefano Zampini b(v_I,p_0) = 0 for all v_I (raise error if not). 15595408967cSStefano Zampini Also, check that PCBDDCBenignGetOrSetP0 works */ 1560*48a46eb9SPierre Jolivet if (pcbddc->benign_saddle_point && pcbddc->dbg_flag > 1) PetscCall(PCBDDCBenignCheck(pc, zerodiag)); 15619566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zerodiag)); 156206f24817SStefano Zampini 1563b96c3477SStefano Zampini /* Setup local dirichlet solver ksp_D and sub_schurs solvers */ 1564*48a46eb9SPierre Jolivet if (computesubschurs && pcbddc->recompute_topography) PetscCall(PCBDDCInitSubSchurs(pc)); 15659d54b7f4SStefano Zampini /* SetUp Scaling operator (scaling matrices could be needed in SubSchursSetUp)*/ 1566*48a46eb9SPierre Jolivet if (!pcbddc->use_deluxe_scaling) PetscCall(PCBDDCScalingSetUp(pc)); 1567c703fcc7SStefano Zampini 1568c703fcc7SStefano Zampini /* finish setup solvers and do adaptive selection of constraints */ 1569b334f244SStefano Zampini sub_schurs = pcbddc->sub_schurs; 1570b334f244SStefano Zampini if (sub_schurs && sub_schurs->schur_explicit) { 15711baa6e33SBarry Smith if (computesubschurs) PetscCall(PCBDDCSetUpSubSchurs(pc)); 15729566063dSJacob Faibussowitsch PetscCall(PCBDDCSetUpLocalSolvers(pc, PETSC_TRUE, PETSC_FALSE)); 1573d5574798SStefano Zampini } else { 15749566063dSJacob Faibussowitsch PetscCall(PCBDDCSetUpLocalSolvers(pc, PETSC_TRUE, PETSC_FALSE)); 15751baa6e33SBarry Smith if (computesubschurs) PetscCall(PCBDDCSetUpSubSchurs(pc)); 15762070dbb6SStefano Zampini } 157708122e43SStefano Zampini if (pcbddc->adaptive_selection) { 15789566063dSJacob Faibussowitsch PetscCall(PCBDDCAdaptiveSelection(pc)); 15798de1fae6SStefano Zampini computeconstraintsmatrix = PETSC_TRUE; 1580b7eb3628SStefano Zampini } 1581684f6988SStefano Zampini 1582f4ddd8eeSStefano Zampini /* infer if NullSpace object attached to Mat via MatSetNearNullSpace has changed */ 1583fb8d54d4SStefano Zampini new_nearnullspace_provided = PETSC_FALSE; 15849566063dSJacob Faibussowitsch PetscCall(MatGetNearNullSpace(pc->pmat, &nearnullspace)); 1585f4ddd8eeSStefano Zampini if (pcbddc->onearnullspace) { /* already used nearnullspace */ 1586f4ddd8eeSStefano Zampini if (!nearnullspace) { /* near null space attached to mat has been destroyed */ 1587f4ddd8eeSStefano Zampini new_nearnullspace_provided = PETSC_TRUE; 1588f4ddd8eeSStefano Zampini } else { 1589f4ddd8eeSStefano Zampini /* determine if the two nullspaces are different (should be lightweight) */ 1590f4ddd8eeSStefano Zampini if (nearnullspace != pcbddc->onearnullspace) { 1591f4ddd8eeSStefano Zampini new_nearnullspace_provided = PETSC_TRUE; 1592165b64e2SStefano Zampini } else { /* maybe the user has changed the content of the nearnullspace so check vectors ObjectStateId */ 1593f4ddd8eeSStefano Zampini PetscInt i; 1594165b64e2SStefano Zampini const Vec *nearnullvecs; 1595165b64e2SStefano Zampini PetscObjectState state; 1596165b64e2SStefano Zampini PetscInt nnsp_size; 15979566063dSJacob Faibussowitsch PetscCall(MatNullSpaceGetVecs(nearnullspace, NULL, &nnsp_size, &nearnullvecs)); 1598f4ddd8eeSStefano Zampini for (i = 0; i < nnsp_size; i++) { 15999566063dSJacob Faibussowitsch PetscCall(PetscObjectStateGet((PetscObject)nearnullvecs[i], &state)); 1600165b64e2SStefano Zampini if (pcbddc->onearnullvecs_state[i] != state) { 1601f4ddd8eeSStefano Zampini new_nearnullspace_provided = PETSC_TRUE; 1602f4ddd8eeSStefano Zampini break; 1603f4ddd8eeSStefano Zampini } 1604f4ddd8eeSStefano Zampini } 1605f4ddd8eeSStefano Zampini } 1606f4ddd8eeSStefano Zampini } 1607f4ddd8eeSStefano Zampini } else { 1608f4ddd8eeSStefano Zampini if (!nearnullspace) { /* both nearnullspaces are null */ 1609f4ddd8eeSStefano Zampini new_nearnullspace_provided = PETSC_FALSE; 1610f4ddd8eeSStefano Zampini } else { /* nearnullspace attached later */ 1611f4ddd8eeSStefano Zampini new_nearnullspace_provided = PETSC_TRUE; 1612f4ddd8eeSStefano Zampini } 1613f4ddd8eeSStefano Zampini } 1614f4ddd8eeSStefano Zampini 1615f4ddd8eeSStefano Zampini /* Setup constraints and related work vectors */ 1616727cdba6SStefano Zampini /* reset primal space flags */ 16179566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_LocalWork[pcbddc->current_level], pc, 0, 0, 0)); 1618f4ddd8eeSStefano Zampini pcbddc->new_primal_space = PETSC_FALSE; 1619727cdba6SStefano Zampini pcbddc->new_primal_space_local = PETSC_FALSE; 16208de1fae6SStefano Zampini if (computeconstraintsmatrix || new_nearnullspace_provided) { 1621727cdba6SStefano Zampini /* It also sets the primal space flags */ 16229566063dSJacob Faibussowitsch PetscCall(PCBDDCConstraintsSetUp(pc)); 16239543d0ffSStefano Zampini } 1624e7b262bdSStefano Zampini /* Allocate needed local vectors (which depends on quantities defined during ConstraintsSetUp) */ 16259566063dSJacob Faibussowitsch PetscCall(PCBDDCSetUpLocalWorkVectors(pc)); 16265e8657edSStefano Zampini 16275e8657edSStefano Zampini if (pcbddc->use_change_of_basis) { 16285e8657edSStefano Zampini PC_IS *pcis = (PC_IS *)(pc->data); 16295e8657edSStefano Zampini 16309566063dSJacob Faibussowitsch PetscCall(PCBDDCComputeLocalMatrix(pc, pcbddc->ChangeOfBasisMatrix)); 16314f1b2e48SStefano Zampini if (pcbddc->benign_change) { 16329566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->benign_B0)); 1633c263805aSStefano Zampini /* pop B0 from pcbddc->local_mat */ 16349566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignPopOrPushB0(pc, PETSC_TRUE)); 1635c263805aSStefano Zampini } 16365e8657edSStefano Zampini /* get submatrices */ 16379566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcis->A_IB)); 16389566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcis->A_BI)); 16399566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcis->A_BB)); 16409566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->local_mat, pcis->is_B_local, pcis->is_B_local, MAT_INITIAL_MATRIX, &pcis->A_BB)); 16419566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->local_mat, pcis->is_I_local, pcis->is_B_local, MAT_INITIAL_MATRIX, &pcis->A_IB)); 16429566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->local_mat, pcis->is_B_local, pcis->is_I_local, MAT_INITIAL_MATRIX, &pcis->A_BI)); 16433975b054SStefano Zampini /* set flag in pcis to not reuse submatrices during PCISCreate */ 16443975b054SStefano Zampini pcis->reusesubmatrices = PETSC_FALSE; 16459c6a02ceSStefano Zampini } else if (!pcbddc->user_ChangeOfBasisMatrix && !pcbddc->benign_change) { 16469566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_mat)); 16479566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)matis->A)); 16485e8657edSStefano Zampini pcbddc->local_mat = matis->A; 16495e8657edSStefano Zampini } 165035509ce9Sstefano_zampini 165135509ce9Sstefano_zampini /* interface pressure block row for B_C */ 16529566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_lP", (PetscObject *)&lP)); 16539566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_lA", (PetscObject *)&lA)); 165435509ce9Sstefano_zampini if (lA && lP) { 165535509ce9Sstefano_zampini PC_IS *pcis = (PC_IS *)pc->data; 165635509ce9Sstefano_zampini Mat B_BI, B_BB, Bt_BI, Bt_BB; 165735509ce9Sstefano_zampini PetscBool issym; 1658b94d7dedSBarry Smith 16599566063dSJacob Faibussowitsch PetscCall(MatIsSymmetric(lA, PETSC_SMALL, &issym)); 16606cc1294bSstefano_zampini if (issym) { 16619566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(lA, lP, pcis->is_I_local, MAT_INITIAL_MATRIX, &B_BI)); 16629566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(lA, lP, pcis->is_B_local, MAT_INITIAL_MATRIX, &B_BB)); 16639566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(B_BI, &Bt_BI)); 16649566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(B_BB, &Bt_BB)); 166535509ce9Sstefano_zampini } else { 16669566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(lA, lP, pcis->is_I_local, MAT_INITIAL_MATRIX, &B_BI)); 16679566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(lA, lP, pcis->is_B_local, MAT_INITIAL_MATRIX, &B_BB)); 16689566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(lA, pcis->is_I_local, lP, MAT_INITIAL_MATRIX, &Bt_BI)); 16699566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(lA, pcis->is_B_local, lP, MAT_INITIAL_MATRIX, &Bt_BB)); 167035509ce9Sstefano_zampini } 16719566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)pc, "__KSPFETIDP_B_BI", (PetscObject)B_BI)); 16729566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)pc, "__KSPFETIDP_B_BB", (PetscObject)B_BB)); 16739566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)pc, "__KSPFETIDP_Bt_BI", (PetscObject)Bt_BI)); 16749566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)pc, "__KSPFETIDP_Bt_BB", (PetscObject)Bt_BB)); 16759566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B_BI)); 16769566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B_BB)); 16779566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Bt_BI)); 16789566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Bt_BB)); 167935509ce9Sstefano_zampini } 16809566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_LocalWork[pcbddc->current_level], pc, 0, 0, 0)); 168135509ce9Sstefano_zampini 1682b96c3477SStefano Zampini /* SetUp coarse and local Neumann solvers */ 16839566063dSJacob Faibussowitsch PetscCall(PCBDDCSetUpSolvers(pc)); 1684b96c3477SStefano Zampini /* SetUp Scaling operator */ 16851baa6e33SBarry Smith if (pcbddc->use_deluxe_scaling) PetscCall(PCBDDCScalingSetUp(pc)); 1686c703fcc7SStefano Zampini 16871dd7afcfSStefano Zampini /* mark topography as done */ 168856282151SStefano Zampini pcbddc->recompute_topography = PETSC_FALSE; 16890369aaf7SStefano Zampini 16901dd7afcfSStefano Zampini /* wrap pcis->A_IB and pcis->A_BI if we did not change explicitly the variables on the pressures */ 16919566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignShellMat(pc, PETSC_FALSE)); 16921dd7afcfSStefano Zampini 169358a03d70SStefano Zampini if (pcbddc->dbg_flag) { 16949566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISubtractTab(pcbddc->dbg_viewer, 2 * pcbddc->current_level)); 16959566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer)); 16962b510759SStefano Zampini } 16970c7d97c5SJed Brown PetscFunctionReturn(0); 16980c7d97c5SJed Brown } 16990c7d97c5SJed Brown 17000c7d97c5SJed Brown /* 170150efa1b5SStefano Zampini PCApply_BDDC - Applies the BDDC operator to a vector. 17020c7d97c5SJed Brown 17030c7d97c5SJed Brown Input Parameters: 17040f202f7eSStefano Zampini + pc - the preconditioner context 17050f202f7eSStefano Zampini - r - input vector (global) 17060c7d97c5SJed Brown 17070c7d97c5SJed Brown Output Parameter: 17080c7d97c5SJed Brown . z - output vector (global) 17090c7d97c5SJed Brown 17100c7d97c5SJed Brown Application Interface Routine: PCApply() 17110c7d97c5SJed Brown */ 17129371c9d4SSatish Balay PetscErrorCode PCApply_BDDC(PC pc, Vec r, Vec z) { 17130c7d97c5SJed Brown PC_IS *pcis = (PC_IS *)(pc->data); 17140c7d97c5SJed Brown PC_BDDC *pcbddc = (PC_BDDC *)(pc->data); 1715b3338236SStefano Zampini Mat lA = NULL; 1716b097fa66SStefano Zampini PetscInt n_B = pcis->n_B, n_D = pcis->n - n_B; 17173b03a366Sstefano_zampini const PetscScalar one = 1.0; 17183b03a366Sstefano_zampini const PetscScalar m_one = -1.0; 17192617d88aSStefano Zampini const PetscScalar zero = 0.0; 17200c7d97c5SJed Brown /* This code is similar to that provided in nn.c for PCNN 17210c7d97c5SJed Brown NN interface preconditioner changed to BDDC 1722b097fa66SStefano Zampini Added support for M_3 preconditioner in the reference article (code is active if pcbddc->switch_static == PETSC_TRUE) */ 17230c7d97c5SJed Brown 17240c7d97c5SJed Brown PetscFunctionBegin; 17259566063dSJacob Faibussowitsch PetscCall(PetscCitationsRegister(citation, &cited)); 1726*48a46eb9SPierre Jolivet if (pcbddc->switch_static) PetscCall(MatISGetLocalMat(pc->useAmat ? pc->mat : pc->pmat, &lA)); 1727b3338236SStefano Zampini 17281dd7afcfSStefano Zampini if (pcbddc->ChangeOfBasisMatrix) { 17291dd7afcfSStefano Zampini Vec swap; 173027b6a85dSStefano Zampini 17319566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, r, pcbddc->work_change)); 17321dd7afcfSStefano Zampini swap = pcbddc->work_change; 17331dd7afcfSStefano Zampini pcbddc->work_change = r; 17341dd7afcfSStefano Zampini r = swap; 17351dd7afcfSStefano Zampini /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */ 17369cc2a9b1Sstefano_zampini if (pcbddc->benign_apply_coarse_only && pcbddc->use_exact_dirichlet_trick && pcbddc->change_interior) { 17379566063dSJacob Faibussowitsch PetscCall(VecCopy(r, pcis->vec1_global)); 17389566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(pcis->vec1_global)); 17391dd7afcfSStefano Zampini } 17401dd7afcfSStefano Zampini } 174127b6a85dSStefano Zampini if (pcbddc->benign_have_null) { /* get p0 from r */ 17429566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignGetOrSetP0(pc, r, PETSC_TRUE)); 1743efc2fbd9SStefano Zampini } 1744bc960bbfSJed Brown if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_DIRICHLET && !pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) { 17459566063dSJacob Faibussowitsch PetscCall(VecCopy(r, z)); 17460c7d97c5SJed Brown /* First Dirichlet solve */ 17479566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD)); 17489566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD)); 17490c7d97c5SJed Brown /* 17500c7d97c5SJed Brown Assembling right hand side for BDDC operator 1751b097fa66SStefano Zampini - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE) 1752674ae819SStefano Zampini - pcis->vec1_B the interface part of the global vector z 17530c7d97c5SJed Brown */ 1754b097fa66SStefano Zampini if (n_D) { 17559566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0)); 17569566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_D, pcis->vec1_D, pcis->vec2_D)); 17579566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0)); 17589566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec2_D)); 17599566063dSJacob Faibussowitsch PetscCall(VecScale(pcis->vec2_D, m_one)); 176016909a7fSStefano Zampini if (pcbddc->switch_static) { 17619566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_N, 0.)); 17629566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE)); 17639566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE)); 176416909a7fSStefano Zampini if (!pcbddc->switch_static_change) { 17659566063dSJacob Faibussowitsch PetscCall(MatMult(lA, pcis->vec1_N, pcis->vec2_N)); 176616909a7fSStefano Zampini } else { 17679566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N)); 17689566063dSJacob Faibussowitsch PetscCall(MatMult(lA, pcis->vec2_N, pcis->vec1_N)); 17699566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N)); 177016909a7fSStefano Zampini } 17719566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_N, pcis->vec1_D, ADD_VALUES, SCATTER_FORWARD)); 17729566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_N, pcis->vec1_D, ADD_VALUES, SCATTER_FORWARD)); 17739566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_B, pcis->vec2_N, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD)); 17749566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_B, pcis->vec2_N, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD)); 177516909a7fSStefano Zampini } else { 17769566063dSJacob Faibussowitsch PetscCall(MatMult(pcis->A_BI, pcis->vec2_D, pcis->vec1_B)); 177716909a7fSStefano Zampini } 1778b097fa66SStefano Zampini } else { 17799566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_B, zero)); 1780b097fa66SStefano Zampini } 17819566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_B, pcis->vec1_B, z, ADD_VALUES, SCATTER_REVERSE)); 17829566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_B, pcis->vec1_B, z, ADD_VALUES, SCATTER_REVERSE)); 17839566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingRestriction(pc, z, pcis->vec1_B)); 1784b76ba322SStefano Zampini } else { 1785*48a46eb9SPierre Jolivet if (!pcbddc->benign_apply_coarse_only) PetscCall(PCBDDCScalingRestriction(pc, r, pcis->vec1_B)); 17864fee134fSStefano Zampini } 1787bc960bbfSJed Brown if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_LUMP) { 178828b400f6SJacob Faibussowitsch PetscCheck(pcbddc->switch_static, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "You forgot to pass -pc_bddc_switch_static"); 17899566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD)); 17909566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD)); 1791bc960bbfSJed Brown } 1792b76ba322SStefano Zampini 17932617d88aSStefano Zampini /* Apply interface preconditioner 17942617d88aSStefano Zampini input/output vecs: pcis->vec1_B and pcis->vec1_D */ 17959566063dSJacob Faibussowitsch PetscCall(PCBDDCApplyInterfacePreconditioner(pc, PETSC_FALSE)); 17962617d88aSStefano Zampini 1797674ae819SStefano Zampini /* Apply transpose of partition of unity operator */ 17989566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingExtension(pc, pcis->vec1_B, z)); 1799bc960bbfSJed Brown if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_LUMP) { 18009566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec1_D, z, INSERT_VALUES, SCATTER_REVERSE)); 18019566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec1_D, z, INSERT_VALUES, SCATTER_REVERSE)); 1802bc960bbfSJed Brown PetscFunctionReturn(0); 1803bc960bbfSJed Brown } 18043b03a366Sstefano_zampini /* Second Dirichlet solve and assembling of output */ 18059566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_B, z, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD)); 18069566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_B, z, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD)); 1807b097fa66SStefano Zampini if (n_B) { 180816909a7fSStefano Zampini if (pcbddc->switch_static) { 18099566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec1_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE)); 18109566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec1_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE)); 18119566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_B, pcis->vec1_B, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE)); 18129566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_B, pcis->vec1_B, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE)); 181316909a7fSStefano Zampini if (!pcbddc->switch_static_change) { 18149566063dSJacob Faibussowitsch PetscCall(MatMult(lA, pcis->vec1_N, pcis->vec2_N)); 181516909a7fSStefano Zampini } else { 18169566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N)); 18179566063dSJacob Faibussowitsch PetscCall(MatMult(lA, pcis->vec2_N, pcis->vec1_N)); 18189566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N)); 181916909a7fSStefano Zampini } 18209566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_N, pcis->vec3_D, INSERT_VALUES, SCATTER_FORWARD)); 18219566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_N, pcis->vec3_D, INSERT_VALUES, SCATTER_FORWARD)); 182216909a7fSStefano Zampini } else { 18239566063dSJacob Faibussowitsch PetscCall(MatMult(pcis->A_IB, pcis->vec1_B, pcis->vec3_D)); 182416909a7fSStefano Zampini } 182516909a7fSStefano Zampini } else if (pcbddc->switch_static) { /* n_B is zero */ 182616909a7fSStefano Zampini if (!pcbddc->switch_static_change) { 18279566063dSJacob Faibussowitsch PetscCall(MatMult(lA, pcis->vec1_D, pcis->vec3_D)); 182816909a7fSStefano Zampini } else { 18299566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_D, pcis->vec1_N)); 18309566063dSJacob Faibussowitsch PetscCall(MatMult(lA, pcis->vec1_N, pcis->vec2_N)); 18319566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec2_N, pcis->vec3_D)); 183216909a7fSStefano Zampini } 1833b097fa66SStefano Zampini } 18349566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0)); 18359566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_D, pcis->vec3_D, pcis->vec4_D)); 18369566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0)); 18379566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec4_D)); 1838efc2fbd9SStefano Zampini 18398ae0ca82SStefano Zampini if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) { 1840b097fa66SStefano Zampini if (pcbddc->switch_static) { 18419566063dSJacob Faibussowitsch PetscCall(VecAXPBYPCZ(pcis->vec2_D, m_one, one, m_one, pcis->vec4_D, pcis->vec1_D)); 1842b097fa66SStefano Zampini } else { 18439566063dSJacob Faibussowitsch PetscCall(VecAXPBY(pcis->vec2_D, m_one, m_one, pcis->vec4_D)); 1844b097fa66SStefano Zampini } 18459566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec2_D, z, INSERT_VALUES, SCATTER_REVERSE)); 18469566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec2_D, z, INSERT_VALUES, SCATTER_REVERSE)); 1847b097fa66SStefano Zampini } else { 1848b097fa66SStefano Zampini if (pcbddc->switch_static) { 18499566063dSJacob Faibussowitsch PetscCall(VecAXPBY(pcis->vec4_D, one, m_one, pcis->vec1_D)); 1850b097fa66SStefano Zampini } else { 18519566063dSJacob Faibussowitsch PetscCall(VecScale(pcis->vec4_D, m_one)); 1852b097fa66SStefano Zampini } 18539566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec4_D, z, INSERT_VALUES, SCATTER_REVERSE)); 18549566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec4_D, z, INSERT_VALUES, SCATTER_REVERSE)); 1855b097fa66SStefano Zampini } 185627b6a85dSStefano Zampini if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */ 18571baa6e33SBarry Smith if (pcbddc->benign_apply_coarse_only) PetscCall(PetscArrayzero(pcbddc->benign_p0, pcbddc->benign_n)); 18589566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignGetOrSetP0(pc, z, PETSC_FALSE)); 1859efc2fbd9SStefano Zampini } 18601f4df5f7SStefano Zampini 18611dd7afcfSStefano Zampini if (pcbddc->ChangeOfBasisMatrix) { 1862f913dca9SStefano Zampini pcbddc->work_change = r; 18639566063dSJacob Faibussowitsch PetscCall(VecCopy(z, pcbddc->work_change)); 18649566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix, pcbddc->work_change, z)); 18651dd7afcfSStefano Zampini } 18660c7d97c5SJed Brown PetscFunctionReturn(0); 18670c7d97c5SJed Brown } 186850efa1b5SStefano Zampini 186950efa1b5SStefano Zampini /* 187050efa1b5SStefano Zampini PCApplyTranspose_BDDC - Applies the transpose of the BDDC operator to a vector. 187150efa1b5SStefano Zampini 187250efa1b5SStefano Zampini Input Parameters: 18730f202f7eSStefano Zampini + pc - the preconditioner context 18740f202f7eSStefano Zampini - r - input vector (global) 187550efa1b5SStefano Zampini 187650efa1b5SStefano Zampini Output Parameter: 187750efa1b5SStefano Zampini . z - output vector (global) 187850efa1b5SStefano Zampini 187950efa1b5SStefano Zampini Application Interface Routine: PCApplyTranspose() 188050efa1b5SStefano Zampini */ 18819371c9d4SSatish Balay PetscErrorCode PCApplyTranspose_BDDC(PC pc, Vec r, Vec z) { 188250efa1b5SStefano Zampini PC_IS *pcis = (PC_IS *)(pc->data); 188350efa1b5SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)(pc->data); 1884b3338236SStefano Zampini Mat lA = NULL; 1885b097fa66SStefano Zampini PetscInt n_B = pcis->n_B, n_D = pcis->n - n_B; 188650efa1b5SStefano Zampini const PetscScalar one = 1.0; 188750efa1b5SStefano Zampini const PetscScalar m_one = -1.0; 188850efa1b5SStefano Zampini const PetscScalar zero = 0.0; 188950efa1b5SStefano Zampini 189050efa1b5SStefano Zampini PetscFunctionBegin; 18919566063dSJacob Faibussowitsch PetscCall(PetscCitationsRegister(citation, &cited)); 1892*48a46eb9SPierre Jolivet if (pcbddc->switch_static) PetscCall(MatISGetLocalMat(pc->useAmat ? pc->mat : pc->pmat, &lA)); 18931dd7afcfSStefano Zampini if (pcbddc->ChangeOfBasisMatrix) { 18941dd7afcfSStefano Zampini Vec swap; 189527b6a85dSStefano Zampini 18969566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, r, pcbddc->work_change)); 18971dd7afcfSStefano Zampini swap = pcbddc->work_change; 18981dd7afcfSStefano Zampini pcbddc->work_change = r; 18991dd7afcfSStefano Zampini r = swap; 190027b6a85dSStefano Zampini /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */ 19018ae0ca82SStefano Zampini if (pcbddc->benign_apply_coarse_only && pcbddc->exact_dirichlet_trick_app && pcbddc->change_interior) { 19029566063dSJacob Faibussowitsch PetscCall(VecCopy(r, pcis->vec1_global)); 19039566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(pcis->vec1_global)); 19041dd7afcfSStefano Zampini } 190527b6a85dSStefano Zampini } 190627b6a85dSStefano Zampini if (pcbddc->benign_have_null) { /* get p0 from r */ 19079566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignGetOrSetP0(pc, r, PETSC_TRUE)); 1908537c1cdfSStefano Zampini } 19098ae0ca82SStefano Zampini if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) { 19109566063dSJacob Faibussowitsch PetscCall(VecCopy(r, z)); 191150efa1b5SStefano Zampini /* First Dirichlet solve */ 19129566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD)); 19139566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD)); 191450efa1b5SStefano Zampini /* 191550efa1b5SStefano Zampini Assembling right hand side for BDDC operator 1916b097fa66SStefano Zampini - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE) 191750efa1b5SStefano Zampini - pcis->vec1_B the interface part of the global vector z 191850efa1b5SStefano Zampini */ 1919b097fa66SStefano Zampini if (n_D) { 19209566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0)); 19219566063dSJacob Faibussowitsch PetscCall(KSPSolveTranspose(pcbddc->ksp_D, pcis->vec1_D, pcis->vec2_D)); 19229566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0)); 19239566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec2_D)); 19249566063dSJacob Faibussowitsch PetscCall(VecScale(pcis->vec2_D, m_one)); 192516909a7fSStefano Zampini if (pcbddc->switch_static) { 19269566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_N, 0.)); 19279566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE)); 19289566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE)); 192916909a7fSStefano Zampini if (!pcbddc->switch_static_change) { 19309566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(lA, pcis->vec1_N, pcis->vec2_N)); 193116909a7fSStefano Zampini } else { 19329566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N)); 19339566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(lA, pcis->vec2_N, pcis->vec1_N)); 19349566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N)); 193516909a7fSStefano Zampini } 19369566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_N, pcis->vec1_D, ADD_VALUES, SCATTER_FORWARD)); 19379566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_N, pcis->vec1_D, ADD_VALUES, SCATTER_FORWARD)); 19389566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_B, pcis->vec2_N, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD)); 19399566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_B, pcis->vec2_N, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD)); 194016909a7fSStefano Zampini } else { 19419566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcis->A_IB, pcis->vec2_D, pcis->vec1_B)); 194216909a7fSStefano Zampini } 1943b097fa66SStefano Zampini } else { 19449566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_B, zero)); 1945b097fa66SStefano Zampini } 19469566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_B, pcis->vec1_B, z, ADD_VALUES, SCATTER_REVERSE)); 19479566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_B, pcis->vec1_B, z, ADD_VALUES, SCATTER_REVERSE)); 19489566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingRestriction(pc, z, pcis->vec1_B)); 194950efa1b5SStefano Zampini } else { 19509566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingRestriction(pc, r, pcis->vec1_B)); 195150efa1b5SStefano Zampini } 195250efa1b5SStefano Zampini 195350efa1b5SStefano Zampini /* Apply interface preconditioner 195450efa1b5SStefano Zampini input/output vecs: pcis->vec1_B and pcis->vec1_D */ 19559566063dSJacob Faibussowitsch PetscCall(PCBDDCApplyInterfacePreconditioner(pc, PETSC_TRUE)); 195650efa1b5SStefano Zampini 195750efa1b5SStefano Zampini /* Apply transpose of partition of unity operator */ 19589566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingExtension(pc, pcis->vec1_B, z)); 195950efa1b5SStefano Zampini 196050efa1b5SStefano Zampini /* Second Dirichlet solve and assembling of output */ 19619566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_B, z, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD)); 19629566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_B, z, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD)); 1963b097fa66SStefano Zampini if (n_B) { 196416909a7fSStefano Zampini if (pcbddc->switch_static) { 19659566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec1_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE)); 19669566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec1_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE)); 19679566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_B, pcis->vec1_B, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE)); 19689566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_B, pcis->vec1_B, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE)); 196916909a7fSStefano Zampini if (!pcbddc->switch_static_change) { 19709566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(lA, pcis->vec1_N, pcis->vec2_N)); 197116909a7fSStefano Zampini } else { 19729566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N)); 19739566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(lA, pcis->vec2_N, pcis->vec1_N)); 19749566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N)); 197516909a7fSStefano Zampini } 19769566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_N, pcis->vec3_D, INSERT_VALUES, SCATTER_FORWARD)); 19779566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_N, pcis->vec3_D, INSERT_VALUES, SCATTER_FORWARD)); 197816909a7fSStefano Zampini } else { 19799566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcis->A_BI, pcis->vec1_B, pcis->vec3_D)); 198016909a7fSStefano Zampini } 198116909a7fSStefano Zampini } else if (pcbddc->switch_static) { /* n_B is zero */ 198216909a7fSStefano Zampini if (!pcbddc->switch_static_change) { 19839566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(lA, pcis->vec1_D, pcis->vec3_D)); 198416909a7fSStefano Zampini } else { 19859566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_D, pcis->vec1_N)); 19869566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(lA, pcis->vec1_N, pcis->vec2_N)); 19879566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec2_N, pcis->vec3_D)); 198816909a7fSStefano Zampini } 1989b097fa66SStefano Zampini } 19909566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0)); 19919566063dSJacob Faibussowitsch PetscCall(KSPSolveTranspose(pcbddc->ksp_D, pcis->vec3_D, pcis->vec4_D)); 19929566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0)); 19939566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec4_D)); 19948ae0ca82SStefano Zampini if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) { 1995b097fa66SStefano Zampini if (pcbddc->switch_static) { 19969566063dSJacob Faibussowitsch PetscCall(VecAXPBYPCZ(pcis->vec2_D, m_one, one, m_one, pcis->vec4_D, pcis->vec1_D)); 1997b097fa66SStefano Zampini } else { 19989566063dSJacob Faibussowitsch PetscCall(VecAXPBY(pcis->vec2_D, m_one, m_one, pcis->vec4_D)); 1999b097fa66SStefano Zampini } 20009566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec2_D, z, INSERT_VALUES, SCATTER_REVERSE)); 20019566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec2_D, z, INSERT_VALUES, SCATTER_REVERSE)); 2002b097fa66SStefano Zampini } else { 2003b097fa66SStefano Zampini if (pcbddc->switch_static) { 20049566063dSJacob Faibussowitsch PetscCall(VecAXPBY(pcis->vec4_D, one, m_one, pcis->vec1_D)); 2005b097fa66SStefano Zampini } else { 20069566063dSJacob Faibussowitsch PetscCall(VecScale(pcis->vec4_D, m_one)); 2007b097fa66SStefano Zampini } 20089566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec4_D, z, INSERT_VALUES, SCATTER_REVERSE)); 20099566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec4_D, z, INSERT_VALUES, SCATTER_REVERSE)); 2010b097fa66SStefano Zampini } 201127b6a85dSStefano Zampini if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */ 20129566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignGetOrSetP0(pc, z, PETSC_FALSE)); 2013537c1cdfSStefano Zampini } 20141dd7afcfSStefano Zampini if (pcbddc->ChangeOfBasisMatrix) { 2015f913dca9SStefano Zampini pcbddc->work_change = r; 20169566063dSJacob Faibussowitsch PetscCall(VecCopy(z, pcbddc->work_change)); 20179566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix, pcbddc->work_change, z)); 20181dd7afcfSStefano Zampini } 201950efa1b5SStefano Zampini PetscFunctionReturn(0); 202050efa1b5SStefano Zampini } 2021674ae819SStefano Zampini 20229371c9d4SSatish Balay PetscErrorCode PCReset_BDDC(PC pc) { 2023da1bb401SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 20249326c5c6Sstefano_zampini PC_IS *pcis = (PC_IS *)pc->data; 20259326c5c6Sstefano_zampini KSP kspD, kspR, kspC; 2026da1bb401SStefano Zampini 2027da1bb401SStefano Zampini PetscFunctionBegin; 2028674ae819SStefano Zampini /* free BDDC custom data */ 20299566063dSJacob Faibussowitsch PetscCall(PCBDDCResetCustomization(pc)); 2030674ae819SStefano Zampini /* destroy objects related to topography */ 20319566063dSJacob Faibussowitsch PetscCall(PCBDDCResetTopography(pc)); 203234a97f8cSStefano Zampini /* destroy objects for scaling operator */ 20339566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingDestroy(pc)); 2034674ae819SStefano Zampini /* free solvers stuff */ 20359566063dSJacob Faibussowitsch PetscCall(PCBDDCResetSolvers(pc)); 203662a6ff1dSStefano Zampini /* free global vectors needed in presolve */ 20379566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->temp_solution)); 20389566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->original_rhs)); 20391dd7afcfSStefano Zampini /* free data created by PCIS */ 20409566063dSJacob Faibussowitsch PetscCall(PCISDestroy(pc)); 20419326c5c6Sstefano_zampini 20429326c5c6Sstefano_zampini /* restore defaults */ 20439326c5c6Sstefano_zampini kspD = pcbddc->ksp_D; 20449326c5c6Sstefano_zampini kspR = pcbddc->ksp_R; 20459326c5c6Sstefano_zampini kspC = pcbddc->coarse_ksp; 20469566063dSJacob Faibussowitsch PetscCall(PetscMemzero(pc->data, sizeof(*pcbddc))); 20479326c5c6Sstefano_zampini pcis->n_neigh = -1; 20489326c5c6Sstefano_zampini pcis->scaling_factor = 1.0; 20499326c5c6Sstefano_zampini pcis->reusesubmatrices = PETSC_TRUE; 20509326c5c6Sstefano_zampini pcbddc->use_local_adj = PETSC_TRUE; 20519326c5c6Sstefano_zampini pcbddc->use_vertices = PETSC_TRUE; 20529326c5c6Sstefano_zampini pcbddc->use_edges = PETSC_TRUE; 20539326c5c6Sstefano_zampini pcbddc->symmetric_primal = PETSC_TRUE; 20549326c5c6Sstefano_zampini pcbddc->vertex_size = 1; 20559326c5c6Sstefano_zampini pcbddc->recompute_topography = PETSC_TRUE; 20569326c5c6Sstefano_zampini pcbddc->coarse_size = -1; 20579326c5c6Sstefano_zampini pcbddc->use_exact_dirichlet_trick = PETSC_TRUE; 20589326c5c6Sstefano_zampini pcbddc->coarsening_ratio = 8; 20599326c5c6Sstefano_zampini pcbddc->coarse_eqs_per_proc = 1; 20609326c5c6Sstefano_zampini pcbddc->benign_compute_correction = PETSC_TRUE; 20619326c5c6Sstefano_zampini pcbddc->nedfield = -1; 20629326c5c6Sstefano_zampini pcbddc->nedglobal = PETSC_TRUE; 20639326c5c6Sstefano_zampini pcbddc->graphmaxcount = PETSC_MAX_INT; 20649326c5c6Sstefano_zampini pcbddc->sub_schurs_layers = -1; 20659326c5c6Sstefano_zampini pcbddc->ksp_D = kspD; 20669326c5c6Sstefano_zampini pcbddc->ksp_R = kspR; 20679326c5c6Sstefano_zampini pcbddc->coarse_ksp = kspC; 20689326c5c6Sstefano_zampini PetscFunctionReturn(0); 20699326c5c6Sstefano_zampini } 20709326c5c6Sstefano_zampini 20719371c9d4SSatish Balay PetscErrorCode PCDestroy_BDDC(PC pc) { 20729326c5c6Sstefano_zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 20739326c5c6Sstefano_zampini 20749326c5c6Sstefano_zampini PetscFunctionBegin; 20759566063dSJacob Faibussowitsch PetscCall(PCReset_BDDC(pc)); 20769566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&pcbddc->ksp_D)); 20779566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&pcbddc->ksp_R)); 20789566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&pcbddc->coarse_ksp)); 20799566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDiscreteGradient_C", NULL)); 20809566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDivergenceMat_C", NULL)); 20819566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetChangeOfBasisMat_C", NULL)); 20829566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetPrimalVerticesLocalIS_C", NULL)); 20839566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetPrimalVerticesIS_C", NULL)); 208432fe681dSStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetPrimalVerticesLocalIS_C", NULL)); 208532fe681dSStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetPrimalVerticesIS_C", NULL)); 20869566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetCoarseningRatio_C", NULL)); 20879566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLevel_C", NULL)); 20889566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetUseExactDirichlet_C", NULL)); 20899566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLevels_C", NULL)); 20909566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDirichletBoundaries_C", NULL)); 20919566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDirichletBoundariesLocal_C", NULL)); 20929566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetNeumannBoundaries_C", NULL)); 20939566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetNeumannBoundariesLocal_C", NULL)); 20949566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetDirichletBoundaries_C", NULL)); 20959566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetDirichletBoundariesLocal_C", NULL)); 20969566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetNeumannBoundaries_C", NULL)); 20979566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetNeumannBoundariesLocal_C", NULL)); 20989566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDofsSplitting_C", NULL)); 20999566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDofsSplittingLocal_C", NULL)); 21009566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLocalAdjacencyGraph_C", NULL)); 21019566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCCreateFETIDPOperators_C", NULL)); 21029566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCMatFETIDPGetRHS_C", NULL)); 21039566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCMatFETIDPGetSolution_C", NULL)); 21049566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCPreSolveChangeRHS_C", NULL)); 21059566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", NULL)); 21069566063dSJacob Faibussowitsch PetscCall(PetscFree(pc->data)); 2107da1bb401SStefano Zampini PetscFunctionReturn(0); 2108da1bb401SStefano Zampini } 21091e6b0712SBarry Smith 21109371c9d4SSatish Balay static PetscErrorCode PCSetCoordinates_BDDC(PC pc, PetscInt dim, PetscInt nloc, PetscReal *coords) { 2111ab8c8b98SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 2112ab8c8b98SStefano Zampini PCBDDCGraph mat_graph = pcbddc->mat_graph; 2113ab8c8b98SStefano Zampini 2114ab8c8b98SStefano Zampini PetscFunctionBegin; 21159566063dSJacob Faibussowitsch PetscCall(PetscFree(mat_graph->coords)); 21169566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nloc * dim, &mat_graph->coords)); 21179566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(mat_graph->coords, coords, nloc * dim)); 2118ab8c8b98SStefano Zampini mat_graph->cnloc = nloc; 2119ab8c8b98SStefano Zampini mat_graph->cdim = dim; 2120ab8c8b98SStefano Zampini mat_graph->cloc = PETSC_FALSE; 21214f819b78SStefano Zampini /* flg setup */ 21224f819b78SStefano Zampini pcbddc->recompute_topography = PETSC_TRUE; 21234f819b78SStefano Zampini pcbddc->corner_selected = PETSC_FALSE; 2124ab8c8b98SStefano Zampini PetscFunctionReturn(0); 2125ab8c8b98SStefano Zampini } 2126ab8c8b98SStefano Zampini 21279371c9d4SSatish Balay static PetscErrorCode PCPreSolveChangeRHS_BDDC(PC pc, PetscBool *change) { 2128a06fd7f2SStefano Zampini PetscFunctionBegin; 2129a06fd7f2SStefano Zampini *change = PETSC_TRUE; 2130a06fd7f2SStefano Zampini PetscFunctionReturn(0); 2131a06fd7f2SStefano Zampini } 2132a06fd7f2SStefano Zampini 21339371c9d4SSatish Balay static PetscErrorCode PCBDDCMatFETIDPGetRHS_BDDC(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs) { 2134674ae819SStefano Zampini FETIDPMat_ctx mat_ctx; 2135266e20e9SStefano Zampini Vec work; 21363425bc38SStefano Zampini PC_IS *pcis; 21373425bc38SStefano Zampini PC_BDDC *pcbddc; 21380c7d97c5SJed Brown 21393425bc38SStefano Zampini PetscFunctionBegin; 21409566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(fetidp_mat, &mat_ctx)); 21413425bc38SStefano Zampini pcis = (PC_IS *)mat_ctx->pc->data; 21423425bc38SStefano Zampini pcbddc = (PC_BDDC *)mat_ctx->pc->data; 21433425bc38SStefano Zampini 21449566063dSJacob Faibussowitsch PetscCall(VecSet(fetidp_flux_rhs, 0.0)); 2145229984c5Sstefano_zampini /* copy rhs since we may change it during PCPreSolve_BDDC */ 2146*48a46eb9SPierre Jolivet if (!pcbddc->original_rhs) PetscCall(VecDuplicate(pcis->vec1_global, &pcbddc->original_rhs)); 21476cc1294bSstefano_zampini if (mat_ctx->rhs_flip) { 21489566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(pcbddc->original_rhs, standard_rhs, mat_ctx->rhs_flip)); 21496cc1294bSstefano_zampini } else { 21509566063dSJacob Faibussowitsch PetscCall(VecCopy(standard_rhs, pcbddc->original_rhs)); 21516cc1294bSstefano_zampini } 2152af140850Sstefano_zampini if (mat_ctx->g2g_p) { 2153229984c5Sstefano_zampini /* interface pressure rhs */ 21549566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat_ctx->g2g_p, fetidp_flux_rhs, pcbddc->original_rhs, INSERT_VALUES, SCATTER_REVERSE)); 21559566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat_ctx->g2g_p, fetidp_flux_rhs, pcbddc->original_rhs, INSERT_VALUES, SCATTER_REVERSE)); 21569566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat_ctx->g2g_p, standard_rhs, fetidp_flux_rhs, INSERT_VALUES, SCATTER_FORWARD)); 21579566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat_ctx->g2g_p, standard_rhs, fetidp_flux_rhs, INSERT_VALUES, SCATTER_FORWARD)); 2158*48a46eb9SPierre Jolivet if (!mat_ctx->rhs_flip) PetscCall(VecScale(fetidp_flux_rhs, -1.)); 21596cc1294bSstefano_zampini } 2160c08af4c6SStefano Zampini /* 2161c08af4c6SStefano Zampini change of basis for physical rhs if needed 2162c08af4c6SStefano Zampini It also changes the rhs in case of dirichlet boundaries 2163c08af4c6SStefano Zampini */ 21649566063dSJacob Faibussowitsch PetscCall(PCPreSolve_BDDC(mat_ctx->pc, NULL, pcbddc->original_rhs, NULL)); 2165fc17d649SStefano Zampini if (pcbddc->ChangeOfBasisMatrix) { 21669566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, pcbddc->original_rhs, pcbddc->work_change)); 21673738a8e6SStefano Zampini work = pcbddc->work_change; 2168fc17d649SStefano Zampini } else { 21693738a8e6SStefano Zampini work = pcbddc->original_rhs; 2170fc17d649SStefano Zampini } 21713425bc38SStefano Zampini /* store vectors for computation of fetidp final solution */ 21729566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, work, mat_ctx->temp_solution_D, INSERT_VALUES, SCATTER_FORWARD)); 21739566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, work, mat_ctx->temp_solution_D, INSERT_VALUES, SCATTER_FORWARD)); 2174fb223d50SStefano Zampini /* scale rhs since it should be unassembled */ 2175fb223d50SStefano Zampini /* TODO use counter scaling? (also below) */ 21769566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_B, work, mat_ctx->temp_solution_B, INSERT_VALUES, SCATTER_FORWARD)); 21779566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_B, work, mat_ctx->temp_solution_B, INSERT_VALUES, SCATTER_FORWARD)); 2178674ae819SStefano Zampini /* Apply partition of unity */ 21799566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(mat_ctx->temp_solution_B, pcis->D, mat_ctx->temp_solution_B)); 21809566063dSJacob Faibussowitsch /* PetscCall(PCBDDCScalingRestriction(mat_ctx->pc,work,mat_ctx->temp_solution_B)); */ 21818eeda7d8SStefano Zampini if (!pcbddc->switch_static) { 21823425bc38SStefano Zampini /* compute partially subassembled Schur complement right-hand side */ 21839566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], mat_ctx->pc, 0, 0, 0)); 21849566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_D, mat_ctx->temp_solution_D, pcis->vec1_D)); 21859566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], mat_ctx->pc, 0, 0, 0)); 2186c0decd05SBarry Smith /* Cannot propagate up error in KSPSolve() because there is no access to the PC */ 21879566063dSJacob Faibussowitsch PetscCall(MatMult(pcis->A_BI, pcis->vec1_D, pcis->vec1_B)); 21889566063dSJacob Faibussowitsch PetscCall(VecAXPY(mat_ctx->temp_solution_B, -1.0, pcis->vec1_B)); 21899566063dSJacob Faibussowitsch PetscCall(VecSet(work, 0.0)); 21909566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_B, mat_ctx->temp_solution_B, work, ADD_VALUES, SCATTER_REVERSE)); 21919566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_B, mat_ctx->temp_solution_B, work, ADD_VALUES, SCATTER_REVERSE)); 21929566063dSJacob Faibussowitsch /* PetscCall(PCBDDCScalingRestriction(mat_ctx->pc,work,mat_ctx->temp_solution_B)); */ 21939566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_B, work, mat_ctx->temp_solution_B, INSERT_VALUES, SCATTER_FORWARD)); 21949566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_B, work, mat_ctx->temp_solution_B, INSERT_VALUES, SCATTER_FORWARD)); 21959566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(mat_ctx->temp_solution_B, pcis->D, mat_ctx->temp_solution_B)); 21963425bc38SStefano Zampini } 21973425bc38SStefano Zampini /* BDDC rhs */ 21989566063dSJacob Faibussowitsch PetscCall(VecCopy(mat_ctx->temp_solution_B, pcis->vec1_B)); 21991baa6e33SBarry Smith if (pcbddc->switch_static) PetscCall(VecCopy(mat_ctx->temp_solution_D, pcis->vec1_D)); 22003425bc38SStefano Zampini /* apply BDDC */ 22019566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(pcbddc->benign_p0, pcbddc->benign_n)); 22029566063dSJacob Faibussowitsch PetscCall(PCBDDCApplyInterfacePreconditioner(mat_ctx->pc, PETSC_FALSE)); 22039566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(pcbddc->benign_p0, pcbddc->benign_n)); 2204229984c5Sstefano_zampini 22053425bc38SStefano Zampini /* Application of B_delta and assembling of rhs for fetidp fluxes */ 22069566063dSJacob Faibussowitsch PetscCall(MatMult(mat_ctx->B_delta, pcis->vec1_B, mat_ctx->lambda_local)); 22079566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat_ctx->l2g_lambda, mat_ctx->lambda_local, fetidp_flux_rhs, ADD_VALUES, SCATTER_FORWARD)); 22089566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat_ctx->l2g_lambda, mat_ctx->lambda_local, fetidp_flux_rhs, ADD_VALUES, SCATTER_FORWARD)); 2209229984c5Sstefano_zampini /* Add contribution to interface pressures */ 2210229984c5Sstefano_zampini if (mat_ctx->l2g_p) { 22119566063dSJacob Faibussowitsch PetscCall(MatMult(mat_ctx->B_BB, pcis->vec1_B, mat_ctx->vP)); 22121baa6e33SBarry Smith if (pcbddc->switch_static) PetscCall(MatMultAdd(mat_ctx->B_BI, pcis->vec1_D, mat_ctx->vP, mat_ctx->vP)); 22139566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat_ctx->l2g_p, mat_ctx->vP, fetidp_flux_rhs, ADD_VALUES, SCATTER_FORWARD)); 22149566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat_ctx->l2g_p, mat_ctx->vP, fetidp_flux_rhs, ADD_VALUES, SCATTER_FORWARD)); 2215229984c5Sstefano_zampini } 22163425bc38SStefano Zampini PetscFunctionReturn(0); 22173425bc38SStefano Zampini } 22181e6b0712SBarry Smith 22193425bc38SStefano Zampini /*@ 22200f202f7eSStefano Zampini PCBDDCMatFETIDPGetRHS - Compute the right-hand side for FETI-DP linear system using the physical right-hand side 22213425bc38SStefano Zampini 22223425bc38SStefano Zampini Collective 22233425bc38SStefano Zampini 22243425bc38SStefano Zampini Input Parameters: 22250f202f7eSStefano Zampini + fetidp_mat - the FETI-DP matrix object obtained by a call to PCBDDCCreateFETIDPOperators 22260f202f7eSStefano Zampini - standard_rhs - the right-hand side of the original linear system 22273425bc38SStefano Zampini 22283425bc38SStefano Zampini Output Parameters: 22290f202f7eSStefano Zampini . fetidp_flux_rhs - the right-hand side for the FETI-DP linear system 22303425bc38SStefano Zampini 22313425bc38SStefano Zampini Level: developer 22323425bc38SStefano Zampini 22333425bc38SStefano Zampini Notes: 22343425bc38SStefano Zampini 223516b07851SJed Brown .seealso: `PCBDDC`, `PCBDDCCreateFETIDPOperators()`, `PCBDDCMatFETIDPGetSolution()` 22363425bc38SStefano Zampini @*/ 22379371c9d4SSatish Balay PetscErrorCode PCBDDCMatFETIDPGetRHS(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs) { 2238674ae819SStefano Zampini FETIDPMat_ctx mat_ctx; 22393425bc38SStefano Zampini 22403425bc38SStefano Zampini PetscFunctionBegin; 2241266e20e9SStefano Zampini PetscValidHeaderSpecific(fetidp_mat, MAT_CLASSID, 1); 2242266e20e9SStefano Zampini PetscValidHeaderSpecific(standard_rhs, VEC_CLASSID, 2); 2243266e20e9SStefano Zampini PetscValidHeaderSpecific(fetidp_flux_rhs, VEC_CLASSID, 3); 22449566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(fetidp_mat, &mat_ctx)); 2245cac4c232SBarry Smith PetscUseMethod(mat_ctx->pc, "PCBDDCMatFETIDPGetRHS_C", (Mat, Vec, Vec), (fetidp_mat, standard_rhs, fetidp_flux_rhs)); 22463425bc38SStefano Zampini PetscFunctionReturn(0); 22473425bc38SStefano Zampini } 22481e6b0712SBarry Smith 22499371c9d4SSatish Balay static PetscErrorCode PCBDDCMatFETIDPGetSolution_BDDC(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol) { 2250674ae819SStefano Zampini FETIDPMat_ctx mat_ctx; 22513425bc38SStefano Zampini PC_IS *pcis; 22523425bc38SStefano Zampini PC_BDDC *pcbddc; 2253229984c5Sstefano_zampini Vec work; 22543425bc38SStefano Zampini 22553425bc38SStefano Zampini PetscFunctionBegin; 22569566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(fetidp_mat, &mat_ctx)); 22573425bc38SStefano Zampini pcis = (PC_IS *)mat_ctx->pc->data; 22583425bc38SStefano Zampini pcbddc = (PC_BDDC *)mat_ctx->pc->data; 22593425bc38SStefano Zampini 22603425bc38SStefano Zampini /* apply B_delta^T */ 22619566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_B, 0.)); 22629566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat_ctx->l2g_lambda, fetidp_flux_sol, mat_ctx->lambda_local, INSERT_VALUES, SCATTER_REVERSE)); 22639566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat_ctx->l2g_lambda, fetidp_flux_sol, mat_ctx->lambda_local, INSERT_VALUES, SCATTER_REVERSE)); 22649566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(mat_ctx->B_delta, mat_ctx->lambda_local, pcis->vec1_B)); 2265229984c5Sstefano_zampini if (mat_ctx->l2g_p) { 22669566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat_ctx->l2g_p, fetidp_flux_sol, mat_ctx->vP, INSERT_VALUES, SCATTER_REVERSE)); 22679566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat_ctx->l2g_p, fetidp_flux_sol, mat_ctx->vP, INSERT_VALUES, SCATTER_REVERSE)); 22689566063dSJacob Faibussowitsch PetscCall(MatMultAdd(mat_ctx->Bt_BB, mat_ctx->vP, pcis->vec1_B, pcis->vec1_B)); 2269229984c5Sstefano_zampini } 2270229984c5Sstefano_zampini 22713425bc38SStefano Zampini /* compute rhs for BDDC application */ 22729566063dSJacob Faibussowitsch PetscCall(VecAYPX(pcis->vec1_B, -1.0, mat_ctx->temp_solution_B)); 22738eeda7d8SStefano Zampini if (pcbddc->switch_static) { 22749566063dSJacob Faibussowitsch PetscCall(VecCopy(mat_ctx->temp_solution_D, pcis->vec1_D)); 2275229984c5Sstefano_zampini if (mat_ctx->l2g_p) { 22769566063dSJacob Faibussowitsch PetscCall(VecScale(mat_ctx->vP, -1.)); 22779566063dSJacob Faibussowitsch PetscCall(MatMultAdd(mat_ctx->Bt_BI, mat_ctx->vP, pcis->vec1_D, pcis->vec1_D)); 22783425bc38SStefano Zampini } 2279229984c5Sstefano_zampini } 2280229984c5Sstefano_zampini 22813425bc38SStefano Zampini /* apply BDDC */ 22829566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(pcbddc->benign_p0, pcbddc->benign_n)); 22839566063dSJacob Faibussowitsch PetscCall(PCBDDCApplyInterfacePreconditioner(mat_ctx->pc, PETSC_FALSE)); 2284229984c5Sstefano_zampini 2285229984c5Sstefano_zampini /* put values into global vector */ 2286af140850Sstefano_zampini if (pcbddc->ChangeOfBasisMatrix) work = pcbddc->work_change; 2287af140850Sstefano_zampini else work = standard_sol; 22889566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_B, pcis->vec1_B, work, INSERT_VALUES, SCATTER_REVERSE)); 22899566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_B, pcis->vec1_B, work, INSERT_VALUES, SCATTER_REVERSE)); 22908eeda7d8SStefano Zampini if (!pcbddc->switch_static) { 22913425bc38SStefano Zampini /* compute values into the interior if solved for the partially subassembled Schur complement */ 22929566063dSJacob Faibussowitsch PetscCall(MatMult(pcis->A_IB, pcis->vec1_B, pcis->vec1_D)); 22939566063dSJacob Faibussowitsch PetscCall(VecAYPX(pcis->vec1_D, -1.0, mat_ctx->temp_solution_D)); 22949566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], mat_ctx->pc, 0, 0, 0)); 22959566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_D, pcis->vec1_D, pcis->vec1_D)); 22969566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], mat_ctx->pc, 0, 0, 0)); 2297c0decd05SBarry Smith /* Cannot propagate up error in KSPSolve() because there is no access to the PC */ 22983425bc38SStefano Zampini } 2299229984c5Sstefano_zampini 23009566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec1_D, work, INSERT_VALUES, SCATTER_REVERSE)); 23019566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec1_D, work, INSERT_VALUES, SCATTER_REVERSE)); 2302266e20e9SStefano Zampini /* add p0 solution to final solution */ 23039566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignGetOrSetP0(mat_ctx->pc, work, PETSC_FALSE)); 23041baa6e33SBarry Smith if (pcbddc->ChangeOfBasisMatrix) PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix, work, standard_sol)); 23059566063dSJacob Faibussowitsch PetscCall(PCPostSolve_BDDC(mat_ctx->pc, NULL, NULL, standard_sol)); 2306af140850Sstefano_zampini if (mat_ctx->g2g_p) { 23079566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat_ctx->g2g_p, fetidp_flux_sol, standard_sol, INSERT_VALUES, SCATTER_REVERSE)); 23089566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat_ctx->g2g_p, fetidp_flux_sol, standard_sol, INSERT_VALUES, SCATTER_REVERSE)); 2309229984c5Sstefano_zampini } 23103425bc38SStefano Zampini PetscFunctionReturn(0); 23113425bc38SStefano Zampini } 23121e6b0712SBarry Smith 23139371c9d4SSatish Balay static PetscErrorCode PCView_BDDCIPC(PC pc, PetscViewer viewer) { 23145a1e936bSStefano Zampini BDDCIPC_ctx bddcipc_ctx; 23155a1e936bSStefano Zampini PetscBool isascii; 23165a1e936bSStefano Zampini 23175a1e936bSStefano Zampini PetscFunctionBegin; 23189566063dSJacob Faibussowitsch PetscCall(PCShellGetContext(pc, &bddcipc_ctx)); 23199566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 2320*48a46eb9SPierre Jolivet if (isascii) PetscCall(PetscViewerASCIIPrintf(viewer, "BDDC interface preconditioner\n")); 23219566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 23229566063dSJacob Faibussowitsch PetscCall(PCView(bddcipc_ctx->bddc, viewer)); 23239566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 23245a1e936bSStefano Zampini PetscFunctionReturn(0); 23255a1e936bSStefano Zampini } 23265a1e936bSStefano Zampini 23279371c9d4SSatish Balay static PetscErrorCode PCSetUp_BDDCIPC(PC pc) { 23285a1e936bSStefano Zampini BDDCIPC_ctx bddcipc_ctx; 23295a1e936bSStefano Zampini PetscBool isbddc; 23305a1e936bSStefano Zampini Vec vv; 23315a1e936bSStefano Zampini IS is; 23325a1e936bSStefano Zampini PC_IS *pcis; 23335a1e936bSStefano Zampini 23345a1e936bSStefano Zampini PetscFunctionBegin; 23359566063dSJacob Faibussowitsch PetscCall(PCShellGetContext(pc, &bddcipc_ctx)); 23369566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)bddcipc_ctx->bddc, PCBDDC, &isbddc)); 233728b400f6SJacob Faibussowitsch PetscCheck(isbddc, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Invalid type %s. Must be of type bddc", ((PetscObject)bddcipc_ctx->bddc)->type_name); 23389566063dSJacob Faibussowitsch PetscCall(PCSetUp(bddcipc_ctx->bddc)); 23395a1e936bSStefano Zampini 23405a1e936bSStefano Zampini /* create interface scatter */ 23415a1e936bSStefano Zampini pcis = (PC_IS *)(bddcipc_ctx->bddc->data); 23429566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&bddcipc_ctx->g2l)); 23439566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(pc->pmat, &vv, NULL)); 23449566063dSJacob Faibussowitsch PetscCall(ISRenumber(pcis->is_B_global, NULL, NULL, &is)); 23459566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(vv, is, pcis->vec1_B, NULL, &bddcipc_ctx->g2l)); 23469566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 23479566063dSJacob Faibussowitsch PetscCall(VecDestroy(&vv)); 23485a1e936bSStefano Zampini PetscFunctionReturn(0); 23495a1e936bSStefano Zampini } 23505a1e936bSStefano Zampini 23519371c9d4SSatish Balay static PetscErrorCode PCApply_BDDCIPC(PC pc, Vec r, Vec x) { 23525a1e936bSStefano Zampini BDDCIPC_ctx bddcipc_ctx; 23535a1e936bSStefano Zampini PC_IS *pcis; 23545a1e936bSStefano Zampini VecScatter tmps; 23555a1e936bSStefano Zampini 23565a1e936bSStefano Zampini PetscFunctionBegin; 23579566063dSJacob Faibussowitsch PetscCall(PCShellGetContext(pc, &bddcipc_ctx)); 23585a1e936bSStefano Zampini pcis = (PC_IS *)(bddcipc_ctx->bddc->data); 23595a1e936bSStefano Zampini tmps = pcis->global_to_B; 23605a1e936bSStefano Zampini pcis->global_to_B = bddcipc_ctx->g2l; 23619566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingRestriction(bddcipc_ctx->bddc, r, pcis->vec1_B)); 23629566063dSJacob Faibussowitsch PetscCall(PCBDDCApplyInterfacePreconditioner(bddcipc_ctx->bddc, PETSC_FALSE)); 23639566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingExtension(bddcipc_ctx->bddc, pcis->vec1_B, x)); 23645a1e936bSStefano Zampini pcis->global_to_B = tmps; 23655a1e936bSStefano Zampini PetscFunctionReturn(0); 23665a1e936bSStefano Zampini } 23675a1e936bSStefano Zampini 23689371c9d4SSatish Balay static PetscErrorCode PCApplyTranspose_BDDCIPC(PC pc, Vec r, Vec x) { 23695a1e936bSStefano Zampini BDDCIPC_ctx bddcipc_ctx; 23705a1e936bSStefano Zampini PC_IS *pcis; 23715a1e936bSStefano Zampini VecScatter tmps; 23725a1e936bSStefano Zampini 23735a1e936bSStefano Zampini PetscFunctionBegin; 23749566063dSJacob Faibussowitsch PetscCall(PCShellGetContext(pc, &bddcipc_ctx)); 23755a1e936bSStefano Zampini pcis = (PC_IS *)(bddcipc_ctx->bddc->data); 23765a1e936bSStefano Zampini tmps = pcis->global_to_B; 23775a1e936bSStefano Zampini pcis->global_to_B = bddcipc_ctx->g2l; 23789566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingRestriction(bddcipc_ctx->bddc, r, pcis->vec1_B)); 23799566063dSJacob Faibussowitsch PetscCall(PCBDDCApplyInterfacePreconditioner(bddcipc_ctx->bddc, PETSC_TRUE)); 23809566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingExtension(bddcipc_ctx->bddc, pcis->vec1_B, x)); 23815a1e936bSStefano Zampini pcis->global_to_B = tmps; 23825a1e936bSStefano Zampini PetscFunctionReturn(0); 23835a1e936bSStefano Zampini } 23845a1e936bSStefano Zampini 23859371c9d4SSatish Balay static PetscErrorCode PCDestroy_BDDCIPC(PC pc) { 23865a1e936bSStefano Zampini BDDCIPC_ctx bddcipc_ctx; 23875a1e936bSStefano Zampini 23885a1e936bSStefano Zampini PetscFunctionBegin; 23899566063dSJacob Faibussowitsch PetscCall(PCShellGetContext(pc, &bddcipc_ctx)); 23909566063dSJacob Faibussowitsch PetscCall(PCDestroy(&bddcipc_ctx->bddc)); 23919566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&bddcipc_ctx->g2l)); 23929566063dSJacob Faibussowitsch PetscCall(PetscFree(bddcipc_ctx)); 23935a1e936bSStefano Zampini PetscFunctionReturn(0); 23945a1e936bSStefano Zampini } 23955a1e936bSStefano Zampini 23963425bc38SStefano Zampini /*@ 23970f202f7eSStefano Zampini PCBDDCMatFETIDPGetSolution - Compute the physical solution using the solution of the FETI-DP linear system 23983425bc38SStefano Zampini 23993425bc38SStefano Zampini Collective 24003425bc38SStefano Zampini 24013425bc38SStefano Zampini Input Parameters: 24020f202f7eSStefano Zampini + fetidp_mat - the FETI-DP matrix obtained by a call to PCBDDCCreateFETIDPOperators 24030f202f7eSStefano Zampini - fetidp_flux_sol - the solution of the FETI-DP linear system 24043425bc38SStefano Zampini 24053425bc38SStefano Zampini Output Parameters: 24060f202f7eSStefano Zampini . standard_sol - the solution defined on the physical domain 24073425bc38SStefano Zampini 24083425bc38SStefano Zampini Level: developer 24093425bc38SStefano Zampini 24103425bc38SStefano Zampini Notes: 24113425bc38SStefano Zampini 241216b07851SJed Brown .seealso: `PCBDDC`, `PCBDDCCreateFETIDPOperators()`, `PCBDDCMatFETIDPGetRHS()` 24133425bc38SStefano Zampini @*/ 24149371c9d4SSatish Balay PetscErrorCode PCBDDCMatFETIDPGetSolution(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol) { 2415674ae819SStefano Zampini FETIDPMat_ctx mat_ctx; 24163425bc38SStefano Zampini 24173425bc38SStefano Zampini PetscFunctionBegin; 2418266e20e9SStefano Zampini PetscValidHeaderSpecific(fetidp_mat, MAT_CLASSID, 1); 2419266e20e9SStefano Zampini PetscValidHeaderSpecific(fetidp_flux_sol, VEC_CLASSID, 2); 2420266e20e9SStefano Zampini PetscValidHeaderSpecific(standard_sol, VEC_CLASSID, 3); 24219566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(fetidp_mat, &mat_ctx)); 2422cac4c232SBarry Smith PetscUseMethod(mat_ctx->pc, "PCBDDCMatFETIDPGetSolution_C", (Mat, Vec, Vec), (fetidp_mat, fetidp_flux_sol, standard_sol)); 24233425bc38SStefano Zampini PetscFunctionReturn(0); 24243425bc38SStefano Zampini } 24251e6b0712SBarry Smith 24269371c9d4SSatish Balay static PetscErrorCode PCBDDCCreateFETIDPOperators_BDDC(PC pc, PetscBool fully_redundant, const char *prefix, Mat *fetidp_mat, PC *fetidp_pc) { 2427674ae819SStefano Zampini FETIDPMat_ctx fetidpmat_ctx; 24283425bc38SStefano Zampini Mat newmat; 2429674ae819SStefano Zampini FETIDPPC_ctx fetidppc_ctx; 24303425bc38SStefano Zampini PC newpc; 2431ce94432eSBarry Smith MPI_Comm comm; 24323425bc38SStefano Zampini 24333425bc38SStefano Zampini PetscFunctionBegin; 24349566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)pc, &comm)); 243515579a77SStefano Zampini /* FETI-DP matrix */ 24369566063dSJacob Faibussowitsch PetscCall(PCBDDCCreateFETIDPMatContext(pc, &fetidpmat_ctx)); 24371720468bSStefano Zampini fetidpmat_ctx->fully_redundant = fully_redundant; 24389566063dSJacob Faibussowitsch PetscCall(PCBDDCSetupFETIDPMatContext(fetidpmat_ctx)); 24399566063dSJacob Faibussowitsch PetscCall(MatCreateShell(comm, fetidpmat_ctx->n, fetidpmat_ctx->n, fetidpmat_ctx->N, fetidpmat_ctx->N, fetidpmat_ctx, &newmat)); 24409566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)newmat, !fetidpmat_ctx->l2g_lambda_only ? "F" : "G")); 24419566063dSJacob Faibussowitsch PetscCall(MatShellSetOperation(newmat, MATOP_MULT, (void (*)(void))FETIDPMatMult)); 24429566063dSJacob Faibussowitsch PetscCall(MatShellSetOperation(newmat, MATOP_MULT_TRANSPOSE, (void (*)(void))FETIDPMatMultTranspose)); 24439566063dSJacob Faibussowitsch PetscCall(MatShellSetOperation(newmat, MATOP_DESTROY, (void (*)(void))PCBDDCDestroyFETIDPMat)); 244415579a77SStefano Zampini /* propagate MatOptions */ 244515579a77SStefano Zampini { 244615579a77SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)fetidpmat_ctx->pc->data; 2447b94d7dedSBarry Smith PetscBool isset, issym; 244815579a77SStefano Zampini 2449b94d7dedSBarry Smith PetscCall(MatIsSymmetricKnown(pc->mat, &isset, &issym)); 2450b94d7dedSBarry Smith if ((isset && issym) || pcbddc->symmetric_primal) PetscCall(MatSetOption(newmat, MAT_SYMMETRIC, PETSC_TRUE)); 245115579a77SStefano Zampini } 24529566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(newmat, prefix)); 24539566063dSJacob Faibussowitsch PetscCall(MatAppendOptionsPrefix(newmat, "fetidp_")); 24549566063dSJacob Faibussowitsch PetscCall(MatSetUp(newmat)); 245515579a77SStefano Zampini /* FETI-DP preconditioner */ 24569566063dSJacob Faibussowitsch PetscCall(PCBDDCCreateFETIDPPCContext(pc, &fetidppc_ctx)); 24579566063dSJacob Faibussowitsch PetscCall(PCBDDCSetupFETIDPPCContext(newmat, fetidppc_ctx)); 24589566063dSJacob Faibussowitsch PetscCall(PCCreate(comm, &newpc)); 24599566063dSJacob Faibussowitsch PetscCall(PCSetOperators(newpc, newmat, newmat)); 24609566063dSJacob Faibussowitsch PetscCall(PCSetOptionsPrefix(newpc, prefix)); 24619566063dSJacob Faibussowitsch PetscCall(PCAppendOptionsPrefix(newpc, "fetidp_")); 24629566063dSJacob Faibussowitsch PetscCall(PCSetErrorIfFailure(newpc, pc->erroriffailure)); 246315579a77SStefano Zampini if (!fetidpmat_ctx->l2g_lambda_only) { /* standard FETI-DP */ 24649566063dSJacob Faibussowitsch PetscCall(PCSetType(newpc, PCSHELL)); 24659566063dSJacob Faibussowitsch PetscCall(PCShellSetName(newpc, "FETI-DP multipliers")); 24669566063dSJacob Faibussowitsch PetscCall(PCShellSetContext(newpc, fetidppc_ctx)); 24679566063dSJacob Faibussowitsch PetscCall(PCShellSetApply(newpc, FETIDPPCApply)); 24689566063dSJacob Faibussowitsch PetscCall(PCShellSetApplyTranspose(newpc, FETIDPPCApplyTranspose)); 24699566063dSJacob Faibussowitsch PetscCall(PCShellSetView(newpc, FETIDPPCView)); 24709566063dSJacob Faibussowitsch PetscCall(PCShellSetDestroy(newpc, PCBDDCDestroyFETIDPPC)); 24715a1e936bSStefano Zampini } else { /* saddle-point FETI-DP */ 24725a1e936bSStefano Zampini Mat M; 24735a1e936bSStefano Zampini PetscInt psize; 24745a1e936bSStefano Zampini PetscBool fake = PETSC_FALSE, isfieldsplit; 2475e1214c54Sstefano_zampini 24769566063dSJacob Faibussowitsch PetscCall(ISViewFromOptions(fetidpmat_ctx->lagrange, NULL, "-lag_view")); 24779566063dSJacob Faibussowitsch PetscCall(ISViewFromOptions(fetidpmat_ctx->pressure, NULL, "-press_view")); 24789566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_PPmat", (PetscObject *)&M)); 24799566063dSJacob Faibussowitsch PetscCall(PCSetType(newpc, PCFIELDSPLIT)); 24809566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSetIS(newpc, "lag", fetidpmat_ctx->lagrange)); 24819566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSetIS(newpc, "p", fetidpmat_ctx->pressure)); 24829566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSetType(newpc, PC_COMPOSITE_SCHUR)); 24839566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSetSchurFactType(newpc, PC_FIELDSPLIT_SCHUR_FACT_DIAG)); 24849566063dSJacob Faibussowitsch PetscCall(ISGetSize(fetidpmat_ctx->pressure, &psize)); 24855a1e936bSStefano Zampini if (psize != M->rmap->N) { 24865a1e936bSStefano Zampini Mat M2; 24875a1e936bSStefano Zampini PetscInt lpsize; 24885a1e936bSStefano Zampini 24895a1e936bSStefano Zampini fake = PETSC_TRUE; 24909566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(fetidpmat_ctx->pressure, &lpsize)); 24919566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &M2)); 24929566063dSJacob Faibussowitsch PetscCall(MatSetType(M2, MATAIJ)); 24939566063dSJacob Faibussowitsch PetscCall(MatSetSizes(M2, lpsize, lpsize, psize, psize)); 24949566063dSJacob Faibussowitsch PetscCall(MatSetUp(M2)); 24959566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(M2, MAT_FINAL_ASSEMBLY)); 24969566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(M2, MAT_FINAL_ASSEMBLY)); 24979566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSetSchurPre(newpc, PC_FIELDSPLIT_SCHUR_PRE_USER, M2)); 24989566063dSJacob Faibussowitsch PetscCall(MatDestroy(&M2)); 24995a1e936bSStefano Zampini } else { 25009566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSetSchurPre(newpc, PC_FIELDSPLIT_SCHUR_PRE_USER, M)); 25015a1e936bSStefano Zampini } 25029566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSetSchurScale(newpc, 1.0)); 250315579a77SStefano Zampini 250415579a77SStefano Zampini /* we need to setfromoptions and setup here to access the blocks */ 25059566063dSJacob Faibussowitsch PetscCall(PCSetFromOptions(newpc)); 25069566063dSJacob Faibussowitsch PetscCall(PCSetUp(newpc)); 2507e1214c54Sstefano_zampini 25085a1e936bSStefano Zampini /* user may have changed the type (e.g. -fetidp_pc_type none) */ 25099566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)newpc, PCFIELDSPLIT, &isfieldsplit)); 25105a1e936bSStefano Zampini if (isfieldsplit) { 25115a1e936bSStefano Zampini KSP *ksps; 25125a1e936bSStefano Zampini PC ppc, lagpc; 25135a1e936bSStefano Zampini PetscInt nn; 2514064a4176SStefano Zampini PetscBool ismatis, matisok = PETSC_FALSE, check = PETSC_FALSE; 25155a1e936bSStefano Zampini 2516e1214c54Sstefano_zampini /* set the solver for the (0,0) block */ 25179566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSchurGetSubKSP(newpc, &nn, &ksps)); 25185a1e936bSStefano Zampini if (!nn) { /* not of type PC_COMPOSITE_SCHUR */ 25199566063dSJacob Faibussowitsch PetscCall(PCFieldSplitGetSubKSP(newpc, &nn, &ksps)); 25205a1e936bSStefano Zampini if (!fake) { /* pass pmat to the pressure solver */ 25215a1e936bSStefano Zampini Mat F; 25225a1e936bSStefano Zampini 25239566063dSJacob Faibussowitsch PetscCall(KSPGetOperators(ksps[1], &F, NULL)); 25249566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(ksps[1], F, M)); 25255a1e936bSStefano Zampini } 25265a1e936bSStefano Zampini } else { 2527b94d7dedSBarry Smith PetscBool issym, isset; 25285a1e936bSStefano Zampini Mat S; 25295a1e936bSStefano Zampini 25309566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSchurGetS(newpc, &S)); 2531b94d7dedSBarry Smith PetscCall(MatIsSymmetricKnown(newmat, &isset, &issym)); 2532b94d7dedSBarry Smith if (isset) PetscCall(MatSetOption(S, MAT_SYMMETRIC, issym)); 25335a1e936bSStefano Zampini } 25349566063dSJacob Faibussowitsch PetscCall(KSPGetPC(ksps[0], &lagpc)); 25359566063dSJacob Faibussowitsch PetscCall(PCSetType(lagpc, PCSHELL)); 25369566063dSJacob Faibussowitsch PetscCall(PCShellSetName(lagpc, "FETI-DP multipliers")); 25379566063dSJacob Faibussowitsch PetscCall(PCShellSetContext(lagpc, fetidppc_ctx)); 25389566063dSJacob Faibussowitsch PetscCall(PCShellSetApply(lagpc, FETIDPPCApply)); 25399566063dSJacob Faibussowitsch PetscCall(PCShellSetApplyTranspose(lagpc, FETIDPPCApplyTranspose)); 25409566063dSJacob Faibussowitsch PetscCall(PCShellSetView(lagpc, FETIDPPCView)); 25419566063dSJacob Faibussowitsch PetscCall(PCShellSetDestroy(lagpc, PCBDDCDestroyFETIDPPC)); 25425a1e936bSStefano Zampini 25435a1e936bSStefano Zampini /* Olof's idea: interface Schur complement preconditioner for the mass matrix */ 25449566063dSJacob Faibussowitsch PetscCall(KSPGetPC(ksps[1], &ppc)); 25455a1e936bSStefano Zampini if (fake) { 25465a1e936bSStefano Zampini BDDCIPC_ctx bddcipc_ctx; 2547ff11fd76SStefano Zampini PetscContainer c; 25485a1e936bSStefano Zampini 25495a1e936bSStefano Zampini matisok = PETSC_TRUE; 25505a1e936bSStefano Zampini 25515a1e936bSStefano Zampini /* create inner BDDC solver */ 25529566063dSJacob Faibussowitsch PetscCall(PetscNew(&bddcipc_ctx)); 25539566063dSJacob Faibussowitsch PetscCall(PCCreate(comm, &bddcipc_ctx->bddc)); 25549566063dSJacob Faibussowitsch PetscCall(PCSetType(bddcipc_ctx->bddc, PCBDDC)); 25559566063dSJacob Faibussowitsch PetscCall(PCSetOperators(bddcipc_ctx->bddc, M, M)); 25569566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_pCSR", (PetscObject *)&c)); 25579566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)M, MATIS, &ismatis)); 2558ff11fd76SStefano Zampini if (c && ismatis) { 2559ff11fd76SStefano Zampini Mat lM; 2560ff11fd76SStefano Zampini PetscInt *csr, n; 2561ff11fd76SStefano Zampini 25629566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(M, &lM)); 25639566063dSJacob Faibussowitsch PetscCall(MatGetSize(lM, &n, NULL)); 25649566063dSJacob Faibussowitsch PetscCall(PetscContainerGetPointer(c, (void **)&csr)); 25659566063dSJacob Faibussowitsch PetscCall(PCBDDCSetLocalAdjacencyGraph(bddcipc_ctx->bddc, n, csr, csr + (n + 1), PETSC_COPY_VALUES)); 25669566063dSJacob Faibussowitsch PetscCall(MatISRestoreLocalMat(M, &lM)); 2567ff11fd76SStefano Zampini } 25689566063dSJacob Faibussowitsch PetscCall(PCSetOptionsPrefix(bddcipc_ctx->bddc, ((PetscObject)ksps[1])->prefix)); 25699566063dSJacob Faibussowitsch PetscCall(PCSetErrorIfFailure(bddcipc_ctx->bddc, pc->erroriffailure)); 25709566063dSJacob Faibussowitsch PetscCall(PCSetFromOptions(bddcipc_ctx->bddc)); 25715a1e936bSStefano Zampini 25725a1e936bSStefano Zampini /* wrap the interface application */ 25739566063dSJacob Faibussowitsch PetscCall(PCSetType(ppc, PCSHELL)); 25749566063dSJacob Faibussowitsch PetscCall(PCShellSetName(ppc, "FETI-DP pressure")); 25759566063dSJacob Faibussowitsch PetscCall(PCShellSetContext(ppc, bddcipc_ctx)); 25769566063dSJacob Faibussowitsch PetscCall(PCShellSetSetUp(ppc, PCSetUp_BDDCIPC)); 25779566063dSJacob Faibussowitsch PetscCall(PCShellSetApply(ppc, PCApply_BDDCIPC)); 25789566063dSJacob Faibussowitsch PetscCall(PCShellSetApplyTranspose(ppc, PCApplyTranspose_BDDCIPC)); 25799566063dSJacob Faibussowitsch PetscCall(PCShellSetView(ppc, PCView_BDDCIPC)); 25809566063dSJacob Faibussowitsch PetscCall(PCShellSetDestroy(ppc, PCDestroy_BDDCIPC)); 25815a1e936bSStefano Zampini } 25825a1e936bSStefano Zampini 25835a1e936bSStefano Zampini /* determine if we need to assemble M to construct a preconditioner */ 25845a1e936bSStefano Zampini if (!matisok) { 25859566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)M, MATIS, &ismatis)); 25869566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)ppc, &matisok, PCBDDC, PCJACOBI, PCNONE, PCMG, "")); 2587*48a46eb9SPierre Jolivet if (ismatis && !matisok) PetscCall(MatConvert(M, MATAIJ, MAT_INPLACE_MATRIX, &M)); 25885a1e936bSStefano Zampini } 2589064a4176SStefano Zampini 2590064a4176SStefano Zampini /* run the subproblems to check convergence */ 25919566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, ((PetscObject)newmat)->prefix, "-check_saddlepoint", &check, NULL)); 2592064a4176SStefano Zampini if (check) { 2593064a4176SStefano Zampini PetscInt i; 2594064a4176SStefano Zampini 2595064a4176SStefano Zampini for (i = 0; i < nn; i++) { 2596064a4176SStefano Zampini KSP kspC; 2597064a4176SStefano Zampini PC pc; 2598064a4176SStefano Zampini Mat F, pF; 2599064a4176SStefano Zampini Vec x, y; 2600064a4176SStefano Zampini PetscBool isschur, prec = PETSC_TRUE; 2601064a4176SStefano Zampini 26029566063dSJacob Faibussowitsch PetscCall(KSPCreate(PetscObjectComm((PetscObject)ksps[i]), &kspC)); 26039566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(kspC, ((PetscObject)ksps[i])->prefix)); 26049566063dSJacob Faibussowitsch PetscCall(KSPAppendOptionsPrefix(kspC, "check_")); 26059566063dSJacob Faibussowitsch PetscCall(KSPGetOperators(ksps[i], &F, &pF)); 26069566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)F, MATSCHURCOMPLEMENT, &isschur)); 2607064a4176SStefano Zampini if (isschur) { 2608064a4176SStefano Zampini KSP kspS, kspS2; 2609064a4176SStefano Zampini Mat A00, pA00, A10, A01, A11; 2610064a4176SStefano Zampini char prefix[256]; 2611064a4176SStefano Zampini 26129566063dSJacob Faibussowitsch PetscCall(MatSchurComplementGetKSP(F, &kspS)); 26139566063dSJacob Faibussowitsch PetscCall(MatSchurComplementGetSubMatrices(F, &A00, &pA00, &A01, &A10, &A11)); 26149566063dSJacob Faibussowitsch PetscCall(MatCreateSchurComplement(A00, pA00, A01, A10, A11, &F)); 26159566063dSJacob Faibussowitsch PetscCall(MatSchurComplementGetKSP(F, &kspS2)); 26169566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(prefix, sizeof(prefix), "%sschur_", ((PetscObject)kspC)->prefix)); 26179566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(kspS2, prefix)); 26189566063dSJacob Faibussowitsch PetscCall(KSPGetPC(kspS2, &pc)); 26199566063dSJacob Faibussowitsch PetscCall(PCSetType(pc, PCKSP)); 26209566063dSJacob Faibussowitsch PetscCall(PCKSPSetKSP(pc, kspS)); 26219566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(kspS2)); 26229566063dSJacob Faibussowitsch PetscCall(KSPGetPC(kspS2, &pc)); 26239566063dSJacob Faibussowitsch PetscCall(PCSetUseAmat(pc, PETSC_TRUE)); 2624064a4176SStefano Zampini } else { 26259566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)F)); 2626064a4176SStefano Zampini } 26279566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(kspC)); 26289566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, ((PetscObject)kspC)->prefix, "-preconditioned", &prec, NULL)); 2629064a4176SStefano Zampini if (prec) { 26309566063dSJacob Faibussowitsch PetscCall(KSPGetPC(ksps[i], &pc)); 26319566063dSJacob Faibussowitsch PetscCall(KSPSetPC(kspC, pc)); 2632064a4176SStefano Zampini } 26339566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(kspC, F, pF)); 26349566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(F, &x, &y)); 26359566063dSJacob Faibussowitsch PetscCall(VecSetRandom(x, NULL)); 26369566063dSJacob Faibussowitsch PetscCall(MatMult(F, x, y)); 26379566063dSJacob Faibussowitsch PetscCall(KSPSolve(kspC, y, x)); 26389566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(kspC, pc, x)); 26399566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&kspC)); 26409566063dSJacob Faibussowitsch PetscCall(MatDestroy(&F)); 26419566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x)); 26429566063dSJacob Faibussowitsch PetscCall(VecDestroy(&y)); 2643064a4176SStefano Zampini } 2644064a4176SStefano Zampini } 26459566063dSJacob Faibussowitsch PetscCall(PetscFree(ksps)); 2646e1214c54Sstefano_zampini } 26475a1e936bSStefano Zampini } 26483425bc38SStefano Zampini /* return pointers for objects created */ 26493425bc38SStefano Zampini *fetidp_mat = newmat; 26503425bc38SStefano Zampini *fetidp_pc = newpc; 26513425bc38SStefano Zampini PetscFunctionReturn(0); 26523425bc38SStefano Zampini } 26531e6b0712SBarry Smith 265494ef8ddeSSatish Balay /*@C 26550f202f7eSStefano Zampini PCBDDCCreateFETIDPOperators - Create FETI-DP operators 26563425bc38SStefano Zampini 26573425bc38SStefano Zampini Collective 26583425bc38SStefano Zampini 26593425bc38SStefano Zampini Input Parameters: 26601720468bSStefano Zampini + pc - the BDDC preconditioning context (setup should have been called before) 2661547c9a8eSstefano_zampini . fully_redundant - true for a fully redundant set of Lagrange multipliers 2662547c9a8eSstefano_zampini - prefix - optional options database prefix for the objects to be created (can be NULL) 266328509bceSStefano Zampini 266428509bceSStefano Zampini Output Parameters: 26650f202f7eSStefano Zampini + fetidp_mat - shell FETI-DP matrix object 26660f202f7eSStefano Zampini - fetidp_pc - shell Dirichlet preconditioner for FETI-DP matrix 266728509bceSStefano Zampini 26683425bc38SStefano Zampini Level: developer 26693425bc38SStefano Zampini 26703425bc38SStefano Zampini Notes: 26710f202f7eSStefano Zampini Currently the only operations provided for FETI-DP matrix are MatMult and MatMultTranspose 26723425bc38SStefano Zampini 267316b07851SJed Brown .seealso: `PCBDDC`, `PCBDDCMatFETIDPGetRHS()`, `PCBDDCMatFETIDPGetSolution()` 26743425bc38SStefano Zampini @*/ 26759371c9d4SSatish Balay PetscErrorCode PCBDDCCreateFETIDPOperators(PC pc, PetscBool fully_redundant, const char *prefix, Mat *fetidp_mat, PC *fetidp_pc) { 26763425bc38SStefano Zampini PetscFunctionBegin; 26773425bc38SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 26783425bc38SStefano Zampini if (pc->setupcalled) { 2679cac4c232SBarry Smith PetscUseMethod(pc, "PCBDDCCreateFETIDPOperators_C", (PC, PetscBool, const char *, Mat *, PC *), (pc, fully_redundant, prefix, fetidp_mat, fetidp_pc)); 26806080607fSStefano Zampini } else SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "You must call PCSetup_BDDC() first"); 26813425bc38SStefano Zampini PetscFunctionReturn(0); 26823425bc38SStefano Zampini } 26830c7d97c5SJed Brown /* -------------------------------------------------------------------------- */ 2684da1bb401SStefano Zampini /*MC 2685da1bb401SStefano Zampini PCBDDC - Balancing Domain Decomposition by Constraints. 26860c7d97c5SJed Brown 2687be4a8d98Sprj- An implementation of the BDDC preconditioner based on the bibliography found below. 268828509bceSStefano Zampini 268928509bceSStefano Zampini The matrix to be preconditioned (Pmat) must be of type MATIS. 269028509bceSStefano Zampini 26910f202f7eSStefano Zampini Currently works with MATIS matrices with local matrices of type MATSEQAIJ, MATSEQBAIJ or MATSEQSBAIJ, either with real or complex numbers. 269228509bceSStefano Zampini 269328509bceSStefano Zampini It also works with unsymmetric and indefinite problems. 269428509bceSStefano Zampini 2695b6fdb6dfSStefano 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. 2696b6fdb6dfSStefano Zampini 2697c7017625SStefano 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). 269828509bceSStefano Zampini 26990f202f7eSStefano 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() 270030368db7SStefano Zampini Additional information on dofs can be provided by using PCBDDCSetDofsSplitting(), PCBDDCSetDirichletBoundaries(), PCBDDCSetNeumannBoundaries(), and PCBDDCSetPrimalVerticesIS() and their local counterparts. 270128509bceSStefano Zampini 27020f202f7eSStefano Zampini Constraints can be customized by attaching a MatNullSpace object to the MATIS matrix via MatSetNearNullSpace(). Non-singular modes are retained via SVD. 270328509bceSStefano Zampini 27040f202f7eSStefano 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. 27050f202f7eSStefano Zampini User defined change of basis can be passed to PCBDDC by using PCBDDCSetChangeOfBasisMat() 270628509bceSStefano Zampini 27070f202f7eSStefano Zampini The PETSc implementation also supports multilevel BDDC [3]. Coarse grids are partitioned using a MatPartitioning object. 270828509bceSStefano Zampini 2709df4d28bfSStefano 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. 271028509bceSStefano Zampini 27110f202f7eSStefano 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. 27120f202f7eSStefano Zampini 2713d314f959SVaclav Hapla Options Database Keys (some of them, run with -help for a complete list): 27140f202f7eSStefano Zampini 2715a2b725a8SWilliam Gropp + -pc_bddc_use_vertices <true> - use or not vertices in primal space 27160f202f7eSStefano Zampini . -pc_bddc_use_edges <true> - use or not edges in primal space 27170f202f7eSStefano Zampini . -pc_bddc_use_faces <false> - use or not faces in primal space 27180f202f7eSStefano Zampini . -pc_bddc_symmetric <true> - symmetric computation of primal basis functions. Specify false for unsymmetric problems 27190f202f7eSStefano Zampini . -pc_bddc_use_change_of_basis <false> - use change of basis approach (on edges only) 27200f202f7eSStefano Zampini . -pc_bddc_use_change_on_faces <false> - use change of basis approach on faces if change of basis has been requested 27210f202f7eSStefano Zampini . -pc_bddc_switch_static <false> - switches from M_2 (default) to M_3 operator (see reference article [1]) 272228509bceSStefano Zampini . -pc_bddc_levels <0> - maximum number of levels for multilevel 27230f202f7eSStefano 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) 27245459c157SBarry Smith . -pc_bddc_coarse_redistribute <0> - size of a subset of processors where the coarse problem will be remapped (the value is ignored if not at the coarsest level) 27250f202f7eSStefano Zampini . -pc_bddc_use_deluxe_scaling <false> - use deluxe scaling 272671f2caa7Sprj- . -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) 2727bd2a564bSStefano Zampini . -pc_bddc_adaptive_threshold <0.0> - when a value different than zero is specified, adaptive selection of constraints is performed on edges and faces (requires deluxe scaling and MUMPS or MKL_PARDISO installed) 272828509bceSStefano Zampini - -pc_bddc_check_level <0> - set verbosity level of debugging output 272928509bceSStefano Zampini 273028509bceSStefano Zampini Options for Dirichlet, Neumann or coarse solver can be set with 273128509bceSStefano Zampini .vb 273228509bceSStefano Zampini -pc_bddc_dirichlet_ 273328509bceSStefano Zampini -pc_bddc_neumann_ 273428509bceSStefano Zampini -pc_bddc_coarse_ 273528509bceSStefano Zampini .ve 2736f9ff08acSPierre Jolivet e.g. -pc_bddc_dirichlet_ksp_type richardson -pc_bddc_dirichlet_pc_type gamg. PCBDDC uses by default KSPPREONLY and PCLU. 273728509bceSStefano Zampini 27380f202f7eSStefano Zampini When using a multilevel approach, solvers' options at the N-th level (N > 1) can be specified as 273928509bceSStefano Zampini .vb 2740312be037SStefano Zampini -pc_bddc_dirichlet_lN_ 2741312be037SStefano Zampini -pc_bddc_neumann_lN_ 2742312be037SStefano Zampini -pc_bddc_coarse_lN_ 274328509bceSStefano Zampini .ve 27440f202f7eSStefano Zampini Note that level number ranges from the finest (0) to the coarsest (N). 27450f202f7eSStefano 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. 27460f202f7eSStefano Zampini .vb 27470f202f7eSStefano Zampini -pc_bddc_coarse_pc_bddc_adaptive_threshold 5 -pc_bddc_coarse_l1_pc_bddc_redistribute 3 27480f202f7eSStefano Zampini .ve 27490f202f7eSStefano 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 2750da1bb401SStefano Zampini 2751be4a8d98Sprj- References: 2752606c0280SSatish Balay + * - C. R. Dohrmann. "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149--168, March 2007 2753606c0280SSatish Balay . * - A. Klawonn and O. B. Widlund. "Dual-Primal FETI Methods for Linear Elasticity", Communications on Pure and Applied Mathematics Volume 59, Issue 11, pages 1523--1572, November 2006 2754606c0280SSatish Balay . * - J. Mandel, B. Sousedik, C. R. Dohrmann. "Multispace and Multilevel BDDC", Computing Volume 83, Issue 2--3, pages 55--85, November 2008 2755606c0280SSatish Balay - * - 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 2756be4a8d98Sprj- 2757da1bb401SStefano Zampini Level: intermediate 2758da1bb401SStefano Zampini 2759e94cfbe0SPatrick Sanan Developer Notes: 2760da1bb401SStefano Zampini 2761da1bb401SStefano Zampini Contributed by Stefano Zampini 2762da1bb401SStefano Zampini 2763db781477SPatrick Sanan .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `MATIS` 2764da1bb401SStefano Zampini M*/ 2765b2573a8aSBarry Smith 27669371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode PCCreate_BDDC(PC pc) { 2767da1bb401SStefano Zampini PC_BDDC *pcbddc; 2768da1bb401SStefano Zampini 2769da1bb401SStefano Zampini PetscFunctionBegin; 27709566063dSJacob Faibussowitsch PetscCall(PetscNewLog(pc, &pcbddc)); 27713ec1f749SStefano Zampini pc->data = pcbddc; 2772da1bb401SStefano Zampini 2773da1bb401SStefano Zampini /* create PCIS data structure */ 27749566063dSJacob Faibussowitsch PetscCall(PCISCreate(pc)); 2775da1bb401SStefano Zampini 27769326c5c6Sstefano_zampini /* create local graph structure */ 27779566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphCreate(&pcbddc->mat_graph)); 27789326c5c6Sstefano_zampini 27799326c5c6Sstefano_zampini /* BDDC nonzero defaults */ 27806d9e27e4SStefano Zampini pcbddc->use_nnsp = PETSC_TRUE; 278108a5cf49SStefano Zampini pcbddc->use_local_adj = PETSC_TRUE; 278247d04d0dSStefano Zampini pcbddc->use_vertices = PETSC_TRUE; 278347d04d0dSStefano Zampini pcbddc->use_edges = PETSC_TRUE; 27843301b35fSStefano Zampini pcbddc->symmetric_primal = PETSC_TRUE; 278514f95afaSStefano Zampini pcbddc->vertex_size = 1; 2786c703fcc7SStefano Zampini pcbddc->recompute_topography = PETSC_TRUE; 278768457ee5SStefano Zampini pcbddc->coarse_size = -1; 278885c4d303SStefano Zampini pcbddc->use_exact_dirichlet_trick = PETSC_TRUE; 278947d04d0dSStefano Zampini pcbddc->coarsening_ratio = 8; 279057de7509SStefano Zampini pcbddc->coarse_eqs_per_proc = 1; 279127b6a85dSStefano Zampini pcbddc->benign_compute_correction = PETSC_TRUE; 27921e0482f5SStefano Zampini pcbddc->nedfield = -1; 27931e0482f5SStefano Zampini pcbddc->nedglobal = PETSC_TRUE; 2794be12c134Sstefano_zampini pcbddc->graphmaxcount = PETSC_MAX_INT; 2795b96c3477SStefano Zampini pcbddc->sub_schurs_layers = -1; 2796bd2a564bSStefano Zampini pcbddc->adaptive_threshold[0] = 0.0; 2797bd2a564bSStefano Zampini pcbddc->adaptive_threshold[1] = 0.0; 2798b7eb3628SStefano Zampini 2799da1bb401SStefano Zampini /* function pointers */ 2800da1bb401SStefano Zampini pc->ops->apply = PCApply_BDDC; 280193bd9ae7SStefano Zampini pc->ops->applytranspose = PCApplyTranspose_BDDC; 2802da1bb401SStefano Zampini pc->ops->setup = PCSetUp_BDDC; 2803da1bb401SStefano Zampini pc->ops->destroy = PCDestroy_BDDC; 2804da1bb401SStefano Zampini pc->ops->setfromoptions = PCSetFromOptions_BDDC; 28056b78500eSPatrick Sanan pc->ops->view = PCView_BDDC; 28060a545947SLisandro Dalcin pc->ops->applyrichardson = NULL; 28070a545947SLisandro Dalcin pc->ops->applysymmetricleft = NULL; 28080a545947SLisandro Dalcin pc->ops->applysymmetricright = NULL; 2809534831adSStefano Zampini pc->ops->presolve = PCPreSolve_BDDC; 2810534831adSStefano Zampini pc->ops->postsolve = PCPostSolve_BDDC; 28119326c5c6Sstefano_zampini pc->ops->reset = PCReset_BDDC; 2812da1bb401SStefano Zampini 2813da1bb401SStefano Zampini /* composing function */ 28149566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDiscreteGradient_C", PCBDDCSetDiscreteGradient_BDDC)); 28159566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDivergenceMat_C", PCBDDCSetDivergenceMat_BDDC)); 28169566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetChangeOfBasisMat_C", PCBDDCSetChangeOfBasisMat_BDDC)); 28179566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetPrimalVerticesLocalIS_C", PCBDDCSetPrimalVerticesLocalIS_BDDC)); 28189566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetPrimalVerticesIS_C", PCBDDCSetPrimalVerticesIS_BDDC)); 28199566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetPrimalVerticesLocalIS_C", PCBDDCGetPrimalVerticesLocalIS_BDDC)); 28209566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetPrimalVerticesIS_C", PCBDDCGetPrimalVerticesIS_BDDC)); 28219566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetCoarseningRatio_C", PCBDDCSetCoarseningRatio_BDDC)); 28229566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLevel_C", PCBDDCSetLevel_BDDC)); 28239566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetUseExactDirichlet_C", PCBDDCSetUseExactDirichlet_BDDC)); 28249566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLevels_C", PCBDDCSetLevels_BDDC)); 28259566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDirichletBoundaries_C", PCBDDCSetDirichletBoundaries_BDDC)); 28269566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDirichletBoundariesLocal_C", PCBDDCSetDirichletBoundariesLocal_BDDC)); 28279566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetNeumannBoundaries_C", PCBDDCSetNeumannBoundaries_BDDC)); 28289566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetNeumannBoundariesLocal_C", PCBDDCSetNeumannBoundariesLocal_BDDC)); 28299566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetDirichletBoundaries_C", PCBDDCGetDirichletBoundaries_BDDC)); 28309566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetDirichletBoundariesLocal_C", PCBDDCGetDirichletBoundariesLocal_BDDC)); 28319566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetNeumannBoundaries_C", PCBDDCGetNeumannBoundaries_BDDC)); 28329566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetNeumannBoundariesLocal_C", PCBDDCGetNeumannBoundariesLocal_BDDC)); 28339566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDofsSplitting_C", PCBDDCSetDofsSplitting_BDDC)); 28349566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDofsSplittingLocal_C", PCBDDCSetDofsSplittingLocal_BDDC)); 28359566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLocalAdjacencyGraph_C", PCBDDCSetLocalAdjacencyGraph_BDDC)); 28369566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCCreateFETIDPOperators_C", PCBDDCCreateFETIDPOperators_BDDC)); 28379566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCMatFETIDPGetRHS_C", PCBDDCMatFETIDPGetRHS_BDDC)); 28389566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCMatFETIDPGetSolution_C", PCBDDCMatFETIDPGetSolution_BDDC)); 28399566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCPreSolveChangeRHS_C", PCPreSolveChangeRHS_BDDC)); 28409566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", PCSetCoordinates_BDDC)); 2841da1bb401SStefano Zampini PetscFunctionReturn(0); 2842da1bb401SStefano Zampini } 284343371fb9SStefano Zampini 284443371fb9SStefano Zampini /*@C 284543371fb9SStefano Zampini PCBDDCInitializePackage - This function initializes everything in the PCBDDC package. It is called 28468a690491SBarry Smith from PCInitializePackage(). 284743371fb9SStefano Zampini 284843371fb9SStefano Zampini Level: developer 284943371fb9SStefano Zampini 2850db781477SPatrick Sanan .seealso: `PetscInitialize()` 285143371fb9SStefano Zampini @*/ 28529371c9d4SSatish Balay PetscErrorCode PCBDDCInitializePackage(void) { 285343371fb9SStefano Zampini int i; 285443371fb9SStefano Zampini 285543371fb9SStefano Zampini PetscFunctionBegin; 285643371fb9SStefano Zampini if (PCBDDCPackageInitialized) PetscFunctionReturn(0); 285743371fb9SStefano Zampini PCBDDCPackageInitialized = PETSC_TRUE; 28589566063dSJacob Faibussowitsch PetscCall(PetscRegisterFinalize(PCBDDCFinalizePackage)); 285943371fb9SStefano Zampini 286043371fb9SStefano Zampini /* general events */ 28619566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCTopo", PC_CLASSID, &PC_BDDC_Topology[0])); 28629566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCLKSP", PC_CLASSID, &PC_BDDC_LocalSolvers[0])); 28639566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCLWor", PC_CLASSID, &PC_BDDC_LocalWork[0])); 28649566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCCorr", PC_CLASSID, &PC_BDDC_CorrectionSetUp[0])); 28659566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCASet", PC_CLASSID, &PC_BDDC_ApproxSetUp[0])); 28669566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCAApp", PC_CLASSID, &PC_BDDC_ApproxApply[0])); 28679566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCCSet", PC_CLASSID, &PC_BDDC_CoarseSetUp[0])); 28689566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCCKSP", PC_CLASSID, &PC_BDDC_CoarseSolver[0])); 28699566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCAdap", PC_CLASSID, &PC_BDDC_AdaptiveSetUp[0])); 28709566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCScal", PC_CLASSID, &PC_BDDC_Scaling[0])); 28719566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCSchr", PC_CLASSID, &PC_BDDC_Schurs[0])); 28729566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCDirS", PC_CLASSID, &PC_BDDC_Solves[0][0])); 28739566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCNeuS", PC_CLASSID, &PC_BDDC_Solves[0][1])); 28749566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCCoaS", PC_CLASSID, &PC_BDDC_Solves[0][2])); 287543371fb9SStefano Zampini for (i = 1; i < PETSC_PCBDDC_MAXLEVELS; i++) { 287643371fb9SStefano Zampini char ename[32]; 287743371fb9SStefano Zampini 28789566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCTopo l%02d", i)); 28799566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Topology[i])); 28809566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCLKSP l%02d", i)); 28819566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_LocalSolvers[i])); 28829566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCLWor l%02d", i)); 28839566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_LocalWork[i])); 28849566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCCorr l%02d", i)); 28859566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_CorrectionSetUp[i])); 28869566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCASet l%02d", i)); 28879566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_ApproxSetUp[i])); 28889566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCAApp l%02d", i)); 28899566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_ApproxApply[i])); 28909566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCCSet l%02d", i)); 28919566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_CoarseSetUp[i])); 28929566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCCKSP l%02d", i)); 28939566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_CoarseSolver[i])); 28949566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCAdap l%02d", i)); 28959566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_AdaptiveSetUp[i])); 28969566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCScal l%02d", i)); 28979566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Scaling[i])); 28989566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCSchr l%02d", i)); 28999566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Schurs[i])); 29009566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCDirS l%02d", i)); 29019566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Solves[i][0])); 29029566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCNeuS l%02d", i)); 29039566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Solves[i][1])); 29049566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCCoaS l%02d", i)); 29059566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Solves[i][2])); 290643371fb9SStefano Zampini } 290743371fb9SStefano Zampini PetscFunctionReturn(0); 290843371fb9SStefano Zampini } 290943371fb9SStefano Zampini 291043371fb9SStefano Zampini /*@C 291143371fb9SStefano Zampini PCBDDCFinalizePackage - This function frees everything from the PCBDDC package. It is 291243371fb9SStefano Zampini called from PetscFinalize() automatically. 291343371fb9SStefano Zampini 291443371fb9SStefano Zampini Level: developer 291543371fb9SStefano Zampini 2916db781477SPatrick Sanan .seealso: `PetscFinalize()` 291743371fb9SStefano Zampini @*/ 29189371c9d4SSatish Balay PetscErrorCode PCBDDCFinalizePackage(void) { 291943371fb9SStefano Zampini PetscFunctionBegin; 292043371fb9SStefano Zampini PCBDDCPackageInitialized = PETSC_FALSE; 292143371fb9SStefano Zampini PetscFunctionReturn(0); 292243371fb9SStefano Zampini } 2923