1dd01b7e5SBarry Smith #include <petsc/private/pcbddcimpl.h> /*I "petscpc.h" I*/ /* header file for Fortran wrappers */ 25e5bbd0aSStefano Zampini #include <petsc/private/pcbddcprivateimpl.h> 33b03a366Sstefano_zampini #include <petscblaslapack.h> 4674ae819SStefano Zampini 543371fb9SStefano Zampini static PetscBool PCBDDCPackageInitialized = PETSC_FALSE; 643371fb9SStefano Zampini 7f3d41395Sstefano_zampini static PetscBool cited = PETSC_FALSE; 89371c9d4SSatish Balay static const char citation[] = "@article{ZampiniPCBDDC,\n" 9f3d41395Sstefano_zampini "author = {Stefano Zampini},\n" 10f3d41395Sstefano_zampini "title = {{PCBDDC}: A Class of Robust Dual-Primal Methods in {PETS}c},\n" 11f3d41395Sstefano_zampini "journal = {SIAM Journal on Scientific Computing},\n" 12f3d41395Sstefano_zampini "volume = {38},\n" 13f3d41395Sstefano_zampini "number = {5},\n" 14f3d41395Sstefano_zampini "pages = {S282-S306},\n" 15f3d41395Sstefano_zampini "year = {2016},\n" 16f3d41395Sstefano_zampini "doi = {10.1137/15M1025785},\n" 17f3d41395Sstefano_zampini "URL = {http://dx.doi.org/10.1137/15M1025785},\n" 18f3d41395Sstefano_zampini "eprint = {http://dx.doi.org/10.1137/15M1025785}\n" 19f3d41395Sstefano_zampini "}\n"; 20f3d41395Sstefano_zampini 2143371fb9SStefano Zampini PetscLogEvent PC_BDDC_Topology[PETSC_PCBDDC_MAXLEVELS]; 2243371fb9SStefano Zampini PetscLogEvent PC_BDDC_LocalSolvers[PETSC_PCBDDC_MAXLEVELS]; 2343371fb9SStefano Zampini PetscLogEvent PC_BDDC_LocalWork[PETSC_PCBDDC_MAXLEVELS]; 2443371fb9SStefano Zampini PetscLogEvent PC_BDDC_CorrectionSetUp[PETSC_PCBDDC_MAXLEVELS]; 258ead10e4SStefano Zampini PetscLogEvent PC_BDDC_ApproxSetUp[PETSC_PCBDDC_MAXLEVELS]; 268ead10e4SStefano Zampini PetscLogEvent PC_BDDC_ApproxApply[PETSC_PCBDDC_MAXLEVELS]; 2743371fb9SStefano Zampini PetscLogEvent PC_BDDC_CoarseSetUp[PETSC_PCBDDC_MAXLEVELS]; 2843371fb9SStefano Zampini PetscLogEvent PC_BDDC_CoarseSolver[PETSC_PCBDDC_MAXLEVELS]; 2943371fb9SStefano Zampini PetscLogEvent PC_BDDC_AdaptiveSetUp[PETSC_PCBDDC_MAXLEVELS]; 3043371fb9SStefano Zampini PetscLogEvent PC_BDDC_Scaling[PETSC_PCBDDC_MAXLEVELS]; 3143371fb9SStefano Zampini PetscLogEvent PC_BDDC_Schurs[PETSC_PCBDDC_MAXLEVELS]; 3255c176c0SStefano Zampini PetscLogEvent PC_BDDC_Solves[PETSC_PCBDDC_MAXLEVELS][3]; 3343371fb9SStefano Zampini 34bc960bbfSJed Brown const char *const PCBDDCInterfaceExtTypes[] = {"DIRICHLET", "LUMP", "PCBDDCInterfaceExtType", "PC_BDDC_INTERFACE_EXT_", NULL}; 35bc960bbfSJed Brown 3666976f2fSJacob Faibussowitsch static PetscErrorCode PCApply_BDDC(PC, Vec, Vec); 370369aaf7SStefano Zampini 3866976f2fSJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_BDDC(PC pc, PetscOptionItems *PetscOptionsObject) 39d71ae5a4SJacob Faibussowitsch { 400c7d97c5SJed Brown PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 41e569e4e1SStefano Zampini PetscInt nt, i; 420c7d97c5SJed Brown 430c7d97c5SJed Brown PetscFunctionBegin; 44d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "BDDC options"); 458eeda7d8SStefano Zampini /* Verbose debugging */ 469566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-pc_bddc_check_level", "Verbose output for PCBDDC (intended for debug)", "none", pcbddc->dbg_flag, &pcbddc->dbg_flag, NULL)); 47a13144ffSStefano Zampini /* Approximate solvers */ 489566063dSJacob 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)); 49bc960bbfSJed Brown if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_DIRICHLET) { 509566063dSJacob 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)); 519566063dSJacob 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)); 52bc960bbfSJed Brown } else { 53bc960bbfSJed Brown /* This flag is needed/implied by lumping */ 54bc960bbfSJed Brown pcbddc->switch_static = PETSC_TRUE; 55bc960bbfSJed Brown } 569566063dSJacob 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)); 579566063dSJacob 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)); 586b78500eSPatrick Sanan /* Primal space customization */ 599566063dSJacob 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)); 609566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-pc_bddc_graph_maxcount", "Maximum number of shared subdomains for a connected component", "none", pcbddc->graphmaxcount, &pcbddc->graphmaxcount, NULL)); 619566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_corner_selection", "Activates face-based corner selection", "none", pcbddc->corner_selection, &pcbddc->corner_selection, NULL)); 629566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_use_vertices", "Use or not corner dofs in coarse space", "none", pcbddc->use_vertices, &pcbddc->use_vertices, NULL)); 639566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_use_edges", "Use or not edge constraints in coarse space", "none", pcbddc->use_edges, &pcbddc->use_edges, NULL)); 649566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_use_faces", "Use or not face constraints in coarse space", "none", pcbddc->use_faces, &pcbddc->use_faces, NULL)); 659566063dSJacob 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)); 669566063dSJacob 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)); 679566063dSJacob 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)); 689566063dSJacob 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)); 698eeda7d8SStefano Zampini /* Change of basis */ 709566063dSJacob 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)); 719566063dSJacob 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)); 72ad540459SPierre Jolivet if (!pcbddc->use_change_of_basis) pcbddc->use_change_on_faces = PETSC_FALSE; 738eeda7d8SStefano Zampini /* Switch between M_2 (default) and M_3 preconditioners (as defined by C. Dohrmann in the ref. article) */ 749566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_switch_static", "Switch on static condensation ops around the interface preconditioner", "none", pcbddc->switch_static, &pcbddc->switch_static, NULL)); 759566063dSJacob 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)); 76e569e4e1SStefano Zampini i = pcbddc->coarsening_ratio; 779566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-pc_bddc_coarsening_ratio", "Set coarsening ratio used in multilevel coarsening", "PCBDDCSetCoarseningRatio", i, &i, NULL)); 789566063dSJacob Faibussowitsch PetscCall(PCBDDCSetCoarseningRatio(pc, i)); 79e569e4e1SStefano Zampini i = pcbddc->max_levels; 809566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-pc_bddc_levels", "Set maximum number of levels for multilevel", "PCBDDCSetLevels", i, &i, NULL)); 819566063dSJacob Faibussowitsch PetscCall(PCBDDCSetLevels(pc, i)); 829566063dSJacob 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)); 839566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_use_coarse_estimates", "Use estimated eigenvalues for coarse problem", "none", pcbddc->use_coarse_estimates, &pcbddc->use_coarse_estimates, NULL)); 849566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_use_deluxe_scaling", "Use deluxe scaling for BDDC", "none", pcbddc->use_deluxe_scaling, &pcbddc->use_deluxe_scaling, NULL)); 859566063dSJacob 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)); 869566063dSJacob 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)); 879566063dSJacob 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)); 889566063dSJacob 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)); 899566063dSJacob 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)); 909566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_deluxe_singlemat", "Collapse deluxe operators", "none", pcbddc->deluxe_singlemat, &pcbddc->deluxe_singlemat, NULL)); 919566063dSJacob 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)); 92bd2a564bSStefano Zampini nt = 2; 939566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-pc_bddc_adaptive_threshold", "Thresholds to be used for adaptive selection of constraints", "none", pcbddc->adaptive_threshold, &nt, NULL)); 94bd2a564bSStefano Zampini if (nt == 1) pcbddc->adaptive_threshold[1] = pcbddc->adaptive_threshold[0]; 959566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-pc_bddc_adaptive_nmin", "Minimum number of constraints per connected components", "none", pcbddc->adaptive_nmin, &pcbddc->adaptive_nmin, NULL)); 969566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-pc_bddc_adaptive_nmax", "Maximum number of constraints per connected components", "none", pcbddc->adaptive_nmax, &pcbddc->adaptive_nmax, NULL)); 979566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_symmetric", "Symmetric computation of primal basis functions", "none", pcbddc->symmetric_primal, &pcbddc->symmetric_primal, NULL)); 989566063dSJacob 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)); 999566063dSJacob 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)); 1009566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_benign_change", "Compute the pressure change of basis explicitly", "none", pcbddc->benign_change_explicit, &pcbddc->benign_change_explicit, NULL)); 1019566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_benign_compute_correction", "Compute the benign correction during PreSolve", "none", pcbddc->benign_compute_correction, &pcbddc->benign_compute_correction, NULL)); 1029566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_nonetflux", "Automatic computation of no-net-flux quadrature weights", "none", pcbddc->compute_nonetflux, &pcbddc->compute_nonetflux, NULL)); 1039566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_detect_disconnected", "Detects disconnected subdomains", "none", pcbddc->detect_disconnected, &pcbddc->detect_disconnected, NULL)); 1049566063dSJacob 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)); 1059566063dSJacob 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)); 106d0609cedSBarry Smith PetscOptionsHeadEnd(); 1073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1080c7d97c5SJed Brown } 1096b78500eSPatrick Sanan 110d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_BDDC(PC pc, PetscViewer viewer) 111d71ae5a4SJacob Faibussowitsch { 1126b78500eSPatrick Sanan PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 113e9627c49SStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 11471783a16SStefano Zampini PetscBool isascii; 115e9627c49SStefano Zampini PetscSubcomm subcomm; 116e9627c49SStefano Zampini PetscViewer subviewer; 1176b78500eSPatrick Sanan 1186b78500eSPatrick Sanan PetscFunctionBegin; 1199566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1206b78500eSPatrick Sanan /* ASCII viewer */ 1216b78500eSPatrick Sanan if (isascii) { 1224b2aedd3SStefano Zampini PetscMPIInt color, rank, size; 123fbad9177SStefano Zampini PetscInt64 loc[7], gsum[6], gmax[6], gmin[6], totbenign; 124e9627c49SStefano Zampini PetscScalar interface_size; 125e9627c49SStefano Zampini PetscReal ratio1 = 0., ratio2 = 0.; 126e9627c49SStefano Zampini Vec counter; 1276b78500eSPatrick Sanan 12848a46eb9SPierre Jolivet if (!pc->setupcalled) PetscCall(PetscViewerASCIIPrintf(viewer, " Partial information available: preconditioner has not been setup yet\n")); 12963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use verbose output: %" PetscInt_FMT "\n", pcbddc->dbg_flag)); 1309566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use user-defined CSR: %d\n", !!pcbddc->mat_graph->nvtxs_csr)); 1319566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use local mat graph: %d\n", pcbddc->use_local_adj && !pcbddc->mat_graph->nvtxs_csr)); 132e9627c49SStefano Zampini if (pcbddc->mat_graph->twodim) { 1339566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Connectivity graph topological dimension: 2\n")); 134e9627c49SStefano Zampini } else { 1359566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Connectivity graph topological dimension: 3\n")); 136e9627c49SStefano Zampini } 13748a46eb9SPierre Jolivet if (pcbddc->graphmaxcount != PETSC_MAX_INT) PetscCall(PetscViewerASCIIPrintf(viewer, " Graph max count: %" PetscInt_FMT "\n", pcbddc->graphmaxcount)); 1389566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Corner selection: %d (selected %d)\n", pcbddc->corner_selection, pcbddc->corner_selected)); 13963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use vertices: %d (vertex size %" PetscInt_FMT ")\n", pcbddc->use_vertices, pcbddc->vertex_size)); 1409566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use edges: %d\n", pcbddc->use_edges)); 1419566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use faces: %d\n", pcbddc->use_faces)); 1429566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use true near null space: %d\n", pcbddc->use_nnsp_true)); 1439566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use QR for single constraints on cc: %d\n", pcbddc->use_qr_single)); 1449566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use change of basis on local edge nodes: %d\n", pcbddc->use_change_of_basis)); 1459566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use change of basis on local face nodes: %d\n", pcbddc->use_change_on_faces)); 1469566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " User defined change of basis matrix: %d\n", !!pcbddc->user_ChangeOfBasisMatrix)); 1479566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Has change of basis matrix: %d\n", !!pcbddc->ChangeOfBasisMatrix)); 1489566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Eliminate dirichlet boundary dofs: %d\n", pcbddc->eliminate_dirdofs)); 1499566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Switch on static condensation ops around the interface preconditioner: %d\n", pcbddc->switch_static)); 1509566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use exact dirichlet trick: %d\n", pcbddc->use_exact_dirichlet_trick)); 1519566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Interface extension: %s\n", PCBDDCInterfaceExtTypes[pcbddc->interface_extension])); 15263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Multilevel max levels: %" PetscInt_FMT "\n", pcbddc->max_levels)); 15363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Multilevel coarsening ratio: %" PetscInt_FMT "\n", pcbddc->coarsening_ratio)); 1549566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use estimated eigs for coarse problem: %d\n", pcbddc->use_coarse_estimates)); 1559566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use deluxe scaling: %d\n", pcbddc->use_deluxe_scaling)); 1569566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use deluxe zerorows: %d\n", pcbddc->deluxe_zerorows)); 1579566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use deluxe singlemat: %d\n", pcbddc->deluxe_singlemat)); 1589566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Rebuild interface graph for Schur principal minors: %d\n", pcbddc->sub_schurs_rebuild)); 15963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Number of dofs' layers for the computation of principal minors: %" PetscInt_FMT "\n", pcbddc->sub_schurs_layers)); 1609566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use user CSR graph to compute successive layers: %d\n", pcbddc->sub_schurs_use_useradj)); 161bd2a564bSStefano Zampini if (pcbddc->adaptive_threshold[1] != pcbddc->adaptive_threshold[0]) { 16263a3b9bcSJacob 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])); 163bd2a564bSStefano Zampini } else { 16463a3b9bcSJacob 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])); 165bd2a564bSStefano Zampini } 16663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Min constraints / connected component: %" PetscInt_FMT "\n", pcbddc->adaptive_nmin)); 16763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Max constraints / connected component: %" PetscInt_FMT "\n", pcbddc->adaptive_nmax)); 1689566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Invert exact Schur complement for adaptive selection: %d\n", pcbddc->sub_schurs_exact_schur)); 1699566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Symmetric computation of primal basis functions: %d\n", pcbddc->symmetric_primal)); 17063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Num. Procs. to map coarse adjacency list: %" PetscInt_FMT "\n", pcbddc->coarse_adj_red)); 17163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Coarse eqs per proc (significant at the coarsest level): %" PetscInt_FMT "\n", pcbddc->coarse_eqs_per_proc)); 1729566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Detect disconnected: %d (filter %d)\n", pcbddc->detect_disconnected, pcbddc->detect_disconnected_filter)); 1739566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Benign subspace trick: %d (change explicit %d)\n", pcbddc->benign_saddle_point, pcbddc->benign_change_explicit)); 1749566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Benign subspace trick is active: %d\n", pcbddc->benign_have_null)); 1759566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Algebraic computation of no-net-flux: %d\n", pcbddc->compute_nonetflux)); 1763ba16761SJacob Faibussowitsch if (!pc->setupcalled) PetscFunctionReturn(PETSC_SUCCESS); 1776b78500eSPatrick Sanan 178fbad9177SStefano Zampini /* compute interface size */ 1799566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_B, 1.0)); 1809566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(pc->pmat, &counter, NULL)); 1819566063dSJacob Faibussowitsch PetscCall(VecSet(counter, 0.0)); 1829566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_B, pcis->vec1_B, counter, INSERT_VALUES, SCATTER_REVERSE)); 1839566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_B, pcis->vec1_B, counter, INSERT_VALUES, SCATTER_REVERSE)); 1849566063dSJacob Faibussowitsch PetscCall(VecSum(counter, &interface_size)); 1859566063dSJacob Faibussowitsch PetscCall(VecDestroy(&counter)); 186fbad9177SStefano Zampini 187fbad9177SStefano Zampini /* compute some statistics on the domain decomposition */ 188e9627c49SStefano Zampini gsum[0] = 1; 189fbad9177SStefano Zampini gsum[1] = gsum[2] = gsum[3] = gsum[4] = gsum[5] = 0; 190e9627c49SStefano Zampini loc[0] = !!pcis->n; 191e9627c49SStefano Zampini loc[1] = pcis->n - pcis->n_B; 192e9627c49SStefano Zampini loc[2] = pcis->n_B; 193e9627c49SStefano Zampini loc[3] = pcbddc->local_primal_size; 194345ecf6cSStefano Zampini loc[4] = pcis->n; 195fbad9177SStefano Zampini loc[5] = pcbddc->n_local_subs > 0 ? pcbddc->n_local_subs : (pcis->n ? 1 : 0); 196fbad9177SStefano Zampini loc[6] = pcbddc->benign_n; 1979566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(loc, gsum, 6, MPIU_INT64, MPI_SUM, 0, PetscObjectComm((PetscObject)pc))); 198fbad9177SStefano Zampini if (!loc[0]) loc[1] = loc[2] = loc[3] = loc[4] = loc[5] = -1; 1999566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(loc, gmax, 6, MPIU_INT64, MPI_MAX, 0, PetscObjectComm((PetscObject)pc))); 200fbad9177SStefano Zampini if (!loc[0]) loc[1] = loc[2] = loc[3] = loc[4] = loc[5] = PETSC_MAX_INT; 2019566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(loc, gmin, 6, MPIU_INT64, MPI_MIN, 0, PetscObjectComm((PetscObject)pc))); 2029566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&loc[6], &totbenign, 1, MPIU_INT64, MPI_SUM, 0, PetscObjectComm((PetscObject)pc))); 203e9627c49SStefano Zampini if (pcbddc->coarse_size) { 204e9627c49SStefano Zampini ratio1 = pc->pmat->rmap->N / (1. * pcbddc->coarse_size); 205e9627c49SStefano Zampini ratio2 = PetscRealPart(interface_size) / pcbddc->coarse_size; 206e9627c49SStefano Zampini } 20763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "********************************** STATISTICS AT LEVEL %" PetscInt_FMT " **********************************\n", pcbddc->current_level)); 20863a3b9bcSJacob 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)); 20963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Coarsening ratios: all/coarse %" PetscInt_FMT " interface/coarse %" PetscInt_FMT "\n", (PetscInt)ratio1, (PetscInt)ratio2)); 21063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Active processes : %" PetscInt_FMT "\n", (PetscInt)gsum[0])); 21163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Total subdomains : %" PetscInt_FMT "\n", (PetscInt)gsum[5])); 21248a46eb9SPierre Jolivet if (pcbddc->benign_have_null) PetscCall(PetscViewerASCIIPrintf(viewer, " Benign subs : %" PetscInt_FMT "\n", (PetscInt)totbenign)); 2139566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Dofs type :\tMIN\tMAX\tMEAN\n")); 21463a3b9bcSJacob 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]))); 21563a3b9bcSJacob 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]))); 21663a3b9bcSJacob 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]))); 21763a3b9bcSJacob 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]))); 21863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Local subs :\t%" PetscInt_FMT "\t%" PetscInt_FMT "\n", (PetscInt)gmin[5], (PetscInt)gmax[5])); 2199566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 22015579a77SStefano Zampini 2219566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)pc), &rank)); 22215579a77SStefano Zampini 22315579a77SStefano Zampini /* local solvers */ 2249566063dSJacob Faibussowitsch PetscCall(PetscViewerGetSubViewer(viewer, PetscObjectComm((PetscObject)pcbddc->ksp_D), &subviewer)); 225dd400576SPatrick Sanan if (rank == 0) { 2269566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(subviewer, "--- Interior solver (rank 0)\n")); 2279566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(subviewer)); 2289566063dSJacob Faibussowitsch PetscCall(KSPView(pcbddc->ksp_D, subviewer)); 2299566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(subviewer)); 2309566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(subviewer, "--- Correction solver (rank 0)\n")); 2319566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(subviewer)); 2329566063dSJacob Faibussowitsch PetscCall(KSPView(pcbddc->ksp_R, subviewer)); 2339566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(subviewer)); 2349566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(subviewer)); 23515579a77SStefano Zampini } 2369566063dSJacob Faibussowitsch PetscCall(PetscViewerRestoreSubViewer(viewer, PetscObjectComm((PetscObject)pcbddc->ksp_D), &subviewer)); 237fbad9177SStefano Zampini /* the coarse problem can be handled by a different communicator */ 238e9627c49SStefano Zampini if (pcbddc->coarse_ksp) color = 1; 239e9627c49SStefano Zampini else color = 0; 2409566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc), &size)); 2419566063dSJacob Faibussowitsch PetscCall(PetscSubcommCreate(PetscObjectComm((PetscObject)pc), &subcomm)); 2429566063dSJacob Faibussowitsch PetscCall(PetscSubcommSetNumber(subcomm, PetscMin(size, 2))); 2439566063dSJacob Faibussowitsch PetscCall(PetscSubcommSetTypeGeneral(subcomm, color, rank)); 2449566063dSJacob Faibussowitsch PetscCall(PetscViewerGetSubViewer(viewer, PetscSubcommChild(subcomm), &subviewer)); 245e9627c49SStefano Zampini if (color == 1) { 2469566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(subviewer, "--- Coarse solver\n")); 2479566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(subviewer)); 2489566063dSJacob Faibussowitsch PetscCall(KSPView(pcbddc->coarse_ksp, subviewer)); 2499566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(subviewer)); 2509566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(subviewer)); 251e9627c49SStefano Zampini } 2529566063dSJacob Faibussowitsch PetscCall(PetscViewerRestoreSubViewer(viewer, PetscSubcommChild(subcomm), &subviewer)); 2539566063dSJacob Faibussowitsch PetscCall(PetscSubcommDestroy(&subcomm)); 2549566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 255e9627c49SStefano Zampini } 2563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2576b78500eSPatrick Sanan } 258a13144ffSStefano Zampini 259d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetDiscreteGradient_BDDC(PC pc, Mat G, PetscInt order, PetscInt field, PetscBool global, PetscBool conforming) 260d71ae5a4SJacob Faibussowitsch { 261a13144ffSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 262a13144ffSStefano Zampini 263a13144ffSStefano Zampini PetscFunctionBegin; 2649566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)G)); 2659566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->discretegradient)); 266a13144ffSStefano Zampini pcbddc->discretegradient = G; 267a13144ffSStefano Zampini pcbddc->nedorder = order > 0 ? order : -order; 268495a2a07SStefano Zampini pcbddc->nedfield = field; 2691e0482f5SStefano Zampini pcbddc->nedglobal = global; 2701e0482f5SStefano Zampini pcbddc->conforming = conforming; 2713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 272a13144ffSStefano Zampini } 273a13144ffSStefano Zampini 274a13144ffSStefano Zampini /*@ 27598ad52f2SBarry Smith PCBDDCSetDiscreteGradient - Sets the discrete gradient to be used by the `PCBDDC` preconditioner 276a13144ffSStefano Zampini 277c3339decSBarry Smith Collective 278a13144ffSStefano Zampini 279a13144ffSStefano Zampini Input Parameters: 280a13144ffSStefano Zampini + pc - the preconditioning context 281f1580f4eSBarry Smith . G - the discrete gradient matrix (in `MATAIJ` format) 282a13144ffSStefano Zampini . order - the order of the Nedelec space (1 for the lowest order) 283495a2a07SStefano Zampini . field - the field id of the Nedelec dofs (not used if the fields have not been specified) 28498ad52f2SBarry Smith . global - the type of global ordering for the rows of `G` 285a13144ffSStefano Zampini - conforming - whether the mesh is conforming or not 286a13144ffSStefano Zampini 287a13144ffSStefano Zampini Level: advanced 288a13144ffSStefano Zampini 289f1580f4eSBarry Smith Note: 29020f4b53cSBarry Smith The discrete gradient matrix `G` is used to analyze the subdomain edges, and it should not contain any zero entry. 291495a2a07SStefano Zampini For variable order spaces, the order should be set to zero. 29298ad52f2SBarry Smith If `global` is `PETSC_TRUE`, the rows of `G` should be given in global ordering for the whole dofs; 29398ad52f2SBarry Smith if `PETSC_FALSE`, the ordering should be global for the Nedelec field. 2941e0482f5SStefano 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 2951e0482f5SStefano Zampini and geid the one for the Nedelec field. 296a13144ffSStefano Zampini 297562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetDofsSplitting()`, `PCBDDCSetDofsSplittingLocal()`, `MATAIJ`, `PCBDDCSetDivergenceMat()` 298a13144ffSStefano Zampini @*/ 299d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetDiscreteGradient(PC pc, Mat G, PetscInt order, PetscInt field, PetscBool global, PetscBool conforming) 300d71ae5a4SJacob Faibussowitsch { 301a13144ffSStefano Zampini PetscFunctionBegin; 302a13144ffSStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 303a13144ffSStefano Zampini PetscValidHeaderSpecific(G, MAT_CLASSID, 2); 304a13144ffSStefano Zampini PetscValidLogicalCollectiveInt(pc, order, 3); 3051e0482f5SStefano Zampini PetscValidLogicalCollectiveInt(pc, field, 4); 3061e0482f5SStefano Zampini PetscValidLogicalCollectiveBool(pc, global, 5); 3071e0482f5SStefano Zampini PetscValidLogicalCollectiveBool(pc, conforming, 6); 3081e0482f5SStefano Zampini PetscCheckSameComm(pc, 1, G, 2); 309cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetDiscreteGradient_C", (PC, Mat, PetscInt, PetscInt, PetscBool, PetscBool), (pc, G, order, field, global, conforming)); 3103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 311a13144ffSStefano Zampini } 312a13144ffSStefano Zampini 313d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetDivergenceMat_BDDC(PC pc, Mat divudotp, PetscBool trans, IS vl2l) 314d71ae5a4SJacob Faibussowitsch { 315a198735bSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 3166b78500eSPatrick Sanan 317a198735bSStefano Zampini PetscFunctionBegin; 3189566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)divudotp)); 3199566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->divudotp)); 320a198735bSStefano Zampini pcbddc->divudotp = divudotp; 3218ae0ca82SStefano Zampini pcbddc->divudotp_trans = trans; 322a198735bSStefano Zampini pcbddc->compute_nonetflux = PETSC_TRUE; 323a198735bSStefano Zampini if (vl2l) { 3249566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)vl2l)); 3259566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->divudotp_vl2l)); 326a198735bSStefano Zampini pcbddc->divudotp_vl2l = vl2l; 327a198735bSStefano Zampini } 3283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 329a198735bSStefano Zampini } 3303d996552SStefano Zampini 331a198735bSStefano Zampini /*@ 33298ad52f2SBarry Smith PCBDDCSetDivergenceMat - Sets the linear operator representing \int_\Omega \div {\bf u} \cdot p dx for the `PCBDDC` preconditioner 333a198735bSStefano Zampini 334c3339decSBarry Smith Collective 335a198735bSStefano Zampini 336a198735bSStefano Zampini Input Parameters: 337a198735bSStefano Zampini + pc - the preconditioning context 338f1580f4eSBarry Smith . divudotp - the matrix (must be of type `MATIS`) 33998ad52f2SBarry Smith . trans - if `PETSC_FALSE` (resp. `PETSC_TRUE`), then pressures are in the test (trial) space and velocities are in the trial (test) space. 34098ad52f2SBarry Smith - vl2l - optional index set describing the local (wrt the local matrix in `divudotp`) to local (wrt the local matrix 341f1580f4eSBarry Smith in the preconditioning matrix) map for the velocities 342a198735bSStefano Zampini 343a198735bSStefano Zampini Level: advanced 344a198735bSStefano Zampini 34595452b02SPatrick Sanan Notes: 34695452b02SPatrick Sanan This auxiliary matrix is used to compute quadrature weights representing the net-flux across subdomain boundaries 347f1580f4eSBarry Smith 34898ad52f2SBarry Smith If `vl2l` is `NULL`, the local ordering for velocities in `divudotp` should match that of the preconditioning matrix 349a198735bSStefano Zampini 350562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetDiscreteGradient()` 351a198735bSStefano Zampini @*/ 352d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetDivergenceMat(PC pc, Mat divudotp, PetscBool trans, IS vl2l) 353d71ae5a4SJacob Faibussowitsch { 354a198735bSStefano Zampini PetscBool ismatis; 355a198735bSStefano Zampini 356a198735bSStefano Zampini PetscFunctionBegin; 357a198735bSStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 358a198735bSStefano Zampini PetscValidHeaderSpecific(divudotp, MAT_CLASSID, 2); 359a198735bSStefano Zampini PetscCheckSameComm(pc, 1, divudotp, 2); 3608ae0ca82SStefano Zampini PetscValidLogicalCollectiveBool(pc, trans, 3); 3611b24a7afSStefano Zampini if (vl2l) PetscValidHeaderSpecific(vl2l, IS_CLASSID, 4); 3629566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)divudotp, MATIS, &ismatis)); 36328b400f6SJacob Faibussowitsch PetscCheck(ismatis, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "Divergence matrix needs to be of type MATIS"); 364cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetDivergenceMat_C", (PC, Mat, PetscBool, IS), (pc, divudotp, trans, vl2l)); 3653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 366a198735bSStefano Zampini } 3672d505d7fSStefano Zampini 368d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetChangeOfBasisMat_BDDC(PC pc, Mat change, PetscBool interior) 369d71ae5a4SJacob Faibussowitsch { 370b9b85e73SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 371b9b85e73SStefano Zampini 372b9b85e73SStefano Zampini PetscFunctionBegin; 3739566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)change)); 3749566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->user_ChangeOfBasisMatrix)); 375b9b85e73SStefano Zampini pcbddc->user_ChangeOfBasisMatrix = change; 3761dd7afcfSStefano Zampini pcbddc->change_interior = interior; 3773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 378b9b85e73SStefano Zampini } 37932fe681dSStefano Zampini 380b9b85e73SStefano Zampini /*@ 381906d46d4SStefano Zampini PCBDDCSetChangeOfBasisMat - Set user defined change of basis for dofs 382b9b85e73SStefano Zampini 383c3339decSBarry Smith Collective 384b9b85e73SStefano Zampini 385b9b85e73SStefano Zampini Input Parameters: 386b9b85e73SStefano Zampini + pc - the preconditioning context 3871dd7afcfSStefano Zampini . change - the change of basis matrix 3881dd7afcfSStefano Zampini - interior - whether or not the change of basis modifies interior dofs 389b9b85e73SStefano Zampini 390b9b85e73SStefano Zampini Level: intermediate 391b9b85e73SStefano Zampini 392562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC` 393b9b85e73SStefano Zampini @*/ 394d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetChangeOfBasisMat(PC pc, Mat change, PetscBool interior) 395d71ae5a4SJacob Faibussowitsch { 396b9b85e73SStefano Zampini PetscFunctionBegin; 397b9b85e73SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 398b9b85e73SStefano Zampini PetscValidHeaderSpecific(change, MAT_CLASSID, 2); 399906d46d4SStefano Zampini PetscCheckSameComm(pc, 1, change, 2); 400906d46d4SStefano Zampini if (pc->mat) { 401906d46d4SStefano Zampini PetscInt rows_c, cols_c, rows, cols; 4029566063dSJacob Faibussowitsch PetscCall(MatGetSize(pc->mat, &rows, &cols)); 4039566063dSJacob Faibussowitsch PetscCall(MatGetSize(change, &rows_c, &cols_c)); 40463a3b9bcSJacob 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); 40563a3b9bcSJacob 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); 4069566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(pc->mat, &rows, &cols)); 4079566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(change, &rows_c, &cols_c)); 40863a3b9bcSJacob 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); 40963a3b9bcSJacob 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); 410906d46d4SStefano Zampini } 411cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetChangeOfBasisMat_C", (PC, Mat, PetscBool), (pc, change, interior)); 4123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 413b9b85e73SStefano Zampini } 4142d505d7fSStefano Zampini 415d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetPrimalVerticesIS_BDDC(PC pc, IS PrimalVertices) 416d71ae5a4SJacob Faibussowitsch { 41730368db7SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 41856282151SStefano Zampini PetscBool isequal = PETSC_FALSE; 41930368db7SStefano Zampini 42030368db7SStefano Zampini PetscFunctionBegin; 4219566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)PrimalVertices)); 42248a46eb9SPierre Jolivet if (pcbddc->user_primal_vertices) PetscCall(ISEqual(PrimalVertices, pcbddc->user_primal_vertices, &isequal)); 4239566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->user_primal_vertices)); 4249566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->user_primal_vertices_local)); 42530368db7SStefano Zampini pcbddc->user_primal_vertices = PrimalVertices; 42656282151SStefano Zampini if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 4273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 42830368db7SStefano Zampini } 429ab8c8b98SStefano Zampini 43030368db7SStefano Zampini /*@ 431f1580f4eSBarry Smith PCBDDCSetPrimalVerticesIS - Set additional user defined primal vertices in `PCBDDC` 43230368db7SStefano Zampini 43330368db7SStefano Zampini Collective 43430368db7SStefano Zampini 43530368db7SStefano Zampini Input Parameters: 43630368db7SStefano Zampini + pc - the preconditioning context 43730368db7SStefano Zampini - PrimalVertices - index set of primal vertices in global numbering (can be empty) 43830368db7SStefano Zampini 43930368db7SStefano Zampini Level: intermediate 44030368db7SStefano Zampini 441f1580f4eSBarry Smith Note: 44230368db7SStefano Zampini Any process can list any global node 44330368db7SStefano Zampini 444562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCGetPrimalVerticesIS()`, `PCBDDCSetPrimalVerticesLocalIS()`, `PCBDDCGetPrimalVerticesLocalIS()` 44530368db7SStefano Zampini @*/ 446d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetPrimalVerticesIS(PC pc, IS PrimalVertices) 447d71ae5a4SJacob Faibussowitsch { 44830368db7SStefano Zampini PetscFunctionBegin; 44930368db7SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 45030368db7SStefano Zampini PetscValidHeaderSpecific(PrimalVertices, IS_CLASSID, 2); 45130368db7SStefano Zampini PetscCheckSameComm(pc, 1, PrimalVertices, 2); 452cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetPrimalVerticesIS_C", (PC, IS), (pc, PrimalVertices)); 4533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 45430368db7SStefano Zampini } 4552d505d7fSStefano Zampini 456d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCGetPrimalVerticesIS_BDDC(PC pc, IS *is) 457d71ae5a4SJacob Faibussowitsch { 4583100ebe3SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 4593100ebe3SStefano Zampini 4603100ebe3SStefano Zampini PetscFunctionBegin; 4613100ebe3SStefano Zampini *is = pcbddc->user_primal_vertices; 4623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4633100ebe3SStefano Zampini } 4643100ebe3SStefano Zampini 4653100ebe3SStefano Zampini /*@ 466f1580f4eSBarry Smith PCBDDCGetPrimalVerticesIS - Get user defined primal vertices set with `PCBDDCSetPrimalVerticesIS()` 4673100ebe3SStefano Zampini 4683100ebe3SStefano Zampini Collective 4693100ebe3SStefano Zampini 470f1580f4eSBarry Smith Input Parameter: 4713100ebe3SStefano Zampini . pc - the preconditioning context 4723100ebe3SStefano Zampini 473f1580f4eSBarry Smith Output Parameter: 47420f4b53cSBarry Smith . is - index set of primal vertices in global numbering (`NULL` if not set) 4753100ebe3SStefano Zampini 4763100ebe3SStefano Zampini Level: intermediate 4773100ebe3SStefano Zampini 478562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetPrimalVerticesIS()`, `PCBDDCSetPrimalVerticesLocalIS()`, `PCBDDCGetPrimalVerticesLocalIS()` 4793100ebe3SStefano Zampini @*/ 480d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGetPrimalVerticesIS(PC pc, IS *is) 481d71ae5a4SJacob Faibussowitsch { 4823100ebe3SStefano Zampini PetscFunctionBegin; 4833100ebe3SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 4844f572ea9SToby Isaac PetscAssertPointer(is, 2); 485cac4c232SBarry Smith PetscUseMethod(pc, "PCBDDCGetPrimalVerticesIS_C", (PC, IS *), (pc, is)); 4863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4873100ebe3SStefano Zampini } 4883100ebe3SStefano Zampini 489d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetPrimalVerticesLocalIS_BDDC(PC pc, IS PrimalVertices) 490d71ae5a4SJacob Faibussowitsch { 491674ae819SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 49256282151SStefano Zampini PetscBool isequal = PETSC_FALSE; 4931e6b0712SBarry Smith 494674ae819SStefano Zampini PetscFunctionBegin; 4959566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)PrimalVertices)); 49648a46eb9SPierre Jolivet if (pcbddc->user_primal_vertices_local) PetscCall(ISEqual(PrimalVertices, pcbddc->user_primal_vertices_local, &isequal)); 4979566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->user_primal_vertices)); 4989566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->user_primal_vertices_local)); 49930368db7SStefano Zampini pcbddc->user_primal_vertices_local = PrimalVertices; 50056282151SStefano Zampini if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 5013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 502674ae819SStefano Zampini } 5033100ebe3SStefano Zampini 504674ae819SStefano Zampini /*@ 505f1580f4eSBarry Smith PCBDDCSetPrimalVerticesLocalIS - Set additional user defined primal vertices in `PCBDDC` 506674ae819SStefano Zampini 50717eb1463SStefano Zampini Collective 508674ae819SStefano Zampini 509674ae819SStefano Zampini Input Parameters: 510674ae819SStefano Zampini + pc - the preconditioning context 51117eb1463SStefano Zampini - PrimalVertices - index set of primal vertices in local numbering (can be empty) 512674ae819SStefano Zampini 513674ae819SStefano Zampini Level: intermediate 514674ae819SStefano Zampini 515562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetPrimalVerticesIS()`, `PCBDDCGetPrimalVerticesIS()`, `PCBDDCGetPrimalVerticesLocalIS()` 516674ae819SStefano Zampini @*/ 517d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetPrimalVerticesLocalIS(PC pc, IS PrimalVertices) 518d71ae5a4SJacob Faibussowitsch { 519674ae819SStefano Zampini PetscFunctionBegin; 520674ae819SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 521674ae819SStefano Zampini PetscValidHeaderSpecific(PrimalVertices, IS_CLASSID, 2); 52217eb1463SStefano Zampini PetscCheckSameComm(pc, 1, PrimalVertices, 2); 523cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetPrimalVerticesLocalIS_C", (PC, IS), (pc, PrimalVertices)); 5243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 525674ae819SStefano Zampini } 5262d505d7fSStefano Zampini 527d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCGetPrimalVerticesLocalIS_BDDC(PC pc, IS *is) 528d71ae5a4SJacob Faibussowitsch { 5293100ebe3SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 5303100ebe3SStefano Zampini 5313100ebe3SStefano Zampini PetscFunctionBegin; 5323100ebe3SStefano Zampini *is = pcbddc->user_primal_vertices_local; 5333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5343100ebe3SStefano Zampini } 5353100ebe3SStefano Zampini 5363100ebe3SStefano Zampini /*@ 537f1580f4eSBarry Smith PCBDDCGetPrimalVerticesLocalIS - Get user defined primal vertices set with `PCBDDCSetPrimalVerticesLocalIS()` 5383100ebe3SStefano Zampini 5393100ebe3SStefano Zampini Collective 5403100ebe3SStefano Zampini 541f1580f4eSBarry Smith Input Parameter: 5423100ebe3SStefano Zampini . pc - the preconditioning context 5433100ebe3SStefano Zampini 544f1580f4eSBarry Smith Output Parameter: 54520f4b53cSBarry Smith . is - index set of primal vertices in local numbering (`NULL` if not set) 5463100ebe3SStefano Zampini 5473100ebe3SStefano Zampini Level: intermediate 5483100ebe3SStefano Zampini 549562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetPrimalVerticesIS()`, `PCBDDCGetPrimalVerticesIS()`, `PCBDDCSetPrimalVerticesLocalIS()` 5503100ebe3SStefano Zampini @*/ 551d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGetPrimalVerticesLocalIS(PC pc, IS *is) 552d71ae5a4SJacob Faibussowitsch { 5533100ebe3SStefano Zampini PetscFunctionBegin; 5543100ebe3SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 5554f572ea9SToby Isaac PetscAssertPointer(is, 2); 556cac4c232SBarry Smith PetscUseMethod(pc, "PCBDDCGetPrimalVerticesLocalIS_C", (PC, IS *), (pc, is)); 5573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5583100ebe3SStefano Zampini } 5593100ebe3SStefano Zampini 560d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetCoarseningRatio_BDDC(PC pc, PetscInt k) 561d71ae5a4SJacob Faibussowitsch { 5624fad6a16SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 5634fad6a16SStefano Zampini 5644fad6a16SStefano Zampini PetscFunctionBegin; 5654fad6a16SStefano Zampini pcbddc->coarsening_ratio = k; 5663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5674fad6a16SStefano Zampini } 5681e6b0712SBarry Smith 5694fad6a16SStefano Zampini /*@ 57098ad52f2SBarry Smith PCBDDCSetCoarseningRatio - Set coarsening ratio used in the multi-level version of `PCBDDC` 5714fad6a16SStefano Zampini 57220f4b53cSBarry Smith Logically Collective 5734fad6a16SStefano Zampini 5744fad6a16SStefano Zampini Input Parameters: 5754fad6a16SStefano Zampini + pc - the preconditioning context 57628509bceSStefano Zampini - k - coarsening ratio (H/h at the coarser level) 5774fad6a16SStefano Zampini 578f1580f4eSBarry Smith Options Database Key: 57998ad52f2SBarry Smith . -pc_bddc_coarsening_ratio <int> - Set the coarsening ratio used in multi-level coarsening 5804fad6a16SStefano Zampini 5814fad6a16SStefano Zampini Level: intermediate 5824fad6a16SStefano Zampini 583f1580f4eSBarry Smith Note: 58420f4b53cSBarry Smith Approximately `k` subdomains at the finer level will be aggregated into a single subdomain at the coarser level 5854fad6a16SStefano Zampini 586562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetLevels()` 5874fad6a16SStefano Zampini @*/ 588d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetCoarseningRatio(PC pc, PetscInt k) 589d71ae5a4SJacob Faibussowitsch { 5904fad6a16SStefano Zampini PetscFunctionBegin; 5914fad6a16SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 5922b510759SStefano Zampini PetscValidLogicalCollectiveInt(pc, k, 2); 593cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetCoarseningRatio_C", (PC, PetscInt), (pc, k)); 5943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5954fad6a16SStefano Zampini } 5962b510759SStefano Zampini 597b8ffe317SStefano Zampini /* The following functions (PCBDDCSetUseExactDirichlet PCBDDCSetLevel) are not public */ 598d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetUseExactDirichlet_BDDC(PC pc, PetscBool flg) 599d71ae5a4SJacob Faibussowitsch { 600b8ffe317SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 601b8ffe317SStefano Zampini 602b8ffe317SStefano Zampini PetscFunctionBegin; 60385c4d303SStefano Zampini pcbddc->use_exact_dirichlet_trick = flg; 6043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 605b8ffe317SStefano Zampini } 606b8ffe317SStefano Zampini 607d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetUseExactDirichlet(PC pc, PetscBool flg) 608d71ae5a4SJacob Faibussowitsch { 6092b510759SStefano Zampini PetscFunctionBegin; 6102b510759SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 611b8ffe317SStefano Zampini PetscValidLogicalCollectiveBool(pc, flg, 2); 612cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetUseExactDirichlet_C", (PC, PetscBool), (pc, flg)); 6133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6142b510759SStefano Zampini } 6151e6b0712SBarry Smith 616d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetLevel_BDDC(PC pc, PetscInt level) 617d71ae5a4SJacob Faibussowitsch { 6184fad6a16SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 6194fad6a16SStefano Zampini 6204fad6a16SStefano Zampini PetscFunctionBegin; 6212b510759SStefano Zampini pcbddc->current_level = level; 6223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6234fad6a16SStefano Zampini } 6241e6b0712SBarry Smith 625d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetLevel(PC pc, PetscInt level) 626d71ae5a4SJacob Faibussowitsch { 627b8ffe317SStefano Zampini PetscFunctionBegin; 628b8ffe317SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 629b8ffe317SStefano Zampini PetscValidLogicalCollectiveInt(pc, level, 2); 630cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetLevel_C", (PC, PetscInt), (pc, level)); 6313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 632b8ffe317SStefano Zampini } 633b8ffe317SStefano Zampini 634d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetLevels_BDDC(PC pc, PetscInt levels) 635d71ae5a4SJacob Faibussowitsch { 6362b510759SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 6372b510759SStefano Zampini 6382b510759SStefano Zampini PetscFunctionBegin; 6397827d75bSBarry 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); 6402b510759SStefano Zampini pcbddc->max_levels = levels; 6413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6422b510759SStefano Zampini } 6432b510759SStefano Zampini 6444fad6a16SStefano Zampini /*@ 645f1580f4eSBarry Smith PCBDDCSetLevels - Sets the maximum number of additional levels allowed for multilevel `PCBDDC` 6464fad6a16SStefano Zampini 64720f4b53cSBarry Smith Logically Collective 6484fad6a16SStefano Zampini 6494fad6a16SStefano Zampini Input Parameters: 6504fad6a16SStefano Zampini + pc - the preconditioning context 65137ebbdf7SStefano Zampini - levels - the maximum number of levels 6524fad6a16SStefano Zampini 653f1580f4eSBarry Smith Options Database Key: 65467b8a455SSatish Balay . -pc_bddc_levels <int> - Set maximum number of levels for multilevel 6554fad6a16SStefano Zampini 6564fad6a16SStefano Zampini Level: intermediate 6574fad6a16SStefano Zampini 658f1580f4eSBarry Smith Note: 65998ad52f2SBarry Smith The default value is 0, that gives the classical two-levels BDDC algorithm 6604fad6a16SStefano Zampini 661562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetCoarseningRatio()` 6624fad6a16SStefano Zampini @*/ 663d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetLevels(PC pc, PetscInt levels) 664d71ae5a4SJacob Faibussowitsch { 6654fad6a16SStefano Zampini PetscFunctionBegin; 6664fad6a16SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 6672b510759SStefano Zampini PetscValidLogicalCollectiveInt(pc, levels, 2); 668cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetLevels_C", (PC, PetscInt), (pc, levels)); 6693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6704fad6a16SStefano Zampini } 6711e6b0712SBarry Smith 672d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetDirichletBoundaries_BDDC(PC pc, IS DirichletBoundaries) 673d71ae5a4SJacob Faibussowitsch { 6743b03a366Sstefano_zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 67556282151SStefano Zampini PetscBool isequal = PETSC_FALSE; 6763b03a366Sstefano_zampini 6773b03a366Sstefano_zampini PetscFunctionBegin; 6789566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)DirichletBoundaries)); 67948a46eb9SPierre Jolivet if (pcbddc->DirichletBoundaries) PetscCall(ISEqual(DirichletBoundaries, pcbddc->DirichletBoundaries, &isequal)); 680a5b23f4aSJose E. Roman /* last user setting takes precedence -> destroy any other customization */ 6819566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->DirichletBoundariesLocal)); 6829566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->DirichletBoundaries)); 68336e030ebSStefano Zampini pcbddc->DirichletBoundaries = DirichletBoundaries; 68456282151SStefano Zampini if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 6853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6863b03a366Sstefano_zampini } 6871e6b0712SBarry Smith 6883b03a366Sstefano_zampini /*@ 68998ad52f2SBarry Smith PCBDDCSetDirichletBoundaries - Set the `IS` defining Dirichlet boundaries for the global problem. 6903b03a366Sstefano_zampini 691785d1243SStefano Zampini Collective 6923b03a366Sstefano_zampini 6933b03a366Sstefano_zampini Input Parameters: 6943b03a366Sstefano_zampini + pc - the preconditioning context 69520f4b53cSBarry Smith - DirichletBoundaries - parallel `IS` defining the Dirichlet boundaries 6963b03a366Sstefano_zampini 6973b03a366Sstefano_zampini Level: intermediate 6983b03a366Sstefano_zampini 699f1580f4eSBarry Smith Note: 700f1580f4eSBarry Smith Provide the information if you used `MatZeroRows()` or `MatZeroRowsColumns()`. Any process can list any global node 7013b03a366Sstefano_zampini 702562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetDirichletBoundariesLocal()`, `MatZeroRows()`, `MatZeroRowsColumns()` 7033b03a366Sstefano_zampini @*/ 704d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetDirichletBoundaries(PC pc, IS DirichletBoundaries) 705d71ae5a4SJacob Faibussowitsch { 7063b03a366Sstefano_zampini PetscFunctionBegin; 7073b03a366Sstefano_zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 708674ae819SStefano Zampini PetscValidHeaderSpecific(DirichletBoundaries, IS_CLASSID, 2); 709785d1243SStefano Zampini PetscCheckSameComm(pc, 1, DirichletBoundaries, 2); 710cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetDirichletBoundaries_C", (PC, IS), (pc, DirichletBoundaries)); 7113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7123b03a366Sstefano_zampini } 7131e6b0712SBarry Smith 714d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetDirichletBoundariesLocal_BDDC(PC pc, IS DirichletBoundaries) 715d71ae5a4SJacob Faibussowitsch { 7163b03a366Sstefano_zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 71756282151SStefano Zampini PetscBool isequal = PETSC_FALSE; 7183b03a366Sstefano_zampini 7193b03a366Sstefano_zampini PetscFunctionBegin; 7209566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)DirichletBoundaries)); 72148a46eb9SPierre Jolivet if (pcbddc->DirichletBoundariesLocal) PetscCall(ISEqual(DirichletBoundaries, pcbddc->DirichletBoundariesLocal, &isequal)); 722a5b23f4aSJose E. Roman /* last user setting takes precedence -> destroy any other customization */ 7239566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->DirichletBoundariesLocal)); 7249566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->DirichletBoundaries)); 725785d1243SStefano Zampini pcbddc->DirichletBoundariesLocal = DirichletBoundaries; 72656282151SStefano Zampini if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 7273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7283b03a366Sstefano_zampini } 7293b03a366Sstefano_zampini 7303b03a366Sstefano_zampini /*@ 73198ad52f2SBarry Smith PCBDDCSetDirichletBoundariesLocal - Set the `IS` defining Dirichlet boundaries for the global problem in local ordering. 7323b03a366Sstefano_zampini 733785d1243SStefano Zampini Collective 7343b03a366Sstefano_zampini 7353b03a366Sstefano_zampini Input Parameters: 7363b03a366Sstefano_zampini + pc - the preconditioning context 73720f4b53cSBarry Smith - DirichletBoundaries - parallel `IS` defining the Dirichlet boundaries (in local ordering) 7383b03a366Sstefano_zampini 7393b03a366Sstefano_zampini Level: intermediate 7403b03a366Sstefano_zampini 741562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetDirichletBoundaries()`, `MatZeroRows()`, `MatZeroRowsColumns()` 7423b03a366Sstefano_zampini @*/ 743d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetDirichletBoundariesLocal(PC pc, IS DirichletBoundaries) 744d71ae5a4SJacob Faibussowitsch { 7453b03a366Sstefano_zampini PetscFunctionBegin; 7463b03a366Sstefano_zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 7473b03a366Sstefano_zampini PetscValidHeaderSpecific(DirichletBoundaries, IS_CLASSID, 2); 74882ba6b80SStefano Zampini PetscCheckSameComm(pc, 1, DirichletBoundaries, 2); 749cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetDirichletBoundariesLocal_C", (PC, IS), (pc, DirichletBoundaries)); 7503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7513b03a366Sstefano_zampini } 7523b03a366Sstefano_zampini 753d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc, IS NeumannBoundaries) 754d71ae5a4SJacob Faibussowitsch { 7550c7d97c5SJed Brown PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 75656282151SStefano Zampini PetscBool isequal = PETSC_FALSE; 7570c7d97c5SJed Brown 7580c7d97c5SJed Brown PetscFunctionBegin; 7599566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)NeumannBoundaries)); 76048a46eb9SPierre Jolivet if (pcbddc->NeumannBoundaries) PetscCall(ISEqual(NeumannBoundaries, pcbddc->NeumannBoundaries, &isequal)); 761a5b23f4aSJose E. Roman /* last user setting takes precedence -> destroy any other customization */ 7629566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->NeumannBoundariesLocal)); 7639566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->NeumannBoundaries)); 76436e030ebSStefano Zampini pcbddc->NeumannBoundaries = NeumannBoundaries; 76556282151SStefano Zampini if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 7663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7670c7d97c5SJed Brown } 7681e6b0712SBarry Smith 76957527edcSJed Brown /*@ 77098ad52f2SBarry Smith PCBDDCSetNeumannBoundaries - Set the `IS` defining Neumann boundaries for the global problem. 77157527edcSJed Brown 772c3339decSBarry Smith Collective 77357527edcSJed Brown 77457527edcSJed Brown Input Parameters: 77557527edcSJed Brown + pc - the preconditioning context 77620f4b53cSBarry Smith - NeumannBoundaries - parallel `IS` defining the Neumann boundaries 77757527edcSJed Brown 77857527edcSJed Brown Level: intermediate 77957527edcSJed Brown 780f1580f4eSBarry Smith Note: 7810f202f7eSStefano Zampini Any process can list any global node 78257527edcSJed Brown 783562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetNeumannBoundariesLocal()` 78457527edcSJed Brown @*/ 785d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc, IS NeumannBoundaries) 786d71ae5a4SJacob Faibussowitsch { 7870c7d97c5SJed Brown PetscFunctionBegin; 7880c7d97c5SJed Brown PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 789674ae819SStefano Zampini PetscValidHeaderSpecific(NeumannBoundaries, IS_CLASSID, 2); 790785d1243SStefano Zampini PetscCheckSameComm(pc, 1, NeumannBoundaries, 2); 791cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetNeumannBoundaries_C", (PC, IS), (pc, NeumannBoundaries)); 7923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 79353cdbc3dSStefano Zampini } 7941e6b0712SBarry Smith 795d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetNeumannBoundariesLocal_BDDC(PC pc, IS NeumannBoundaries) 796d71ae5a4SJacob Faibussowitsch { 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)); 80248a46eb9SPierre 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; 8083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8090c7d97c5SJed Brown } 8100c7d97c5SJed Brown 8110c7d97c5SJed Brown /*@ 81298ad52f2SBarry Smith PCBDDCSetNeumannBoundariesLocal - Set the `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 81820f4b53cSBarry Smith - NeumannBoundaries - parallel `IS` defining the subdomain part of Neumann boundaries (in local ordering) 8190c7d97c5SJed Brown 8200c7d97c5SJed Brown Level: intermediate 8210c7d97c5SJed Brown 822562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetNeumannBoundaries()`, `PCBDDCGetDirichletBoundaries()` 8230c7d97c5SJed Brown @*/ 824d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetNeumannBoundariesLocal(PC pc, IS NeumannBoundaries) 825d71ae5a4SJacob Faibussowitsch { 8260c7d97c5SJed Brown PetscFunctionBegin; 8270c7d97c5SJed Brown PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 8280c7d97c5SJed Brown PetscValidHeaderSpecific(NeumannBoundaries, IS_CLASSID, 2); 82982ba6b80SStefano Zampini PetscCheckSameComm(pc, 1, NeumannBoundaries, 2); 830cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetNeumannBoundariesLocal_C", (PC, IS), (pc, NeumannBoundaries)); 8313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 83253cdbc3dSStefano Zampini } 83353cdbc3dSStefano Zampini 834d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCGetDirichletBoundaries_BDDC(PC pc, IS *DirichletBoundaries) 835d71ae5a4SJacob Faibussowitsch { 836da1bb401SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 837da1bb401SStefano Zampini 838da1bb401SStefano Zampini PetscFunctionBegin; 839da1bb401SStefano Zampini *DirichletBoundaries = pcbddc->DirichletBoundaries; 8403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 841da1bb401SStefano Zampini } 8421e6b0712SBarry Smith 843da1bb401SStefano Zampini /*@ 844f1580f4eSBarry Smith PCBDDCGetDirichletBoundaries - Get parallel `IS` for Dirichlet boundaries 845da1bb401SStefano Zampini 846785d1243SStefano Zampini Collective 847785d1243SStefano Zampini 848f1580f4eSBarry Smith Input Parameter: 849785d1243SStefano Zampini . pc - the preconditioning context 850785d1243SStefano Zampini 851f1580f4eSBarry Smith Output Parameter: 852785d1243SStefano Zampini . DirichletBoundaries - index set defining the Dirichlet boundaries 853785d1243SStefano Zampini 854785d1243SStefano Zampini Level: intermediate 855785d1243SStefano Zampini 856f1580f4eSBarry Smith Note: 857f1580f4eSBarry Smith The `IS` returned (if any) is the same passed in earlier by the user with `PCBDDCSetDirichletBoundaries()` 858785d1243SStefano Zampini 859562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetDirichletBoundaries()` 860785d1243SStefano Zampini @*/ 861d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGetDirichletBoundaries(PC pc, IS *DirichletBoundaries) 862d71ae5a4SJacob Faibussowitsch { 863785d1243SStefano Zampini PetscFunctionBegin; 864785d1243SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 865cac4c232SBarry Smith PetscUseMethod(pc, "PCBDDCGetDirichletBoundaries_C", (PC, IS *), (pc, DirichletBoundaries)); 8663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 867785d1243SStefano Zampini } 868785d1243SStefano Zampini 869d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCGetDirichletBoundariesLocal_BDDC(PC pc, IS *DirichletBoundaries) 870d71ae5a4SJacob Faibussowitsch { 871785d1243SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 872785d1243SStefano Zampini 873785d1243SStefano Zampini PetscFunctionBegin; 874785d1243SStefano Zampini *DirichletBoundaries = pcbddc->DirichletBoundariesLocal; 8753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 876785d1243SStefano Zampini } 877785d1243SStefano Zampini 878da1bb401SStefano Zampini /*@ 879f1580f4eSBarry Smith PCBDDCGetDirichletBoundariesLocal - Get parallel `IS` for Dirichlet boundaries (in local ordering) 880da1bb401SStefano Zampini 881785d1243SStefano Zampini Collective 882da1bb401SStefano Zampini 883f1580f4eSBarry Smith Input Parameter: 88428509bceSStefano Zampini . pc - the preconditioning context 885da1bb401SStefano Zampini 886f1580f4eSBarry Smith Output Parameter: 88728509bceSStefano Zampini . DirichletBoundaries - index set defining the subdomain part of Dirichlet boundaries 888da1bb401SStefano Zampini 889da1bb401SStefano Zampini Level: intermediate 890da1bb401SStefano Zampini 891f1580f4eSBarry Smith Note: 892f1580f4eSBarry Smith The `IS` returned could be the same passed in earlier by the user (if provided with `PCBDDCSetDirichletBoundariesLocal()`) 893f1580f4eSBarry Smith or a global-to-local map of the global `IS` (if provided with `PCBDDCSetDirichletBoundaries()`). 894f1580f4eSBarry Smith In the latter case, the `IS` will be available only after `PCSetUp()`. 895da1bb401SStefano Zampini 896562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCGetDirichletBoundaries()`, `PCBDDCSetDirichletBoundaries()` 897da1bb401SStefano Zampini @*/ 898d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGetDirichletBoundariesLocal(PC pc, IS *DirichletBoundaries) 899d71ae5a4SJacob Faibussowitsch { 900da1bb401SStefano Zampini PetscFunctionBegin; 901da1bb401SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 902cac4c232SBarry Smith PetscUseMethod(pc, "PCBDDCGetDirichletBoundariesLocal_C", (PC, IS *), (pc, DirichletBoundaries)); 9033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 904da1bb401SStefano Zampini } 9051e6b0712SBarry Smith 906d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc, IS *NeumannBoundaries) 907d71ae5a4SJacob Faibussowitsch { 90853cdbc3dSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 90953cdbc3dSStefano Zampini 91053cdbc3dSStefano Zampini PetscFunctionBegin; 91153cdbc3dSStefano Zampini *NeumannBoundaries = pcbddc->NeumannBoundaries; 9123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 91353cdbc3dSStefano Zampini } 9141e6b0712SBarry Smith 91553cdbc3dSStefano Zampini /*@ 916f1580f4eSBarry Smith PCBDDCGetNeumannBoundaries - Get parallel `IS` for Neumann boundaries 91753cdbc3dSStefano Zampini 918f1580f4eSBarry Smith Not Collective 919785d1243SStefano Zampini 920f1580f4eSBarry Smith Input Parameter: 921785d1243SStefano Zampini . pc - the preconditioning context 922785d1243SStefano Zampini 923f1580f4eSBarry Smith Output Parameter: 924785d1243SStefano Zampini . NeumannBoundaries - index set defining the Neumann boundaries 925785d1243SStefano Zampini 926785d1243SStefano Zampini Level: intermediate 927785d1243SStefano Zampini 928f1580f4eSBarry Smith Note: 929f1580f4eSBarry Smith The `IS` returned (if any) is the same passed in earlier by the user with `PCBDDCSetNeumannBoundaries()` 930785d1243SStefano Zampini 931562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetNeumannBoundaries()`, `PCBDDCGetDirichletBoundaries()`, `PCBDDCSetDirichletBoundaries()` 932785d1243SStefano Zampini @*/ 933d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc, IS *NeumannBoundaries) 934d71ae5a4SJacob Faibussowitsch { 935785d1243SStefano Zampini PetscFunctionBegin; 936785d1243SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 937cac4c232SBarry Smith PetscUseMethod(pc, "PCBDDCGetNeumannBoundaries_C", (PC, IS *), (pc, NeumannBoundaries)); 9383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 939785d1243SStefano Zampini } 940785d1243SStefano Zampini 941d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCGetNeumannBoundariesLocal_BDDC(PC pc, IS *NeumannBoundaries) 942d71ae5a4SJacob Faibussowitsch { 943785d1243SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 944785d1243SStefano Zampini 945785d1243SStefano Zampini PetscFunctionBegin; 946785d1243SStefano Zampini *NeumannBoundaries = pcbddc->NeumannBoundariesLocal; 9473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 948785d1243SStefano Zampini } 949785d1243SStefano Zampini 95053cdbc3dSStefano Zampini /*@ 951f1580f4eSBarry Smith PCBDDCGetNeumannBoundariesLocal - Get parallel `IS` for Neumann boundaries (in local ordering) 95253cdbc3dSStefano Zampini 953f1580f4eSBarry Smith Not Collective 95453cdbc3dSStefano Zampini 955f1580f4eSBarry Smith Input Parameter: 95628509bceSStefano Zampini . pc - the preconditioning context 95753cdbc3dSStefano Zampini 958f1580f4eSBarry Smith Output Parameter: 95928509bceSStefano Zampini . NeumannBoundaries - index set defining the subdomain part of Neumann boundaries 96053cdbc3dSStefano Zampini 96153cdbc3dSStefano Zampini Level: intermediate 96253cdbc3dSStefano Zampini 963f1580f4eSBarry Smith Note: 964f1580f4eSBarry Smith The `IS` returned could be the same passed in earlier by the user (if provided with `PCBDDCSetNeumannBoundariesLocal()` 965f1580f4eSBarry Smith or a global-to-local map of the global `IS` (if provided with `PCBDDCSetNeumannBoundaries()`). 966f1580f4eSBarry Smith In the latter case, the `IS` will be available after `PCSetUp()`. 96753cdbc3dSStefano Zampini 968562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetNeumannBoundaries()`, `PCBDDCSetNeumannBoundariesLocal)`, `PCBDDCGetNeumannBoundaries()` 96953cdbc3dSStefano Zampini @*/ 970d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGetNeumannBoundariesLocal(PC pc, IS *NeumannBoundaries) 971d71ae5a4SJacob Faibussowitsch { 97253cdbc3dSStefano Zampini PetscFunctionBegin; 97353cdbc3dSStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 974cac4c232SBarry Smith PetscUseMethod(pc, "PCBDDCGetNeumannBoundariesLocal_C", (PC, IS *), (pc, NeumannBoundaries)); 9753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9760c7d97c5SJed Brown } 9771e6b0712SBarry Smith 978d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetLocalAdjacencyGraph_BDDC(PC pc, PetscInt nvtxs, const PetscInt xadj[], const PetscInt adjncy[], PetscCopyMode copymode) 979d71ae5a4SJacob Faibussowitsch { 98036e030ebSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 981da1bb401SStefano Zampini PCBDDCGraph mat_graph = pcbddc->mat_graph; 98256282151SStefano Zampini PetscBool same_data = PETSC_FALSE; 98336e030ebSStefano Zampini 98436e030ebSStefano Zampini PetscFunctionBegin; 9858687889aSStefano Zampini if (!nvtxs) { 98604194a47SStefano Zampini if (copymode == PETSC_OWN_POINTER) { 9879566063dSJacob Faibussowitsch PetscCall(PetscFree(xadj)); 9889566063dSJacob Faibussowitsch PetscCall(PetscFree(adjncy)); 98904194a47SStefano Zampini } 9909566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphResetCSR(mat_graph)); 9913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9928687889aSStefano Zampini } 99366da6bd7Sstefano_zampini if (mat_graph->nvtxs == nvtxs && mat_graph->freecsr) { /* we own the data */ 99456282151SStefano Zampini if (mat_graph->xadj == xadj && mat_graph->adjncy == adjncy) same_data = PETSC_TRUE; 99556282151SStefano Zampini if (!same_data && mat_graph->xadj[nvtxs] == xadj[nvtxs]) { 9969566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(xadj, mat_graph->xadj, nvtxs + 1, &same_data)); 99748a46eb9SPierre Jolivet if (same_data) PetscCall(PetscArraycmp(adjncy, mat_graph->adjncy, xadj[nvtxs], &same_data)); 99856282151SStefano Zampini } 99956282151SStefano Zampini } 100056282151SStefano Zampini if (!same_data) { 1001674ae819SStefano Zampini /* free old CSR */ 10029566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphResetCSR(mat_graph)); 1003674ae819SStefano Zampini /* get CSR into graph structure */ 1004da1bb401SStefano Zampini if (copymode == PETSC_COPY_VALUES) { 10059566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nvtxs + 1, &mat_graph->xadj)); 10069566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(xadj[nvtxs], &mat_graph->adjncy)); 10079566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(mat_graph->xadj, xadj, nvtxs + 1)); 10089566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(mat_graph->adjncy, adjncy, xadj[nvtxs])); 1009a1dbd327SStefano Zampini mat_graph->freecsr = PETSC_TRUE; 1010da1bb401SStefano Zampini } else if (copymode == PETSC_OWN_POINTER) { 10111a83f524SJed Brown mat_graph->xadj = (PetscInt *)xadj; 10121a83f524SJed Brown mat_graph->adjncy = (PetscInt *)adjncy; 1013a1dbd327SStefano Zampini mat_graph->freecsr = PETSC_TRUE; 1014a1dbd327SStefano Zampini } else if (copymode == PETSC_USE_POINTER) { 1015a1dbd327SStefano Zampini mat_graph->xadj = (PetscInt *)xadj; 1016a1dbd327SStefano Zampini mat_graph->adjncy = (PetscInt *)adjncy; 1017a1dbd327SStefano Zampini mat_graph->freecsr = PETSC_FALSE; 101863a3b9bcSJacob Faibussowitsch } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported copy mode %d", copymode); 1019575ad6abSStefano Zampini mat_graph->nvtxs_csr = nvtxs; 102056282151SStefano Zampini pcbddc->recompute_topography = PETSC_TRUE; 102156282151SStefano Zampini } 10223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 102336e030ebSStefano Zampini } 10241e6b0712SBarry Smith 102536e030ebSStefano Zampini /*@ 102654fffbccSStefano Zampini PCBDDCSetLocalAdjacencyGraph - Set adjacency structure (CSR graph) of the local degrees of freedom. 102736e030ebSStefano Zampini 102836e030ebSStefano Zampini Not collective 102936e030ebSStefano Zampini 103036e030ebSStefano Zampini Input Parameters: 103154fffbccSStefano Zampini + pc - the preconditioning context. 103254fffbccSStefano Zampini . nvtxs - number of local vertices of the graph (i.e., the number of local dofs). 103304c3f3b8SBarry Smith . xadj - CSR format row pointers for the connectivity of the dofs 103404c3f3b8SBarry Smith . adjncy - CSR format column pointers for the connectivity of the dofs 1035f1580f4eSBarry Smith - copymode - supported modes are `PETSC_COPY_VALUES`, `PETSC_USE_POINTER` or `PETSC_OWN_POINTER`. 103636e030ebSStefano Zampini 103736e030ebSStefano Zampini Level: intermediate 103836e030ebSStefano Zampini 1039f1580f4eSBarry Smith Note: 104095452b02SPatrick Sanan A dof is considered connected with all local dofs if xadj[dof+1]-xadj[dof] == 1 and adjncy[xadj[dof]] is negative. 104136e030ebSStefano Zampini 1042562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PetscCopyMode` 104336e030ebSStefano Zampini @*/ 1044d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetLocalAdjacencyGraph(PC pc, PetscInt nvtxs, const PetscInt xadj[], const PetscInt adjncy[], PetscCopyMode copymode) 1045d71ae5a4SJacob Faibussowitsch { 10460a545947SLisandro Dalcin void (*f)(void) = NULL; 104736e030ebSStefano Zampini 104836e030ebSStefano Zampini PetscFunctionBegin; 104936e030ebSStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 10508687889aSStefano Zampini if (nvtxs) { 10514f572ea9SToby Isaac PetscAssertPointer(xadj, 3); 10524f572ea9SToby Isaac if (xadj[nvtxs]) PetscAssertPointer(adjncy, 4); 10538687889aSStefano Zampini } 1054cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetLocalAdjacencyGraph_C", (PC, PetscInt, const PetscInt[], const PetscInt[], PetscCopyMode), (pc, nvtxs, xadj, adjncy, copymode)); 1055575ad6abSStefano Zampini /* free arrays if PCBDDC is not the PC type */ 10569566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)pc, "PCBDDCSetLocalAdjacencyGraph_C", &f)); 1057575ad6abSStefano Zampini if (!f && copymode == PETSC_OWN_POINTER) { 10589566063dSJacob Faibussowitsch PetscCall(PetscFree(xadj)); 10599566063dSJacob Faibussowitsch PetscCall(PetscFree(adjncy)); 1060da1bb401SStefano Zampini } 10613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 106236e030ebSStefano Zampini } 10631e6b0712SBarry Smith 1064d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetDofsSplittingLocal_BDDC(PC pc, PetscInt n_is, IS ISForDofs[]) 1065d71ae5a4SJacob Faibussowitsch { 106663602bcaSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 106763602bcaSStefano Zampini PetscInt i; 106856282151SStefano Zampini PetscBool isequal = PETSC_FALSE; 106963602bcaSStefano Zampini 107063602bcaSStefano Zampini PetscFunctionBegin; 107156282151SStefano Zampini if (pcbddc->n_ISForDofsLocal == n_is) { 107256282151SStefano Zampini for (i = 0; i < n_is; i++) { 107356282151SStefano Zampini PetscBool isequalt; 10749566063dSJacob Faibussowitsch PetscCall(ISEqual(ISForDofs[i], pcbddc->ISForDofsLocal[i], &isequalt)); 107556282151SStefano Zampini if (!isequalt) break; 107656282151SStefano Zampini } 107756282151SStefano Zampini if (i == n_is) isequal = PETSC_TRUE; 107856282151SStefano Zampini } 107948a46eb9SPierre Jolivet for (i = 0; i < n_is; i++) PetscCall(PetscObjectReference((PetscObject)ISForDofs[i])); 108063602bcaSStefano Zampini /* Destroy ISes if they were already set */ 108148a46eb9SPierre Jolivet for (i = 0; i < pcbddc->n_ISForDofsLocal; i++) PetscCall(ISDestroy(&pcbddc->ISForDofsLocal[i])); 10829566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->ISForDofsLocal)); 1083a5b23f4aSJose E. Roman /* last user setting takes precedence -> destroy any other customization */ 108448a46eb9SPierre Jolivet for (i = 0; i < pcbddc->n_ISForDofs; i++) PetscCall(ISDestroy(&pcbddc->ISForDofs[i])); 10859566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->ISForDofs)); 108663602bcaSStefano Zampini pcbddc->n_ISForDofs = 0; 108763602bcaSStefano Zampini /* allocate space then set */ 108848a46eb9SPierre Jolivet if (n_is) PetscCall(PetscMalloc1(n_is, &pcbddc->ISForDofsLocal)); 1089ad540459SPierre Jolivet for (i = 0; i < n_is; i++) pcbddc->ISForDofsLocal[i] = ISForDofs[i]; 109063602bcaSStefano Zampini pcbddc->n_ISForDofsLocal = n_is; 109163602bcaSStefano Zampini if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE; 109256282151SStefano Zampini if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 10933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 109463602bcaSStefano Zampini } 109563602bcaSStefano Zampini 109663602bcaSStefano Zampini /*@ 109798ad52f2SBarry Smith PCBDDCSetDofsSplittingLocal - Set the `IS` defining fields of the local subdomain matrix 109863602bcaSStefano Zampini 109963602bcaSStefano Zampini Collective 110063602bcaSStefano Zampini 110163602bcaSStefano Zampini Input Parameters: 110263602bcaSStefano Zampini + pc - the preconditioning context 110398ad52f2SBarry Smith . n_is - number of index sets defining the fields, must be the same on all MPI processes 1104f1580f4eSBarry Smith - ISForDofs - array of `IS` describing the fields in local ordering 110563602bcaSStefano Zampini 110663602bcaSStefano Zampini Level: intermediate 110763602bcaSStefano Zampini 1108f1580f4eSBarry Smith Note: 1109feefa0e1SJacob Faibussowitsch Not all nodes need to be listed, unlisted nodes will belong to the complement field. 111063602bcaSStefano Zampini 1111562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetDofsSplitting()` 111263602bcaSStefano Zampini @*/ 1113d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetDofsSplittingLocal(PC pc, PetscInt n_is, IS ISForDofs[]) 1114d71ae5a4SJacob Faibussowitsch { 111563602bcaSStefano Zampini PetscInt i; 111663602bcaSStefano Zampini 111763602bcaSStefano Zampini PetscFunctionBegin; 111863602bcaSStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 111963602bcaSStefano Zampini PetscValidLogicalCollectiveInt(pc, n_is, 2); 112063602bcaSStefano Zampini for (i = 0; i < n_is; i++) { 112163602bcaSStefano Zampini PetscCheckSameComm(pc, 1, ISForDofs[i], 3); 112263602bcaSStefano Zampini PetscValidHeaderSpecific(ISForDofs[i], IS_CLASSID, 3); 112363602bcaSStefano Zampini } 1124cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetDofsSplittingLocal_C", (PC, PetscInt, IS[]), (pc, n_is, ISForDofs)); 11253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 112663602bcaSStefano Zampini } 112763602bcaSStefano Zampini 1128d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc, PetscInt n_is, IS ISForDofs[]) 1129d71ae5a4SJacob Faibussowitsch { 11309c0446d6SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 11319c0446d6SStefano Zampini PetscInt i; 113256282151SStefano Zampini PetscBool isequal = PETSC_FALSE; 11339c0446d6SStefano Zampini 11349c0446d6SStefano Zampini PetscFunctionBegin; 113556282151SStefano Zampini if (pcbddc->n_ISForDofs == n_is) { 113656282151SStefano Zampini for (i = 0; i < n_is; i++) { 113756282151SStefano Zampini PetscBool isequalt; 11389566063dSJacob Faibussowitsch PetscCall(ISEqual(ISForDofs[i], pcbddc->ISForDofs[i], &isequalt)); 113956282151SStefano Zampini if (!isequalt) break; 114056282151SStefano Zampini } 114156282151SStefano Zampini if (i == n_is) isequal = PETSC_TRUE; 114256282151SStefano Zampini } 114348a46eb9SPierre Jolivet for (i = 0; i < n_is; i++) PetscCall(PetscObjectReference((PetscObject)ISForDofs[i])); 1144da1bb401SStefano Zampini /* Destroy ISes if they were already set */ 114548a46eb9SPierre Jolivet for (i = 0; i < pcbddc->n_ISForDofs; i++) PetscCall(ISDestroy(&pcbddc->ISForDofs[i])); 11469566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->ISForDofs)); 1147a5b23f4aSJose E. Roman /* last user setting takes precedence -> destroy any other customization */ 114848a46eb9SPierre Jolivet for (i = 0; i < pcbddc->n_ISForDofsLocal; i++) PetscCall(ISDestroy(&pcbddc->ISForDofsLocal[i])); 11499566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->ISForDofsLocal)); 115063602bcaSStefano Zampini pcbddc->n_ISForDofsLocal = 0; 1151da1bb401SStefano Zampini /* allocate space then set */ 115248a46eb9SPierre Jolivet if (n_is) PetscCall(PetscMalloc1(n_is, &pcbddc->ISForDofs)); 1153ad540459SPierre Jolivet for (i = 0; i < n_is; i++) pcbddc->ISForDofs[i] = ISForDofs[i]; 11549c0446d6SStefano Zampini pcbddc->n_ISForDofs = n_is; 115563602bcaSStefano Zampini if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE; 115656282151SStefano Zampini if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 11573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11589c0446d6SStefano Zampini } 11591e6b0712SBarry Smith 11609c0446d6SStefano Zampini /*@ 116198ad52f2SBarry Smith PCBDDCSetDofsSplitting - Set the `IS` defining fields of the global matrix 11629c0446d6SStefano Zampini 116363602bcaSStefano Zampini Collective 11649c0446d6SStefano Zampini 11659c0446d6SStefano Zampini Input Parameters: 11669c0446d6SStefano Zampini + pc - the preconditioning context 11670f202f7eSStefano Zampini . n_is - number of index sets defining the fields 116898ad52f2SBarry Smith - ISForDofs - array of `IS` describing the fields in global ordering 11699c0446d6SStefano Zampini 11709c0446d6SStefano Zampini Level: intermediate 11719c0446d6SStefano Zampini 1172f1580f4eSBarry Smith Note: 11730f202f7eSStefano Zampini Any process can list any global node. Not all nodes need to be listed: unlisted nodes will belong to the complement field. 11749c0446d6SStefano Zampini 1175562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetDofsSplittingLocal()` 11769c0446d6SStefano Zampini @*/ 1177d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetDofsSplitting(PC pc, PetscInt n_is, IS ISForDofs[]) 1178d71ae5a4SJacob Faibussowitsch { 11792b510759SStefano Zampini PetscInt i; 11809c0446d6SStefano Zampini 11819c0446d6SStefano Zampini PetscFunctionBegin; 11829c0446d6SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 118363602bcaSStefano Zampini PetscValidLogicalCollectiveInt(pc, n_is, 2); 11842b510759SStefano Zampini for (i = 0; i < n_is; i++) { 118563602bcaSStefano Zampini PetscValidHeaderSpecific(ISForDofs[i], IS_CLASSID, 3); 1186a011d5a7Sstefano_zampini PetscCheckSameComm(pc, 1, ISForDofs[i], 3); 11872b510759SStefano Zampini } 1188cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetDofsSplitting_C", (PC, PetscInt, IS[]), (pc, n_is, ISForDofs)); 11893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11909c0446d6SStefano Zampini } 1191906d46d4SStefano Zampini 1192d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCPreSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x) 1193d71ae5a4SJacob Faibussowitsch { 1194534831adSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 1195*f4f49eeaSPierre Jolivet PC_IS *pcis = (PC_IS *)pc->data; 11963972b0daSStefano Zampini Vec used_vec; 1197fcb54b1cSPierre Jolivet PetscBool iscg, save_rhs = PETSC_TRUE, benign_correction_computed; 1198534831adSStefano Zampini 1199534831adSStefano Zampini PetscFunctionBegin; 12001f4df5f7SStefano Zampini /* if we are working with CG, one dirichlet solve can be avoided during Krylov iterations */ 120185c4d303SStefano Zampini if (ksp) { 1202fcb54b1cSPierre Jolivet PetscCall(PetscObjectTypeCompareAny((PetscObject)ksp, &iscg, KSPCG, KSPGROPPCG, KSPPIPECG, KSPPIPELCG, KSPPIPECGRR, "")); 120348a46eb9SPierre Jolivet if (pcbddc->benign_apply_coarse_only || pcbddc->switch_static || !iscg || pc->mat != pc->pmat) PetscCall(PCBDDCSetUseExactDirichlet(pc, PETSC_FALSE)); 120485c4d303SStefano Zampini } 120548a46eb9SPierre Jolivet if (pcbddc->benign_apply_coarse_only || pcbddc->switch_static || pc->mat != pc->pmat) PetscCall(PCBDDCSetUseExactDirichlet(pc, PETSC_FALSE)); 12061f4df5f7SStefano Zampini 120785c4d303SStefano Zampini /* Creates parallel work vectors used in presolve */ 120848a46eb9SPierre Jolivet if (!pcbddc->original_rhs) PetscCall(VecDuplicate(pcis->vec1_global, &pcbddc->original_rhs)); 120948a46eb9SPierre Jolivet if (!pcbddc->temp_solution) PetscCall(VecDuplicate(pcis->vec1_global, &pcbddc->temp_solution)); 12108d00608fSStefano Zampini 121127b6a85dSStefano Zampini pcbddc->temp_solution_used = PETSC_FALSE; 12123972b0daSStefano Zampini if (x) { 12139566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)x)); 12143972b0daSStefano Zampini used_vec = x; 12158d00608fSStefano Zampini } else { /* it can only happen when calling PCBDDCMatFETIDPGetRHS */ 12169566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)pcbddc->temp_solution)); 12173972b0daSStefano Zampini used_vec = pcbddc->temp_solution; 12189566063dSJacob Faibussowitsch PetscCall(VecSet(used_vec, 0.0)); 121927b6a85dSStefano Zampini pcbddc->temp_solution_used = PETSC_TRUE; 12209566063dSJacob Faibussowitsch PetscCall(VecCopy(rhs, pcbddc->original_rhs)); 1221266e20e9SStefano Zampini save_rhs = PETSC_FALSE; 1222266e20e9SStefano Zampini pcbddc->eliminate_dirdofs = PETSC_TRUE; 12233972b0daSStefano Zampini } 12248efcfb23SStefano Zampini 12258efcfb23SStefano Zampini /* hack into ksp data structure since PCPreSolve comes earlier than setting to zero the guess in src/ksp/ksp/interface/itfunc.c */ 12263972b0daSStefano Zampini if (ksp) { 1227a0cb1b98SStefano Zampini /* store the flag for the initial guess since it will be restored back during PCPostSolve_BDDC */ 12289566063dSJacob Faibussowitsch PetscCall(KSPGetInitialGuessNonzero(ksp, &pcbddc->ksp_guess_nonzero)); 122948a46eb9SPierre Jolivet if (!pcbddc->ksp_guess_nonzero) PetscCall(VecSet(used_vec, 0.0)); 12303972b0daSStefano Zampini } 12313308cffdSStefano Zampini 12328d00608fSStefano Zampini pcbddc->rhs_change = PETSC_FALSE; 12333972b0daSStefano Zampini /* Take into account zeroed rows -> change rhs and store solution removed */ 123470c64980SStefano Zampini if (rhs && pcbddc->eliminate_dirdofs) { 12353975b054SStefano Zampini IS dirIS = NULL; 12363975b054SStefano Zampini 1237a07ea27aSStefano Zampini /* DirichletBoundariesLocal may not be consistent among neighbours; gets a dirichlet dofs IS from graph (may be cached) */ 12389566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph, &dirIS)); 12393975b054SStefano Zampini if (dirIS) { 1240906d46d4SStefano Zampini Mat_IS *matis = (Mat_IS *)pc->pmat->data; 1241785d1243SStefano Zampini PetscInt dirsize, i, *is_indices; 12422b095fd8SStefano Zampini PetscScalar *array_x; 12432b095fd8SStefano Zampini const PetscScalar *array_diagonal; 1244785d1243SStefano Zampini 12459566063dSJacob Faibussowitsch PetscCall(MatGetDiagonal(pc->pmat, pcis->vec1_global)); 12469566063dSJacob Faibussowitsch PetscCall(VecPointwiseDivide(pcis->vec1_global, rhs, pcis->vec1_global)); 12479566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx, pcis->vec1_global, pcis->vec2_N, INSERT_VALUES, SCATTER_FORWARD)); 12489566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx, pcis->vec1_global, pcis->vec2_N, INSERT_VALUES, SCATTER_FORWARD)); 12499566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx, used_vec, pcis->vec1_N, INSERT_VALUES, SCATTER_FORWARD)); 12509566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx, used_vec, pcis->vec1_N, INSERT_VALUES, SCATTER_FORWARD)); 12519566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(dirIS, &dirsize)); 12529566063dSJacob Faibussowitsch PetscCall(VecGetArray(pcis->vec1_N, &array_x)); 12539566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(pcis->vec2_N, &array_diagonal)); 12549566063dSJacob Faibussowitsch PetscCall(ISGetIndices(dirIS, (const PetscInt **)&is_indices)); 12552fa5cd67SKarl Rupp for (i = 0; i < dirsize; i++) array_x[is_indices[i]] = array_diagonal[is_indices[i]]; 12569566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(dirIS, (const PetscInt **)&is_indices)); 12579566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(pcis->vec2_N, &array_diagonal)); 12589566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(pcis->vec1_N, &array_x)); 12599566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx, pcis->vec1_N, used_vec, INSERT_VALUES, SCATTER_REVERSE)); 12609566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx, pcis->vec1_N, used_vec, INSERT_VALUES, SCATTER_REVERSE)); 12618d00608fSStefano Zampini pcbddc->rhs_change = PETSC_TRUE; 12629566063dSJacob Faibussowitsch PetscCall(ISDestroy(&dirIS)); 12638efcfb23SStefano Zampini } 1264a07ea27aSStefano Zampini } 1265b76ba322SStefano Zampini 12668efcfb23SStefano Zampini /* remove the computed solution or the initial guess from the rhs */ 12678d00608fSStefano Zampini if (pcbddc->rhs_change || (ksp && pcbddc->ksp_guess_nonzero)) { 126827b6a85dSStefano Zampini /* save the original rhs */ 126927b6a85dSStefano Zampini if (save_rhs) { 12709566063dSJacob Faibussowitsch PetscCall(VecSwap(rhs, pcbddc->original_rhs)); 127127b6a85dSStefano Zampini save_rhs = PETSC_FALSE; 12728d00608fSStefano Zampini } 12738d00608fSStefano Zampini pcbddc->rhs_change = PETSC_TRUE; 12749566063dSJacob Faibussowitsch PetscCall(VecScale(used_vec, -1.0)); 12759566063dSJacob Faibussowitsch PetscCall(MatMultAdd(pc->mat, used_vec, pcbddc->original_rhs, rhs)); 12769566063dSJacob Faibussowitsch PetscCall(VecScale(used_vec, -1.0)); 12779566063dSJacob Faibussowitsch PetscCall(VecCopy(used_vec, pcbddc->temp_solution)); 127827b6a85dSStefano Zampini pcbddc->temp_solution_used = PETSC_TRUE; 12791baa6e33SBarry Smith if (ksp) PetscCall(KSPSetInitialGuessNonzero(ksp, PETSC_FALSE)); 12803308cffdSStefano Zampini } 12819566063dSJacob Faibussowitsch PetscCall(VecDestroy(&used_vec)); 1282b76ba322SStefano Zampini 1283fc17d649SStefano Zampini /* compute initial vector in benign space if needed 128427b6a85dSStefano Zampini and remove non-benign solution from the rhs */ 128527b6a85dSStefano Zampini benign_correction_computed = PETSC_FALSE; 128608af2428SStefano Zampini if (rhs && pcbddc->benign_compute_correction && (pcbddc->benign_have_null || pcbddc->benign_apply_coarse_only)) { 12871f4df5f7SStefano Zampini /* compute u^*_h using ideas similar to those in Xuemin Tu's PhD thesis (see Section 4.8.1) 12881f4df5f7SStefano Zampini Recursively apply BDDC in the multilevel case */ 128948a46eb9SPierre Jolivet if (!pcbddc->benign_vec) PetscCall(VecDuplicate(rhs, &pcbddc->benign_vec)); 1290c69e9cc1SStefano Zampini /* keep applying coarse solver unless we no longer have benign subdomains */ 1291c69e9cc1SStefano Zampini pcbddc->benign_apply_coarse_only = pcbddc->benign_have_null ? PETSC_TRUE : PETSC_FALSE; 129227b6a85dSStefano Zampini if (!pcbddc->benign_skip_correction) { 12939566063dSJacob Faibussowitsch PetscCall(PCApply_BDDC(pc, rhs, pcbddc->benign_vec)); 12943bca92a6SStefano Zampini benign_correction_computed = PETSC_TRUE; 12951baa6e33SBarry Smith if (pcbddc->temp_solution_used) PetscCall(VecAXPY(pcbddc->temp_solution, 1.0, pcbddc->benign_vec)); 12969566063dSJacob Faibussowitsch PetscCall(VecScale(pcbddc->benign_vec, -1.0)); 129727b6a85dSStefano Zampini /* store the original rhs if not done earlier */ 12981baa6e33SBarry Smith if (save_rhs) PetscCall(VecSwap(rhs, pcbddc->original_rhs)); 129927b6a85dSStefano Zampini if (pcbddc->rhs_change) { 13009566063dSJacob Faibussowitsch PetscCall(MatMultAdd(pc->mat, pcbddc->benign_vec, rhs, rhs)); 130127b6a85dSStefano Zampini } else { 13029566063dSJacob Faibussowitsch PetscCall(MatMultAdd(pc->mat, pcbddc->benign_vec, pcbddc->original_rhs, rhs)); 130327b6a85dSStefano Zampini } 13040369aaf7SStefano Zampini pcbddc->rhs_change = PETSC_TRUE; 130527b6a85dSStefano Zampini } 130627b6a85dSStefano Zampini pcbddc->benign_apply_coarse_only = PETSC_FALSE; 13074df7a6bfSStefano Zampini } else { 13089566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->benign_vec)); 13090369aaf7SStefano Zampini } 13102d4c4fecSStefano Zampini 13112d4c4fecSStefano Zampini /* dbg output */ 1312a198735bSStefano Zampini if (pcbddc->dbg_flag && benign_correction_computed) { 13131f4df5f7SStefano Zampini Vec v; 1314c69e9cc1SStefano Zampini 13159566063dSJacob Faibussowitsch PetscCall(VecDuplicate(pcis->vec1_global, &v)); 1316c69e9cc1SStefano Zampini if (pcbddc->ChangeOfBasisMatrix) { 13179566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, rhs, v)); 1318c69e9cc1SStefano Zampini } else { 13199566063dSJacob Faibussowitsch PetscCall(VecCopy(rhs, v)); 1320c69e9cc1SStefano Zampini } 13219566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignGetOrSetP0(pc, v, PETSC_TRUE)); 132263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "LEVEL %" PetscInt_FMT ": is the correction benign?\n", pcbddc->current_level)); 13239566063dSJacob Faibussowitsch PetscCall(PetscScalarView(pcbddc->benign_n, pcbddc->benign_p0, pcbddc->dbg_viewer)); 13249566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 13259566063dSJacob Faibussowitsch PetscCall(VecDestroy(&v)); 13261f4df5f7SStefano Zampini } 13270369aaf7SStefano Zampini 13280369aaf7SStefano Zampini /* set initial guess if using PCG */ 13298ae0ca82SStefano Zampini pcbddc->exact_dirichlet_trick_app = PETSC_FALSE; 13300369aaf7SStefano Zampini if (x && pcbddc->use_exact_dirichlet_trick) { 13319566063dSJacob Faibussowitsch PetscCall(VecSet(x, 0.0)); 13321dd7afcfSStefano Zampini if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) { 133327b6a85dSStefano Zampini if (benign_correction_computed) { /* we have already saved the changed rhs */ 13349566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(pcis->vec1_global)); 13351dd7afcfSStefano Zampini } else { 13369566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, rhs, pcis->vec1_global)); 13371dd7afcfSStefano Zampini } 13389566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec1_global, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD)); 13399566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec1_global, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD)); 13401dd7afcfSStefano Zampini } else { 13419566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, rhs, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD)); 13429566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, rhs, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD)); 13431dd7afcfSStefano Zampini } 13449566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0)); 13459566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_D, pcis->vec1_D, pcis->vec2_D)); 13469566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0)); 13479566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec2_D)); 13481dd7afcfSStefano Zampini if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) { 13499566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_global, 0.)); 13509566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec2_D, pcis->vec1_global, INSERT_VALUES, SCATTER_REVERSE)); 13519566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec2_D, pcis->vec1_global, INSERT_VALUES, SCATTER_REVERSE)); 13529566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix, pcis->vec1_global, x)); 13531dd7afcfSStefano Zampini } else { 13549566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec2_D, x, INSERT_VALUES, SCATTER_REVERSE)); 13559566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec2_D, x, INSERT_VALUES, SCATTER_REVERSE)); 13561dd7afcfSStefano Zampini } 13571baa6e33SBarry Smith if (ksp) PetscCall(KSPSetInitialGuessNonzero(ksp, PETSC_TRUE)); 13588ae0ca82SStefano Zampini pcbddc->exact_dirichlet_trick_app = PETSC_TRUE; 1359266e20e9SStefano Zampini } else if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior && benign_correction_computed && pcbddc->use_exact_dirichlet_trick) { 13609566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(pcis->vec1_global)); 13610369aaf7SStefano Zampini } 13623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1363534831adSStefano Zampini } 1364906d46d4SStefano Zampini 1365d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCPostSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x) 1366d71ae5a4SJacob Faibussowitsch { 1367534831adSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 1368534831adSStefano Zampini 1369534831adSStefano Zampini PetscFunctionBegin; 13703972b0daSStefano Zampini /* add solution removed in presolve */ 13716bcfc461SStefano Zampini if (x && pcbddc->rhs_change) { 137227b6a85dSStefano Zampini if (pcbddc->temp_solution_used) { 13739566063dSJacob Faibussowitsch PetscCall(VecAXPY(x, 1.0, pcbddc->temp_solution)); 1374af140850Sstefano_zampini } else if (pcbddc->benign_compute_correction && pcbddc->benign_vec) { 13759566063dSJacob Faibussowitsch PetscCall(VecAXPY(x, -1.0, pcbddc->benign_vec)); 13763425bc38SStefano Zampini } 1377af140850Sstefano_zampini /* restore to original state (not for FETI-DP) */ 1378af140850Sstefano_zampini if (ksp) pcbddc->temp_solution_used = PETSC_FALSE; 137927b6a85dSStefano Zampini } 138027b6a85dSStefano Zampini 1381266e20e9SStefano Zampini /* restore rhs to its original state (not needed for FETI-DP) */ 13828d00608fSStefano Zampini if (rhs && pcbddc->rhs_change) { 13839566063dSJacob Faibussowitsch PetscCall(VecSwap(rhs, pcbddc->original_rhs)); 13848d00608fSStefano Zampini pcbddc->rhs_change = PETSC_FALSE; 1385af140850Sstefano_zampini } 13868efcfb23SStefano Zampini /* restore ksp guess state */ 13878efcfb23SStefano Zampini if (ksp) { 13889566063dSJacob Faibussowitsch PetscCall(KSPSetInitialGuessNonzero(ksp, pcbddc->ksp_guess_nonzero)); 13898ae0ca82SStefano Zampini /* reset flag for exact dirichlet trick */ 13908ae0ca82SStefano Zampini pcbddc->exact_dirichlet_trick_app = PETSC_FALSE; 1391af140850Sstefano_zampini } 13923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1393534831adSStefano Zampini } 1394af140850Sstefano_zampini 139566976f2fSJacob Faibussowitsch static PetscErrorCode PCSetUp_BDDC(PC pc) 1396d71ae5a4SJacob Faibussowitsch { 13970c7d97c5SJed Brown PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 1398c703fcc7SStefano Zampini PCBDDCSubSchurs sub_schurs; 13995e8657edSStefano Zampini Mat_IS *matis; 140008122e43SStefano Zampini MatNullSpace nearnullspace; 140135509ce9Sstefano_zampini Mat lA; 140235509ce9Sstefano_zampini IS lP, zerodiag = NULL; 140391e8d312SStefano Zampini PetscInt nrows, ncols; 140486bfa4cfSStefano Zampini PetscMPIInt size; 1405c703fcc7SStefano Zampini PetscBool computesubschurs; 14068de1fae6SStefano Zampini PetscBool computeconstraintsmatrix; 14073b03f7bbSStefano Zampini PetscBool new_nearnullspace_provided, ismatis, rl; 1408b94d7dedSBarry Smith PetscBool isset, issym, isspd; 14090c7d97c5SJed Brown 14100c7d97c5SJed Brown PetscFunctionBegin; 14119566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATIS, &ismatis)); 141228b400f6SJacob Faibussowitsch PetscCheck(ismatis, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "PCBDDC preconditioner requires matrix of type MATIS"); 14139566063dSJacob Faibussowitsch PetscCall(MatGetSize(pc->pmat, &nrows, &ncols)); 14147827d75bSBarry Smith PetscCheck(nrows == ncols, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "PCBDDC preconditioner requires a square preconditioning matrix"); 14159566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc), &size)); 141686bfa4cfSStefano Zampini 14175e8657edSStefano Zampini matis = (Mat_IS *)pc->pmat->data; 1418f4ddd8eeSStefano Zampini /* the following lines of code should be replaced by a better logic between PCIS, PCNN, PCBDDC and other future nonoverlapping preconditioners */ 14193b03a366Sstefano_zampini /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup 142071582508SStefano Zampini Also, BDDC builds its own KSP for the Dirichlet problem */ 14213b03f7bbSStefano Zampini rl = pcbddc->recompute_topography; 14223b03f7bbSStefano Zampini if (!pc->setupcalled || pc->flag == DIFFERENT_NONZERO_PATTERN) rl = PETSC_TRUE; 14231c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&rl, &pcbddc->recompute_topography, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)pc))); 1424c83e1ba7SStefano Zampini if (pcbddc->recompute_topography) { 1425c83e1ba7SStefano Zampini pcbddc->graphanalyzed = PETSC_FALSE; 1426c83e1ba7SStefano Zampini computeconstraintsmatrix = PETSC_TRUE; 1427c83e1ba7SStefano Zampini } else { 14288de1fae6SStefano Zampini computeconstraintsmatrix = PETSC_FALSE; 1429c83e1ba7SStefano Zampini } 1430b087196eSStefano Zampini 1431b087196eSStefano Zampini /* check parameters' compatibility */ 1432b7ab4a40SStefano Zampini if (!pcbddc->use_deluxe_scaling) pcbddc->deluxe_zerorows = PETSC_FALSE; 1433bd2a564bSStefano Zampini pcbddc->adaptive_selection = (PetscBool)(pcbddc->adaptive_threshold[0] != 0.0 || pcbddc->adaptive_threshold[1] != 0.0); 143486bfa4cfSStefano Zampini pcbddc->use_deluxe_scaling = (PetscBool)(pcbddc->use_deluxe_scaling && size > 1); 143586bfa4cfSStefano Zampini pcbddc->adaptive_selection = (PetscBool)(pcbddc->adaptive_selection && size > 1); 1436bf3a8328SStefano Zampini pcbddc->adaptive_userdefined = (PetscBool)(pcbddc->adaptive_selection && pcbddc->adaptive_userdefined); 1437862806e4SStefano Zampini if (pcbddc->adaptive_selection) pcbddc->use_faces = PETSC_TRUE; 1438862806e4SStefano Zampini 14395a95e1ceSStefano Zampini computesubschurs = (PetscBool)(pcbddc->adaptive_selection || pcbddc->use_deluxe_scaling); 144016909a7fSStefano Zampini 144171582508SStefano Zampini /* activate all connected components if the netflux has been requested */ 1442bb05f991SStefano Zampini if (pcbddc->compute_nonetflux) { 1443bb05f991SStefano Zampini pcbddc->use_vertices = PETSC_TRUE; 1444bb05f991SStefano Zampini pcbddc->use_edges = PETSC_TRUE; 1445bb05f991SStefano Zampini pcbddc->use_faces = PETSC_TRUE; 1446bb05f991SStefano Zampini } 1447bb05f991SStefano Zampini 1448f4ddd8eeSStefano Zampini /* Get stdout for dbg */ 144970cf5478SStefano Zampini if (pcbddc->dbg_flag) { 1450ad540459SPierre Jolivet if (!pcbddc->dbg_viewer) pcbddc->dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pc)); 14519566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 14529566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIAddTab(pcbddc->dbg_viewer, 2 * pcbddc->current_level)); 1453f4ddd8eeSStefano Zampini } 1454f4ddd8eeSStefano Zampini 1455c703fcc7SStefano Zampini /* process topology information */ 14569566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Topology[pcbddc->current_level], pc, 0, 0, 0)); 145771582508SStefano Zampini if (pcbddc->recompute_topography) { 14589566063dSJacob Faibussowitsch PetscCall(PCBDDCComputeLocalTopologyInfo(pc)); 14591baa6e33SBarry Smith if (pcbddc->discretegradient) PetscCall(PCBDDCNedelecSupport(pc)); 1460c703fcc7SStefano Zampini } 14614f819b78SStefano Zampini if (pcbddc->corner_selected) pcbddc->use_vertices = PETSC_TRUE; 1462a13144ffSStefano Zampini 1463c703fcc7SStefano Zampini /* change basis if requested by the user */ 14645e8657edSStefano Zampini if (pcbddc->user_ChangeOfBasisMatrix) { 14655e8657edSStefano Zampini /* use_change_of_basis flag is used to automatically compute a change of basis from constraints */ 14665e8657edSStefano Zampini pcbddc->use_change_of_basis = PETSC_FALSE; 14679566063dSJacob Faibussowitsch PetscCall(PCBDDCComputeLocalMatrix(pc, pcbddc->user_ChangeOfBasisMatrix)); 14685e8657edSStefano Zampini } else { 14699566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_mat)); 14709566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)matis->A)); 14715e8657edSStefano Zampini pcbddc->local_mat = matis->A; 1472d16cbb6bSStefano Zampini } 1473d16cbb6bSStefano Zampini 14744f1b2e48SStefano Zampini /* 1475c703fcc7SStefano Zampini Compute change of basis on local pressures (aka zerodiag dofs) with the benign trick 14764f1b2e48SStefano Zampini This should come earlier then PCISSetUp for extracting the correct subdomain matrices 14774f1b2e48SStefano Zampini */ 14789566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignShellMat(pc, PETSC_TRUE)); 1479d16cbb6bSStefano Zampini if (pcbddc->benign_saddle_point) { 14809f47a83aSStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 14819f47a83aSStefano Zampini 148205b28244SStefano Zampini if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->use_change_of_basis || !computesubschurs) pcbddc->benign_change_explicit = PETSC_TRUE; 14833b03f7bbSStefano Zampini /* detect local saddle point and change the basis in pcbddc->local_mat */ 14849566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignDetectSaddlePoint(pc, (PetscBool)(!pcbddc->recompute_topography), &zerodiag)); 1485a3df083aSStefano Zampini /* pop B0 mat from local mat */ 14869566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignPopOrPushB0(pc, PETSC_TRUE)); 14871dd7afcfSStefano Zampini /* give pcis a hint to not reuse submatrices during PCISCreate */ 14881dd7afcfSStefano Zampini if (pc->flag == SAME_NONZERO_PATTERN && pcis->reusesubmatrices == PETSC_TRUE) { 14891dd7afcfSStefano Zampini if (pcbddc->benign_n && (pcbddc->benign_change_explicit || pcbddc->dbg_flag)) { 14901dd7afcfSStefano Zampini pcis->reusesubmatrices = PETSC_FALSE; 14911dd7afcfSStefano Zampini } else { 1492a3df083aSStefano Zampini pcis->reusesubmatrices = PETSC_TRUE; 14931dd7afcfSStefano Zampini } 1494a3df083aSStefano Zampini } else { 14959f47a83aSStefano Zampini pcis->reusesubmatrices = PETSC_FALSE; 1496674ae819SStefano Zampini } 1497a3df083aSStefano Zampini } 149827b6a85dSStefano Zampini 14998037d520SStefano Zampini /* propagate relevant information */ 1500b94d7dedSBarry Smith PetscCall(MatIsSymmetricKnown(matis->A, &isset, &issym)); 1501b94d7dedSBarry Smith if (isset) PetscCall(MatSetOption(pcbddc->local_mat, MAT_SYMMETRIC, issym)); 1502b94d7dedSBarry Smith PetscCall(MatIsSPDKnown(matis->A, &isset, &isspd)); 1503b94d7dedSBarry Smith if (isset) PetscCall(MatSetOption(pcbddc->local_mat, MAT_SPD, isspd)); 1504e496cd5dSStefano Zampini 15055e8657edSStefano Zampini /* Set up all the "iterative substructuring" common block without computing solvers */ 15065e8657edSStefano Zampini { 15075e8657edSStefano Zampini Mat temp_mat; 15085e8657edSStefano Zampini 15095e8657edSStefano Zampini temp_mat = matis->A; 15105e8657edSStefano Zampini matis->A = pcbddc->local_mat; 15119566063dSJacob Faibussowitsch PetscCall(PCISSetUp(pc, PETSC_TRUE, PETSC_FALSE)); 15125e8657edSStefano Zampini pcbddc->local_mat = matis->A; 15135e8657edSStefano Zampini matis->A = temp_mat; 15145e8657edSStefano Zampini } 1515684f6988SStefano Zampini 151681d14e9dSStefano Zampini /* Analyze interface */ 151764ac59b8SStefano Zampini if (!pcbddc->graphanalyzed) { 15189566063dSJacob Faibussowitsch PetscCall(PCBDDCAnalyzeInterface(pc)); 15198de1fae6SStefano Zampini computeconstraintsmatrix = PETSC_TRUE; 15200fdf79fbSJacob Faibussowitsch PetscCheck(!(pcbddc->adaptive_selection && !pcbddc->use_deluxe_scaling && !pcbddc->mat_graph->twodim), PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Cannot compute the adaptive primal space for a problem with 3D edges without deluxe scaling"); 1521a198735bSStefano Zampini if (pcbddc->compute_nonetflux) { 1522669cc0f4SStefano Zampini MatNullSpace nnfnnsp; 1523669cc0f4SStefano Zampini 152428b400f6SJacob Faibussowitsch PetscCheck(pcbddc->divudotp, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Missing divudotp operator"); 15259566063dSJacob Faibussowitsch PetscCall(PCBDDCComputeNoNetFlux(pc->pmat, pcbddc->divudotp, pcbddc->divudotp_trans, pcbddc->divudotp_vl2l, pcbddc->mat_graph, &nnfnnsp)); 152671582508SStefano Zampini /* TODO what if a nearnullspace is already attached? */ 15278037d520SStefano Zampini if (nnfnnsp) { 15289566063dSJacob Faibussowitsch PetscCall(MatSetNearNullSpace(pc->pmat, nnfnnsp)); 15299566063dSJacob Faibussowitsch PetscCall(MatNullSpaceDestroy(&nnfnnsp)); 1530669cc0f4SStefano Zampini } 1531674ae819SStefano Zampini } 15328037d520SStefano Zampini } 15339566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Topology[pcbddc->current_level], pc, 0, 0, 0)); 1534fb8d54d4SStefano Zampini 15355408967cSStefano Zampini /* check existence of a divergence free extension, i.e. 15365408967cSStefano Zampini b(v_I,p_0) = 0 for all v_I (raise error if not). 15375408967cSStefano Zampini Also, check that PCBDDCBenignGetOrSetP0 works */ 153848a46eb9SPierre Jolivet if (pcbddc->benign_saddle_point && pcbddc->dbg_flag > 1) PetscCall(PCBDDCBenignCheck(pc, zerodiag)); 15399566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zerodiag)); 154006f24817SStefano Zampini 1541b96c3477SStefano Zampini /* Setup local dirichlet solver ksp_D and sub_schurs solvers */ 154248a46eb9SPierre Jolivet if (computesubschurs && pcbddc->recompute_topography) PetscCall(PCBDDCInitSubSchurs(pc)); 15439d54b7f4SStefano Zampini /* SetUp Scaling operator (scaling matrices could be needed in SubSchursSetUp)*/ 154448a46eb9SPierre Jolivet if (!pcbddc->use_deluxe_scaling) PetscCall(PCBDDCScalingSetUp(pc)); 1545c703fcc7SStefano Zampini 1546c703fcc7SStefano Zampini /* finish setup solvers and do adaptive selection of constraints */ 1547b334f244SStefano Zampini sub_schurs = pcbddc->sub_schurs; 1548b334f244SStefano Zampini if (sub_schurs && sub_schurs->schur_explicit) { 15491baa6e33SBarry Smith if (computesubschurs) PetscCall(PCBDDCSetUpSubSchurs(pc)); 15509566063dSJacob Faibussowitsch PetscCall(PCBDDCSetUpLocalSolvers(pc, PETSC_TRUE, PETSC_FALSE)); 1551d5574798SStefano Zampini } else { 15529566063dSJacob Faibussowitsch PetscCall(PCBDDCSetUpLocalSolvers(pc, PETSC_TRUE, PETSC_FALSE)); 15531baa6e33SBarry Smith if (computesubschurs) PetscCall(PCBDDCSetUpSubSchurs(pc)); 15542070dbb6SStefano Zampini } 155508122e43SStefano Zampini if (pcbddc->adaptive_selection) { 15569566063dSJacob Faibussowitsch PetscCall(PCBDDCAdaptiveSelection(pc)); 15578de1fae6SStefano Zampini computeconstraintsmatrix = PETSC_TRUE; 1558b7eb3628SStefano Zampini } 1559684f6988SStefano Zampini 1560f4ddd8eeSStefano Zampini /* infer if NullSpace object attached to Mat via MatSetNearNullSpace has changed */ 1561fb8d54d4SStefano Zampini new_nearnullspace_provided = PETSC_FALSE; 15629566063dSJacob Faibussowitsch PetscCall(MatGetNearNullSpace(pc->pmat, &nearnullspace)); 1563f4ddd8eeSStefano Zampini if (pcbddc->onearnullspace) { /* already used nearnullspace */ 1564f4ddd8eeSStefano Zampini if (!nearnullspace) { /* near null space attached to mat has been destroyed */ 1565f4ddd8eeSStefano Zampini new_nearnullspace_provided = PETSC_TRUE; 1566f4ddd8eeSStefano Zampini } else { 1567f4ddd8eeSStefano Zampini /* determine if the two nullspaces are different (should be lightweight) */ 1568f4ddd8eeSStefano Zampini if (nearnullspace != pcbddc->onearnullspace) { 1569f4ddd8eeSStefano Zampini new_nearnullspace_provided = PETSC_TRUE; 1570165b64e2SStefano Zampini } else { /* maybe the user has changed the content of the nearnullspace so check vectors ObjectStateId */ 1571f4ddd8eeSStefano Zampini PetscInt i; 1572165b64e2SStefano Zampini const Vec *nearnullvecs; 1573165b64e2SStefano Zampini PetscObjectState state; 1574165b64e2SStefano Zampini PetscInt nnsp_size; 15759566063dSJacob Faibussowitsch PetscCall(MatNullSpaceGetVecs(nearnullspace, NULL, &nnsp_size, &nearnullvecs)); 1576f4ddd8eeSStefano Zampini for (i = 0; i < nnsp_size; i++) { 15779566063dSJacob Faibussowitsch PetscCall(PetscObjectStateGet((PetscObject)nearnullvecs[i], &state)); 1578165b64e2SStefano Zampini if (pcbddc->onearnullvecs_state[i] != state) { 1579f4ddd8eeSStefano Zampini new_nearnullspace_provided = PETSC_TRUE; 1580f4ddd8eeSStefano Zampini break; 1581f4ddd8eeSStefano Zampini } 1582f4ddd8eeSStefano Zampini } 1583f4ddd8eeSStefano Zampini } 1584f4ddd8eeSStefano Zampini } 1585f4ddd8eeSStefano Zampini } else { 1586f4ddd8eeSStefano Zampini if (!nearnullspace) { /* both nearnullspaces are null */ 1587f4ddd8eeSStefano Zampini new_nearnullspace_provided = PETSC_FALSE; 1588f4ddd8eeSStefano Zampini } else { /* nearnullspace attached later */ 1589f4ddd8eeSStefano Zampini new_nearnullspace_provided = PETSC_TRUE; 1590f4ddd8eeSStefano Zampini } 1591f4ddd8eeSStefano Zampini } 1592f4ddd8eeSStefano Zampini 1593f4ddd8eeSStefano Zampini /* Setup constraints and related work vectors */ 1594727cdba6SStefano Zampini /* reset primal space flags */ 15959566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_LocalWork[pcbddc->current_level], pc, 0, 0, 0)); 1596f4ddd8eeSStefano Zampini pcbddc->new_primal_space = PETSC_FALSE; 1597727cdba6SStefano Zampini pcbddc->new_primal_space_local = PETSC_FALSE; 15988de1fae6SStefano Zampini if (computeconstraintsmatrix || new_nearnullspace_provided) { 1599727cdba6SStefano Zampini /* It also sets the primal space flags */ 16009566063dSJacob Faibussowitsch PetscCall(PCBDDCConstraintsSetUp(pc)); 16019543d0ffSStefano Zampini } 1602e7b262bdSStefano Zampini /* Allocate needed local vectors (which depends on quantities defined during ConstraintsSetUp) */ 16039566063dSJacob Faibussowitsch PetscCall(PCBDDCSetUpLocalWorkVectors(pc)); 16045e8657edSStefano Zampini 16055e8657edSStefano Zampini if (pcbddc->use_change_of_basis) { 1606*f4f49eeaSPierre Jolivet PC_IS *pcis = (PC_IS *)pc->data; 16075e8657edSStefano Zampini 16089566063dSJacob Faibussowitsch PetscCall(PCBDDCComputeLocalMatrix(pc, pcbddc->ChangeOfBasisMatrix)); 16094f1b2e48SStefano Zampini if (pcbddc->benign_change) { 16109566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->benign_B0)); 1611c263805aSStefano Zampini /* pop B0 from pcbddc->local_mat */ 16129566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignPopOrPushB0(pc, PETSC_TRUE)); 1613c263805aSStefano Zampini } 16145e8657edSStefano Zampini /* get submatrices */ 16159566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcis->A_IB)); 16169566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcis->A_BI)); 16179566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcis->A_BB)); 16189566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->local_mat, pcis->is_B_local, pcis->is_B_local, MAT_INITIAL_MATRIX, &pcis->A_BB)); 16199566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->local_mat, pcis->is_I_local, pcis->is_B_local, MAT_INITIAL_MATRIX, &pcis->A_IB)); 16209566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->local_mat, pcis->is_B_local, pcis->is_I_local, MAT_INITIAL_MATRIX, &pcis->A_BI)); 16213975b054SStefano Zampini /* set flag in pcis to not reuse submatrices during PCISCreate */ 16223975b054SStefano Zampini pcis->reusesubmatrices = PETSC_FALSE; 16239c6a02ceSStefano Zampini } else if (!pcbddc->user_ChangeOfBasisMatrix && !pcbddc->benign_change) { 16249566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_mat)); 16259566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)matis->A)); 16265e8657edSStefano Zampini pcbddc->local_mat = matis->A; 16275e8657edSStefano Zampini } 162835509ce9Sstefano_zampini 162935509ce9Sstefano_zampini /* interface pressure block row for B_C */ 16309566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_lP", (PetscObject *)&lP)); 16319566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_lA", (PetscObject *)&lA)); 163235509ce9Sstefano_zampini if (lA && lP) { 163335509ce9Sstefano_zampini PC_IS *pcis = (PC_IS *)pc->data; 163435509ce9Sstefano_zampini Mat B_BI, B_BB, Bt_BI, Bt_BB; 163535509ce9Sstefano_zampini PetscBool issym; 1636b94d7dedSBarry Smith 16379566063dSJacob Faibussowitsch PetscCall(MatIsSymmetric(lA, PETSC_SMALL, &issym)); 16386cc1294bSstefano_zampini if (issym) { 16399566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(lA, lP, pcis->is_I_local, MAT_INITIAL_MATRIX, &B_BI)); 16409566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(lA, lP, pcis->is_B_local, MAT_INITIAL_MATRIX, &B_BB)); 16419566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(B_BI, &Bt_BI)); 16429566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(B_BB, &Bt_BB)); 164335509ce9Sstefano_zampini } else { 16449566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(lA, lP, pcis->is_I_local, MAT_INITIAL_MATRIX, &B_BI)); 16459566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(lA, lP, pcis->is_B_local, MAT_INITIAL_MATRIX, &B_BB)); 16469566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(lA, pcis->is_I_local, lP, MAT_INITIAL_MATRIX, &Bt_BI)); 16479566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(lA, pcis->is_B_local, lP, MAT_INITIAL_MATRIX, &Bt_BB)); 164835509ce9Sstefano_zampini } 16499566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)pc, "__KSPFETIDP_B_BI", (PetscObject)B_BI)); 16509566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)pc, "__KSPFETIDP_B_BB", (PetscObject)B_BB)); 16519566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)pc, "__KSPFETIDP_Bt_BI", (PetscObject)Bt_BI)); 16529566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)pc, "__KSPFETIDP_Bt_BB", (PetscObject)Bt_BB)); 16539566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B_BI)); 16549566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B_BB)); 16559566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Bt_BI)); 16569566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Bt_BB)); 165735509ce9Sstefano_zampini } 16589566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_LocalWork[pcbddc->current_level], pc, 0, 0, 0)); 165935509ce9Sstefano_zampini 1660b96c3477SStefano Zampini /* SetUp coarse and local Neumann solvers */ 16619566063dSJacob Faibussowitsch PetscCall(PCBDDCSetUpSolvers(pc)); 1662b96c3477SStefano Zampini /* SetUp Scaling operator */ 16631baa6e33SBarry Smith if (pcbddc->use_deluxe_scaling) PetscCall(PCBDDCScalingSetUp(pc)); 1664c703fcc7SStefano Zampini 16651dd7afcfSStefano Zampini /* mark topography as done */ 166656282151SStefano Zampini pcbddc->recompute_topography = PETSC_FALSE; 16670369aaf7SStefano Zampini 16681dd7afcfSStefano Zampini /* wrap pcis->A_IB and pcis->A_BI if we did not change explicitly the variables on the pressures */ 16699566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignShellMat(pc, PETSC_FALSE)); 16701dd7afcfSStefano Zampini 167158a03d70SStefano Zampini if (pcbddc->dbg_flag) { 16729566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISubtractTab(pcbddc->dbg_viewer, 2 * pcbddc->current_level)); 16739566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer)); 16742b510759SStefano Zampini } 16753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 16760c7d97c5SJed Brown } 16770c7d97c5SJed Brown 167866976f2fSJacob Faibussowitsch static PetscErrorCode PCApply_BDDC(PC pc, Vec r, Vec z) 1679d71ae5a4SJacob Faibussowitsch { 1680*f4f49eeaSPierre Jolivet PC_IS *pcis = (PC_IS *)pc->data; 1681*f4f49eeaSPierre Jolivet PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 1682b3338236SStefano Zampini Mat lA = NULL; 1683b097fa66SStefano Zampini PetscInt n_B = pcis->n_B, n_D = pcis->n - n_B; 16843b03a366Sstefano_zampini const PetscScalar one = 1.0; 16853b03a366Sstefano_zampini const PetscScalar m_one = -1.0; 16862617d88aSStefano Zampini const PetscScalar zero = 0.0; 16870c7d97c5SJed Brown /* This code is similar to that provided in nn.c for PCNN 16880c7d97c5SJed Brown NN interface preconditioner changed to BDDC 1689b097fa66SStefano Zampini Added support for M_3 preconditioner in the reference article (code is active if pcbddc->switch_static == PETSC_TRUE) */ 16900c7d97c5SJed Brown 16910c7d97c5SJed Brown PetscFunctionBegin; 16929566063dSJacob Faibussowitsch PetscCall(PetscCitationsRegister(citation, &cited)); 169348a46eb9SPierre Jolivet if (pcbddc->switch_static) PetscCall(MatISGetLocalMat(pc->useAmat ? pc->mat : pc->pmat, &lA)); 1694b3338236SStefano Zampini 16951dd7afcfSStefano Zampini if (pcbddc->ChangeOfBasisMatrix) { 16961dd7afcfSStefano Zampini Vec swap; 169727b6a85dSStefano Zampini 16989566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, r, pcbddc->work_change)); 16991dd7afcfSStefano Zampini swap = pcbddc->work_change; 17001dd7afcfSStefano Zampini pcbddc->work_change = r; 17011dd7afcfSStefano Zampini r = swap; 17021dd7afcfSStefano Zampini /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */ 17039cc2a9b1Sstefano_zampini if (pcbddc->benign_apply_coarse_only && pcbddc->use_exact_dirichlet_trick && pcbddc->change_interior) { 17049566063dSJacob Faibussowitsch PetscCall(VecCopy(r, pcis->vec1_global)); 17059566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(pcis->vec1_global)); 17061dd7afcfSStefano Zampini } 17071dd7afcfSStefano Zampini } 170827b6a85dSStefano Zampini if (pcbddc->benign_have_null) { /* get p0 from r */ 17099566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignGetOrSetP0(pc, r, PETSC_TRUE)); 1710efc2fbd9SStefano Zampini } 1711bc960bbfSJed Brown if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_DIRICHLET && !pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) { 17129566063dSJacob Faibussowitsch PetscCall(VecCopy(r, z)); 17130c7d97c5SJed Brown /* First Dirichlet solve */ 17149566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD)); 17159566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD)); 17160c7d97c5SJed Brown /* 17170c7d97c5SJed Brown Assembling right hand side for BDDC operator 1718b097fa66SStefano Zampini - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE) 1719674ae819SStefano Zampini - pcis->vec1_B the interface part of the global vector z 17200c7d97c5SJed Brown */ 17219566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0)); 1722a1cb837bSStefano Zampini if (n_D) { 17239566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_D, pcis->vec1_D, pcis->vec2_D)); 17249566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0)); 17259566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec2_D)); 17269566063dSJacob Faibussowitsch PetscCall(VecScale(pcis->vec2_D, m_one)); 172716909a7fSStefano Zampini if (pcbddc->switch_static) { 17289566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_N, 0.)); 17299566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE)); 17309566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE)); 173116909a7fSStefano Zampini if (!pcbddc->switch_static_change) { 17329566063dSJacob Faibussowitsch PetscCall(MatMult(lA, pcis->vec1_N, pcis->vec2_N)); 173316909a7fSStefano Zampini } else { 17349566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N)); 17359566063dSJacob Faibussowitsch PetscCall(MatMult(lA, pcis->vec2_N, pcis->vec1_N)); 17369566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N)); 173716909a7fSStefano Zampini } 17389566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_N, pcis->vec1_D, ADD_VALUES, SCATTER_FORWARD)); 17399566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_N, pcis->vec1_D, ADD_VALUES, SCATTER_FORWARD)); 17409566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_B, pcis->vec2_N, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD)); 17419566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_B, pcis->vec2_N, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD)); 174216909a7fSStefano Zampini } else { 17439566063dSJacob Faibussowitsch PetscCall(MatMult(pcis->A_BI, pcis->vec2_D, pcis->vec1_B)); 174416909a7fSStefano Zampini } 1745b097fa66SStefano Zampini } else { 1746a1cb837bSStefano Zampini PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0)); 17479566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_B, zero)); 1748b097fa66SStefano Zampini } 17499566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_B, pcis->vec1_B, z, ADD_VALUES, SCATTER_REVERSE)); 17509566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_B, pcis->vec1_B, z, ADD_VALUES, SCATTER_REVERSE)); 17519566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingRestriction(pc, z, pcis->vec1_B)); 1752b76ba322SStefano Zampini } else { 175348a46eb9SPierre Jolivet if (!pcbddc->benign_apply_coarse_only) PetscCall(PCBDDCScalingRestriction(pc, r, pcis->vec1_B)); 17544fee134fSStefano Zampini } 1755bc960bbfSJed Brown if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_LUMP) { 175628b400f6SJacob Faibussowitsch PetscCheck(pcbddc->switch_static, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "You forgot to pass -pc_bddc_switch_static"); 17579566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD)); 17589566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD)); 1759bc960bbfSJed Brown } 1760b76ba322SStefano Zampini 17612617d88aSStefano Zampini /* Apply interface preconditioner 17622617d88aSStefano Zampini input/output vecs: pcis->vec1_B and pcis->vec1_D */ 17639566063dSJacob Faibussowitsch PetscCall(PCBDDCApplyInterfacePreconditioner(pc, PETSC_FALSE)); 17642617d88aSStefano Zampini 1765674ae819SStefano Zampini /* Apply transpose of partition of unity operator */ 17669566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingExtension(pc, pcis->vec1_B, z)); 1767bc960bbfSJed Brown if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_LUMP) { 17689566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec1_D, z, INSERT_VALUES, SCATTER_REVERSE)); 17699566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec1_D, z, INSERT_VALUES, SCATTER_REVERSE)); 17703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1771bc960bbfSJed Brown } 17723b03a366Sstefano_zampini /* Second Dirichlet solve and assembling of output */ 17739566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_B, z, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD)); 17749566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_B, z, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD)); 1775b097fa66SStefano Zampini if (n_B) { 177616909a7fSStefano Zampini if (pcbddc->switch_static) { 17779566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec1_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE)); 17789566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec1_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE)); 17799566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_B, pcis->vec1_B, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE)); 17809566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_B, pcis->vec1_B, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE)); 178116909a7fSStefano Zampini if (!pcbddc->switch_static_change) { 17829566063dSJacob Faibussowitsch PetscCall(MatMult(lA, pcis->vec1_N, pcis->vec2_N)); 178316909a7fSStefano Zampini } else { 17849566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N)); 17859566063dSJacob Faibussowitsch PetscCall(MatMult(lA, pcis->vec2_N, pcis->vec1_N)); 17869566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N)); 178716909a7fSStefano Zampini } 17889566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_N, pcis->vec3_D, INSERT_VALUES, SCATTER_FORWARD)); 17899566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_N, pcis->vec3_D, INSERT_VALUES, SCATTER_FORWARD)); 179016909a7fSStefano Zampini } else { 17919566063dSJacob Faibussowitsch PetscCall(MatMult(pcis->A_IB, pcis->vec1_B, pcis->vec3_D)); 179216909a7fSStefano Zampini } 179316909a7fSStefano Zampini } else if (pcbddc->switch_static) { /* n_B is zero */ 179416909a7fSStefano Zampini if (!pcbddc->switch_static_change) { 17959566063dSJacob Faibussowitsch PetscCall(MatMult(lA, pcis->vec1_D, pcis->vec3_D)); 179616909a7fSStefano Zampini } else { 17979566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_D, pcis->vec1_N)); 17989566063dSJacob Faibussowitsch PetscCall(MatMult(lA, pcis->vec1_N, pcis->vec2_N)); 17999566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec2_N, pcis->vec3_D)); 180016909a7fSStefano Zampini } 1801b097fa66SStefano Zampini } 18029566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0)); 18039566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_D, pcis->vec3_D, pcis->vec4_D)); 18049566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0)); 18059566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec4_D)); 1806efc2fbd9SStefano Zampini 18078ae0ca82SStefano Zampini if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) { 1808b097fa66SStefano Zampini if (pcbddc->switch_static) { 18099566063dSJacob Faibussowitsch PetscCall(VecAXPBYPCZ(pcis->vec2_D, m_one, one, m_one, pcis->vec4_D, pcis->vec1_D)); 1810b097fa66SStefano Zampini } else { 18119566063dSJacob Faibussowitsch PetscCall(VecAXPBY(pcis->vec2_D, m_one, m_one, pcis->vec4_D)); 1812b097fa66SStefano Zampini } 18139566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec2_D, z, INSERT_VALUES, SCATTER_REVERSE)); 18149566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec2_D, z, INSERT_VALUES, SCATTER_REVERSE)); 1815b097fa66SStefano Zampini } else { 1816b097fa66SStefano Zampini if (pcbddc->switch_static) { 18179566063dSJacob Faibussowitsch PetscCall(VecAXPBY(pcis->vec4_D, one, m_one, pcis->vec1_D)); 1818b097fa66SStefano Zampini } else { 18199566063dSJacob Faibussowitsch PetscCall(VecScale(pcis->vec4_D, m_one)); 1820b097fa66SStefano Zampini } 18219566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec4_D, z, INSERT_VALUES, SCATTER_REVERSE)); 18229566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec4_D, z, INSERT_VALUES, SCATTER_REVERSE)); 1823b097fa66SStefano Zampini } 182427b6a85dSStefano Zampini if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */ 18251baa6e33SBarry Smith if (pcbddc->benign_apply_coarse_only) PetscCall(PetscArrayzero(pcbddc->benign_p0, pcbddc->benign_n)); 18269566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignGetOrSetP0(pc, z, PETSC_FALSE)); 1827efc2fbd9SStefano Zampini } 18281f4df5f7SStefano Zampini 18291dd7afcfSStefano Zampini if (pcbddc->ChangeOfBasisMatrix) { 1830f913dca9SStefano Zampini pcbddc->work_change = r; 18319566063dSJacob Faibussowitsch PetscCall(VecCopy(z, pcbddc->work_change)); 18329566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix, pcbddc->work_change, z)); 18331dd7afcfSStefano Zampini } 18343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18350c7d97c5SJed Brown } 183650efa1b5SStefano Zampini 183766976f2fSJacob Faibussowitsch static PetscErrorCode PCApplyTranspose_BDDC(PC pc, Vec r, Vec z) 1838d71ae5a4SJacob Faibussowitsch { 1839*f4f49eeaSPierre Jolivet PC_IS *pcis = (PC_IS *)pc->data; 1840*f4f49eeaSPierre Jolivet PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 1841b3338236SStefano Zampini Mat lA = NULL; 1842b097fa66SStefano Zampini PetscInt n_B = pcis->n_B, n_D = pcis->n - n_B; 184350efa1b5SStefano Zampini const PetscScalar one = 1.0; 184450efa1b5SStefano Zampini const PetscScalar m_one = -1.0; 184550efa1b5SStefano Zampini const PetscScalar zero = 0.0; 184650efa1b5SStefano Zampini 184750efa1b5SStefano Zampini PetscFunctionBegin; 18489566063dSJacob Faibussowitsch PetscCall(PetscCitationsRegister(citation, &cited)); 184948a46eb9SPierre Jolivet if (pcbddc->switch_static) PetscCall(MatISGetLocalMat(pc->useAmat ? pc->mat : pc->pmat, &lA)); 18501dd7afcfSStefano Zampini if (pcbddc->ChangeOfBasisMatrix) { 18511dd7afcfSStefano Zampini Vec swap; 185227b6a85dSStefano Zampini 18539566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, r, pcbddc->work_change)); 18541dd7afcfSStefano Zampini swap = pcbddc->work_change; 18551dd7afcfSStefano Zampini pcbddc->work_change = r; 18561dd7afcfSStefano Zampini r = swap; 185727b6a85dSStefano Zampini /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */ 18588ae0ca82SStefano Zampini if (pcbddc->benign_apply_coarse_only && pcbddc->exact_dirichlet_trick_app && pcbddc->change_interior) { 18599566063dSJacob Faibussowitsch PetscCall(VecCopy(r, pcis->vec1_global)); 18609566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(pcis->vec1_global)); 18611dd7afcfSStefano Zampini } 186227b6a85dSStefano Zampini } 186327b6a85dSStefano Zampini if (pcbddc->benign_have_null) { /* get p0 from r */ 18649566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignGetOrSetP0(pc, r, PETSC_TRUE)); 1865537c1cdfSStefano Zampini } 18668ae0ca82SStefano Zampini if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) { 18679566063dSJacob Faibussowitsch PetscCall(VecCopy(r, z)); 186850efa1b5SStefano Zampini /* First Dirichlet solve */ 18699566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD)); 18709566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD)); 187150efa1b5SStefano Zampini /* 187250efa1b5SStefano Zampini Assembling right hand side for BDDC operator 1873b097fa66SStefano Zampini - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE) 187450efa1b5SStefano Zampini - pcis->vec1_B the interface part of the global vector z 187550efa1b5SStefano Zampini */ 1876b097fa66SStefano Zampini if (n_D) { 18779566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0)); 18789566063dSJacob Faibussowitsch PetscCall(KSPSolveTranspose(pcbddc->ksp_D, pcis->vec1_D, pcis->vec2_D)); 18799566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0)); 18809566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec2_D)); 18819566063dSJacob Faibussowitsch PetscCall(VecScale(pcis->vec2_D, m_one)); 188216909a7fSStefano Zampini if (pcbddc->switch_static) { 18839566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_N, 0.)); 18849566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE)); 18859566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE)); 188616909a7fSStefano Zampini if (!pcbddc->switch_static_change) { 18879566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(lA, pcis->vec1_N, pcis->vec2_N)); 188816909a7fSStefano Zampini } else { 18899566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N)); 18909566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(lA, pcis->vec2_N, pcis->vec1_N)); 18919566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N)); 189216909a7fSStefano Zampini } 18939566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_N, pcis->vec1_D, ADD_VALUES, SCATTER_FORWARD)); 18949566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_N, pcis->vec1_D, ADD_VALUES, SCATTER_FORWARD)); 18959566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_B, pcis->vec2_N, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD)); 18969566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_B, pcis->vec2_N, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD)); 189716909a7fSStefano Zampini } else { 18989566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcis->A_IB, pcis->vec2_D, pcis->vec1_B)); 189916909a7fSStefano Zampini } 1900b097fa66SStefano Zampini } else { 19019566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_B, zero)); 1902b097fa66SStefano Zampini } 19039566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_B, pcis->vec1_B, z, ADD_VALUES, SCATTER_REVERSE)); 19049566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_B, pcis->vec1_B, z, ADD_VALUES, SCATTER_REVERSE)); 19059566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingRestriction(pc, z, pcis->vec1_B)); 190650efa1b5SStefano Zampini } else { 19079566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingRestriction(pc, r, pcis->vec1_B)); 190850efa1b5SStefano Zampini } 190950efa1b5SStefano Zampini 191050efa1b5SStefano Zampini /* Apply interface preconditioner 191150efa1b5SStefano Zampini input/output vecs: pcis->vec1_B and pcis->vec1_D */ 19129566063dSJacob Faibussowitsch PetscCall(PCBDDCApplyInterfacePreconditioner(pc, PETSC_TRUE)); 191350efa1b5SStefano Zampini 191450efa1b5SStefano Zampini /* Apply transpose of partition of unity operator */ 19159566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingExtension(pc, pcis->vec1_B, z)); 191650efa1b5SStefano Zampini 191750efa1b5SStefano Zampini /* Second Dirichlet solve and assembling of output */ 19189566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_B, z, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD)); 19199566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_B, z, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD)); 1920b097fa66SStefano Zampini if (n_B) { 192116909a7fSStefano Zampini if (pcbddc->switch_static) { 19229566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec1_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE)); 19239566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec1_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE)); 19249566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_B, pcis->vec1_B, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE)); 19259566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_B, pcis->vec1_B, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE)); 192616909a7fSStefano Zampini if (!pcbddc->switch_static_change) { 19279566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(lA, pcis->vec1_N, pcis->vec2_N)); 192816909a7fSStefano Zampini } else { 19299566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N)); 19309566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(lA, pcis->vec2_N, pcis->vec1_N)); 19319566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N)); 193216909a7fSStefano Zampini } 19339566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_N, pcis->vec3_D, INSERT_VALUES, SCATTER_FORWARD)); 19349566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_N, pcis->vec3_D, INSERT_VALUES, SCATTER_FORWARD)); 193516909a7fSStefano Zampini } else { 19369566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcis->A_BI, pcis->vec1_B, pcis->vec3_D)); 193716909a7fSStefano Zampini } 193816909a7fSStefano Zampini } else if (pcbddc->switch_static) { /* n_B is zero */ 193916909a7fSStefano Zampini if (!pcbddc->switch_static_change) { 19409566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(lA, pcis->vec1_D, pcis->vec3_D)); 194116909a7fSStefano Zampini } else { 19429566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_D, pcis->vec1_N)); 19439566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(lA, pcis->vec1_N, pcis->vec2_N)); 19449566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec2_N, pcis->vec3_D)); 194516909a7fSStefano Zampini } 1946b097fa66SStefano Zampini } 19479566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0)); 19489566063dSJacob Faibussowitsch PetscCall(KSPSolveTranspose(pcbddc->ksp_D, pcis->vec3_D, pcis->vec4_D)); 19499566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0)); 19509566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec4_D)); 19518ae0ca82SStefano Zampini if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) { 1952b097fa66SStefano Zampini if (pcbddc->switch_static) { 19539566063dSJacob Faibussowitsch PetscCall(VecAXPBYPCZ(pcis->vec2_D, m_one, one, m_one, pcis->vec4_D, pcis->vec1_D)); 1954b097fa66SStefano Zampini } else { 19559566063dSJacob Faibussowitsch PetscCall(VecAXPBY(pcis->vec2_D, m_one, m_one, pcis->vec4_D)); 1956b097fa66SStefano Zampini } 19579566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec2_D, z, INSERT_VALUES, SCATTER_REVERSE)); 19589566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec2_D, z, INSERT_VALUES, SCATTER_REVERSE)); 1959b097fa66SStefano Zampini } else { 1960b097fa66SStefano Zampini if (pcbddc->switch_static) { 19619566063dSJacob Faibussowitsch PetscCall(VecAXPBY(pcis->vec4_D, one, m_one, pcis->vec1_D)); 1962b097fa66SStefano Zampini } else { 19639566063dSJacob Faibussowitsch PetscCall(VecScale(pcis->vec4_D, m_one)); 1964b097fa66SStefano Zampini } 19659566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec4_D, z, INSERT_VALUES, SCATTER_REVERSE)); 19669566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec4_D, z, INSERT_VALUES, SCATTER_REVERSE)); 1967b097fa66SStefano Zampini } 196827b6a85dSStefano Zampini if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */ 19699566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignGetOrSetP0(pc, z, PETSC_FALSE)); 1970537c1cdfSStefano Zampini } 19711dd7afcfSStefano Zampini if (pcbddc->ChangeOfBasisMatrix) { 1972f913dca9SStefano Zampini pcbddc->work_change = r; 19739566063dSJacob Faibussowitsch PetscCall(VecCopy(z, pcbddc->work_change)); 19749566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix, pcbddc->work_change, z)); 19751dd7afcfSStefano Zampini } 19763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 197750efa1b5SStefano Zampini } 1978674ae819SStefano Zampini 197966976f2fSJacob Faibussowitsch static PetscErrorCode PCReset_BDDC(PC pc) 1980d71ae5a4SJacob Faibussowitsch { 1981da1bb401SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 19829326c5c6Sstefano_zampini PC_IS *pcis = (PC_IS *)pc->data; 19839326c5c6Sstefano_zampini KSP kspD, kspR, kspC; 1984da1bb401SStefano Zampini 1985da1bb401SStefano Zampini PetscFunctionBegin; 1986674ae819SStefano Zampini /* free BDDC custom data */ 19879566063dSJacob Faibussowitsch PetscCall(PCBDDCResetCustomization(pc)); 1988674ae819SStefano Zampini /* destroy objects related to topography */ 19899566063dSJacob Faibussowitsch PetscCall(PCBDDCResetTopography(pc)); 199034a97f8cSStefano Zampini /* destroy objects for scaling operator */ 19919566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingDestroy(pc)); 1992674ae819SStefano Zampini /* free solvers stuff */ 19939566063dSJacob Faibussowitsch PetscCall(PCBDDCResetSolvers(pc)); 199462a6ff1dSStefano Zampini /* free global vectors needed in presolve */ 19959566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->temp_solution)); 19969566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->original_rhs)); 19971dd7afcfSStefano Zampini /* free data created by PCIS */ 199804c3f3b8SBarry Smith PetscCall(PCISReset(pc)); 19999326c5c6Sstefano_zampini 20009326c5c6Sstefano_zampini /* restore defaults */ 20019326c5c6Sstefano_zampini kspD = pcbddc->ksp_D; 20029326c5c6Sstefano_zampini kspR = pcbddc->ksp_R; 20039326c5c6Sstefano_zampini kspC = pcbddc->coarse_ksp; 20049566063dSJacob Faibussowitsch PetscCall(PetscMemzero(pc->data, sizeof(*pcbddc))); 20059326c5c6Sstefano_zampini pcis->n_neigh = -1; 20069326c5c6Sstefano_zampini pcis->scaling_factor = 1.0; 20079326c5c6Sstefano_zampini pcis->reusesubmatrices = PETSC_TRUE; 20089326c5c6Sstefano_zampini pcbddc->use_local_adj = PETSC_TRUE; 20099326c5c6Sstefano_zampini pcbddc->use_vertices = PETSC_TRUE; 20109326c5c6Sstefano_zampini pcbddc->use_edges = PETSC_TRUE; 20119326c5c6Sstefano_zampini pcbddc->symmetric_primal = PETSC_TRUE; 20129326c5c6Sstefano_zampini pcbddc->vertex_size = 1; 20139326c5c6Sstefano_zampini pcbddc->recompute_topography = PETSC_TRUE; 20149326c5c6Sstefano_zampini pcbddc->coarse_size = -1; 20159326c5c6Sstefano_zampini pcbddc->use_exact_dirichlet_trick = PETSC_TRUE; 20169326c5c6Sstefano_zampini pcbddc->coarsening_ratio = 8; 20179326c5c6Sstefano_zampini pcbddc->coarse_eqs_per_proc = 1; 20189326c5c6Sstefano_zampini pcbddc->benign_compute_correction = PETSC_TRUE; 20199326c5c6Sstefano_zampini pcbddc->nedfield = -1; 20209326c5c6Sstefano_zampini pcbddc->nedglobal = PETSC_TRUE; 20219326c5c6Sstefano_zampini pcbddc->graphmaxcount = PETSC_MAX_INT; 20229326c5c6Sstefano_zampini pcbddc->sub_schurs_layers = -1; 20239326c5c6Sstefano_zampini pcbddc->ksp_D = kspD; 20249326c5c6Sstefano_zampini pcbddc->ksp_R = kspR; 20259326c5c6Sstefano_zampini pcbddc->coarse_ksp = kspC; 20263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 20279326c5c6Sstefano_zampini } 20289326c5c6Sstefano_zampini 202966976f2fSJacob Faibussowitsch static PetscErrorCode PCDestroy_BDDC(PC pc) 2030d71ae5a4SJacob Faibussowitsch { 20319326c5c6Sstefano_zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 20329326c5c6Sstefano_zampini 20339326c5c6Sstefano_zampini PetscFunctionBegin; 20349566063dSJacob Faibussowitsch PetscCall(PCReset_BDDC(pc)); 20359566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&pcbddc->ksp_D)); 20369566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&pcbddc->ksp_R)); 20379566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&pcbddc->coarse_ksp)); 20389566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDiscreteGradient_C", NULL)); 20399566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDivergenceMat_C", NULL)); 20409566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetChangeOfBasisMat_C", NULL)); 20419566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetPrimalVerticesLocalIS_C", NULL)); 20429566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetPrimalVerticesIS_C", NULL)); 204332fe681dSStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetPrimalVerticesLocalIS_C", NULL)); 204432fe681dSStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetPrimalVerticesIS_C", NULL)); 20459566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetCoarseningRatio_C", NULL)); 20469566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLevel_C", NULL)); 20479566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetUseExactDirichlet_C", NULL)); 20489566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLevels_C", NULL)); 20499566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDirichletBoundaries_C", NULL)); 20509566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDirichletBoundariesLocal_C", NULL)); 20519566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetNeumannBoundaries_C", NULL)); 20529566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetNeumannBoundariesLocal_C", NULL)); 20539566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetDirichletBoundaries_C", NULL)); 20549566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetDirichletBoundariesLocal_C", NULL)); 20559566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetNeumannBoundaries_C", NULL)); 20569566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetNeumannBoundariesLocal_C", NULL)); 20579566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDofsSplitting_C", NULL)); 20589566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDofsSplittingLocal_C", NULL)); 20599566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLocalAdjacencyGraph_C", NULL)); 20609566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCCreateFETIDPOperators_C", NULL)); 20619566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCMatFETIDPGetRHS_C", NULL)); 20629566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCMatFETIDPGetSolution_C", NULL)); 20639566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCPreSolveChangeRHS_C", NULL)); 20649566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", NULL)); 20659566063dSJacob Faibussowitsch PetscCall(PetscFree(pc->data)); 20663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2067da1bb401SStefano Zampini } 20681e6b0712SBarry Smith 2069d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetCoordinates_BDDC(PC pc, PetscInt dim, PetscInt nloc, PetscReal *coords) 2070d71ae5a4SJacob Faibussowitsch { 2071ab8c8b98SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 2072ab8c8b98SStefano Zampini PCBDDCGraph mat_graph = pcbddc->mat_graph; 2073ab8c8b98SStefano Zampini 2074ab8c8b98SStefano Zampini PetscFunctionBegin; 20759566063dSJacob Faibussowitsch PetscCall(PetscFree(mat_graph->coords)); 20769566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nloc * dim, &mat_graph->coords)); 20779566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(mat_graph->coords, coords, nloc * dim)); 2078ab8c8b98SStefano Zampini mat_graph->cnloc = nloc; 2079ab8c8b98SStefano Zampini mat_graph->cdim = dim; 2080ab8c8b98SStefano Zampini mat_graph->cloc = PETSC_FALSE; 20814f819b78SStefano Zampini /* flg setup */ 20824f819b78SStefano Zampini pcbddc->recompute_topography = PETSC_TRUE; 20834f819b78SStefano Zampini pcbddc->corner_selected = PETSC_FALSE; 20843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2085ab8c8b98SStefano Zampini } 2086ab8c8b98SStefano Zampini 2087d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCPreSolveChangeRHS_BDDC(PC pc, PetscBool *change) 2088d71ae5a4SJacob Faibussowitsch { 2089a06fd7f2SStefano Zampini PetscFunctionBegin; 2090a06fd7f2SStefano Zampini *change = PETSC_TRUE; 20913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2092a06fd7f2SStefano Zampini } 2093a06fd7f2SStefano Zampini 2094d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCMatFETIDPGetRHS_BDDC(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs) 2095d71ae5a4SJacob Faibussowitsch { 2096674ae819SStefano Zampini FETIDPMat_ctx mat_ctx; 2097266e20e9SStefano Zampini Vec work; 20983425bc38SStefano Zampini PC_IS *pcis; 20993425bc38SStefano Zampini PC_BDDC *pcbddc; 21000c7d97c5SJed Brown 21013425bc38SStefano Zampini PetscFunctionBegin; 21029566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(fetidp_mat, &mat_ctx)); 21033425bc38SStefano Zampini pcis = (PC_IS *)mat_ctx->pc->data; 21043425bc38SStefano Zampini pcbddc = (PC_BDDC *)mat_ctx->pc->data; 21053425bc38SStefano Zampini 21069566063dSJacob Faibussowitsch PetscCall(VecSet(fetidp_flux_rhs, 0.0)); 2107229984c5Sstefano_zampini /* copy rhs since we may change it during PCPreSolve_BDDC */ 210848a46eb9SPierre Jolivet if (!pcbddc->original_rhs) PetscCall(VecDuplicate(pcis->vec1_global, &pcbddc->original_rhs)); 21096cc1294bSstefano_zampini if (mat_ctx->rhs_flip) { 21109566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(pcbddc->original_rhs, standard_rhs, mat_ctx->rhs_flip)); 21116cc1294bSstefano_zampini } else { 21129566063dSJacob Faibussowitsch PetscCall(VecCopy(standard_rhs, pcbddc->original_rhs)); 21136cc1294bSstefano_zampini } 2114af140850Sstefano_zampini if (mat_ctx->g2g_p) { 2115229984c5Sstefano_zampini /* interface pressure rhs */ 21169566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat_ctx->g2g_p, fetidp_flux_rhs, pcbddc->original_rhs, INSERT_VALUES, SCATTER_REVERSE)); 21179566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat_ctx->g2g_p, fetidp_flux_rhs, pcbddc->original_rhs, INSERT_VALUES, SCATTER_REVERSE)); 21189566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat_ctx->g2g_p, standard_rhs, fetidp_flux_rhs, INSERT_VALUES, SCATTER_FORWARD)); 21199566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat_ctx->g2g_p, standard_rhs, fetidp_flux_rhs, INSERT_VALUES, SCATTER_FORWARD)); 212048a46eb9SPierre Jolivet if (!mat_ctx->rhs_flip) PetscCall(VecScale(fetidp_flux_rhs, -1.)); 21216cc1294bSstefano_zampini } 2122c08af4c6SStefano Zampini /* 2123c08af4c6SStefano Zampini change of basis for physical rhs if needed 2124c08af4c6SStefano Zampini It also changes the rhs in case of dirichlet boundaries 2125c08af4c6SStefano Zampini */ 21269566063dSJacob Faibussowitsch PetscCall(PCPreSolve_BDDC(mat_ctx->pc, NULL, pcbddc->original_rhs, NULL)); 2127fc17d649SStefano Zampini if (pcbddc->ChangeOfBasisMatrix) { 21289566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, pcbddc->original_rhs, pcbddc->work_change)); 21293738a8e6SStefano Zampini work = pcbddc->work_change; 2130fc17d649SStefano Zampini } else { 21313738a8e6SStefano Zampini work = pcbddc->original_rhs; 2132fc17d649SStefano Zampini } 21333425bc38SStefano Zampini /* store vectors for computation of fetidp final solution */ 21349566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, work, mat_ctx->temp_solution_D, INSERT_VALUES, SCATTER_FORWARD)); 21359566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, work, mat_ctx->temp_solution_D, INSERT_VALUES, SCATTER_FORWARD)); 2136fb223d50SStefano Zampini /* scale rhs since it should be unassembled */ 2137fb223d50SStefano Zampini /* TODO use counter scaling? (also below) */ 21389566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_B, work, mat_ctx->temp_solution_B, INSERT_VALUES, SCATTER_FORWARD)); 21399566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_B, work, mat_ctx->temp_solution_B, INSERT_VALUES, SCATTER_FORWARD)); 2140674ae819SStefano Zampini /* Apply partition of unity */ 21419566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(mat_ctx->temp_solution_B, pcis->D, mat_ctx->temp_solution_B)); 21429566063dSJacob Faibussowitsch /* PetscCall(PCBDDCScalingRestriction(mat_ctx->pc,work,mat_ctx->temp_solution_B)); */ 21438eeda7d8SStefano Zampini if (!pcbddc->switch_static) { 21443425bc38SStefano Zampini /* compute partially subassembled Schur complement right-hand side */ 21459566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], mat_ctx->pc, 0, 0, 0)); 21469566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_D, mat_ctx->temp_solution_D, pcis->vec1_D)); 21479566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], mat_ctx->pc, 0, 0, 0)); 2148c0decd05SBarry Smith /* Cannot propagate up error in KSPSolve() because there is no access to the PC */ 21499566063dSJacob Faibussowitsch PetscCall(MatMult(pcis->A_BI, pcis->vec1_D, pcis->vec1_B)); 21509566063dSJacob Faibussowitsch PetscCall(VecAXPY(mat_ctx->temp_solution_B, -1.0, pcis->vec1_B)); 21519566063dSJacob Faibussowitsch PetscCall(VecSet(work, 0.0)); 21529566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_B, mat_ctx->temp_solution_B, work, ADD_VALUES, SCATTER_REVERSE)); 21539566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_B, mat_ctx->temp_solution_B, work, ADD_VALUES, SCATTER_REVERSE)); 21549566063dSJacob Faibussowitsch /* PetscCall(PCBDDCScalingRestriction(mat_ctx->pc,work,mat_ctx->temp_solution_B)); */ 21559566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_B, work, mat_ctx->temp_solution_B, INSERT_VALUES, SCATTER_FORWARD)); 21569566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_B, work, mat_ctx->temp_solution_B, INSERT_VALUES, SCATTER_FORWARD)); 21579566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(mat_ctx->temp_solution_B, pcis->D, mat_ctx->temp_solution_B)); 21583425bc38SStefano Zampini } 21593425bc38SStefano Zampini /* BDDC rhs */ 21609566063dSJacob Faibussowitsch PetscCall(VecCopy(mat_ctx->temp_solution_B, pcis->vec1_B)); 21611baa6e33SBarry Smith if (pcbddc->switch_static) PetscCall(VecCopy(mat_ctx->temp_solution_D, pcis->vec1_D)); 21623425bc38SStefano Zampini /* apply BDDC */ 21639566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(pcbddc->benign_p0, pcbddc->benign_n)); 21649566063dSJacob Faibussowitsch PetscCall(PCBDDCApplyInterfacePreconditioner(mat_ctx->pc, PETSC_FALSE)); 21659566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(pcbddc->benign_p0, pcbddc->benign_n)); 2166229984c5Sstefano_zampini 21673425bc38SStefano Zampini /* Application of B_delta and assembling of rhs for fetidp fluxes */ 21689566063dSJacob Faibussowitsch PetscCall(MatMult(mat_ctx->B_delta, pcis->vec1_B, mat_ctx->lambda_local)); 21699566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat_ctx->l2g_lambda, mat_ctx->lambda_local, fetidp_flux_rhs, ADD_VALUES, SCATTER_FORWARD)); 21709566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat_ctx->l2g_lambda, mat_ctx->lambda_local, fetidp_flux_rhs, ADD_VALUES, SCATTER_FORWARD)); 2171229984c5Sstefano_zampini /* Add contribution to interface pressures */ 2172229984c5Sstefano_zampini if (mat_ctx->l2g_p) { 21739566063dSJacob Faibussowitsch PetscCall(MatMult(mat_ctx->B_BB, pcis->vec1_B, mat_ctx->vP)); 21741baa6e33SBarry Smith if (pcbddc->switch_static) PetscCall(MatMultAdd(mat_ctx->B_BI, pcis->vec1_D, mat_ctx->vP, mat_ctx->vP)); 21759566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat_ctx->l2g_p, mat_ctx->vP, fetidp_flux_rhs, ADD_VALUES, SCATTER_FORWARD)); 21769566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat_ctx->l2g_p, mat_ctx->vP, fetidp_flux_rhs, ADD_VALUES, SCATTER_FORWARD)); 2177229984c5Sstefano_zampini } 21783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 21793425bc38SStefano Zampini } 21801e6b0712SBarry Smith 21813425bc38SStefano Zampini /*@ 218298ad52f2SBarry Smith PCBDDCMatFETIDPGetRHS - Compute the right-hand side for a FETI-DP linear system using the physical right-hand side 21833425bc38SStefano Zampini 21843425bc38SStefano Zampini Collective 21853425bc38SStefano Zampini 21863425bc38SStefano Zampini Input Parameters: 2187f1580f4eSBarry Smith + fetidp_mat - the FETI-DP matrix object obtained by a call to `PCBDDCCreateFETIDPOperators()` 21880f202f7eSStefano Zampini - standard_rhs - the right-hand side of the original linear system 21893425bc38SStefano Zampini 2190f1580f4eSBarry Smith Output Parameter: 21910f202f7eSStefano Zampini . fetidp_flux_rhs - the right-hand side for the FETI-DP linear system 21923425bc38SStefano Zampini 21933425bc38SStefano Zampini Level: developer 21943425bc38SStefano Zampini 2195562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCCreateFETIDPOperators()`, `PCBDDCMatFETIDPGetSolution()` 21963425bc38SStefano Zampini @*/ 2197d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCMatFETIDPGetRHS(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs) 2198d71ae5a4SJacob Faibussowitsch { 2199674ae819SStefano Zampini FETIDPMat_ctx mat_ctx; 22003425bc38SStefano Zampini 22013425bc38SStefano Zampini PetscFunctionBegin; 2202266e20e9SStefano Zampini PetscValidHeaderSpecific(fetidp_mat, MAT_CLASSID, 1); 2203266e20e9SStefano Zampini PetscValidHeaderSpecific(standard_rhs, VEC_CLASSID, 2); 2204266e20e9SStefano Zampini PetscValidHeaderSpecific(fetidp_flux_rhs, VEC_CLASSID, 3); 22059566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(fetidp_mat, &mat_ctx)); 2206cac4c232SBarry Smith PetscUseMethod(mat_ctx->pc, "PCBDDCMatFETIDPGetRHS_C", (Mat, Vec, Vec), (fetidp_mat, standard_rhs, fetidp_flux_rhs)); 22073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22083425bc38SStefano Zampini } 22091e6b0712SBarry Smith 2210d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCMatFETIDPGetSolution_BDDC(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol) 2211d71ae5a4SJacob Faibussowitsch { 2212674ae819SStefano Zampini FETIDPMat_ctx mat_ctx; 22133425bc38SStefano Zampini PC_IS *pcis; 22143425bc38SStefano Zampini PC_BDDC *pcbddc; 2215229984c5Sstefano_zampini Vec work; 22163425bc38SStefano Zampini 22173425bc38SStefano Zampini PetscFunctionBegin; 22189566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(fetidp_mat, &mat_ctx)); 22193425bc38SStefano Zampini pcis = (PC_IS *)mat_ctx->pc->data; 22203425bc38SStefano Zampini pcbddc = (PC_BDDC *)mat_ctx->pc->data; 22213425bc38SStefano Zampini 22223425bc38SStefano Zampini /* apply B_delta^T */ 22239566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_B, 0.)); 22249566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat_ctx->l2g_lambda, fetidp_flux_sol, mat_ctx->lambda_local, INSERT_VALUES, SCATTER_REVERSE)); 22259566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat_ctx->l2g_lambda, fetidp_flux_sol, mat_ctx->lambda_local, INSERT_VALUES, SCATTER_REVERSE)); 22269566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(mat_ctx->B_delta, mat_ctx->lambda_local, pcis->vec1_B)); 2227229984c5Sstefano_zampini if (mat_ctx->l2g_p) { 22289566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat_ctx->l2g_p, fetidp_flux_sol, mat_ctx->vP, INSERT_VALUES, SCATTER_REVERSE)); 22299566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat_ctx->l2g_p, fetidp_flux_sol, mat_ctx->vP, INSERT_VALUES, SCATTER_REVERSE)); 22309566063dSJacob Faibussowitsch PetscCall(MatMultAdd(mat_ctx->Bt_BB, mat_ctx->vP, pcis->vec1_B, pcis->vec1_B)); 2231229984c5Sstefano_zampini } 2232229984c5Sstefano_zampini 22333425bc38SStefano Zampini /* compute rhs for BDDC application */ 22349566063dSJacob Faibussowitsch PetscCall(VecAYPX(pcis->vec1_B, -1.0, mat_ctx->temp_solution_B)); 22358eeda7d8SStefano Zampini if (pcbddc->switch_static) { 22369566063dSJacob Faibussowitsch PetscCall(VecCopy(mat_ctx->temp_solution_D, pcis->vec1_D)); 2237229984c5Sstefano_zampini if (mat_ctx->l2g_p) { 22389566063dSJacob Faibussowitsch PetscCall(VecScale(mat_ctx->vP, -1.)); 22399566063dSJacob Faibussowitsch PetscCall(MatMultAdd(mat_ctx->Bt_BI, mat_ctx->vP, pcis->vec1_D, pcis->vec1_D)); 22403425bc38SStefano Zampini } 2241229984c5Sstefano_zampini } 2242229984c5Sstefano_zampini 22433425bc38SStefano Zampini /* apply BDDC */ 22449566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(pcbddc->benign_p0, pcbddc->benign_n)); 22459566063dSJacob Faibussowitsch PetscCall(PCBDDCApplyInterfacePreconditioner(mat_ctx->pc, PETSC_FALSE)); 2246229984c5Sstefano_zampini 2247229984c5Sstefano_zampini /* put values into global vector */ 2248af140850Sstefano_zampini if (pcbddc->ChangeOfBasisMatrix) work = pcbddc->work_change; 2249af140850Sstefano_zampini else work = standard_sol; 22509566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_B, pcis->vec1_B, work, INSERT_VALUES, SCATTER_REVERSE)); 22519566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_B, pcis->vec1_B, work, INSERT_VALUES, SCATTER_REVERSE)); 22528eeda7d8SStefano Zampini if (!pcbddc->switch_static) { 22533425bc38SStefano Zampini /* compute values into the interior if solved for the partially subassembled Schur complement */ 22549566063dSJacob Faibussowitsch PetscCall(MatMult(pcis->A_IB, pcis->vec1_B, pcis->vec1_D)); 22559566063dSJacob Faibussowitsch PetscCall(VecAYPX(pcis->vec1_D, -1.0, mat_ctx->temp_solution_D)); 22569566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], mat_ctx->pc, 0, 0, 0)); 22579566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_D, pcis->vec1_D, pcis->vec1_D)); 22589566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], mat_ctx->pc, 0, 0, 0)); 2259c0decd05SBarry Smith /* Cannot propagate up error in KSPSolve() because there is no access to the PC */ 22603425bc38SStefano Zampini } 2261229984c5Sstefano_zampini 22629566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec1_D, work, INSERT_VALUES, SCATTER_REVERSE)); 22639566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec1_D, work, INSERT_VALUES, SCATTER_REVERSE)); 2264266e20e9SStefano Zampini /* add p0 solution to final solution */ 22659566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignGetOrSetP0(mat_ctx->pc, work, PETSC_FALSE)); 22661baa6e33SBarry Smith if (pcbddc->ChangeOfBasisMatrix) PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix, work, standard_sol)); 22679566063dSJacob Faibussowitsch PetscCall(PCPostSolve_BDDC(mat_ctx->pc, NULL, NULL, standard_sol)); 2268af140850Sstefano_zampini if (mat_ctx->g2g_p) { 22699566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat_ctx->g2g_p, fetidp_flux_sol, standard_sol, INSERT_VALUES, SCATTER_REVERSE)); 22709566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat_ctx->g2g_p, fetidp_flux_sol, standard_sol, INSERT_VALUES, SCATTER_REVERSE)); 2271229984c5Sstefano_zampini } 22723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22733425bc38SStefano Zampini } 22741e6b0712SBarry Smith 2275d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_BDDCIPC(PC pc, PetscViewer viewer) 2276d71ae5a4SJacob Faibussowitsch { 22775a1e936bSStefano Zampini BDDCIPC_ctx bddcipc_ctx; 22785a1e936bSStefano Zampini PetscBool isascii; 22795a1e936bSStefano Zampini 22805a1e936bSStefano Zampini PetscFunctionBegin; 22819566063dSJacob Faibussowitsch PetscCall(PCShellGetContext(pc, &bddcipc_ctx)); 22829566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 228348a46eb9SPierre Jolivet if (isascii) PetscCall(PetscViewerASCIIPrintf(viewer, "BDDC interface preconditioner\n")); 22849566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 22859566063dSJacob Faibussowitsch PetscCall(PCView(bddcipc_ctx->bddc, viewer)); 22869566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 22873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22885a1e936bSStefano Zampini } 22895a1e936bSStefano Zampini 2290d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetUp_BDDCIPC(PC pc) 2291d71ae5a4SJacob Faibussowitsch { 22925a1e936bSStefano Zampini BDDCIPC_ctx bddcipc_ctx; 22935a1e936bSStefano Zampini PetscBool isbddc; 22945a1e936bSStefano Zampini Vec vv; 22955a1e936bSStefano Zampini IS is; 22965a1e936bSStefano Zampini PC_IS *pcis; 22975a1e936bSStefano Zampini 22985a1e936bSStefano Zampini PetscFunctionBegin; 22999566063dSJacob Faibussowitsch PetscCall(PCShellGetContext(pc, &bddcipc_ctx)); 23009566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)bddcipc_ctx->bddc, PCBDDC, &isbddc)); 230128b400f6SJacob Faibussowitsch PetscCheck(isbddc, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Invalid type %s. Must be of type bddc", ((PetscObject)bddcipc_ctx->bddc)->type_name); 23029566063dSJacob Faibussowitsch PetscCall(PCSetUp(bddcipc_ctx->bddc)); 23035a1e936bSStefano Zampini 23045a1e936bSStefano Zampini /* create interface scatter */ 2305*f4f49eeaSPierre Jolivet pcis = (PC_IS *)bddcipc_ctx->bddc->data; 23069566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&bddcipc_ctx->g2l)); 23079566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(pc->pmat, &vv, NULL)); 23089566063dSJacob Faibussowitsch PetscCall(ISRenumber(pcis->is_B_global, NULL, NULL, &is)); 23099566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(vv, is, pcis->vec1_B, NULL, &bddcipc_ctx->g2l)); 23109566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 23119566063dSJacob Faibussowitsch PetscCall(VecDestroy(&vv)); 23123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23135a1e936bSStefano Zampini } 23145a1e936bSStefano Zampini 2315d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApply_BDDCIPC(PC pc, Vec r, Vec x) 2316d71ae5a4SJacob Faibussowitsch { 23175a1e936bSStefano Zampini BDDCIPC_ctx bddcipc_ctx; 23185a1e936bSStefano Zampini PC_IS *pcis; 23195a1e936bSStefano Zampini VecScatter tmps; 23205a1e936bSStefano Zampini 23215a1e936bSStefano Zampini PetscFunctionBegin; 23229566063dSJacob Faibussowitsch PetscCall(PCShellGetContext(pc, &bddcipc_ctx)); 2323*f4f49eeaSPierre Jolivet pcis = (PC_IS *)bddcipc_ctx->bddc->data; 23245a1e936bSStefano Zampini tmps = pcis->global_to_B; 23255a1e936bSStefano Zampini pcis->global_to_B = bddcipc_ctx->g2l; 23269566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingRestriction(bddcipc_ctx->bddc, r, pcis->vec1_B)); 23279566063dSJacob Faibussowitsch PetscCall(PCBDDCApplyInterfacePreconditioner(bddcipc_ctx->bddc, PETSC_FALSE)); 23289566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingExtension(bddcipc_ctx->bddc, pcis->vec1_B, x)); 23295a1e936bSStefano Zampini pcis->global_to_B = tmps; 23303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23315a1e936bSStefano Zampini } 23325a1e936bSStefano Zampini 2333d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApplyTranspose_BDDCIPC(PC pc, Vec r, Vec x) 2334d71ae5a4SJacob Faibussowitsch { 23355a1e936bSStefano Zampini BDDCIPC_ctx bddcipc_ctx; 23365a1e936bSStefano Zampini PC_IS *pcis; 23375a1e936bSStefano Zampini VecScatter tmps; 23385a1e936bSStefano Zampini 23395a1e936bSStefano Zampini PetscFunctionBegin; 23409566063dSJacob Faibussowitsch PetscCall(PCShellGetContext(pc, &bddcipc_ctx)); 2341*f4f49eeaSPierre Jolivet pcis = (PC_IS *)bddcipc_ctx->bddc->data; 23425a1e936bSStefano Zampini tmps = pcis->global_to_B; 23435a1e936bSStefano Zampini pcis->global_to_B = bddcipc_ctx->g2l; 23449566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingRestriction(bddcipc_ctx->bddc, r, pcis->vec1_B)); 23459566063dSJacob Faibussowitsch PetscCall(PCBDDCApplyInterfacePreconditioner(bddcipc_ctx->bddc, PETSC_TRUE)); 23469566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingExtension(bddcipc_ctx->bddc, pcis->vec1_B, x)); 23475a1e936bSStefano Zampini pcis->global_to_B = tmps; 23483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23495a1e936bSStefano Zampini } 23505a1e936bSStefano Zampini 2351d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCDestroy_BDDCIPC(PC pc) 2352d71ae5a4SJacob Faibussowitsch { 23535a1e936bSStefano Zampini BDDCIPC_ctx bddcipc_ctx; 23545a1e936bSStefano Zampini 23555a1e936bSStefano Zampini PetscFunctionBegin; 23569566063dSJacob Faibussowitsch PetscCall(PCShellGetContext(pc, &bddcipc_ctx)); 23579566063dSJacob Faibussowitsch PetscCall(PCDestroy(&bddcipc_ctx->bddc)); 23589566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&bddcipc_ctx->g2l)); 23599566063dSJacob Faibussowitsch PetscCall(PetscFree(bddcipc_ctx)); 23603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23615a1e936bSStefano Zampini } 23625a1e936bSStefano Zampini 23633425bc38SStefano Zampini /*@ 23640f202f7eSStefano Zampini PCBDDCMatFETIDPGetSolution - Compute the physical solution using the solution of the FETI-DP linear system 23653425bc38SStefano Zampini 23663425bc38SStefano Zampini Collective 23673425bc38SStefano Zampini 23683425bc38SStefano Zampini Input Parameters: 236920f4b53cSBarry Smith + fetidp_mat - the FETI-DP matrix obtained by a call to `PCBDDCCreateFETIDPOperators()` 2370f1580f4eSBarry Smith - fetidp_flux_sol - the solution of the FETI-DP linear system` 23713425bc38SStefano Zampini 2372f1580f4eSBarry Smith Output Parameter: 23730f202f7eSStefano Zampini . standard_sol - the solution defined on the physical domain 23743425bc38SStefano Zampini 23753425bc38SStefano Zampini Level: developer 23763425bc38SStefano Zampini 2377562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCCreateFETIDPOperators()`, `PCBDDCMatFETIDPGetRHS()` 23783425bc38SStefano Zampini @*/ 2379d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCMatFETIDPGetSolution(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol) 2380d71ae5a4SJacob Faibussowitsch { 2381674ae819SStefano Zampini FETIDPMat_ctx mat_ctx; 23823425bc38SStefano Zampini 23833425bc38SStefano Zampini PetscFunctionBegin; 2384266e20e9SStefano Zampini PetscValidHeaderSpecific(fetidp_mat, MAT_CLASSID, 1); 2385266e20e9SStefano Zampini PetscValidHeaderSpecific(fetidp_flux_sol, VEC_CLASSID, 2); 2386266e20e9SStefano Zampini PetscValidHeaderSpecific(standard_sol, VEC_CLASSID, 3); 23879566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(fetidp_mat, &mat_ctx)); 2388cac4c232SBarry Smith PetscUseMethod(mat_ctx->pc, "PCBDDCMatFETIDPGetSolution_C", (Mat, Vec, Vec), (fetidp_mat, fetidp_flux_sol, standard_sol)); 23893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23903425bc38SStefano Zampini } 23911e6b0712SBarry Smith 2392d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCCreateFETIDPOperators_BDDC(PC pc, PetscBool fully_redundant, const char *prefix, Mat *fetidp_mat, PC *fetidp_pc) 2393d71ae5a4SJacob Faibussowitsch { 2394674ae819SStefano Zampini FETIDPMat_ctx fetidpmat_ctx; 23953425bc38SStefano Zampini Mat newmat; 2396674ae819SStefano Zampini FETIDPPC_ctx fetidppc_ctx; 23973425bc38SStefano Zampini PC newpc; 2398ce94432eSBarry Smith MPI_Comm comm; 23993425bc38SStefano Zampini 24003425bc38SStefano Zampini PetscFunctionBegin; 24019566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)pc, &comm)); 240215579a77SStefano Zampini /* FETI-DP matrix */ 24039566063dSJacob Faibussowitsch PetscCall(PCBDDCCreateFETIDPMatContext(pc, &fetidpmat_ctx)); 24041720468bSStefano Zampini fetidpmat_ctx->fully_redundant = fully_redundant; 24059566063dSJacob Faibussowitsch PetscCall(PCBDDCSetupFETIDPMatContext(fetidpmat_ctx)); 24069566063dSJacob Faibussowitsch PetscCall(MatCreateShell(comm, fetidpmat_ctx->n, fetidpmat_ctx->n, fetidpmat_ctx->N, fetidpmat_ctx->N, fetidpmat_ctx, &newmat)); 24079566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)newmat, !fetidpmat_ctx->l2g_lambda_only ? "F" : "G")); 24089566063dSJacob Faibussowitsch PetscCall(MatShellSetOperation(newmat, MATOP_MULT, (void (*)(void))FETIDPMatMult)); 24099566063dSJacob Faibussowitsch PetscCall(MatShellSetOperation(newmat, MATOP_MULT_TRANSPOSE, (void (*)(void))FETIDPMatMultTranspose)); 24109566063dSJacob Faibussowitsch PetscCall(MatShellSetOperation(newmat, MATOP_DESTROY, (void (*)(void))PCBDDCDestroyFETIDPMat)); 241115579a77SStefano Zampini /* propagate MatOptions */ 241215579a77SStefano Zampini { 241315579a77SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)fetidpmat_ctx->pc->data; 2414b94d7dedSBarry Smith PetscBool isset, issym; 241515579a77SStefano Zampini 2416b94d7dedSBarry Smith PetscCall(MatIsSymmetricKnown(pc->mat, &isset, &issym)); 2417b94d7dedSBarry Smith if ((isset && issym) || pcbddc->symmetric_primal) PetscCall(MatSetOption(newmat, MAT_SYMMETRIC, PETSC_TRUE)); 241815579a77SStefano Zampini } 24199566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(newmat, prefix)); 24209566063dSJacob Faibussowitsch PetscCall(MatAppendOptionsPrefix(newmat, "fetidp_")); 24219566063dSJacob Faibussowitsch PetscCall(MatSetUp(newmat)); 242215579a77SStefano Zampini /* FETI-DP preconditioner */ 24239566063dSJacob Faibussowitsch PetscCall(PCBDDCCreateFETIDPPCContext(pc, &fetidppc_ctx)); 24249566063dSJacob Faibussowitsch PetscCall(PCBDDCSetupFETIDPPCContext(newmat, fetidppc_ctx)); 24259566063dSJacob Faibussowitsch PetscCall(PCCreate(comm, &newpc)); 24269566063dSJacob Faibussowitsch PetscCall(PCSetOperators(newpc, newmat, newmat)); 24279566063dSJacob Faibussowitsch PetscCall(PCSetOptionsPrefix(newpc, prefix)); 24289566063dSJacob Faibussowitsch PetscCall(PCAppendOptionsPrefix(newpc, "fetidp_")); 24299566063dSJacob Faibussowitsch PetscCall(PCSetErrorIfFailure(newpc, pc->erroriffailure)); 243015579a77SStefano Zampini if (!fetidpmat_ctx->l2g_lambda_only) { /* standard FETI-DP */ 24319566063dSJacob Faibussowitsch PetscCall(PCSetType(newpc, PCSHELL)); 24329566063dSJacob Faibussowitsch PetscCall(PCShellSetName(newpc, "FETI-DP multipliers")); 24339566063dSJacob Faibussowitsch PetscCall(PCShellSetContext(newpc, fetidppc_ctx)); 24349566063dSJacob Faibussowitsch PetscCall(PCShellSetApply(newpc, FETIDPPCApply)); 24359566063dSJacob Faibussowitsch PetscCall(PCShellSetApplyTranspose(newpc, FETIDPPCApplyTranspose)); 24369566063dSJacob Faibussowitsch PetscCall(PCShellSetView(newpc, FETIDPPCView)); 24379566063dSJacob Faibussowitsch PetscCall(PCShellSetDestroy(newpc, PCBDDCDestroyFETIDPPC)); 24385a1e936bSStefano Zampini } else { /* saddle-point FETI-DP */ 24395a1e936bSStefano Zampini Mat M; 24405a1e936bSStefano Zampini PetscInt psize; 24415a1e936bSStefano Zampini PetscBool fake = PETSC_FALSE, isfieldsplit; 2442e1214c54Sstefano_zampini 24439566063dSJacob Faibussowitsch PetscCall(ISViewFromOptions(fetidpmat_ctx->lagrange, NULL, "-lag_view")); 24449566063dSJacob Faibussowitsch PetscCall(ISViewFromOptions(fetidpmat_ctx->pressure, NULL, "-press_view")); 24459566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_PPmat", (PetscObject *)&M)); 24469566063dSJacob Faibussowitsch PetscCall(PCSetType(newpc, PCFIELDSPLIT)); 24479566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSetIS(newpc, "lag", fetidpmat_ctx->lagrange)); 24489566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSetIS(newpc, "p", fetidpmat_ctx->pressure)); 24499566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSetType(newpc, PC_COMPOSITE_SCHUR)); 24509566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSetSchurFactType(newpc, PC_FIELDSPLIT_SCHUR_FACT_DIAG)); 24519566063dSJacob Faibussowitsch PetscCall(ISGetSize(fetidpmat_ctx->pressure, &psize)); 24525a1e936bSStefano Zampini if (psize != M->rmap->N) { 24535a1e936bSStefano Zampini Mat M2; 24545a1e936bSStefano Zampini PetscInt lpsize; 24555a1e936bSStefano Zampini 24565a1e936bSStefano Zampini fake = PETSC_TRUE; 24579566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(fetidpmat_ctx->pressure, &lpsize)); 24589566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &M2)); 24599566063dSJacob Faibussowitsch PetscCall(MatSetType(M2, MATAIJ)); 24609566063dSJacob Faibussowitsch PetscCall(MatSetSizes(M2, lpsize, lpsize, psize, psize)); 24619566063dSJacob Faibussowitsch PetscCall(MatSetUp(M2)); 24629566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(M2, MAT_FINAL_ASSEMBLY)); 24639566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(M2, MAT_FINAL_ASSEMBLY)); 24649566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSetSchurPre(newpc, PC_FIELDSPLIT_SCHUR_PRE_USER, M2)); 24659566063dSJacob Faibussowitsch PetscCall(MatDestroy(&M2)); 24665a1e936bSStefano Zampini } else { 24679566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSetSchurPre(newpc, PC_FIELDSPLIT_SCHUR_PRE_USER, M)); 24685a1e936bSStefano Zampini } 24699566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSetSchurScale(newpc, 1.0)); 247015579a77SStefano Zampini 247115579a77SStefano Zampini /* we need to setfromoptions and setup here to access the blocks */ 24729566063dSJacob Faibussowitsch PetscCall(PCSetFromOptions(newpc)); 24739566063dSJacob Faibussowitsch PetscCall(PCSetUp(newpc)); 2474e1214c54Sstefano_zampini 24755a1e936bSStefano Zampini /* user may have changed the type (e.g. -fetidp_pc_type none) */ 24769566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)newpc, PCFIELDSPLIT, &isfieldsplit)); 24775a1e936bSStefano Zampini if (isfieldsplit) { 24785a1e936bSStefano Zampini KSP *ksps; 24795a1e936bSStefano Zampini PC ppc, lagpc; 24805a1e936bSStefano Zampini PetscInt nn; 2481064a4176SStefano Zampini PetscBool ismatis, matisok = PETSC_FALSE, check = PETSC_FALSE; 24825a1e936bSStefano Zampini 2483e1214c54Sstefano_zampini /* set the solver for the (0,0) block */ 24849566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSchurGetSubKSP(newpc, &nn, &ksps)); 24855a1e936bSStefano Zampini if (!nn) { /* not of type PC_COMPOSITE_SCHUR */ 24869566063dSJacob Faibussowitsch PetscCall(PCFieldSplitGetSubKSP(newpc, &nn, &ksps)); 24875a1e936bSStefano Zampini if (!fake) { /* pass pmat to the pressure solver */ 24885a1e936bSStefano Zampini Mat F; 24895a1e936bSStefano Zampini 24909566063dSJacob Faibussowitsch PetscCall(KSPGetOperators(ksps[1], &F, NULL)); 24919566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(ksps[1], F, M)); 24925a1e936bSStefano Zampini } 24935a1e936bSStefano Zampini } else { 2494b94d7dedSBarry Smith PetscBool issym, isset; 24955a1e936bSStefano Zampini Mat S; 24965a1e936bSStefano Zampini 24979566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSchurGetS(newpc, &S)); 2498b94d7dedSBarry Smith PetscCall(MatIsSymmetricKnown(newmat, &isset, &issym)); 2499b94d7dedSBarry Smith if (isset) PetscCall(MatSetOption(S, MAT_SYMMETRIC, issym)); 25005a1e936bSStefano Zampini } 25019566063dSJacob Faibussowitsch PetscCall(KSPGetPC(ksps[0], &lagpc)); 25029566063dSJacob Faibussowitsch PetscCall(PCSetType(lagpc, PCSHELL)); 25039566063dSJacob Faibussowitsch PetscCall(PCShellSetName(lagpc, "FETI-DP multipliers")); 25049566063dSJacob Faibussowitsch PetscCall(PCShellSetContext(lagpc, fetidppc_ctx)); 25059566063dSJacob Faibussowitsch PetscCall(PCShellSetApply(lagpc, FETIDPPCApply)); 25069566063dSJacob Faibussowitsch PetscCall(PCShellSetApplyTranspose(lagpc, FETIDPPCApplyTranspose)); 25079566063dSJacob Faibussowitsch PetscCall(PCShellSetView(lagpc, FETIDPPCView)); 25089566063dSJacob Faibussowitsch PetscCall(PCShellSetDestroy(lagpc, PCBDDCDestroyFETIDPPC)); 25095a1e936bSStefano Zampini 25105a1e936bSStefano Zampini /* Olof's idea: interface Schur complement preconditioner for the mass matrix */ 25119566063dSJacob Faibussowitsch PetscCall(KSPGetPC(ksps[1], &ppc)); 25125a1e936bSStefano Zampini if (fake) { 25135a1e936bSStefano Zampini BDDCIPC_ctx bddcipc_ctx; 2514ff11fd76SStefano Zampini PetscContainer c; 25155a1e936bSStefano Zampini 25165a1e936bSStefano Zampini matisok = PETSC_TRUE; 25175a1e936bSStefano Zampini 25185a1e936bSStefano Zampini /* create inner BDDC solver */ 25199566063dSJacob Faibussowitsch PetscCall(PetscNew(&bddcipc_ctx)); 25209566063dSJacob Faibussowitsch PetscCall(PCCreate(comm, &bddcipc_ctx->bddc)); 25219566063dSJacob Faibussowitsch PetscCall(PCSetType(bddcipc_ctx->bddc, PCBDDC)); 25229566063dSJacob Faibussowitsch PetscCall(PCSetOperators(bddcipc_ctx->bddc, M, M)); 25239566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_pCSR", (PetscObject *)&c)); 25249566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)M, MATIS, &ismatis)); 2525ff11fd76SStefano Zampini if (c && ismatis) { 2526ff11fd76SStefano Zampini Mat lM; 2527ff11fd76SStefano Zampini PetscInt *csr, n; 2528ff11fd76SStefano Zampini 25299566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(M, &lM)); 25309566063dSJacob Faibussowitsch PetscCall(MatGetSize(lM, &n, NULL)); 25319566063dSJacob Faibussowitsch PetscCall(PetscContainerGetPointer(c, (void **)&csr)); 25329566063dSJacob Faibussowitsch PetscCall(PCBDDCSetLocalAdjacencyGraph(bddcipc_ctx->bddc, n, csr, csr + (n + 1), PETSC_COPY_VALUES)); 25339566063dSJacob Faibussowitsch PetscCall(MatISRestoreLocalMat(M, &lM)); 2534ff11fd76SStefano Zampini } 25359566063dSJacob Faibussowitsch PetscCall(PCSetOptionsPrefix(bddcipc_ctx->bddc, ((PetscObject)ksps[1])->prefix)); 25369566063dSJacob Faibussowitsch PetscCall(PCSetErrorIfFailure(bddcipc_ctx->bddc, pc->erroriffailure)); 25379566063dSJacob Faibussowitsch PetscCall(PCSetFromOptions(bddcipc_ctx->bddc)); 25385a1e936bSStefano Zampini 25395a1e936bSStefano Zampini /* wrap the interface application */ 25409566063dSJacob Faibussowitsch PetscCall(PCSetType(ppc, PCSHELL)); 25419566063dSJacob Faibussowitsch PetscCall(PCShellSetName(ppc, "FETI-DP pressure")); 25429566063dSJacob Faibussowitsch PetscCall(PCShellSetContext(ppc, bddcipc_ctx)); 25439566063dSJacob Faibussowitsch PetscCall(PCShellSetSetUp(ppc, PCSetUp_BDDCIPC)); 25449566063dSJacob Faibussowitsch PetscCall(PCShellSetApply(ppc, PCApply_BDDCIPC)); 25459566063dSJacob Faibussowitsch PetscCall(PCShellSetApplyTranspose(ppc, PCApplyTranspose_BDDCIPC)); 25469566063dSJacob Faibussowitsch PetscCall(PCShellSetView(ppc, PCView_BDDCIPC)); 25479566063dSJacob Faibussowitsch PetscCall(PCShellSetDestroy(ppc, PCDestroy_BDDCIPC)); 25485a1e936bSStefano Zampini } 25495a1e936bSStefano Zampini 25505a1e936bSStefano Zampini /* determine if we need to assemble M to construct a preconditioner */ 25515a1e936bSStefano Zampini if (!matisok) { 25529566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)M, MATIS, &ismatis)); 25539566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)ppc, &matisok, PCBDDC, PCJACOBI, PCNONE, PCMG, "")); 255448a46eb9SPierre Jolivet if (ismatis && !matisok) PetscCall(MatConvert(M, MATAIJ, MAT_INPLACE_MATRIX, &M)); 25555a1e936bSStefano Zampini } 2556064a4176SStefano Zampini 2557064a4176SStefano Zampini /* run the subproblems to check convergence */ 25589566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, ((PetscObject)newmat)->prefix, "-check_saddlepoint", &check, NULL)); 2559064a4176SStefano Zampini if (check) { 2560064a4176SStefano Zampini PetscInt i; 2561064a4176SStefano Zampini 2562064a4176SStefano Zampini for (i = 0; i < nn; i++) { 2563064a4176SStefano Zampini KSP kspC; 2564e8f11ae9SBarry Smith PC npc; 2565064a4176SStefano Zampini Mat F, pF; 2566064a4176SStefano Zampini Vec x, y; 2567064a4176SStefano Zampini PetscBool isschur, prec = PETSC_TRUE; 2568064a4176SStefano Zampini 25699566063dSJacob Faibussowitsch PetscCall(KSPCreate(PetscObjectComm((PetscObject)ksps[i]), &kspC)); 25703821be0aSBarry Smith PetscCall(KSPSetNestLevel(kspC, pc->kspnestlevel)); 25719566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(kspC, ((PetscObject)ksps[i])->prefix)); 25729566063dSJacob Faibussowitsch PetscCall(KSPAppendOptionsPrefix(kspC, "check_")); 25739566063dSJacob Faibussowitsch PetscCall(KSPGetOperators(ksps[i], &F, &pF)); 25749566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)F, MATSCHURCOMPLEMENT, &isschur)); 2575064a4176SStefano Zampini if (isschur) { 2576064a4176SStefano Zampini KSP kspS, kspS2; 2577064a4176SStefano Zampini Mat A00, pA00, A10, A01, A11; 2578064a4176SStefano Zampini char prefix[256]; 2579064a4176SStefano Zampini 25809566063dSJacob Faibussowitsch PetscCall(MatSchurComplementGetKSP(F, &kspS)); 25819566063dSJacob Faibussowitsch PetscCall(MatSchurComplementGetSubMatrices(F, &A00, &pA00, &A01, &A10, &A11)); 25829566063dSJacob Faibussowitsch PetscCall(MatCreateSchurComplement(A00, pA00, A01, A10, A11, &F)); 25839566063dSJacob Faibussowitsch PetscCall(MatSchurComplementGetKSP(F, &kspS2)); 25849566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(prefix, sizeof(prefix), "%sschur_", ((PetscObject)kspC)->prefix)); 25859566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(kspS2, prefix)); 2586e8f11ae9SBarry Smith PetscCall(KSPGetPC(kspS2, &npc)); 2587e8f11ae9SBarry Smith PetscCall(PCSetType(npc, PCKSP)); 2588e8f11ae9SBarry Smith PetscCall(PCKSPSetKSP(npc, kspS)); 25899566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(kspS2)); 2590e8f11ae9SBarry Smith PetscCall(KSPGetPC(kspS2, &npc)); 2591e8f11ae9SBarry Smith PetscCall(PCSetUseAmat(npc, PETSC_TRUE)); 2592064a4176SStefano Zampini } else { 25939566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)F)); 2594064a4176SStefano Zampini } 25959566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(kspC)); 25969566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, ((PetscObject)kspC)->prefix, "-preconditioned", &prec, NULL)); 2597064a4176SStefano Zampini if (prec) { 2598e8f11ae9SBarry Smith PetscCall(KSPGetPC(ksps[i], &npc)); 2599e8f11ae9SBarry Smith PetscCall(KSPSetPC(kspC, npc)); 2600064a4176SStefano Zampini } 26019566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(kspC, F, pF)); 26029566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(F, &x, &y)); 26039566063dSJacob Faibussowitsch PetscCall(VecSetRandom(x, NULL)); 26049566063dSJacob Faibussowitsch PetscCall(MatMult(F, x, y)); 26059566063dSJacob Faibussowitsch PetscCall(KSPSolve(kspC, y, x)); 2606e8f11ae9SBarry Smith PetscCall(KSPCheckSolve(kspC, npc, x)); 26079566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&kspC)); 26089566063dSJacob Faibussowitsch PetscCall(MatDestroy(&F)); 26099566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x)); 26109566063dSJacob Faibussowitsch PetscCall(VecDestroy(&y)); 2611064a4176SStefano Zampini } 2612064a4176SStefano Zampini } 26139566063dSJacob Faibussowitsch PetscCall(PetscFree(ksps)); 2614e1214c54Sstefano_zampini } 26155a1e936bSStefano Zampini } 26163425bc38SStefano Zampini /* return pointers for objects created */ 26173425bc38SStefano Zampini *fetidp_mat = newmat; 26183425bc38SStefano Zampini *fetidp_pc = newpc; 26193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 26203425bc38SStefano Zampini } 26211e6b0712SBarry Smith 262294ef8ddeSSatish Balay /*@C 26230f202f7eSStefano Zampini PCBDDCCreateFETIDPOperators - Create FETI-DP operators 26243425bc38SStefano Zampini 26253425bc38SStefano Zampini Collective 26263425bc38SStefano Zampini 26273425bc38SStefano Zampini Input Parameters: 262898ad52f2SBarry Smith + pc - the `PCBDDC` preconditioning context (setup should have been called before) 2629547c9a8eSstefano_zampini . fully_redundant - true for a fully redundant set of Lagrange multipliers 263020f4b53cSBarry Smith - prefix - optional options database prefix for the objects to be created (can be `NULL`) 263128509bceSStefano Zampini 263228509bceSStefano Zampini Output Parameters: 26330f202f7eSStefano Zampini + fetidp_mat - shell FETI-DP matrix object 26340f202f7eSStefano Zampini - fetidp_pc - shell Dirichlet preconditioner for FETI-DP matrix 263528509bceSStefano Zampini 26363425bc38SStefano Zampini Level: developer 26373425bc38SStefano Zampini 2638f1580f4eSBarry Smith Note: 2639f1580f4eSBarry Smith Currently the only operations provided for FETI-DP matrix are `MatMult()` and `MatMultTranspose()` 26403425bc38SStefano Zampini 2641562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCMatFETIDPGetRHS()`, `PCBDDCMatFETIDPGetSolution()` 26423425bc38SStefano Zampini @*/ 2643d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCCreateFETIDPOperators(PC pc, PetscBool fully_redundant, const char *prefix, Mat *fetidp_mat, PC *fetidp_pc) 2644d71ae5a4SJacob Faibussowitsch { 26453425bc38SStefano Zampini PetscFunctionBegin; 26463425bc38SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 26470fdf79fbSJacob Faibussowitsch PetscCheck(pc->setupcalled, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "You must call PCSetup_BDDC() first"); 2648cac4c232SBarry Smith PetscUseMethod(pc, "PCBDDCCreateFETIDPOperators_C", (PC, PetscBool, const char *, Mat *, PC *), (pc, fully_redundant, prefix, fetidp_mat, fetidp_pc)); 26493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 26503425bc38SStefano Zampini } 2651f1580f4eSBarry Smith 2652da1bb401SStefano Zampini /*MC 26531d27aa22SBarry Smith PCBDDC - Balancing Domain Decomposition by Constraints preconditioners, {cite}`dohrmann2007approximate`, {cite}`klawonn2006dual`, {cite}`mandel2008multispace` 26540c7d97c5SJed Brown 2655f1580f4eSBarry Smith Requires `MATIS` matrices (Pmat) with local matrices (inside the `MATIS`) of type `MATSEQAIJ`, `MATSEQBAIJ` or `MATSEQSBAIJ` 265628509bceSStefano Zampini 265728509bceSStefano Zampini It also works with unsymmetric and indefinite problems. 265828509bceSStefano Zampini 2659f1580f4eSBarry Smith Unlike 'conventional' interface preconditioners, `PCBDDC` iterates over all degrees of freedom, not just those on the interface. This allows the use 2660f1580f4eSBarry Smith of approximate solvers on the subdomains. 2661b6fdb6dfSStefano Zampini 26621d27aa22SBarry Smith Approximate local solvers are automatically adapted (see {cite}`dohrmann2007approximate`,) if the user has attached a nullspace object to the subdomain matrices, and informed 2663f1580f4eSBarry Smith `PCBDDC` of using approximate solvers (via the command line). 266428509bceSStefano Zampini 2665f1580f4eSBarry Smith 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. 2666f1580f4eSBarry Smith The latter can be customized by using `PCBDDCSetLocalAdjacencyGraph()` 266728509bceSStefano Zampini 2668f1580f4eSBarry Smith Additional information on dofs can be provided by using `PCBDDCSetDofsSplitting()`, `PCBDDCSetDirichletBoundaries()`, `PCBDDCSetNeumannBoundaries()`, and 2669f1580f4eSBarry Smith `PCBDDCSetPrimalVerticesIS()` and their local counterparts. 267028509bceSStefano Zampini 2671f1580f4eSBarry Smith Constraints can be customized by attaching a `MatNullSpace` object to the `MATIS` matrix via `MatSetNearNullSpace()`. Non-singular modes are retained via SVD. 267228509bceSStefano Zampini 26731d27aa22SBarry Smith Change of basis is performed similarly to {cite}`klawonn2006dual` when requested. When more than one constraint is present on a single connected component 2674f1580f4eSBarry Smith (i.e. an edge or a face), a robust method based on local QR factorizations is used. 2675f1580f4eSBarry Smith User defined change of basis can be passed to `PCBDDC` with `PCBDDCSetChangeOfBasisMat()` 267628509bceSStefano Zampini 26771d27aa22SBarry Smith The PETSc implementation also supports multilevel `PCBDDC` {cite}`mandel2008multispace`. Coarse grids are partitioned using a `MatPartitioning` object. 267828509bceSStefano Zampini 26791d27aa22SBarry Smith Adaptive selection of primal constraints is supported for SPD systems with high-contrast in the coefficients if MUMPS or MKL_PARDISO are present. 2680f1580f4eSBarry Smith Future versions of the code will also consider using PASTIX. 26810f202f7eSStefano Zampini 2682f1580f4eSBarry Smith An experimental interface to the FETI-DP method is available. FETI-DP operators could be created using `PCBDDCCreateFETIDPOperators()`. 2683f1580f4eSBarry Smith A stand-alone class for the FETI-DP method will be provided in the next releases. 26840f202f7eSStefano Zampini 2685f1580f4eSBarry Smith Options Database Keys: 2686a2b725a8SWilliam Gropp + -pc_bddc_use_vertices <true> - use or not vertices in primal space 26870f202f7eSStefano Zampini . -pc_bddc_use_edges <true> - use or not edges in primal space 26880f202f7eSStefano Zampini . -pc_bddc_use_faces <false> - use or not faces in primal space 26890f202f7eSStefano Zampini . -pc_bddc_symmetric <true> - symmetric computation of primal basis functions. Specify false for unsymmetric problems 26900f202f7eSStefano Zampini . -pc_bddc_use_change_of_basis <false> - use change of basis approach (on edges only) 26910f202f7eSStefano Zampini . -pc_bddc_use_change_on_faces <false> - use change of basis approach on faces if change of basis has been requested 26920f202f7eSStefano Zampini . -pc_bddc_switch_static <false> - switches from M_2 (default) to M_3 operator (see reference article [1]) 269328509bceSStefano Zampini . -pc_bddc_levels <0> - maximum number of levels for multilevel 26940f202f7eSStefano 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) 26955459c157SBarry 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) 26960f202f7eSStefano Zampini . -pc_bddc_use_deluxe_scaling <false> - use deluxe scaling 269771f2caa7Sprj- . -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) 2698bd2a564bSStefano 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) 269928509bceSStefano Zampini - -pc_bddc_check_level <0> - set verbosity level of debugging output 270028509bceSStefano Zampini 2701f1580f4eSBarry Smith Options for Dirichlet, Neumann or coarse solver can be set using the appropriate options prefix 270228509bceSStefano Zampini .vb 270328509bceSStefano Zampini -pc_bddc_dirichlet_ 270428509bceSStefano Zampini -pc_bddc_neumann_ 270528509bceSStefano Zampini -pc_bddc_coarse_ 270628509bceSStefano Zampini .ve 2707f1580f4eSBarry Smith e.g. -pc_bddc_dirichlet_ksp_type richardson -pc_bddc_dirichlet_pc_type gamg. `PCBDDC` uses by default `KSPPREONLY` and `PCLU`. 270828509bceSStefano Zampini 2709f1580f4eSBarry Smith When using a multilevel approach, solvers' options at the N-th level (N > 1) can be specified using the options prefix 271028509bceSStefano Zampini .vb 2711312be037SStefano Zampini -pc_bddc_dirichlet_lN_ 2712312be037SStefano Zampini -pc_bddc_neumann_lN_ 2713312be037SStefano Zampini -pc_bddc_coarse_lN_ 271428509bceSStefano Zampini .ve 27150f202f7eSStefano Zampini Note that level number ranges from the finest (0) to the coarsest (N). 2716f1580f4eSBarry Smith In order to specify options for the `PCBDDC` operators at the coarser levels (and not for the solvers), prepend -pc_bddc_coarse_ or -pc_bddc_coarse_l 2717f1580f4eSBarry Smith to the option, e.g. 27180f202f7eSStefano Zampini .vb 27190f202f7eSStefano Zampini -pc_bddc_coarse_pc_bddc_adaptive_threshold 5 -pc_bddc_coarse_l1_pc_bddc_redistribute 3 27200f202f7eSStefano Zampini .ve 27210f202f7eSStefano 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 2722da1bb401SStefano Zampini 2723da1bb401SStefano Zampini Level: intermediate 2724da1bb401SStefano Zampini 27251d27aa22SBarry Smith Contributed by: 27261d27aa22SBarry Smith Stefano Zampini 2727da1bb401SStefano Zampini 2728562efe2eSBarry Smith .seealso: [](ch_ksp), `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `MATIS`, `PCLU`, `PCGAMG`, `PC`, `PCBDDCSetLocalAdjacencyGraph()`, `PCBDDCSetDofsSplitting()`, 2729f1580f4eSBarry Smith `PCBDDCSetDirichletBoundaries()`, `PCBDDCSetNeumannBoundaries()`, `PCBDDCSetPrimalVerticesIS()`, `MatNullSpace`, `MatSetNearNullSpace()`, 2730f1580f4eSBarry Smith `PCBDDCSetChangeOfBasisMat()`, `PCBDDCCreateFETIDPOperators()`, `PCNN` 2731da1bb401SStefano Zampini M*/ 2732b2573a8aSBarry Smith 2733d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_BDDC(PC pc) 2734d71ae5a4SJacob Faibussowitsch { 2735da1bb401SStefano Zampini PC_BDDC *pcbddc; 2736da1bb401SStefano Zampini 2737da1bb401SStefano Zampini PetscFunctionBegin; 27384dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&pcbddc)); 27393ec1f749SStefano Zampini pc->data = pcbddc; 2740da1bb401SStefano Zampini 274104c3f3b8SBarry Smith PetscCall(PCISInitialize(pc)); 2742da1bb401SStefano Zampini 27439326c5c6Sstefano_zampini /* create local graph structure */ 27449566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphCreate(&pcbddc->mat_graph)); 27459326c5c6Sstefano_zampini 27469326c5c6Sstefano_zampini /* BDDC nonzero defaults */ 27476d9e27e4SStefano Zampini pcbddc->use_nnsp = PETSC_TRUE; 274808a5cf49SStefano Zampini pcbddc->use_local_adj = PETSC_TRUE; 274947d04d0dSStefano Zampini pcbddc->use_vertices = PETSC_TRUE; 275047d04d0dSStefano Zampini pcbddc->use_edges = PETSC_TRUE; 27513301b35fSStefano Zampini pcbddc->symmetric_primal = PETSC_TRUE; 275214f95afaSStefano Zampini pcbddc->vertex_size = 1; 2753c703fcc7SStefano Zampini pcbddc->recompute_topography = PETSC_TRUE; 275468457ee5SStefano Zampini pcbddc->coarse_size = -1; 275585c4d303SStefano Zampini pcbddc->use_exact_dirichlet_trick = PETSC_TRUE; 275647d04d0dSStefano Zampini pcbddc->coarsening_ratio = 8; 275757de7509SStefano Zampini pcbddc->coarse_eqs_per_proc = 1; 275827b6a85dSStefano Zampini pcbddc->benign_compute_correction = PETSC_TRUE; 27591e0482f5SStefano Zampini pcbddc->nedfield = -1; 27601e0482f5SStefano Zampini pcbddc->nedglobal = PETSC_TRUE; 2761be12c134Sstefano_zampini pcbddc->graphmaxcount = PETSC_MAX_INT; 2762b96c3477SStefano Zampini pcbddc->sub_schurs_layers = -1; 2763bd2a564bSStefano Zampini pcbddc->adaptive_threshold[0] = 0.0; 2764bd2a564bSStefano Zampini pcbddc->adaptive_threshold[1] = 0.0; 2765b7eb3628SStefano Zampini 2766da1bb401SStefano Zampini /* function pointers */ 2767da1bb401SStefano Zampini pc->ops->apply = PCApply_BDDC; 276893bd9ae7SStefano Zampini pc->ops->applytranspose = PCApplyTranspose_BDDC; 2769da1bb401SStefano Zampini pc->ops->setup = PCSetUp_BDDC; 2770da1bb401SStefano Zampini pc->ops->destroy = PCDestroy_BDDC; 2771da1bb401SStefano Zampini pc->ops->setfromoptions = PCSetFromOptions_BDDC; 27726b78500eSPatrick Sanan pc->ops->view = PCView_BDDC; 27730a545947SLisandro Dalcin pc->ops->applyrichardson = NULL; 27740a545947SLisandro Dalcin pc->ops->applysymmetricleft = NULL; 27750a545947SLisandro Dalcin pc->ops->applysymmetricright = NULL; 2776534831adSStefano Zampini pc->ops->presolve = PCPreSolve_BDDC; 2777534831adSStefano Zampini pc->ops->postsolve = PCPostSolve_BDDC; 27789326c5c6Sstefano_zampini pc->ops->reset = PCReset_BDDC; 2779da1bb401SStefano Zampini 2780da1bb401SStefano Zampini /* composing function */ 27819566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDiscreteGradient_C", PCBDDCSetDiscreteGradient_BDDC)); 27829566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDivergenceMat_C", PCBDDCSetDivergenceMat_BDDC)); 27839566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetChangeOfBasisMat_C", PCBDDCSetChangeOfBasisMat_BDDC)); 27849566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetPrimalVerticesLocalIS_C", PCBDDCSetPrimalVerticesLocalIS_BDDC)); 27859566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetPrimalVerticesIS_C", PCBDDCSetPrimalVerticesIS_BDDC)); 27869566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetPrimalVerticesLocalIS_C", PCBDDCGetPrimalVerticesLocalIS_BDDC)); 27879566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetPrimalVerticesIS_C", PCBDDCGetPrimalVerticesIS_BDDC)); 27889566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetCoarseningRatio_C", PCBDDCSetCoarseningRatio_BDDC)); 27899566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLevel_C", PCBDDCSetLevel_BDDC)); 27909566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetUseExactDirichlet_C", PCBDDCSetUseExactDirichlet_BDDC)); 27919566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLevels_C", PCBDDCSetLevels_BDDC)); 27929566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDirichletBoundaries_C", PCBDDCSetDirichletBoundaries_BDDC)); 27939566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDirichletBoundariesLocal_C", PCBDDCSetDirichletBoundariesLocal_BDDC)); 27949566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetNeumannBoundaries_C", PCBDDCSetNeumannBoundaries_BDDC)); 27959566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetNeumannBoundariesLocal_C", PCBDDCSetNeumannBoundariesLocal_BDDC)); 27969566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetDirichletBoundaries_C", PCBDDCGetDirichletBoundaries_BDDC)); 27979566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetDirichletBoundariesLocal_C", PCBDDCGetDirichletBoundariesLocal_BDDC)); 27989566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetNeumannBoundaries_C", PCBDDCGetNeumannBoundaries_BDDC)); 27999566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetNeumannBoundariesLocal_C", PCBDDCGetNeumannBoundariesLocal_BDDC)); 28009566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDofsSplitting_C", PCBDDCSetDofsSplitting_BDDC)); 28019566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDofsSplittingLocal_C", PCBDDCSetDofsSplittingLocal_BDDC)); 28029566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLocalAdjacencyGraph_C", PCBDDCSetLocalAdjacencyGraph_BDDC)); 28039566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCCreateFETIDPOperators_C", PCBDDCCreateFETIDPOperators_BDDC)); 28049566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCMatFETIDPGetRHS_C", PCBDDCMatFETIDPGetRHS_BDDC)); 28059566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCMatFETIDPGetSolution_C", PCBDDCMatFETIDPGetSolution_BDDC)); 28069566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCPreSolveChangeRHS_C", PCPreSolveChangeRHS_BDDC)); 28079566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", PCSetCoordinates_BDDC)); 28083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2809da1bb401SStefano Zampini } 281043371fb9SStefano Zampini 281143371fb9SStefano Zampini /*@C 2812f1580f4eSBarry Smith PCBDDCInitializePackage - This function initializes everything in the `PCBDDC` package. It is called 2813f1580f4eSBarry Smith from `PCInitializePackage()`. 281443371fb9SStefano Zampini 281543371fb9SStefano Zampini Level: developer 281643371fb9SStefano Zampini 2817562efe2eSBarry Smith .seealso: [](ch_ksp), `PetscInitialize()`, `PCBDDCFinalizePackage()` 281843371fb9SStefano Zampini @*/ 2819d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCInitializePackage(void) 2820d71ae5a4SJacob Faibussowitsch { 282143371fb9SStefano Zampini int i; 282243371fb9SStefano Zampini 282343371fb9SStefano Zampini PetscFunctionBegin; 28243ba16761SJacob Faibussowitsch if (PCBDDCPackageInitialized) PetscFunctionReturn(PETSC_SUCCESS); 282543371fb9SStefano Zampini PCBDDCPackageInitialized = PETSC_TRUE; 28269566063dSJacob Faibussowitsch PetscCall(PetscRegisterFinalize(PCBDDCFinalizePackage)); 282743371fb9SStefano Zampini 282843371fb9SStefano Zampini /* general events */ 28299566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCTopo", PC_CLASSID, &PC_BDDC_Topology[0])); 28309566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCLKSP", PC_CLASSID, &PC_BDDC_LocalSolvers[0])); 28319566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCLWor", PC_CLASSID, &PC_BDDC_LocalWork[0])); 28329566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCCorr", PC_CLASSID, &PC_BDDC_CorrectionSetUp[0])); 28339566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCASet", PC_CLASSID, &PC_BDDC_ApproxSetUp[0])); 28349566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCAApp", PC_CLASSID, &PC_BDDC_ApproxApply[0])); 28359566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCCSet", PC_CLASSID, &PC_BDDC_CoarseSetUp[0])); 28369566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCCKSP", PC_CLASSID, &PC_BDDC_CoarseSolver[0])); 28379566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCAdap", PC_CLASSID, &PC_BDDC_AdaptiveSetUp[0])); 28389566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCScal", PC_CLASSID, &PC_BDDC_Scaling[0])); 28399566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCSchr", PC_CLASSID, &PC_BDDC_Schurs[0])); 28409566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCDirS", PC_CLASSID, &PC_BDDC_Solves[0][0])); 28419566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCNeuS", PC_CLASSID, &PC_BDDC_Solves[0][1])); 28429566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCCoaS", PC_CLASSID, &PC_BDDC_Solves[0][2])); 284343371fb9SStefano Zampini for (i = 1; i < PETSC_PCBDDC_MAXLEVELS; i++) { 284443371fb9SStefano Zampini char ename[32]; 284543371fb9SStefano Zampini 28469566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCTopo l%02d", i)); 28479566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Topology[i])); 28489566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCLKSP l%02d", i)); 28499566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_LocalSolvers[i])); 28509566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCLWor l%02d", i)); 28519566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_LocalWork[i])); 28529566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCCorr l%02d", i)); 28539566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_CorrectionSetUp[i])); 28549566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCASet l%02d", i)); 28559566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_ApproxSetUp[i])); 28569566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCAApp l%02d", i)); 28579566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_ApproxApply[i])); 28589566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCCSet l%02d", i)); 28599566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_CoarseSetUp[i])); 28609566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCCKSP l%02d", i)); 28619566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_CoarseSolver[i])); 28629566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCAdap l%02d", i)); 28639566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_AdaptiveSetUp[i])); 28649566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCScal l%02d", i)); 28659566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Scaling[i])); 28669566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCSchr l%02d", i)); 28679566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Schurs[i])); 28689566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCDirS l%02d", i)); 28699566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Solves[i][0])); 28709566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCNeuS l%02d", i)); 28719566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Solves[i][1])); 28729566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCCoaS l%02d", i)); 28739566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Solves[i][2])); 287443371fb9SStefano Zampini } 28753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 287643371fb9SStefano Zampini } 287743371fb9SStefano Zampini 287843371fb9SStefano Zampini /*@C 2879f1580f4eSBarry Smith PCBDDCFinalizePackage - This function frees everything from the `PCBDDC` package. It is 2880f1580f4eSBarry Smith called from `PetscFinalize()` automatically. 288143371fb9SStefano Zampini 288243371fb9SStefano Zampini Level: developer 288343371fb9SStefano Zampini 2884562efe2eSBarry Smith .seealso: [](ch_ksp), `PetscFinalize()`, `PCBDDCInitializePackage()` 288543371fb9SStefano Zampini @*/ 2886d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCFinalizePackage(void) 2887d71ae5a4SJacob Faibussowitsch { 288843371fb9SStefano Zampini PetscFunctionBegin; 288943371fb9SStefano Zampini PCBDDCPackageInitialized = PETSC_FALSE; 28903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 289143371fb9SStefano Zampini } 2892